/*
Copyright (C) 2000-2010  Ministere de la culture et de la communication (France), AJLSM
See LICENCE file
*/
package fr.gouv.culture.sdx.pipeline;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.excalibur.source.SourceResolver;

import fr.gouv.culture.sdx.documentbase.DefaultIDGenerator;
import fr.gouv.culture.sdx.exception.SDXException;
import fr.gouv.culture.sdx.utils.Identifiable;
import fr.gouv.culture.sdx.utils.Utilities;
import fr.gouv.culture.sdx.utils.xml.AbstractSdxXMLPipe;

/**
 * An abstract transformation for basic operations.
 *
 * <p>
 * This abstract class properly handle the super.getLog() and the parameters.
 */
public abstract class AbstractTransformation extends AbstractSdxXMLPipe implements Transformation {


    protected static final String PARAMETER_NAME_DISABLE = "disable";
    protected static final String PARAMETER_NAME_ENABLE = "enable";

		/** The SourceResolver to use. */
    protected SourceResolver _resolver;

		/**
     * Keeps the SourceResolver.
     */
    public void service(ServiceManager serviceManager) throws ServiceException {
        super.service(serviceManager);
        this._resolver = (SourceResolver)_manager.lookup(SourceResolver.ROLE);
    }

    /** The parameters for this transformation provided by the pipeline via the setParameters() method.
     *
     *@see this.setParameters()
     */
    protected Parameters parameters;

    /** The parameters for this transformation provided by the Parameteriable interface's
     * parameterize method.
     *
     *@see this.parameterize();
     */
    protected Parameters transParameters;

    /**Indicates wheter the result of this transformation step should be kept*/
    private boolean keepResult = false; //defaulted

    public Parameters getParameters() {
        return parameters;
    }

    /** Sets some parameters from a pipeline.
     * @param p The parameters
     */
    public void setParameters(Parameters p) {
        this.parameters = p;

    }

    /**Recycles the contentHandler, lexicalHandler, and xmlConsumer for the transformation*/
    public void recycle() {
        super.recycle();
    }

    /**Loads base configuration common to all transformations.
     *
     * Currently loads the id from the configuraion object.
     * It will eventually load the optional "keep" parameter which
     * is used to specify that the results of the transformation
     * should be retained.
     *
     *@param configuration   The configuration object
     *@throws ConfigurationException
     */
    public void configure(Configuration configuration) throws ConfigurationException {
        try {
            super.setId(configuration.getAttribute(Identifiable.ConfigurationNode.ID, new DefaultIDGenerator().generate()));
        } catch (SDXException e) {
            throw new ConfigurationException(e.getMessage(), e);
        }
        super.configure(configuration);
        //getting the "keep" attribute,
        this.keepResult = configuration.getAttributeAsBoolean(Transformation.ATTRIBUTE_KEEP, false);
        if (configuration != null) {
            this.transParameters = Parameters.fromConfiguration(configuration);
            verifyConfigurationParameters(this.transParameters);
        }

    }

    protected void verifyConfigurationParameters(Parameters params) {
        if (params != null) {
            String[] paramNames = params.getNames();
            for (int i = 0; i < paramNames.length; i++) {
                String paramName = paramNames[i];
                if (Utilities.checkString(paramName)) {
                    String paramValue = params.getParameter(paramName, null);
                    if (paramValue == null || paramValue.equals("null"))
                        params.removeParameter(paramName);
                }


            }
        }

    }

    /**Indicates wheter the results of this transfomation should be retained*/
    public boolean shouldKeepResult() {
        return keepResult;
    }

    /**Returns a boolean indicating whether
     * this transformation is enabled
     * first check the tranformations parameters
     * secondly checking the parameters passed
     * from the containing pipeline
     *
     */
    protected boolean isStepEnabled() {
        boolean enabled = true;
        //verifying the 'disable' parameter from this TRANSFORMATION's parameters
        if (transParameters != null) {
            String enable = transParameters.getParameter(PARAMETER_NAME_ENABLE, "true");
            enabled = Boolean.getBoolean(enable);
            if (enabled) {
                String disable = transParameters.getParameter(PARAMETER_NAME_DISABLE, "false");
                enabled = !Boolean.getBoolean(disable);
            }
        }

        /*verifying the 'disable' parameter from the GOVERNING PIPELINE parameters
        *currently any pipeline parameters passed will
        *be overriding in nature with regards to this
        *parameter and method
        */
        if (parameters != null) {
            if (!enabled) {
                String enableTransId = parameters.getParameter(PARAMETER_NAME_ENABLE, null);
                if (Utilities.checkString(enableTransId)) {
                    if (enableTransId.equals(this.getId()))
                        enabled = true;
                }
            } else {
                /*if the step is enabled we check for a 'disable' parameter
                */
                String disableTransId = parameters.getParameter(PARAMETER_NAME_DISABLE, null);
                if (Utilities.checkString(disableTransId)) {
                    if (disableTransId.equals(this.getId()))
                        enabled = false;
                }
            }
        }

        return enabled;
    }

    protected String getClassNameSuffix() {
        return Transformation.CLASS_NAME_SUFFIX;
    }

	protected boolean initToSax() {
		this._xmlizable_objects.put("ID", this.getId());
		this._xmlizable_objects.put("Encoding", this.getEncoding());
		this._xmlizable_objects.put("XML-Lang", this.getXmlLang());
		this._xmlizable_objects.put("Locale", this.getLocale().toString());
		this._xmlizable_objects.put("Keep_Result", String.valueOf(this.keepResult));
		//TODO: Is it useful to send the parameters?
		/*if((this.getParameters()!=null) && (this.getParameters().getNames()!=null)){
			String[] names=this.getParameters().getNames();
			for(int i=0; i< names.length;i++){
				try{
					this._xmlizable_objects.put(names[i], this.getParameters().getParameter(names[i]));
				} catch(ParameterException e){
				}
			}
		}*/
		return true;
	}

	/**Init the LinkedHashMap _xmlizable_volatile_objects with the objects in order to describ them in XML
	 * Some objects need to be refresh each time a toSAX is called*/
	protected void initVolatileObjectsToSax() {
		this._xmlizable_objects.put("Keep_Result", String.valueOf(this.keepResult));
	}
}
