/** * Copyright (c) 2004-2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM - Initial API and implementation */ package org.eclipse.emf.ant.taskdefs.codegen.ecore; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.EnumeratedAttribute; import org.eclipse.emf.ant.taskdefs.EMFTask; import org.eclipse.emf.codegen.ecore.Generator; import org.eclipse.emf.codegen.ecore.genmodel.GenJDKLevel; import org.eclipse.emf.common.util.URI; /** * <p> * Base class for all the "generator tasks" that provides the common attributes * and behavior. A "generator task" is an Ant task that encompasses the * two operations performed when generating code with EMF: the creation of the EMF files * (genmodel and ecore) from a given model specification and the code generation. * </p> * <p> * These are the common attributes provided by this class: * </p> * <table order="1" cellpadding="2" cellspacing="0"> * <tr><td><b>Attribute</b></td><td><b>Description</b></td></tr> * <tr> * <td valign="top">model</td> * <td>The file that defines the model.</td> * </tr> * <tr> * <td valign="top">genModel</td> * <td>The .genmodel file.</td> * </tr> * <tr> * <td valign="top">reconcileGenModel</td> * <td>Specifies how the genmodel file is to be supposed to be handled. The possible values are: * <ul> * <li>overwrite - <i>(default)</i>Replaces the genmodel file if it exists;</li> * <li>keep - Doesn't generate the genmodel if one is provided; and</li> * <li>reload - Reloads the genmodel to reflect model changes.</li> * </ul> * </td> * </tr> * <tr> * <td valign="top">generateJavaCode</td> * <td>Boolean value indicating whether the java code should be generated. Should be set to * <tt>false</tt> when you want to generate only the .ecore and .genmodel files</td> * </tr> * <tr> * <td valign="top">generateModelProject</td> * <td>The model project will be only generated if this attribute is set to <tt>true</tt> and if the project's * information is specified in the task. * <br />The default value is <tt>true</tt>.</td> * </tr> * <tr> * <td valign="top">generateEditProject</td> * <td>The edit project will be only generated if this attribute is set to <tt>true</tt> and if the project's * information is specified in the task. * <br />The default value is <tt>true</tt>.</td> * </tr> * <tr> * <td valign="top">generateEditorProject</td> * <td>The editor project will be only generated if this attribute is set to <tt>true</tt> and if the project's * information is specified in the task. * <br />The default value is <tt>true</tt>.</td> * </tr> * <tr> * <td valign="top">templatePath</td> * <td>The directory where your customized JET templates are located.</td> * </tr> * <tr> * <td valign="top">modelProject</td> * <td>The directory where the files generated for the model will be placed into.</td> * </tr> * <tr> * <td valign="top">modelProjectFragmentPath</td> * <td>The model project relative path of the source folder.</td> * </tr> * <tr> * <td valign="top">modelPluginID</td> * <td>The ID of the generated model plugin.</td> * </tr> * <tr> * <td valign="top">autoBuild</td> * <td>Boolean value that sets the Eclipse's 'Build Automatically' flag. If not specified, this task doesn't * change the current workspace's setting.</td> * </tr> * <tr> * <td valign="top">sdo</td> * <td>Boolean value indicating whether the SDO API should be generated.</td> * </tr> * <tr> * <td valign="top">copyright</td> * <td>The copyright text.</td> * </tr> * <tr> * <td valign="top">jdkLevel</td> * <td>The JDK level for the generated code. "1.4", "5.0", and * "6.0" are valid values.</td> * </tr> * <tr> * <td valign="top">validateModel</td> * <td>Boolean value indicating whether the Ecore model should be validated before * generating the code.</td> * </tr> * </table> * * <p>If the Ant task knows how to handle multiple model specifications, * <model> elements can be used (instead of the <tt>model</tt> attribute). Here's * an example:</p> * * <pre> * <model uri="http://www.example.eclipse.org/library.xsd"/> * <model file="c:/common.xsd"/> * </pre> * * @since 2.1.0 */ public abstract class GeneratorTask extends EMFTask { public static class ModelLocation { private File file; private String uri; public File getFile() { return file; } public void setFile(File file) { this.file = file; } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } } public static class ReconcileGenModelType extends EnumeratedAttribute { @Override public String[] getValues() { return new String []{ "overwrite", "keep", "reload" }; } } protected static final int GENMODEL_OVERWRITE = 0; protected static final int GENMODEL_KEEP = 1; protected static final int GENMODEL_RELOAD = 2; protected File model; private List<ModelLocation> modelLocations; protected File genModel; protected File modelProject; protected String modelPluginID; protected String modelProjectFragmentPath; protected File templatePath; protected String copyright; protected boolean sdo = false; protected String jdkLevel; protected String validateModel; protected int reconcileGenModel = GENMODEL_OVERWRITE; protected boolean generateJavaCode = true; protected Commandline commandline; protected boolean generateModelProject = true; protected boolean generateEditProject = true; protected boolean generateEditorProject = true; protected boolean generateTestsProject = true; protected Boolean autoBuild; protected boolean supportMultipleURIs() { return true; } public void setModel(File model) { this.model = model; } public ModelLocation createModel() { if (supportMultipleURIs()) { ModelLocation modelLocation = new ModelLocation(); if (modelLocations == null) { modelLocations = new ArrayList<ModelLocation>(); modelLocations.add(modelLocation); } else { modelLocations.add(0, modelLocation); } return modelLocation; } else { throw new BuildException("This importer doesn't support multiple models"); } } public void setGenModel(File genModel) { this.genModel = genModel; } public void setModelProject(File modelProject) { this.modelProject = modelProject; } public void setModelProjectFragmentPath(String modelProjectFragmentPath) { this.modelProjectFragmentPath = modelProjectFragmentPath; } public void setModelPluginID(String modelPluginID) { this.modelPluginID = modelPluginID; } public void setGenerateModelProject(boolean generate) { generateModelProject = generate; } public void setGenerateEditProject(boolean generate) { generateEditProject = generate; } public void setGenerateEditorProject(boolean generate) { generateEditorProject = generate; } public void setGenerateTestsProject(boolean generate) { generateTestsProject = generate; } public Commandline.Argument createArg() { return getCommandline().createArgument(); } public void setTemplatePath(File templatePath) { this.templatePath = templatePath; } public void setCopyright(String copyright) { this.copyright = copyright; } public void setSDO(boolean sdo) { this.sdo = sdo; } public void setReconcileGenModel(ReconcileGenModelType type) { setReconcileGenModel(type.getValue()); } public void setReconcileGenModel(String type) { if ("overwrite".equals(type)) { reconcileGenModel = GENMODEL_OVERWRITE; } else if ("keep".equals(type)) { reconcileGenModel = GENMODEL_KEEP; } else if ("reload".equals(type)) { reconcileGenModel = GENMODEL_RELOAD; } } public void setGenerateJavaCode(boolean generateJavaCode) { this.generateJavaCode = generateJavaCode; } public void setAutoBuild(boolean autoBuild) { this.autoBuild = Boolean.valueOf(autoBuild); } public void setValidateModel(boolean validateModel) { this.validateModel = Boolean.toString(validateModel); } public void setJdkLevel(String jdkLevel) { this.jdkLevel = jdkLevel; } protected GenJDKLevel getJDKLevel() { return GenJDKLevel.get(jdkLevel); } protected Commandline getCommandline() { if (commandline == null) { commandline = new Commandline(); } return commandline; } @Override protected void checkAttributes() throws BuildException { if (modelLocations == null) { assertTrue("The 'model' attribute must be specified.", model != null && modelLocations == null); } else { for (ModelLocation modelLocation : modelLocations) { assertTrue("Either the 'file' or the 'uri' attributes of a 'model' element must be specified.", modelLocation.getFile() != null || modelLocation.getUri() != null); } } assertTrue("The 'genModel' attribute must be specified.", genModel != null); assertTrue("The specifed 'templatePath' attribute is not a valid directory.", templatePath == null || templatePath.isDirectory()); } @Override protected void doExecute() throws Exception { switch (reconcileGenModel) { case GENMODEL_KEEP: { if (genModel.exists()) break; } case GENMODEL_RELOAD: case GENMODEL_OVERWRITE: { addGenModelArguments(); adjustEditAndEditorProjects(); createGenModel(getCommandline().getArguments()); break; } } if (generateJavaCode) { List<String> arguments = getGeneratorArguments(); generateCodeFromGenModel(arguments.toArray(new String [arguments.size()])); } } abstract protected void createGenModel(String[] arguments) throws Exception; protected void addGenModelPathArgument() { if (genModel != null) { getCommandline().createArgument(true).setValue(genModel.getAbsolutePath()); if (reconcileGenModel == GENMODEL_RELOAD) { getCommandline().createArgument().setValue("-reload"); } } } protected void addModelPathArgument() { if (model != null) { getCommandline().createArgument(true).setValue(model.getAbsolutePath()); } if (modelLocations != null) { for (ModelLocation modelLocation : modelLocations) { String argument = modelLocation.getUri(); if (argument == null) { try { argument = URI.createFileURI(modelLocation.getFile().getCanonicalPath()).toString(); } catch (IOException e) { argument = URI.createFileURI(modelLocation.getFile().getAbsolutePath()).toString(); } } getCommandline().createArgument(true).setValue(argument); } } } protected void addGenModelArguments() { addGenModelPathArgument(); addModelPathArgument(); if (modelProject != null) { getCommandline().createArgument().setValue("-modelProject"); getCommandline().createArgument().setValue(modelProject.getAbsolutePath()); } if (modelProjectFragmentPath != null) { getCommandline().createArgument().setValue(modelProjectFragmentPath); } if (templatePath != null) { getCommandline().createArgument().setValue("-templatePath"); getCommandline().createArgument().setValue(templatePath.getAbsolutePath()); } if (modelPluginID != null) { getCommandline().createArgument().setValue("-modelPluginID"); getCommandline().createArgument().setValue(modelPluginID); } if (copyright != null) { getCommandline().createArgument().setValue("-copyright"); getCommandline().createArgument().setValue(copyright); } if (validateModel != null) { getCommandline().createArgument().setValue("-validateModel"); getCommandline().createArgument().setValue(validateModel); } if (jdkLevel != null) { GenJDKLevel genJDKLevel = getJDKLevel(); if (genJDKLevel != null) { getCommandline().createArgument().setValue("-jdkLevel"); getCommandline().createArgument().setValue(genJDKLevel.getLiteral()); } } if (sdo) { getCommandline().createArgument().setValue("-sdo"); } } protected void adjustEditAndEditorProjects() { String arguments = getCommandline().toString(); generateModelProject &= arguments.indexOf("-modelProject") >= 0; generateEditProject &= arguments.indexOf("-editProject") >= 0; generateEditorProject &= arguments.indexOf("-editorProject") >= 0; generateTestsProject &= arguments.indexOf("-testsProject") >= 0; } protected List<String> getGeneratorArguments() { List<String> arguments = new ArrayList<String>(); if (generateModelProject) arguments.add("-model"); if (generateEditProject) arguments.add("-edit"); if (generateEditorProject) arguments.add("-editor"); if (generateTestsProject) arguments.add("-tests"); if (autoBuild != null) { arguments.add("-autoBuild"); arguments.add(autoBuild.toString()); } if (templatePath != null) { arguments.add("-dynamicTemplates"); } arguments.add(genModel.getAbsolutePath()); return arguments; } protected void generateCodeFromGenModel(String[] arguments) { new Generator().run(arguments); } }