package org.dresdenocl.codegen.adapter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.codegen.ecore.CodeGenEcorePlugin;
import org.eclipse.emf.codegen.ecore.generator.GeneratorAdapterFactory;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.codegen.ecore.genmodel.generator.GenBaseGeneratorAdapter;
import org.eclipse.emf.codegen.jet.JETEmitter;
import org.eclipse.emf.codegen.jet.JETException;
import org.eclipse.emf.codegen.util.CodeGenUtil;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.JavaRuntime;
/**
* Code generation for GenClass independent GenModel elements such as the
* plugin.xml, messages, etc.
*
* @author Michael Thiele
*
*/
public class GenModelPivotAdapterGeneratorAdapter extends
GenBaseGeneratorAdapter {
public static final String PIVOTADAPTER_PROJECT_TYPE = "org.dresdenocl.codegen.generator.PivotAdapter";
protected static final int MANIFEST_MF_ID = 0;
protected static final int PLUGIN_XML_ID = 1;
protected static final int PLUGIN_JAVA_ID = 2;
protected static final int ADAPTER_FACTORY_ID = 3;
protected static final int MODEL_ID = 4;
protected static final int MODEL_MESSAGES_ID = 5;
protected static final int MESSAGES_ID = 6;
protected static final int PROVIDER_ID = 7;
protected static final int LOG4JPROPERTIES_ID = 8;
protected static final JETEmitterDescriptor[] JET_EMITTER_DESCRIPTORS = {
new JETEmitterDescriptor("manifest.mfjet",
"org.dresdenocl.codegen.adapter.templates.ManifestMF"),
new JETEmitterDescriptor("plugin.xmljet",
"org.dresdenocl.codegen.adapter.templates.PluginXML"),
new JETEmitterDescriptor("Plugin.javajet",
"org.dresdenocl.codegen.adapter.templates.PluginJava"),
new JETEmitterDescriptor("model/AdapterFactory.javajet",
"org.dresdenocl.codegen.adapter.templates.AdapterFactory"),
new JETEmitterDescriptor("model/Model.javajet",
"org.dresdenocl.codegen.adapter.templates.Model"),
new JETEmitterDescriptor("model/ModelMessages.javajet",
"org.dresdenocl.codegen.adpater.templates.ModelMessages"),
new JETEmitterDescriptor("model/Messages.propertiesjet",
"org.dresdenocl.codegen.adapter.templates.Messages"),
new JETEmitterDescriptor("provider/ModelProvider.javajet",
"org.dresdenocl.codegen.adapter.templates.ModelProvider"),
new JETEmitterDescriptor("log4j.propertiesjet",
"org.dresdenocl.codegen.adapter.templates.Log4jProperties") };
protected JETEmitterDescriptor[] getJETEmitterDescriptors() {
return JET_EMITTER_DESCRIPTORS;
}
public GenModelPivotAdapterGeneratorAdapter() {
super();
}
public GenModelPivotAdapterGeneratorAdapter(
GeneratorAdapterFactory generatorAdapterFactory) {
super(generatorAdapterFactory);
}
/**
* Returns the {@link GenModel}'s packages.
*/
@Override
public Collection<?> getGenerateChildren(Object object, Object projectType) {
return new ArrayList<GenPackage>(((GenModel) object).getGenPackages());
}
/**
* Returns <code>true</code> for the appropriate project type
* (PIVOTADAPTER_PROJECT_TYPE)
*/
@Override
public boolean canGenerate(Object object, Object projectType) {
return PIVOTADAPTER_PROJECT_TYPE.equals(projectType);
}
/**
* Is called by <code>org.eclipse.emf.codegen.ecore.generator.Generator</code>
* during generation process.
*/
@Override
public Diagnostic doGenerate(Object object, Object projectType,
Monitor monitor) {
if (PIVOTADAPTER_PROJECT_TYPE.equals(projectType))
return generateModel(object, monitor);
throw new IllegalArgumentException("Invalid projectType: "
+ projectType.toString());
}
/**
* The following code has been adopted from
* org.eclipse.emf.codegen.ecore.Generator$EclipseHelper.createEMFProject
*/
protected void ensureProjectExists(String projectName) {
List<IClasspathEntry> classpathEntries = new UniqueEList<IClasspathEntry>();
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(
projectName);
try {
boolean isEmptyProject = true;
IProjectDescription projectDescription = null;
IJavaProject javaProject = JavaCore.create(project);
if (!project.exists()) {
projectDescription = ResourcesPlugin.getWorkspace()
.newProjectDescription(projectName);
project.create(new NullProgressMonitor());
} else {
isEmptyProject = false;
projectDescription = project.getDescription();
classpathEntries.addAll(Arrays.asList(javaProject.getRawClasspath()));
}
// set the nature (Java + PDE) of the project if not already done
String[] natureIds = projectDescription.getNatureIds();
if (natureIds == null) {
natureIds = new String[] { JavaCore.NATURE_ID };
} else {
boolean hasJavaNature = false;
boolean hasPDENature = false;
for (int i = 0; i < natureIds.length; ++i) {
if (JavaCore.NATURE_ID.equals(natureIds[i])) {
hasJavaNature = true;
}
if ("org.eclipse.pde.PluginNature".equals(natureIds[i])) {
hasPDENature = true;
}
}
if (!hasJavaNature) {
String[] oldNatureIds = natureIds;
natureIds = new String[oldNatureIds.length + 1];
System.arraycopy(oldNatureIds, 0, natureIds, 0, oldNatureIds.length);
natureIds[oldNatureIds.length] = JavaCore.NATURE_ID;
}
if (!hasPDENature) {
String[] oldNatureIds = natureIds;
natureIds = new String[oldNatureIds.length + 1];
System.arraycopy(oldNatureIds, 0, natureIds, 0, oldNatureIds.length);
natureIds[oldNatureIds.length] = "org.eclipse.pde.PluginNature";
}
}
projectDescription.setNatureIds(natureIds);
// set the builders (Manifest + Schema) of the project if not
// already done
ICommand[] builders = projectDescription.getBuildSpec();
if (builders == null) {
builders = new ICommand[0];
}
boolean hasManifestBuilder = false;
boolean hasSchemaBuilder = false;
for (int i = 0; i < builders.length; ++i) {
if ("org.eclipse.pde.ManifestBuilder".equals(builders[i]
.getBuilderName())) {
hasManifestBuilder = true;
}
if ("org.eclipse.pde.SchemaBuilder"
.equals(builders[i].getBuilderName())) {
hasSchemaBuilder = true;
}
}
if (!hasManifestBuilder) {
ICommand[] oldBuilders = builders;
builders = new ICommand[oldBuilders.length + 1];
System.arraycopy(oldBuilders, 0, builders, 0, oldBuilders.length);
builders[oldBuilders.length] = projectDescription.newCommand();
builders[oldBuilders.length]
.setBuilderName("org.eclipse.pde.ManifestBuilder");
}
if (!hasSchemaBuilder) {
ICommand[] oldBuilders = builders;
builders = new ICommand[oldBuilders.length + 1];
System.arraycopy(oldBuilders, 0, builders, 0, oldBuilders.length);
builders[oldBuilders.length] = projectDescription.newCommand();
builders[oldBuilders.length]
.setBuilderName("org.eclipse.pde.SchemaBuilder");
}
projectDescription.setBuildSpec(builders);
project.open(new NullProgressMonitor());
project.setDescription(projectDescription, new NullProgressMonitor());
// if the project has just been created, generate...
if (isEmptyProject) {
// ... the source folder
IFolder sourceContainer = project.getFolder("src");
sourceContainer.create(false, true, new NullProgressMonitor());
IClasspathEntry sourceClasspathEntry = JavaCore
.newSourceEntry(new Path("/" + projectName + "/src"));
classpathEntries.add(0, sourceClasspathEntry);
// ... the jre
String jreContainer = JavaRuntime.JRE_CONTAINER;
String complianceLevel = CodeGenUtil.EclipseUtil
.getJavaComplianceLevel(project);
if ("1.5".equals(complianceLevel)) {
jreContainer += "/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5";
} else if ("1.6".equals(complianceLevel)) {
jreContainer += "/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6";
}
classpathEntries
.add(JavaCore.newContainerEntry(new Path(jreContainer)));
classpathEntries.add(JavaCore.newContainerEntry(new Path(
"org.eclipse.pde.core.requiredPlugins")));
// ...the output folder
javaProject.setOutputLocation(new Path("/" + projectName + "/bin"),
new NullProgressMonitor());
}
javaProject.setRawClasspath(classpathEntries
.toArray(new IClasspathEntry[classpathEntries.size()]),
new NullProgressMonitor());
} catch (CoreException e) {
e.printStackTrace();
CodeGenEcorePlugin.INSTANCE.log(e);
}
}
protected void generateManifestMF(String projectName, Monitor monitor) {
monitor.beginTask("", 2);
message = PivotAdapterGeneratorPlugin.INSTANCE
.getString("GeneratingManifest.message");
monitor.subTask(message);
String targetFile = projectName + "/META-INF/MANIFEST.MF";
generateText(targetFile, getJETEmitter(getJETEmitterDescriptors(),
MANIFEST_MF_ID), null, true, getEncoding(URI.createURI(targetFile)),
createMonitor(monitor, 1));
}
protected void generatePluginXML(String projectName, Monitor monitor) {
monitor.beginTask("", 2);
message = PivotAdapterGeneratorPlugin.INSTANCE
.getString("GeneratingPluginXML.message");
monitor.subTask(message);
String targetFile = projectName + "/plugin.xml";
generateText(targetFile, getJETEmitter(getJETEmitterDescriptors(),
PLUGIN_XML_ID), null, true, getEncoding(URI.createURI(targetFile)),
createMonitor(monitor, 1));
}
protected void generatePluginJava(String projectName, GenModel genModel,
Monitor monitor) {
String className = PivotAdapterGeneratorUtil
.startWithCapitalLetter(genModel.getModelName())
+ "MetamodelPlugin";
monitor.beginTask("", 2);
message = PivotAdapterGeneratorPlugin.INSTANCE.getString(
"GeneratingPluginJava.message", new Object[] { className });
monitor.subTask(message);
String targetPath = projectName + "/src";
// projectName == packageName
generateJava(targetPath, projectName, className, getJETEmitter(
getJETEmitterDescriptors(), PLUGIN_JAVA_ID), null, createMonitor(
monitor, 1));
}
protected void generateAdapterFactory(String projectName, GenModel genModel,
Monitor monitor) {
String className = PivotAdapterGeneratorUtil
.startWithCapitalLetter(genModel.getModelName())
+ "AdapterFactory";
monitor.beginTask("", 2);
message = PivotAdapterGeneratorPlugin.INSTANCE.getString(
"GeneratingAdapterFactory.message", new Object[] { className });
monitor.subTask(message);
String targetPath = projectName + "/src";
generateJava(targetPath, PivotAdapterGeneratorUtil
.getAdapterPackage(genModel), className, getJETEmitter(
getJETEmitterDescriptors(), ADAPTER_FACTORY_ID), null, createMonitor(
monitor, 1));
}
protected void generatePivotModel(String projectName, GenModel genModel,
Monitor monitor) {
String className = PivotAdapterGeneratorUtil
.startWithCapitalLetter(genModel.getModelName())
+ "Model";
monitor.beginTask("", 2);
message = PivotAdapterGeneratorPlugin.INSTANCE.getString(
"GeneratingModel.message", new Object[] { className });
monitor.subTask(message);
String targetPath = projectName + "/src";
generateJava(targetPath, PivotAdapterGeneratorUtil
.getAdapterPackage(genModel), className, getJETEmitter(
getJETEmitterDescriptors(), MODEL_ID), null, createMonitor(monitor, 1));
}
protected void generateModelMessages(String projectName, GenModel genModel,
Monitor monitor) {
String className = PivotAdapterGeneratorUtil
.startWithCapitalLetter(genModel.getModelName())
+ "ModelMessages";
monitor.beginTask("", 2);
message = PivotAdapterGeneratorPlugin.INSTANCE.getString(
"GeneratingModelMessages.message", new Object[] { className });
monitor.subTask(message);
String targetPath = projectName + "/src";
generateJava(targetPath, PivotAdapterGeneratorUtil
.getAdapterPackage(genModel), className, getJETEmitter(
getJETEmitterDescriptors(), MODEL_MESSAGES_ID), null, createMonitor(
monitor, 1));
}
protected void generateMessages(String projectName, GenModel genModel,
Monitor monitor) {
monitor.beginTask("", 2);
message = PivotAdapterGeneratorPlugin.INSTANCE
.getString("GeneratingMessages.message");
monitor.subTask(message);
String targetFile = projectName
+ "/src/"
+ PivotAdapterGeneratorUtil.getAdapterPackage(genModel).replace('.',
'/') + "/messages.properties";
generateText(targetFile, getJETEmitter(getJETEmitterDescriptors(),
MESSAGES_ID), null, true, getEncoding(URI.createURI(targetFile)),
createMonitor(monitor, 1));
}
protected void generateModelProvider(String projectName, GenModel genModel,
Monitor monitor) {
String className = PivotAdapterGeneratorUtil
.startWithCapitalLetter(genModel.getModelName())
+ "ModelProvider";
monitor.beginTask("", 2);
message = PivotAdapterGeneratorPlugin.INSTANCE.getString(
"GeneratingModelProvider.message", new Object[] { className });
monitor.subTask(message);
String targetPath = projectName + "/src";
generateJava(targetPath, PivotAdapterGeneratorUtil
.getProviderPackage(genModel), className, getJETEmitter(
getJETEmitterDescriptors(), PROVIDER_ID), null, createMonitor(monitor,
1));
}
protected void generateLog4jProperties(String projectName, GenModel genModel,
Monitor monitor) {
monitor.beginTask("", 2);
message = PivotAdapterGeneratorPlugin.INSTANCE
.getString("GeneratingLog4jProperties.message");
monitor.subTask(message);
String targetFile = projectName + "/log4j.properties";
generateText(targetFile, getJETEmitter(getJETEmitterDescriptors(),
LOG4JPROPERTIES_ID), null, true,
getEncoding(URI.createURI(targetFile)), createMonitor(monitor, 1));
}
@Override
protected Diagnostic generateModel(Object object, Monitor monitor) {
GenModel genModel = (GenModel) object;
String projectName = PivotAdapterGeneratorUtil.getProjectName(genModel);
ensureProjectExists(projectName);
generateManifestMF(projectName, monitor);
generatePluginXML(projectName, monitor);
generatePluginJava(projectName, genModel, monitor);
generateAdapterFactory(projectName, genModel, monitor);
generatePivotModel(projectName, genModel, monitor);
generateModelMessages(projectName, genModel, monitor);
generateMessages(projectName, genModel, monitor);
generateModelProvider(projectName, genModel, monitor);
generateLog4jProperties(projectName, genModel, monitor);
return Diagnostic.OK_INSTANCE;
}
@Override
protected void addBaseTemplatePathEntries(List<String> templatePath) {
templatePath.add(PivotAdapterGeneratorUtil.TEMPLATE_LOCATION);
super.addBaseTemplatePathEntries(templatePath);
}
@Override
protected void addClasspathEntries(JETEmitter jetEmitter) throws JETException {
super.addClasspathEntries(jetEmitter);
jetEmitter.addVariable(PivotAdapterGeneratorUtil.CLASSPATH_VARIABLE_NAME,
PivotAdapterGeneratorPlugin.ID);
}
}