// AbstractRenderer.java
//
// Created: February 2006
//
// This file is a component of the BioMoby project.
// Copyright Martin Senger (martin.senger@gmail.com).
//

package org.biomoby.service.dashboard.renderers;

import org.biomoby.shared.MobyException;
import org.biomoby.service.dashboard.data.DataContainer;

import org.tulsoft.tools.gui.SwingUtils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;

import javax.swing.Icon;
import javax.swing.JComponent;


/**
 * Abstract rendering class. <p>
 *
 * @author <A HREF="mailto:martin.senger@gmail.com">Martin Senger</A>
 * (based on work by Matthew Pocock for <a
 * href="http://taverna.sf.net">Taverna</a>)
 * @version $Id: AbstractRenderer.java,v 1.4 2006/02/20 05:51:11 senger Exp $
 */

public abstract class AbstractRenderer
    implements Renderer {

    private String name;
    private Icon icon;

    protected String iconFileName;

    /*********************************************************************
     *
     ********************************************************************/
    public AbstractRenderer (String name) {
	this.name = name;
    }

    /*********************************************************************
     *
     ********************************************************************/
    public AbstractRenderer (String name, Icon icon) {
	this.name = name;
	this.icon = icon;
    }

    /*********************************************************************
     *
     ********************************************************************/
    public AbstractRenderer (String name, String iconFileName) {
	this.name = name;
	this.iconFileName = iconFileName;
    }

    /*********************************************************************
     *
     ********************************************************************/
    public Icon getIcon() {
	if (icon == null && iconFileName != null)
	    icon = SwingUtils.createIcon (iconFileName, this);
	return icon;
    }

    /*********************************************************************
     *
     ********************************************************************/
    public final String getName() {
	return name;
    }

    /**************************************************************************
     * Default implementation. <p>
     *
     * If it gets a byte array, it saves it in the given file. <p>
     *
     * If it gets any other array, it looks at its elements and - if
     * the elements are of type byte array, they all are stored
     * separately, to more files (this is done with the help of the
     * {@link CollectionRenderer}). Other types of elements are
     * converted to strings by calling their toString() method, and
     * all of them are store in one file. <p>
     *
     * It 'data' do not contain an array, they are treated similarly
     * as above: they are converted to string using its toString()
     * method and put in a file. <p>
     **************************************************************************/
    public boolean save2File (DataContainer data, File file)
	throws MobyException {

	if (data == null)
	    return false;

	Object d = data.getData();

	// byte array goes in a file
	if (d instanceof byte[]) {
	    return saveBytes ((byte[])d, file);
	}

	if (d.getClass().isArray()) {
	    // if it is an array (meaning that it is coming form a moby
	    // collection)...
	    Object[] ds = (Object[])d;

	    // ...and the elements are byte arrays, we want store them
	    // separately, in more files (this is mainly for images)
	    if (byte[].class == ds.getClass().getComponentType()) {
		CollectionRenderer collRend = new BoxCollectionRenderer (this);
		return collRend.save2File (data, file);
	    }

	    // ...and the elements are *not* byte arrays, we store
	    // them in one file after calling their toString() method
	    try {
		PrintWriter fileout = new PrintWriter
		    (new BufferedWriter (new FileWriter (file)));
		for (int i = 0; i < ds.length; i++)
		    fileout.print (ds[i].toString());
		fileout.close();
		return true;
	    } catch (IOException e) {
		throw new MobyException (error (e, file));
	    }

	} else {
	    // if it is not an array, just store it in a file
	    try {
		PrintWriter fileout = new PrintWriter
		    (new BufferedWriter (new FileWriter (file)));
		fileout.print ( data.getData().toString() );
		fileout.close();
		return true;
	    } catch (IOException e) {
		throw new MobyException (error (e, file));
	    }
	}
    }

    /*********************************************************************
     * 
     ********************************************************************/
    protected String error (Exception e, File file) {
	return
	    "Problem with file " +  file.getAbsolutePath() +
	    ": " + e.toString();
    }

    /*********************************************************************
     * 
     ********************************************************************/
    protected boolean saveBytes (byte[] bytes, File file)
	throws MobyException {
	try {
	    BufferedOutputStream fileout = new BufferedOutputStream
		(new FileOutputStream (file));
	    fileout.write (bytes);
	    fileout.close();
	    return true;
	} catch (IOException e) {
	    throw new MobyException (error (e, file));
	}
    }

    /*********************************************************************
     * 
     ********************************************************************/
    public abstract boolean canHandle (String criterion, Object value);

    /**************************************************************************
     *
     **************************************************************************/
    public abstract JComponent getComponent (DataContainer data)
	throws MobyException;

}
