/*
 *  @(#)ValidateJavaType.java
 *
 * Copyright (C) 2002-2003 Matt Albrecht
 * groboclown@users.sourceforge.net
 * http://groboutils.sourceforge.net
 *
 *  Part of the GroboUtils package at:
 *  http://groboutils.sourceforge.net
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the 
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in 
 *  all copies or substantial portions of the Software. 
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 *  DEALINGS IN THE SOFTWARE.
 */
package net.sourceforge.groboutils.mbtf.v1.ant;

import org.apache.tools.ant.Project;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.Definer;
import org.apache.tools.ant.taskdefs.Property;
import org.apache.tools.ant.types.Reference;

import java.util.Vector;
import java.util.Enumeration;
import java.io.File;

import net.sourceforge.groboutils.mbtf.v1.IValidate;
import net.sourceforge.groboutils.mbtf.v1.IAction;
import net.sourceforge.groboutils.mbtf.v1.IErrors;
import net.sourceforge.groboutils.mbtf.v1.ISystem;

import org.apache.log4j.Logger;


/**
 * A specific IValidate instance, which is Ant compatible, that instantiates
 * a set of Classes using the default constructor, and iterates through them
 * as though they each were IValidate instances.
 *
 * @author     Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
 * @version    $Date: 2003/02/10 22:52:25 $
 * @since      June 13, 2002
 */
public class ValidateJavaType extends Definer implements IValidate, IAction
{
    private static final Logger LOG = Logger.getLogger(
        ValidateJavaType.class );
    
    // intended to be an imbedded task, but can be defined outside
    // the state iterator.
    public static final String DEFAULT_ANT_NAME = "mbtf.validatejava";
    
    private Vector validators = new Vector();
    private Vector properties = new Vector();
    
    public void execute()
            throws BuildException
    {
        if (project == null)
        {
            throw new BuildException("ValidateJavaType project is null");
        }
        
        // clean out the old classes, if any remain
        this.validators = new Vector();
        try
        {
            super.execute();
        }
        catch (BuildException e)
        {
            // allow for the name to be empty
            setName( "ignore" );
            super.execute();
        }
    }
    protected void addDefinition(String name, Class c)
            throws BuildException
    {
        LOG.debug("added "+c);
        addClass( c );
    }
    
    
    public void addClass( Class c )
            throws BuildException
    {
        try
        {
            Object o = c.newInstance();
            this.validators.addElement( o );
        }
        catch (Exception e)
        {
            throw new BuildException("Could not instantiate "+c.getName(),
                e, location );
        }
    }
    
    public void addParam( Property prop )
    {
        if (prop != null)
        {
            this.properties.addElement( prop );
        }
    }
    
    
    public void validate( ISystem system, IErrors errors )
    {
        LOG.debug(this+": Entering validate()");
        try
        {
            execute();
        }
        catch (BuildException e)
        {
            LOG.info("execute() caused exception", e);
            errors.addError("Failed to correctly process Ant structure.", e );
            LOG.debug(this+": Leaving validate() due to build exception");
            return;
        }
        
        Enumeration enum = this.validators.elements();
        int count = 0;
        while (enum.hasMoreElements())
        {
            Object o = enum.nextElement();
            if (o instanceof IValidate)
            {
                ++count;
                setupObject( o );
                LOG.debug(this+": Start Validate "+o);
                ((IValidate)o).validate( system, errors );
                LOG.debug(this+": End Validate "+o);
            }
        }
        LOG.debug(this+": Leaving validate() ["+count+" validators]");
    }
    
    
    public void performAction( ISystem system, IErrors errors )
    {
        LOG.debug( this+": Entering performAction()" );
        try
        {
            execute();
        }
        catch (BuildException e)
        {
            LOG.info("execute() caused exception", e);
            errors.addError("Failed to correctly process Ant structure.", e );
            LOG.debug(this+": Leaving performAction() due to build exception");
            return;
        }
        
        Enumeration enum = this.validators.elements();
        int count = 0;
        while (enum.hasMoreElements())
        {
            Object o = enum.nextElement();
            if (o instanceof IAction)
            {
                ++count;
                setupObject( o );
                LOG.debug(this+": Start Perform action on "+o);
                ((IAction)o).performAction( system, errors );
                LOG.debug(this+": End perform action on "+o);
            }
        }
        LOG.debug(this+": Leaving performAction() ["+count+" actions]");
    }
    
    
    protected void setupObject( Object o )
    {
        if (o != null && o instanceof IUsesProperties)
        {
            IUsesProperties iup = (IUsesProperties)o;
            iup.setProject( project );
            
            Enumeration enum = this.properties.elements();
            while (enum.hasMoreElements())
            {
                Property p = (Property)enum.nextElement();
                String name = p.getName();
                String value = p.getValue();
                File file = p.getFile();
                Reference refid = p.getRefid();
                String resource = p.getResource();
                String env = p.getEnvironment();
                
                if (value != null)
                {
                    iup.addProperty( name, value );
                }
                if (file != null)
                {
                    iup.addFile( name, file );
                }
                if (refid != null)
                {
                    LOG.debug("Adding reference '"+name+"' to '"+refid+"'");
                    iup.addReference( name, refid );
                }
                if (resource != null)
                {
                    iup.addResource( name, resource );
                }
                if (env != null)
                {
                    iup.addEnvironment(name, env );
                }
            }
        }
    }
}

