blob: f4cacd3d76913501c04b6cd58ce8774edbd1bbe7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2016 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink - initial API and implementation
* Adolfo Sanchez-Barbudo Herrera (University of York) - bug397429
*******************************************************************************/
package org.eclipse.ocl.examples.build.xtend;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.emf.codegen.ecore.genmodel.GenJDKLevel;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.plugin.EcorePlugin;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.mwe.core.WorkflowContext;
import org.eclipse.emf.mwe.core.issues.Issues;
import org.eclipse.emf.mwe.core.lib.AbstractWorkflowComponent;
import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.ocl.examples.build.utilities.GenPackageHelper;
import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
import org.eclipse.ocl.pivot.internal.resource.EnvironmentFactoryAdapter;
import org.eclipse.ocl.pivot.internal.utilities.OCLInternal;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.OCL;
import com.google.common.base.Objects;
public abstract class GenerateVisitorsWorkflowComponent extends AbstractWorkflowComponent
{
private static Logger log = Logger.getLogger(GenerateVisitorsWorkflowComponent.class);
private final static @NonNull String EMPTY_STRING = "";
protected static boolean isDefined(final String string) {
return (!Objects.equal(string, null));
}
// Mandatory properties
protected ResourceSet resourceSet = null;
protected String projectName;
protected String genModelFile;
// Optional properties
protected String superProjectName;
protected String superGenModelFile;
protected String baseProjectName;
protected String baseGenModelFile;
// Derived properties
protected String projectPrefix;
protected String modelPackageName;
protected String visitorPackageName;
protected String visitorClassName;
protected String visitablePackageName;
protected String visitableClassName;
protected String javaFolder;
protected String superProjectPrefix;
protected String superVisitorClassName;
protected String superVisitorPackageName;
protected String sourceFile;
protected String copyright;
protected String modelFolder;
protected String outputFolder;
protected GenPackage genPackage = null;
protected GenPackage superGenPackage = null;
protected GenPackage baseGenPackage = null;
@Override
public void checkConfiguration(final Issues issues) {
if (!isDefined(projectName)) {
issues.addError(this, "projectName not specified.");
}
if (!isDefined(genModelFile)) {
issues.addError(this, "genModelFile not specified.");
}
if (isDerived()) {
if (!isDefined(superGenModelFile)) {
issues.addError(this, "superProjectPrefix not specified.");
}
if (!isDefined(baseProjectName)) {
issues.addError(this, "baseProjectName must be specified for derived languages");
}
if (!isDefined(baseGenModelFile)) {
issues.addError(this, "baseGenModelFile must be specified for derived languages");
}
}
}
/**
* <p>Initializes some derived component properties.</p>
*
* <p>It also gives a chance to subclasses to do additional initialization</p>
*
* <p>Derived components may override, but they must call super.{@link #doPropertiesConfiguration(OCL)}
* so the properties of this base component are initialized</p>
*
* @param ocl the component {@link OCL} instance
*/
protected void doPropertiesConfiguration(OCL ocl) {
// load the genPackage
URI genModelURI = getGenModelURI(projectName, genModelFile);
Resource genModelResource = getGenModelResource(ocl, genModelURI);
GenModel genModel = getGenModel(genModelResource);
genModel.reconcile();
genPackage = getGenPackage(genModelResource);
// And configure missing information
GenPackageHelper helper = new GenPackageHelper(genPackage);
projectPrefix = helper.getProjectPrefix();
visitorPackageName = helper.getVisitorPackageName();
visitorClassName = helper.getVisitorClassName();
modelPackageName = helper.getModelPackageName();
javaFolder = helper.getSrcJavaFolder();
if (isDerived()) {
URI superGenModelURI = getGenModelURI(superProjectName, superGenModelFile);
Resource superGenModelResource = getGenModelResource(ocl, superGenModelURI);
superGenPackage = getGenPackage(superGenModelResource);
helper = new GenPackageHelper(superGenPackage);
superProjectPrefix = helper.getProjectPrefix();
superVisitorPackageName = helper.getVisitorPackageName();
superVisitorClassName = helper.getVisitorClassName();
} else { // if not derived, the info related to the base project will be the own project
baseProjectName = projectName;
baseGenModelFile = genModelFile;
}
// Visitable info will be get from base package
URI baseGenModelURI = getGenModelURI(baseProjectName, baseGenModelFile);
Resource baseGenModelResource = getGenModelResource(ocl, baseGenModelURI);
baseGenPackage = getGenPackage(baseGenModelResource);
helper = new GenPackageHelper(baseGenPackage);
visitablePackageName = helper.getVisitablePackageName();
visitableClassName = helper.getVisitableClassName();
}
/**
* It gives a chance to derived components to do some setup subprocess,
* prior to start with the component generation process
*
* derived components may override
*/
protected void doSetup() {
}
public abstract void generateVisitors(/*@NonNull*/ final GenPackage genPackage);
private String getCopyright(GenModel genModel) {
String copyright = genModel.getCopyright("");
return copyright != null ? copyright : EMPTY_STRING;
}
protected @NonNull URI getGenModelURI(String projectName, String genModelFile) {
URI projectResourceURI = URI.createPlatformResourceURI("/" + projectName + "/", true);
return ClassUtil.nonNullState(URI.createURI(genModelFile).resolve(projectResourceURI));
}
protected @NonNull Resource getGenModelResource(OCL ocl, URI genModelURI) {
Resource genModelResource = ocl.getResourceSet().getResource(genModelURI, true);
if (genModelResource == null) {
throw new IllegalStateException("No '" + genModelURI + "' Resource");
}
return genModelResource;
}
private @NonNull GenModel getGenModel(@NonNull Resource genModelResource) {
EList<EObject> contents = genModelResource.getContents();
if (contents.isEmpty()) {
throw new IllegalArgumentException("Illegal empty genModelResource: " + genModelResource.getURI());
}
EObject rootElement = contents.get(0);
if (!(rootElement instanceof GenModel)) {
throw new IllegalArgumentException("Illegal non GenModel root element: " + genModelResource.getURI());
}
return (GenModel) rootElement;
}
protected @NonNull GenPackage getGenPackage(@NonNull Resource genModelResource) {
GenModel genModel = getGenModel(genModelResource);
List<GenPackage> genPackages = genModel.getAllGenPackagesWithClassifiers();
GenPackage genPackage = genPackages.isEmpty() ? null : genPackages.get(0); // We assume we want the first one;
if (genPackage == null) {
throw new IllegalStateException("No '" + genModelResource.getURI() + "' GenPackage");
}
return genPackage;
}
@Override
protected void invokeInternal(WorkflowContext ctx, ProgressMonitor monitor, Issues issues) {
ResourceSet resourceSet2 = resourceSet;
assert resourceSet2 != null;
OCL ocl = OCL.newInstance(resourceSet2);
doPropertiesConfiguration(ocl);
if (!isDefined(visitablePackageName)) {
visitablePackageName = visitorPackageName;
}
if (!isDefined(superVisitorPackageName)) {
superVisitorPackageName = visitorPackageName;
}
if (!isDerived()) {
superProjectPrefix = "";
superVisitorPackageName = "";
superVisitorClassName = "";
}
doSetup();
URI projectFileURI = EcorePlugin.getPlatformResourceMap().get(projectName);
URI genModelURI = getGenModelURI(projectName, genModelFile);
URI modelURI = URI.createURI(javaFolder);
URI resolvedModelURI = modelURI.resolve(projectFileURI);
modelFolder = (resolvedModelURI.isFile() ? resolvedModelURI.toFileString() : resolvedModelURI.toString()) + "/";
// URI outputURI = URI.createURI(javaFolder + '/' + visitorPackageName.replace('.', '/'));
// URI resolvedOutputURI = outputURI.resolve(projectFileURI);
outputFolder = modelFolder + visitorPackageName.replace('.', '/') + "/";
log.info("Loading GenModel '" + genModelURI);
// try {
registerGenModel(ocl, ClassUtil.nonNullState(genPackage.getGenModel()));
copyright = getCopyright(genPackage.getGenModel());
sourceFile = genModelFile;
generateVisitors(genPackage);
// } catch (IOException e) {
// throw new RuntimeException("Problems running " + getClass().getSimpleName(), e);
// }
ocl.dispose();
}
protected boolean isDerived() {
return (isDefined(superProjectName) && superProjectName.length() > 0);
}
protected boolean needsOverride() {
if (genPackage != null) {
GenModel genModel = genPackage.getGenModel();
GenJDKLevel complianceLevel = genModel.getComplianceLevel();
return complianceLevel.compareTo(GenJDKLevel.JDK60_LITERAL) >= 0;
}
return false;
}
private void registerGenModel(@NonNull OCL ocl, @NonNull GenModel genModel) {
@SuppressWarnings("null")@NonNull ResourceSet resourceSet2 = resourceSet;
EnvironmentFactoryAdapter adapter = OCLInternal.adapt(resourceSet2); // We prepare the mManager for the whole resourceSet
PivotMetamodelManager metamodelManager = adapter.getMetamodelManager();
metamodelManager.addGenModel(genModel);
for (@SuppressWarnings("null")@NonNull GenPackage usedGenPackage : genModel.getUsedGenPackages()) {
metamodelManager.addGenPackage(usedGenPackage);
}
}
/**
* The path within the project to the genmodel file that identifies the
* Ecore file from which the EMF generated interfaces derive. Also provides
* the copyright for generated Visitor interfaces. (e.g.
* "model/my.genmodel")
*/
public void setGenModelFile(final String genModelFile) {
this.genModelFile = genModelFile;
}
/**
* The project name containing the genmodel and generated EMF sources. (e.g.
* "org.my.project")
*/
public void setProjectName(final String projectName) {
this.projectName = projectName;
}
/**
* An optional ResourceSet that MWE components may share to reduce model
* loading.
*/
public void setResourceSet(final ResourceSet resourceSet) {
this.resourceSet = resourceSet;
}
/**
* The project name that is extended by the project containing the genmodel
* and generated EMF sources. (e.g. "org.my.superproject").
* It may be null for base languages
*/
public void setSuperProjectName(final String superProjectName) {
this.superProjectName = superProjectName;
}
/**
* The gen model file path of the super project(e.g. "model/superModel.genmodel").
* It may be null for base languages
*/
public void setSuperGenModelFile(final String superGenModelFile) {
this.superGenModelFile = superGenModelFile;
}
/**
* The gen model file path of the base project(e.g. "model/baseModel.genmodel").
* It may be null for base languages
*/
public void setBaseGenModelFile(final String baseGenModelFile) {
this.baseGenModelFile = baseGenModelFile;
}
/**
* The name of the base project (e.g. "org.my.baseproject"). It may be null for base
* languages
*/
public void setBaseProjectName(final String baseProjectName) {
this.baseProjectName = baseProjectName;
}
}