001package org.andromda.maven.plugin;
002
003import java.io.File;
004import java.net.URL;
005import org.andromda.core.AndroMDA;
006import org.andromda.core.common.ResourceUtils;
007import org.andromda.core.configuration.Configuration;
008import org.andromda.core.configuration.Model;
009import org.andromda.core.configuration.Repository;
010import org.apache.maven.plugin.MojoExecutionException;
011
012/**
013 * A Maven2 plugin to run AndroMDA.
014 *
015 * @author Chad Brandon
016 * @goal run
017 * @phase generate-sources
018 * @requiresDependencyResolution runtime
019 */
020public class AndroMDAMojo
021    extends AbstractAndroMDAMojo
022{
023    /**
024     * Whether or not a last modified check should be performed before running AndroMDA again.
025     * Checks files in buildSourceDirectory against configurationUri and referenced model dates.
026     *
027     * @parameter expression="${lastModifiedCheck}"
028     *   default-value=true
029     */
030    private boolean lastModifiedCheck = true;
031
032    /**
033     * Whether or not processing should be skipped (this is if you just want to force AndroMDA
034     * not to run on your model).
035     *
036     * @parameter expression="${andromda.run.skip}"
037     *   default-value=false
038     */
039    private boolean skipProcessing = false;
040
041    /**
042     * The directory to which the build source is located (any generated source).
043     *
044     * @parameter expression="${project.build.directory}/src/main/java"
045     */
046    private File buildSourceDirectory;
047
048    /**
049     * The directory where the model generation output history is located
050     * (Modelname file containing a list of files generated by that model).
051     *
052     * @parameter expression="${project.build.directory}/history"
053     */
054    private File modelOutputHistory;
055
056    /**
057     * @param lastModifiedCheck the lastModifiedCheck to set
058     */
059    public void setLastModifiedCheck(boolean lastModifiedCheck)
060    {
061        this.lastModifiedCheck = lastModifiedCheck;
062    }
063
064    /**
065     * @param buildSourceDirectory the buildSourceDirectory to set
066     */
067    public void setBuildSourceDirectory(File buildSourceDirectory)
068    {
069        this.buildSourceDirectory = buildSourceDirectory;
070    }
071
072    /**
073     * @param modelOutputHistory the modelOutputHistory to set
074     */
075    public void setModelOutputHistory(File modelOutputHistory)
076    {
077        this.modelOutputHistory = modelOutputHistory;
078    }
079
080    /**
081     * @see org.andromda.maven.plugin.AbstractAndroMDAMojo#execute(org.andromda.core.configuration.Configuration)
082     */
083    public void execute(final Configuration configuration)
084        throws MojoExecutionException
085    {
086        if (getLog().isDebugEnabled())
087        {
088            getLog().debug("lastModifiedCheck="+this.lastModifiedCheck + " skipProcessing="+this.skipProcessing 
089                    + " modelOutputHistory="+this.modelOutputHistory + " allowMultipleRuns="+this.allowMultipleRuns);            
090        }
091        if (!this.skipProcessing)
092        {
093            boolean execute = true;
094            if (this.lastModifiedCheck)
095            {
096                long date = this.getLastModelConfigDate(configuration);
097                execute = ResourceUtils.modifiedAfter(date,
098                        this.buildSourceDirectory);
099                if (getLog().isDebugEnabled())
100                {
101                    getLog().debug("this.lastModifiedCheck="+this.lastModifiedCheck + " execute="+execute + " date="+date);            
102                }
103            }
104            if (execute)
105            {
106                final AndroMDA andromda = AndroMDA.newInstance();
107                final String historyPath = this.modelOutputHistory!=null ? this.modelOutputHistory.getAbsolutePath() : null;
108                andromda.run(configuration, lastModifiedCheck,  historyPath);
109                andromda.shutdown();
110            }
111            else
112            {
113                this.getLog().info("Files are up-to-date, skipping AndroMDA execution");
114            }
115        }
116        if (this.buildSourceDirectory != null)
117        {
118            this.getProject().addCompileSourceRoot(this.buildSourceDirectory.getPath());
119        }
120    }
121
122    /**
123     * Find the latest date from the configurationUri (andromda.xml) and all referenced models.
124     * @param configuration The model code generation configuration (model list)
125     */
126    private long getLastModelConfigDate(final Configuration configuration)
127    {
128        final URL configurationUri = ResourceUtils.toURL(this.configurationUri);
129        long date = ResourceUtils.getLastModifiedTime(configurationUri);
130        final Repository[] repositories = configuration.getRepositories();
131        int repositoryCount = repositories.length;
132        for (int ctr = 0; ctr < repositoryCount; ctr++)
133        {
134            final Repository repository = repositories[ctr];
135            if (repository != null)
136            {
137                final Model[] models = repository.getModels();
138                final int modelCount = models.length;
139                for (int ctr2 = 0; ctr2 < modelCount; ctr2++)
140                {
141                    final Model model = models[ctr2];
142                    long newDate = model.getLastModified();
143                    if (newDate > date)
144                    {
145                        date = newDate;
146                    }
147                }
148            }
149        }
150        return date;
151    }
152}