/*
 * Scone - The Web Enhancement Framework
 * Copyright (C) 2009 Harald Weinreich, Volkert Buchmann, Frank Wollenweber, Torsten Haß
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package  scone.util;


import org.w3c.dom.Element;

import scone.Plugin;


/**
 * represents a a Scone plugin which states (enabled/disabled) 
 * are mirrored in an XML element. This class is to be used with
 * the PluginRepository.
 */
public class PluginRepositoryEntry {
    // the Scone plugin
    Plugin plugin = null;
    // the element that mirrors the plugin's state
    Element element = null;
    // whether the plugin is enabled
    boolean enabled = false;

    /**
     * creates a new PluginRepositoryEntry from the definition in an XML element. 
     * The class information is extracted and the apropriate plugin
     * is instatiated. The XML element must look like this:<br>
     * <code>&lt;plugin class="[full.classname]" enabled="[yes|no]"&bt;</code>
     * <p>If the plugin is disabled according to the element, it will not be
     * instantiated since if a plugin is instantiated it might already register stuff.
     * The plugin also cannot be enabled later on since Scone might not meet its
     * requirements. There should be a nicer solution for this, but that's how it works
     * currently.
     * @param     Element the XML element
     */
    PluginRepositoryEntry(Element element) {
        this.element = element;
        if (element.getAttribute("enabled").equals("yes")) {
            instantiatePlugin();
        }
    }

    /**
     * instantiates a Plugin from an XML element
     */
    void instantiatePlugin() {
        try {
            plugin = (Plugin) Class.forName(element.getAttribute("class")).newInstance();
            enabled = true;
        } catch (ClassCastException e) {
            String p = "";

            p = element.getAttribute("class");
            System.out.println("Error!\nThis is no Scone-Plugin: " + p);
            ErrorLog.log(this, "<init>", "could not cast plugin " + p, e);
        } catch (Exception e) {
            String p = "";

            if (element != null) {
                p = element.getAttribute("class");
                if (p == null) {
                    p = "no class!";
                }
            }
            ErrorLog.log(this, "<init>", "could not instanciate plugin " + p, e);
        }
    }
	
    /**
     * disables the plugin and removes the element from its parent.
     * The repository entry is thus removed from the repository.
     */
    public void remove() {
        disable();
        element.getParentNode().removeChild(element);
    }
    
    /**
     * calls Plugin.terminate()
     * does not invoke disable()
     */
    public void terminate() {
        plugin.terminate();
    }

    /**
     * disables the plugin and mirrors this change in the element.
     */
    public void disable() {
        if (enabled) {
            if (plugin != null) {
                plugin.disable();
            }
            element.setAttribute("enabled", "no");
        }
        enabled = false;
    }

    /**
     * enables the plugin and mirrors this change in the element.
     * If the plugin has not yet been instantiated, the change will 
     * be reflected in the element but the plugin will not be activated.
     * Scone has to be restarted to activate the plugin.
     */
    public void enable() {
        if (!enabled) {
            if (plugin != null) {
                plugin.enable();
            }
            element.setAttribute("enabled", "yes");
        }
        enabled = true;
        
    }

    /**
     * returns the requirements of the plugin if the plugin has been 
     * instantiated.
     * @return the plugin's requirements
     */
    public int getRequirements() {
        if (plugin != null) {
            return  plugin.getRequirements();
        } else {
            return  0;
        }
    }

    /**
     * returns the plugin
     * @return the plugin
     */
    public Plugin getPlugin() {
        return  plugin;
    }

    /**
     * check if a plugin is currently enabled
     * @return true if the plugin is enabled.
     */
    public boolean isEnabled() {
        return  enabled;
    }

    /**
     * returns the classname of the plugin
     * @return the plugin's classname
     */
    public String getName() {
        return  element.getAttribute("class");
    }
}

