blob: b55a76f377afcb2cce69cc902fe3b0305a5da21f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2019 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
*******************************************************************************/
package org.eclipse.ocl.examples.build.utilities;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import org.eclipse.emf.codegen.ecore.generator.Generator;
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.codegen.ecore.genmodel.generator.GenBaseGeneratorAdapter;
import org.eclipse.emf.codegen.ecore.genmodel.util.GenModelUtil;
import org.eclipse.emf.common.util.BasicMonitor;
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.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.mwe.core.ConfigurationException;
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.codegen.genmodel.OCLGenModelUtil;
import org.eclipse.ocl.pivot.util.DerivedConstants;
import org.eclipse.ocl.pivot.utilities.OCL;
import org.eclipse.ocl.pivot.utilities.XMIUtil;
/**
* Performs a Generate Model on the designated <tt>genmodel</tt> genModel.
*/
public class GenerateModel extends AbstractWorkflowComponent {
private Logger log = Logger.getLogger(getClass());
private ResourceSet resourceSet = null; // Optional ResourceSet to re-use
protected String genModel; // URI of the genmodel
protected boolean showProgress = false; // Set true to show genmodel new tasks
private boolean clearResourceSet = true;// Set to false to preserve the resource set.
public GenerateModel() {
super();
// BaseLinkingService.DEBUG_RETRY.setState(true);
}
@Override
public void checkConfiguration(Issues issues) {
if (genModel == null) {
issues.addError(this, "uri not specified.");
}
}
private void gatherUsedGenPackages(@NonNull Set<GenPackage> allUsedGenPackages, GenPackage anotherUsedGenPackage) {
if (allUsedGenPackages.add(anotherUsedGenPackage)) {
for (GenPackage usedGenPackage : anotherUsedGenPackage.getGenModel().getUsedGenPackages()) {
gatherUsedGenPackages(allUsedGenPackages, usedGenPackage);
}
}
}
public String getGenModel() {
return genModel;
}
public ResourceSet getResourceSet() {
if (resourceSet == null) {
resourceSet = new ResourceSetImpl();
}
return resourceSet;
}
@Override
public void invokeInternal(WorkflowContext ctx, ProgressMonitor arg1, Issues issues) {
OCLGenModelUtil.initializeGeneratorAdapterFactoryRegistry();
URI fileURI = URI.createPlatformResourceURI(genModel, true);
log.info("Generating Ecore Model using '" + fileURI + "'");
ResourceSet resourceSet = getResourceSet();
if (resourceSet instanceof ResourceSetImpl) {
ResourceSetImpl resourceSetImpl = (ResourceSetImpl) resourceSet;
Map<URI, Resource> uriResourceMap = resourceSetImpl.getURIResourceMap();
if (uriResourceMap != null) {
uriResourceMap.clear();
}
}
if (isClearResourceSet() && !resourceSet.getResources().isEmpty()) {
throw new IllegalStateException("clearResourceSet is not supported see Bug 529484");
// resourceSet.getResources().clear();
}
Resource resource = resourceSet.getResource(fileURI, true);
// EcoreUtil.resolveAll(resourceSet); -- genModel can fail if
// proxies resolved here
// problem arises if genmodel has an obsolete feature for a feature
// moved up the inheritance hierarchy
// since the proxy seems to be successfully resolved giving a double
// feature
ResourceUtils.checkResourceSet(resourceSet);
// MetamodelManager metamodelManager = ElementUtil.findMetamodelManager(resourceSet);
// metamodelManager.setAutoLoadPivotMetamodel(false);
EObject eObject = resource.getContents().get(0);
if (!(eObject instanceof GenModel)) {
throw new ConfigurationException("No GenModel found in '" + resource.getURI() + "'");
}
GenModel genModel = (GenModel) eObject;
List<GenPackage> usedGenPackages = genModel.getUsedGenPackages();
Set<GenPackage> allOldUsedGenPackages = new HashSet<>();
for (GenPackage usedGenPackage : usedGenPackages) {
gatherUsedGenPackages(allOldUsedGenPackages, usedGenPackage);
}
allOldUsedGenPackages.removeAll(usedGenPackages); // Indirectly usedGenPackages
genModel.reconcile();
allOldUsedGenPackages.retainAll(usedGenPackages); // Promoted indirect to direct usedGenPackages
try {
Map<Object, Object> saveOptions = new HashMap<Object, Object>();
saveOptions.put(XMLResource.OPTION_ENCODING, "UTF-8");
saveOptions.put(DerivedConstants.RESOURCE_OPTION_LINE_DELIMITER, "\n");
saveOptions.put(Resource.OPTION_SAVE_ONLY_IF_CHANGED, Resource.OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER);
saveOptions.put(Resource.OPTION_LINE_DELIMITER, Resource.OPTION_LINE_DELIMITER_UNSPECIFIED);
log.info("Saving reconciled '" + fileURI + "'");
usedGenPackages.removeAll(allOldUsedGenPackages);
XMIUtil.retainLineWidth(saveOptions, resource);
resource.save(saveOptions);
usedGenPackages.addAll(allOldUsedGenPackages);
} catch (IOException e) {
throw new ConfigurationException("Failed to save '" + fileURI + "'", e);
}
ResourceUtils.checkResourceSet(resourceSet);
// genModel.setCanGenerate(true);
// validate();
genModel.setValidateModel(true); // The more checks the better
// genModel.setCodeFormatting(true); // Normalize layout
genModel.setForceOverwrite(false); // Don't overwrite read-only
// files
genModel.setCanGenerate(true);
// genModel.setFacadeHelperClass(null); // Non-null gives JDT
// default NPEs
// genModel.setFacadeHelperClass(ASTFacadeHelper.class.getName()); // Bug 308069
// genModel.setValidateModel(true);
genModel.setBundleManifest(false); // New manifests should be
// generated manually
genModel.setUpdateClasspath(false); // New class-paths should be
// generated manually
if (genModel.getComplianceLevel().compareTo(GenJDKLevel.JDK50_LITERAL) < 0) {
genModel.setComplianceLevel(GenJDKLevel.JDK50_LITERAL);
}
// genModel.setRootExtendsClass("org.eclipse.emf.ecore.impl.MinimalEObjectImpl$Container");
OCL ocl = OCL.newInstance(resourceSet);
Diagnostic diagnostic = genModel.diagnose();
reportDiagnostics(issues, diagnostic);
ocl.dispose();
/*
* JavaModelManager.getJavaModelManager().initializePreferences();
* new
* JavaCorePreferenceInitializer().initializeDefaultPreferences();
*
* GenJDKLevel genSDKcomplianceLevel =
* genModel.getComplianceLevel(); String complianceLevel =
* JavaCore.VERSION_1_5; switch (genSDKcomplianceLevel) { case
* JDK60_LITERAL: complianceLevel = JavaCore.VERSION_1_6; case
* JDK14_LITERAL: complianceLevel = JavaCore.VERSION_1_4; default:
* complianceLevel = JavaCore.VERSION_1_5; } // Hashtable<?,?>
* defaultOptions = JavaCore.getDefaultOptions(); //
* JavaCore.setComplianceOptions(complianceLevel, defaultOptions);
* // JavaCore.setOptions(defaultOptions);
*/
// Generator generator = new Generator();
// generator.setInput(genModel);
Generator generator = GenModelUtil.createGenerator(genModel);
Monitor monitor = showProgress ? new LoggerMonitor(log)
: new BasicMonitor();
diagnostic = generator.generate(genModel,
GenBaseGeneratorAdapter.MODEL_PROJECT_TYPE, monitor);
reportDiagnostics(issues, diagnostic);
}
protected void reportDiagnostics(Issues issues, Diagnostic diagnostic) {
int severity = diagnostic.getSeverity();
if (severity != Diagnostic.OK) {
List<Diagnostic> children = diagnostic.getChildren();
if (children.size() > 0) {
for (Diagnostic child : children) {
severity = child.getSeverity();
@SuppressWarnings("unchecked") List<Object> data = (List<Object>) child.getData();
Throwable throwable = null;
String message;
if ((data.size() == 1) && (data.get(0) instanceof Throwable)) {
throwable = (Throwable) data.get(0);
data = null;
message = child.getMessage();
}
else {
message = child.toString();
}
if (severity == Diagnostic.ERROR) {
issues.addError(this, message, null, null, throwable, data);
}
else if (severity == Diagnostic.WARNING) {
issues.addWarning(this, message, null, null, throwable, data);
}
}
}
else {
if (severity == Diagnostic.ERROR) {
issues.addError(this, diagnostic.toString());
}
else if (severity == Diagnostic.WARNING) {
issues.addWarning(this, diagnostic.toString());
}
}
}
}
public boolean isShowProgress() {
return showProgress;
}
/**
* Define the genModel from which to generate a Java model.
*
* @param genModel URI of the genmodel
*/
public void setGenModel(String genModel) {
this.genModel = genModel;
}
/**
* Define a ReseourceSet to be used for for required resources. This allows the same ResourceSet to
* be shared for multiple modeling purposes.
*
* @param resourceSet the ResourceSet
*/
public void setResourceSet(ResourceSet resourceSet) {
this.resourceSet = resourceSet;
}
/**
* Whether to display GenModel newTask activity.
*
* @param showProgress
*/
public void setShowProgress(boolean showProgress) {
this.showProgress = showProgress;
}
public boolean isClearResourceSet() {
return clearResourceSet;
}
/**
* Set to <code>false</code> to preserve the resource set. <code>true</code> by default
* @param clearResourceSet
*/
public void setClearResourceSet(boolean clearResourceSet) {
this.clearResourceSet = clearResourceSet;
}
}