| /******************************************************************************* |
| * Copyright (c) 2012, 2017 CEA LIST 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: |
| * E.D.Willink(CEA LIST) - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ocl.examples.codegen.oclinecore; |
| |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.URIUtil; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenAnnotation; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenClass; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenModel; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenPackage; |
| import org.eclipse.emf.codegen.ecore.genmodel.generator.GenBaseGeneratorAdapter; |
| import org.eclipse.emf.common.EMFPlugin; |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.Notifier; |
| import org.eclipse.emf.common.util.BasicDiagnostic; |
| import org.eclipse.emf.common.util.BasicMonitor; |
| import org.eclipse.emf.common.util.Diagnostic; |
| import org.eclipse.emf.common.util.EMap; |
| import org.eclipse.emf.common.util.Monitor; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.common.util.WrappedException; |
| import org.eclipse.emf.ecore.EAnnotation; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EModelElement; |
| import org.eclipse.emf.ecore.EOperation; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.EcoreFactory; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.resource.URIConverter; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.ocl.common.OCLCommon; |
| import org.eclipse.ocl.common.OCLConstants; |
| import org.eclipse.ocl.common.internal.options.CodeGenerationMode; |
| import org.eclipse.ocl.common.internal.options.CommonOptions; |
| import org.eclipse.ocl.examples.codegen.common.PivotQueries; |
| import org.eclipse.ocl.examples.codegen.generator.AbstractGenModelHelper; |
| import org.eclipse.ocl.examples.codegen.java.ImportUtils; |
| import org.eclipse.ocl.examples.codegen.model.CGLibrary; |
| import org.eclipse.ocl.pivot.Constraint; |
| import org.eclipse.ocl.pivot.Element; |
| import org.eclipse.ocl.pivot.Operation; |
| import org.eclipse.ocl.pivot.Property; |
| import org.eclipse.ocl.pivot.internal.ecore.as2es.AS2Ecore; |
| import org.eclipse.ocl.pivot.internal.ecore.es2as.Ecore2AS; |
| import org.eclipse.ocl.pivot.internal.manager.MetamodelManagerInternal; |
| import org.eclipse.ocl.pivot.internal.utilities.AS2Moniker; |
| import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal; |
| import org.eclipse.ocl.pivot.internal.utilities.OCLInternal; |
| import org.eclipse.ocl.pivot.internal.utilities.PivotConstantsInternal; |
| import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal; |
| import org.eclipse.ocl.pivot.resource.BasicProjectManager; |
| import org.eclipse.ocl.pivot.resource.ProjectManager; |
| import org.eclipse.ocl.pivot.util.PivotPlugin; |
| import org.eclipse.ocl.pivot.utilities.ClassUtil; |
| import org.eclipse.ocl.pivot.utilities.PivotConstants; |
| import org.eclipse.ocl.pivot.utilities.PivotUtil; |
| import org.eclipse.uml2.codegen.ecore.genmodel.util.UML2GenModelUtil; |
| |
| public class OCLinEcoreGenModelGeneratorAdapter extends GenBaseGeneratorAdapter |
| { |
| public static final @NonNull String OCL_GENMODEL_URI = "http://www.eclipse.org/OCL/GenModel"; |
| public static final @NonNull String TABLES_POSTAMBLE_KEY = "Tables Postamble"; |
| public static final @NonNull String USE_DELEGATES_KEY = "Use Delegates"; |
| public static final @NonNull String USE_NULL_ANNOTATIONS_KEY = "Use Null Annotations"; |
| public static final @NonNull String INVARIANT_PREFIX_KEY = "Invariant Prefix"; |
| |
| /** |
| * If the genModel has a {@link #OCL_GENMODEL_URI} GenAnnotation with a |
| * {@link #INVARIANT_PREFIX_KEY} detail returns its value otherwise return null. |
| */ |
| public static @Nullable String getInvariantPrefix(@NonNull GenModel genModel) { |
| GenAnnotation genAnnotation = genModel.getGenAnnotation(OCL_GENMODEL_URI); |
| if (genAnnotation != null) { |
| EMap<String, String> details = genAnnotation.getDetails(); |
| if (details.containsKey(INVARIANT_PREFIX_KEY)) { |
| return String.valueOf(details.get(INVARIANT_PREFIX_KEY)); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Return some non-null text to append before the final brace of the generated Tables file. |
| * This may be used to insert manual text that remedies reported API changes. |
| */ |
| public static @Nullable String tablesPostamble(@NonNull GenModel genModel) { |
| GenAnnotation genAnnotation = genModel.getGenAnnotation(OCL_GENMODEL_URI); |
| if (genAnnotation != null) { |
| EMap<String, String> details = genAnnotation.getDetails(); |
| if (details.containsKey(TABLES_POSTAMBLE_KEY)) { |
| return String.valueOf(details.get(TABLES_POSTAMBLE_KEY)); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Return true if the genModel has a {@link #OCL_GENMODEL_URI} GenAnnotation with a |
| * {@link #USE_DELEGATES_KEY} detail set to true, or if there is no such GenAnnotation and the |
| * global preference {@link CommonOptions#CODE_GENERATION_MODE} |
| * has been set to {@link CodeGenerationMode#DELEGATED} |
| */ |
| public static boolean useDelegates(@NonNull GenModel genModel) { |
| GenAnnotation genAnnotation = genModel.getGenAnnotation(OCL_GENMODEL_URI); |
| if (genAnnotation != null) { |
| EMap<String, String> details = genAnnotation.getDetails(); |
| if (details.containsKey(USE_DELEGATES_KEY)) { |
| return Boolean.valueOf(details.get(USE_DELEGATES_KEY)); |
| } |
| } |
| CodeGenerationMode preference = CommonOptions.CODE_GENERATION_MODE.getPreferredValue(); |
| if (preference == CodeGenerationMode.DELEGATED) { |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Return true if the genModel has a {@link #OCL_GENMODEL_URI} GenAnnotation with a |
| * {@link #USE_NULL_ANNOTATIONS_KEY} detail set to true. |
| */ |
| public static boolean useNullAnnotations(@NonNull GenModel genModel) { |
| GenAnnotation genAnnotation = genModel.getGenAnnotation(OCL_GENMODEL_URI); |
| if (genAnnotation != null) { |
| EMap<String, String> details = genAnnotation.getDetails(); |
| if (details.containsKey(USE_NULL_ANNOTATIONS_KEY)) { |
| return Boolean.valueOf(details.get(USE_NULL_ANNOTATIONS_KEY)); |
| } |
| } |
| // CodeGenerationMode preference = OCLCommon.getPreference(CommonOptions.CODE_GENERATION_MODE, null); |
| // if (preference == CodeGenerationMode.DELEGATED) { |
| // return true; |
| // } |
| return false; |
| } |
| |
| protected static interface Edit |
| { |
| void undo(); |
| } |
| |
| /** |
| * OCLinEcoreStateAdapter caches properties of the input model during doPreGenerate and accumulates all |
| * in-memory modifications so that they are reverted during doPostGenerate. |
| */ |
| protected class OCLinEcoreStateAdapter implements Adapter |
| { |
| protected class AddEAnnotation implements Edit |
| { |
| private final @NonNull List<EAnnotation> eAnnotations; |
| private final @NonNull EAnnotation eAnnotation; |
| |
| @SuppressWarnings("null") |
| public AddEAnnotation(/*@NonNull*/ List<EAnnotation> eAnnotations, @NonNull EAnnotation eAnnotation) { |
| this.eAnnotations = eAnnotations; |
| this.eAnnotation = eAnnotation; |
| eAnnotations.add(eAnnotation); |
| } |
| |
| @Override |
| public void undo() { |
| eAnnotations.remove(eAnnotation); |
| } |
| } |
| |
| protected class AddEOperation implements Edit |
| { |
| private final @NonNull List<EOperation> eOperations; |
| private final @NonNull EOperation eOperation; |
| |
| @SuppressWarnings("null") |
| public AddEOperation(/*@NonNull*/ List<EOperation> eOperations, @NonNull EOperation eOperation) { |
| this.eOperations = eOperations; |
| this.eOperation = eOperation; |
| eOperations.add(eOperation); |
| } |
| |
| @Override |
| public void undo() { |
| eOperations.remove(eOperation); |
| } |
| } |
| |
| protected class AddModelPluginVariable implements Edit |
| { |
| private final @NonNull String modelPluginVariable; |
| |
| public AddModelPluginVariable(@NonNull String modelPluginVariable) { |
| this.modelPluginVariable = modelPluginVariable; |
| genModel.getModelPluginVariables().add(modelPluginVariable); |
| } |
| |
| @Override |
| public void undo() { |
| genModel.getModelPluginVariables().remove(modelPluginVariable); |
| } |
| } |
| |
| protected class RemoveEAnnotation implements Edit |
| { |
| private final @NonNull EAnnotation eAnnotation; |
| private final @NonNull List<EAnnotation> eAnnotations; |
| private final int index; |
| |
| @SuppressWarnings("null") |
| public RemoveEAnnotation(@NonNull EAnnotation eAnnotation) { |
| this.eAnnotation = eAnnotation; |
| this.eAnnotations = ((EModelElement)eAnnotation.eContainer()).getEAnnotations(); |
| this.index = eAnnotations.indexOf(eAnnotation); |
| eAnnotations.remove(eAnnotation); |
| } |
| |
| @Override |
| public void undo() { |
| eAnnotations.add(index, eAnnotation); |
| } |
| } |
| |
| protected class SetEAnnotationDetail implements Edit |
| { |
| private final @NonNull EAnnotation eAnnotation; |
| private final @NonNull String detailName; |
| private final int index; |
| private final @Nullable String value; |
| |
| public SetEAnnotationDetail(@NonNull EAnnotation eAnnotation, @NonNull String detailName) { // RemoveEAnnotationDetail |
| this.eAnnotation = eAnnotation; |
| this.detailName = detailName; |
| EMap<String, String> details = eAnnotation.getDetails(); |
| this.index = details.indexOf(detailName); |
| this.value = details.get(detailName); |
| if (index >= 0) { |
| details.remove(index); |
| } |
| } |
| |
| public SetEAnnotationDetail(@NonNull EAnnotation eAnnotation, @NonNull String detailName, @Nullable String value) { |
| this.eAnnotation = eAnnotation; |
| this.detailName = detailName; |
| EMap<String, String> details = eAnnotation.getDetails(); |
| this.index = details.indexOf(detailName); |
| this.value = details.put(detailName, value); |
| } |
| |
| @Override |
| public void undo() { |
| EMap<String, String> details = eAnnotation.getDetails(); |
| if (index < 0) { |
| details.remove(detailName); |
| } |
| else { |
| details.put(detailName, value); |
| int newIndex = details.indexOf(detailName); |
| if (newIndex != index) { |
| details.move(index, newIndex); |
| } |
| } |
| } |
| } |
| |
| protected class SetInvocationDelegates implements Edit |
| { |
| private final @NonNull EPackage ePackage; |
| private final @NonNull List<String> invocationDelegates; |
| |
| @SuppressWarnings("null") |
| public SetInvocationDelegates(@NonNull EPackage ePackage) { |
| this.ePackage = ePackage; |
| this.invocationDelegates = EcoreUtil.getInvocationDelegates(ePackage); |
| EcoreUtil.setInvocationDelegates(ePackage, pruneDelegates(invocationDelegates)); |
| } |
| |
| @Override |
| public void undo() { |
| EcoreUtil.setInvocationDelegates(ePackage, invocationDelegates); |
| } |
| } |
| |
| protected class SetSettingDelegates implements Edit |
| { |
| private final @NonNull EPackage ePackage; |
| private final @NonNull List<String> settingDelegates; |
| |
| @SuppressWarnings("null") |
| public SetSettingDelegates(@NonNull EPackage ePackage) { |
| this.ePackage = ePackage; |
| this.settingDelegates = EcoreUtil.getSettingDelegates(ePackage); |
| EcoreUtil.setSettingDelegates(ePackage, pruneDelegates(settingDelegates)); |
| } |
| |
| @Override |
| public void undo() { |
| EcoreUtil.setSettingDelegates(ePackage, settingDelegates); |
| } |
| } |
| |
| protected class SetValidationDelegates implements Edit |
| { |
| private final @NonNull EPackage ePackage; |
| private final @NonNull List<String> validationDelegates; |
| |
| @SuppressWarnings("null") |
| public SetValidationDelegates(@NonNull EPackage ePackage) { |
| this.ePackage = ePackage; |
| this.validationDelegates = EcoreUtil.getValidationDelegates(ePackage); |
| EcoreUtil.setValidationDelegates(ePackage, pruneDelegates(validationDelegates)); |
| } |
| |
| @Override |
| public void undo() { |
| EcoreUtil.setValidationDelegates(ePackage, validationDelegates); |
| } |
| } |
| |
| protected final @NonNull OCLInternal ocl; |
| protected final @NonNull GenModel genModel; |
| |
| /** |
| * The Java source text defining the constants used by operation and property bodies that must be emitted |
| * as part of the Tables class. |
| */ |
| private @NonNull Map<@NonNull GenPackage, @NonNull String> constantTexts = new HashMap<>(); |
| |
| /** |
| * The edits applied to the in-memory GenModel that must be undone during postGenerate. |
| */ |
| private @NonNull List<Edit> edits = new ArrayList<>(); |
| |
| private OCLinEcoreStateAdapter(@NonNull GenModel genModel) { |
| Resource eResource = genModel.eResource(); |
| ResourceSet resourceSet = eResource != null ? eResource.getResourceSet() : null; |
| EnvironmentFactoryInternal environmentFactory = resourceSet != null ? PivotUtilInternal.findEnvironmentFactory(resourceSet) : null; |
| if (environmentFactory == null) { |
| ProjectManager projectMap = BasicProjectManager.createDefaultProjectManager(); |
| projectMap.initializeResourceSet(resourceSet); |
| this.ocl = OCLInternal.newInstance(projectMap, resourceSet); |
| } |
| else { |
| this.ocl = OCLInternal.newInstance(environmentFactory); |
| } |
| this.genModel = genModel; |
| genModel.eAdapters().add(this); |
| } |
| |
| protected void addEAnnotationDetail(@NonNull EModelElement eModelElement, /*@NonNull*/ String sourceURI, @NonNull String detailName, @NonNull String value) { |
| EAnnotation eAnnotation = eModelElement.getEAnnotation(sourceURI); |
| if (eAnnotation == null) { |
| eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation(); |
| eAnnotation.setSource(sourceURI); |
| edits.add(new AddEAnnotation(eModelElement.getEAnnotations(), eAnnotation)); |
| } |
| edits.add(new SetEAnnotationDetail(eAnnotation, detailName, value)); |
| } |
| |
| protected void addEOperation(@NonNull EClass eClass, @NonNull EOperation eOperation) { |
| edits.add(new AddEOperation(eClass.getEOperations(), eOperation)); |
| } |
| |
| protected void addModelPluginVariable(@NonNull String modelPluginVariable) { |
| edits.add(new AddModelPluginVariable(modelPluginVariable)); |
| } |
| |
| protected void convertConstraintToOperation(@NonNull Ecore2AS ecore2as, @NonNull GenModel genModel, @NonNull EClass eClass, @NonNull String key, @NonNull String body, @Nullable String message) { |
| org.eclipse.ocl.pivot.Class pType = ecore2as.getCreated(org.eclipse.ocl.pivot.Class.class, eClass); |
| if (pType != null) { |
| List<Constraint> ownedInvariants = pType.getOwnedInvariants(); |
| if (ownedInvariants.size() > 0) { |
| String prefix = UML2GenModelUtil.getInvariantPrefix(genModel); |
| if (prefix == null) { |
| prefix = getInvariantPrefix(genModel); |
| if (prefix == null) { |
| prefix = ""; |
| } |
| } |
| String names = ""; |
| for (Constraint rule : ownedInvariants) { |
| String ruleName = rule.getName(); |
| if (ruleName == null) { |
| ruleName = ""; |
| } |
| if (ruleName.equals(key)) { |
| String prefixedName = prefix + ruleName; |
| names = names.length() == 0 ? prefixedName : names + " " + prefixedName; |
| EOperation eOperation = AS2Ecore.createConstraintEOperation(rule, prefixedName, null); |
| addEOperation(eClass, eOperation); |
| ecore2as.addMapping(eOperation, rule); |
| if (message != null) { |
| body = PivotUtil.createTupleValuedConstraint(body, null, message); |
| } |
| addEAnnotationDetail(eOperation, PivotConstants.OCL_DELEGATE_URI_PIVOT, "body", body); |
| } |
| } |
| addEAnnotationDetail(eClass, EcorePackage.eNS_URI, "constraints", names); |
| } |
| } |
| } |
| |
| protected void convertConstraintsToOperations(@NonNull MetamodelManagerInternal metamodelManager) { |
| List<GenPackage> genPackages = genModel.getAllGenPackagesWithClassifiers(); |
| for (GenPackage genPackage : genPackages) { |
| EPackage ecorePackage = genPackage.getEcorePackage(); |
| removeEAnnotation(ecorePackage.getEAnnotation(PivotConstants.IMPORT_ANNOTATION_SOURCE)); |
| Resource ecoreResource = ecorePackage.eResource(); |
| if (ecoreResource != null) { |
| Ecore2AS ecore2as = Ecore2AS.getAdapter(ecoreResource, metamodelManager.getEnvironmentFactory()); |
| for (GenClass genClass : genPackage.getGenClasses()) { |
| EClass eClass = genClass.getEcoreClass(); |
| if (eClass != null) { |
| List<EAnnotation> obsoleteAnnotations = null; |
| for (EAnnotation eAnnotation : new ArrayList<>(eClass.getEAnnotations())) { |
| String source = eAnnotation.getSource(); |
| if (OCLCommon.isDelegateURI(source)) { |
| @SuppressWarnings("deprecation") |
| String messageAnnotationDetailSuffix = PivotConstantsInternal.MESSAGE_ANNOTATION_DETAIL_SUFFIX; |
| EMap<String, String> details = eAnnotation.getDetails(); |
| for (String key : details.keySet()) { |
| if ((key != null) && !key.endsWith(messageAnnotationDetailSuffix)) { |
| String expression = details.get(key); |
| String messageExpression = details.get(key + messageAnnotationDetailSuffix); |
| if (expression != null) { |
| convertConstraintToOperation(ecore2as, genModel, eClass, key, expression, messageExpression); |
| } |
| } |
| } |
| if (obsoleteAnnotations == null) { |
| obsoleteAnnotations = new ArrayList<>(); |
| } |
| obsoleteAnnotations.add(eAnnotation); |
| } |
| if (EcorePackage.eNS_URI.equals(source)) { |
| removeEAnnotationDetail(eAnnotation, "constraints"); |
| } |
| } |
| if (obsoleteAnnotations != null) { |
| for (EAnnotation eAnnotation : obsoleteAnnotations) { |
| removeEAnnotation(eAnnotation); |
| } |
| } |
| genClass.initialize(eClass); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Create a Map of feature identification to body to be embedded in the EMF model. |
| * @throws IOException |
| */ |
| public @NonNull Map<@NonNull String, @NonNull String> createFeatureBodies(@NonNull GenModel genModel) throws IOException { |
| Map<@NonNull String, @NonNull String> allResults = new HashMap<>(); |
| @SuppressWarnings("null")@NonNull List<GenPackage> allGenPackagesWithClassifiers = genModel.getAllGenPackagesWithClassifiers(); |
| List<@NonNull GenPackage> genPackages = ClassUtil.nullFree(allGenPackagesWithClassifiers); |
| for (GenPackage genPackage : genPackages) { |
| OCLinEcoreCodeGenerator.generatePackage(genPackage, allResults, constantTexts); |
| } |
| List<@NonNull String> resultsKeys = new ArrayList<>(allResults.keySet()); |
| Collections.sort(resultsKeys); |
| return allResults; |
| } |
| |
| public void dispose() { |
| genModel.eAdapters().remove(this); |
| for (int i = edits.size(); --i >= 0; ) { |
| Edit edit = edits.get(i); |
| edit.undo(); |
| } |
| ocl.dispose(); |
| } |
| |
| public @NonNull Map<@NonNull GenPackage, @NonNull String> getConstantTexts() { |
| return constantTexts; |
| } |
| |
| protected @NonNull OCLinEcoreGenModelGeneratorAdapter getGenModelGeneratorAdapter() { |
| return OCLinEcoreGenModelGeneratorAdapter.this; |
| } |
| |
| public @NonNull MetamodelManagerInternal getMetamodelManager() { |
| return ocl.getMetamodelManager(); |
| } |
| |
| @Override |
| public @NonNull GenModel getTarget() { |
| return genModel; |
| } |
| |
| protected void installJavaBodies(@NonNull MetamodelManagerInternal metamodelManager, @NonNull GenModel genModel, @NonNull Map<String, String> results) { |
| List<GenPackage> genPackages = genModel.getAllGenPackagesWithClassifiers(); |
| for (GenPackage genPackage : genPackages) { |
| EPackage ecorePackage = genPackage.getEcorePackage(); |
| Resource ecoreResource = ecorePackage.eResource(); |
| if (ecoreResource != null) { |
| Ecore2AS ecore2as = Ecore2AS.getAdapter(ecoreResource, metamodelManager.getEnvironmentFactory()); |
| for (GenClass genClass : genPackage.getGenClasses()) { |
| EClass eClass = genClass.getEcoreClass(); |
| if (eClass != null) { |
| for (@SuppressWarnings("null")@NonNull EOperation eOperation : eClass.getEOperations()) { |
| installOperation(ecore2as, eOperation, results); |
| } |
| for (@SuppressWarnings("null")@NonNull EStructuralFeature eFeature : eClass.getEStructuralFeatures()) { |
| installProperty(ecore2as, eFeature, results); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| protected void installOperation(@NonNull Ecore2AS ecore2as, @NonNull EOperation eOperation, @NonNull Map<String, String> results) { |
| Element pOperation = ecore2as.getCreated(Element.class, eOperation); |
| String fragmentURI = null; |
| if (pOperation instanceof Operation) { |
| fragmentURI = String.valueOf(EcoreUtil.getURI(pOperation).fragment()); |
| } |
| else if (pOperation instanceof Constraint) { |
| Constraint constraint = (Constraint) pOperation; |
| fragmentURI = String.valueOf(EcoreUtil.getURI(constraint.eContainer()).fragment()) + "==" + constraint.getName(); |
| } |
| String body = fragmentURI != null ? results.get(fragmentURI) : null; |
| if ((body == null) || ((body = body.trim()).length() == 0)) { |
| String javaBody = EcoreUtil.getAnnotation(eOperation, GenModelPackage.eNS_URI, "body"); |
| if (javaBody != null) { |
| return; // Leave an existing Java body unaffected |
| } |
| body = "throw new UnsupportedOperationException(); // FIXME Unimplemented " + (pOperation != null ? AS2Moniker.toString(pOperation) : ""); |
| } |
| addEAnnotationDetail(eOperation, GenModelPackage.eNS_URI, "body", body); |
| removeEAnnotation(eOperation.getEAnnotation(OCLConstants.OCL_DELEGATE_URI)); |
| removeEAnnotation(eOperation.getEAnnotation(OCLConstants.OCL_DELEGATE_URI_LPG)); |
| removeEAnnotation(eOperation.getEAnnotation(PivotConstants.OCL_DELEGATE_URI_PIVOT)); |
| removeEAnnotation(eOperation.getEAnnotation(UML2GenModelUtil.UML2_GEN_MODEL_PACKAGE_1_1_NS_URI)); |
| } |
| |
| protected void installProperty(@NonNull Ecore2AS ecore2as, @NonNull EStructuralFeature eFeature, @NonNull Map<String, String> results) { |
| Property pProperty = ecore2as.getCreated(Property.class, eFeature); |
| String fragmentURI = String.valueOf(EcoreUtil.getURI(pProperty).fragment()); |
| String body = results.get(fragmentURI); |
| if (body == null) { |
| String javaBody = EcoreUtil.getAnnotation(eFeature, GenModelPackage.eNS_URI, "get"); |
| if (javaBody != null) { |
| return; // Leave an existing Java body unaffected |
| } |
| body = "throw new UnsupportedOperationException(); // FIXME Unimplemented " + (pProperty != null ? AS2Moniker.toString(pProperty) : ""); |
| } |
| addEAnnotationDetail(eFeature, GenModelPackage.eNS_URI, "get", body); |
| // addEAnnotationDetail(eFeature, GenModelPackage.eNS_URI, "body", body); |
| removeEAnnotation(eFeature.getEAnnotation(OCLConstants.OCL_DELEGATE_URI)); |
| removeEAnnotation(eFeature.getEAnnotation(OCLConstants.OCL_DELEGATE_URI_LPG)); |
| removeEAnnotation(eFeature.getEAnnotation(PivotConstants.OCL_DELEGATE_URI_PIVOT)); |
| removeEAnnotation(eFeature.getEAnnotation(UML2GenModelUtil.UML2_GEN_MODEL_PACKAGE_1_1_NS_URI)); |
| } |
| |
| |
| /** |
| * Eliminate all OCL validation/setting/invocation delegates. |
| */ |
| protected void pruneDelegates(@NonNull GenModel genModel) { |
| for (GenPackage genPackage : genModel.getAllGenPackagesWithClassifiers()) { |
| EPackage ePackage = genPackage.getEcorePackage(); |
| if ((ePackage != null) && hasDelegates(ePackage)) { |
| edits.add(new SetValidationDelegates(ePackage)); |
| edits.add(new SetSettingDelegates(ePackage)); |
| edits.add(new SetInvocationDelegates(ePackage)); |
| } |
| } |
| } |
| protected @NonNull List<String> pruneDelegates(@Nullable List<String> oldDelegates) { |
| List<String> newDelegates = new ArrayList<>(); |
| if (oldDelegates != null) { |
| for (String aDelegate : oldDelegates) { |
| if (!OCLCommon.isDelegateURI(aDelegate)) { |
| newDelegates.add(aDelegate); |
| } |
| } |
| } |
| return newDelegates; |
| } |
| |
| protected void removeEAnnotation(@Nullable EAnnotation oclAnnotation) { |
| if (oclAnnotation != null) { |
| edits.add(new RemoveEAnnotation(oclAnnotation)); |
| } |
| } |
| |
| protected void removeEAnnotationDetail(@NonNull EAnnotation eAnnotation, @NonNull String detailName) { |
| edits.add(new SetEAnnotationDetail(eAnnotation, detailName)); |
| } |
| |
| @Override |
| public boolean isAdapterForType(Object type) { |
| return false; |
| } |
| |
| @Override |
| public void notifyChanged(Notification notification) {} |
| |
| @Override |
| public void setTarget(Notifier newTarget) { |
| assert (newTarget == null) || (newTarget == genModel); |
| } |
| } |
| |
| |
| public OCLinEcoreGenModelGeneratorAdapter(@NonNull OCLinEcoreGeneratorAdapterFactory generatorAdapterFactory) { |
| super(generatorAdapterFactory); |
| } |
| |
| protected void createDispatchTables(@NonNull GenModel genModel, @NonNull Monitor monitor) throws IOException { |
| try { |
| Map<@NonNull GenPackage, @NonNull String> constantTexts = getStateAdapter(genModel).getConstantTexts(); |
| String lineDelimiter = getLineDelimiter(genModel); |
| genModel.setLineDelimiter(lineDelimiter); |
| File projectFolder = getProjectFolder(genModel); |
| List<GenPackage> genPackages = genModel.getAllGenPackagesWithClassifiers(); |
| for (@SuppressWarnings("null")@NonNull GenPackage genPackage : genPackages) { |
| OCLinEcoreTables generateTables = new OCLinEcoreTables(genPackage); |
| String tablesClass = generateTables.getTablesClassName(); |
| String dir = genPackage.getReflectionPackageName().replace(".", "/"); |
| String constants = constantTexts.get(genPackage); |
| generateTables.generateTablesClass(constants); |
| String str = generateTables.toString(); |
| File tablesFolder = new File(projectFolder, dir); |
| tablesFolder.mkdirs(); |
| File file = new File(tablesFolder, tablesClass + ".java"); |
| FileWriter testFile = new FileWriter(file); |
| testFile.append(str); |
| testFile.close(); |
| } |
| } |
| finally { |
| genModel.setLineDelimiter(null); |
| } |
| } |
| |
| @Override |
| protected Diagnostic doPostGenerate(Object object, Object projectType) { |
| assert object != null; |
| GenModel genModel = (GenModel) object; |
| OCLinEcoreStateAdapter stateAdapter = findStateAdapter(genModel); |
| if (stateAdapter != null) { |
| stateAdapter.dispose(); |
| stateAdapter = null; |
| } |
| return super.doPostGenerate(object, projectType); |
| } |
| |
| @Override |
| protected Diagnostic doPreGenerate(Object object, Object projectType) { |
| assert object != null; |
| GenModel genModel = (GenModel) object; |
| try { |
| if ((projectType == MODEL_PROJECT_TYPE) && !useDelegates(genModel) && hasDelegates(genModel)) { |
| OCLinEcoreStateAdapter stateAdapter = getStateAdapter(genModel); |
| List<String> modelPluginVariables = genModel.getModelPluginVariables(); |
| if (!modelPluginVariables.contains(PivotPlugin.PLUGIN_ID)) { // FIXME delete me BUG 401862 |
| stateAdapter.addModelPluginVariable(PivotPlugin.PLUGIN_ID); |
| } |
| if (!modelPluginVariables.contains("org.eclipse.ocl.examples.codegen")) { // FIXME delete me BUG 401862 |
| stateAdapter.addModelPluginVariable("org.eclipse.ocl.examples.codegen"); |
| } |
| if (useNullAnnotations(genModel) && !modelPluginVariables.contains("org.eclipse.jdt.annotation")) { |
| stateAdapter.addModelPluginVariable("org.eclipse.jdt.annotation"); |
| } |
| for (GenPackage genPackage : genModel.getAllGenPackagesWithClassifiers()) { |
| createImportManager(genPackage.getReflectionPackageName(), genPackage.getFactoryInterfaceName() + AbstractGenModelHelper.TABLES_CLASS_SUFFIX); // Only used to suppress NPE |
| } |
| Resource genResource = genModel.eResource(); |
| ResourceSet resourceSet = genResource.getResourceSet(); |
| if (resourceSet == null) { |
| throw new NullPointerException("No ResourceSet for genmodel"); |
| } |
| MetamodelManagerInternal metamodelManager = stateAdapter.getMetamodelManager(); |
| metamodelManager.getStandardLibrary().getOclAnyType(); |
| for (GenPackage genPackage : genModel.getGenPackages()) { |
| EPackage ecorePackage = genPackage.getEcorePackage(); |
| org.eclipse.ocl.pivot.Package asPackage = metamodelManager.getASOfEcore(org.eclipse.ocl.pivot.Package.class, ecorePackage); |
| assert asPackage != null; |
| } |
| metamodelManager.installRoot(CGLibrary.getDefaultModel()); |
| stateAdapter.convertConstraintsToOperations(metamodelManager); |
| Map<@NonNull String, @NonNull String> results = stateAdapter.createFeatureBodies(genModel); |
| for (String key : results.keySet()) { |
| String oldBody = results.get(key); |
| assert oldBody != null; |
| String newBody = ImportUtils.rewriteManagedImports(oldBody, null); // FIXME transfer imports between CG sessions |
| results.put(key, newBody); |
| } |
| stateAdapter.installJavaBodies(metamodelManager, genModel, results); |
| stateAdapter.pruneDelegates(genModel); |
| } |
| } catch (Exception e) { |
| Throwable t = e instanceof WrappedException ? ((WrappedException)e).getCause() : e;; |
| BasicDiagnostic thisDiagnostic = new BasicDiagnostic(Diagnostic.ERROR, getClass().getPackage().getName(), 0, "Failed to pre-generate " + genModel.getModelPluginID() + " constraints", new Object[]{t}); |
| Diagnostic thatDiagnostic = super.doPreGenerate(object, projectType); |
| if (thatDiagnostic.getSeverity() == Diagnostic.OK) { |
| return thisDiagnostic; |
| } |
| else { |
| thatDiagnostic.getChildren().add(thisDiagnostic); |
| return thatDiagnostic; |
| } |
| } |
| return super.doPreGenerate(object, projectType); |
| } |
| |
| protected @Nullable OCLinEcoreStateAdapter findStateAdapter(@NonNull GenModel genModel) { |
| for (Adapter adapter : genModel.eAdapters()) { |
| if ((adapter instanceof OCLinEcoreStateAdapter) && (((OCLinEcoreStateAdapter)adapter).getGenModelGeneratorAdapter() == this)) { |
| return (OCLinEcoreStateAdapter) adapter; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| protected Diagnostic generateModel(Object object, Monitor monitor) { |
| assert object != null; |
| GenModel genModel = (GenModel) object; |
| OCLinEcoreStateAdapter stateAdapter = findStateAdapter(genModel); |
| try { |
| // if (!useDelegates(genModel) && hadDelegates.contains(genModel)) { |
| if (stateAdapter != null) { |
| monitor.beginTask("", 4); |
| monitor.subTask("Generating Dispatch Tables"); |
| ensureProjectExists |
| (genModel.getModelDirectory(), genModel, MODEL_PROJECT_TYPE, genModel.isUpdateClasspath(), createMonitor(monitor, 1)); |
| if (getImportManager() == null) { |
| for (GenPackage genPackage : genModel.getAllGenPackagesWithClassifiers()) { |
| createImportManager(genPackage.getReflectionPackageName(), genPackage.getFactoryInterfaceName() + AbstractGenModelHelper.TABLES_CLASS_SUFFIX); // Only used to suppress NPE |
| } |
| } |
| createDispatchTables(genModel, monitor); |
| monitor.worked(1); |
| monitor.worked(1); |
| if (EMFPlugin.IS_ECLIPSE_RUNNING) { |
| IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| String modelProjectDirectory = genModel.getModelProjectDirectory(); |
| IProject modelProject = workspace.getRoot().getProject(modelProjectDirectory); |
| modelProject.refreshLocal(IResource.DEPTH_INFINITE, BasicMonitor.toIProgressMonitor(monitor)); |
| } |
| monitor.worked(1); |
| } |
| } catch (Exception e) { |
| BasicDiagnostic thisDiagnostic = new BasicDiagnostic(Diagnostic.ERROR, getClass().getPackage().getName(), 0, "Failed to generate " + genModel.getModelPluginID() + " tables and bodies", new Object[]{e}); |
| // Diagnostic thatDiagnostic = super.generateModel(object, monitor); |
| // if (thatDiagnostic.getSeverity() == Diagnostic.OK) { |
| return thisDiagnostic; |
| // } |
| // else { |
| // thatDiagnostic.getChildren().add(thisDiagnostic); |
| // return thatDiagnostic; |
| // } |
| } |
| return super.generateModel(object, monitor); |
| } |
| |
| /** |
| * Deduce the required line delimiter from the usage in the .project file. |
| */ |
| protected String getLineDelimiter(GenModel genModel) { |
| String modelProjectDirectory = genModel.getModelProjectDirectory() + "/.project"; |
| URI workspacePath = URI.createURI(modelProjectDirectory); |
| String targetFileEncoding = getEncoding(workspacePath); |
| return getLineDelimiter(workspacePath, targetFileEncoding); |
| } |
| |
| protected @NonNull File getProjectFolder(@NonNull GenModel genModel) { |
| String modelProjectDirectory = genModel.getModelProjectDirectory(); |
| String modelDirectory = genModel.getModelDirectory(); |
| if (EMFPlugin.IS_ECLIPSE_RUNNING) { |
| IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| IProject modelProject = workspace.getRoot().getProject(modelProjectDirectory); |
| IPath javaSource = new Path(modelDirectory); |
| IFolder folder = modelProject.getParent().getFolder(javaSource); |
| java.net.URI locationURI = ClassUtil.nonNullState(folder.getLocationURI()); |
| return ClassUtil.nonNullState(URIUtil.toFile(locationURI)); |
| } |
| else { |
| URI locationURI = URI.createPlatformResourceURI(modelDirectory, true); |
| ResourceSet resourceSet = genModel.eResource().getResourceSet(); |
| URIConverter uriConverter = resourceSet != null ? resourceSet.getURIConverter() : URIConverter.INSTANCE; |
| URI normalizedURI = uriConverter.normalize(locationURI); |
| return new File(normalizedURI.toFileString()); |
| } |
| } |
| |
| protected @NonNull OCLinEcoreStateAdapter getStateAdapter(@NonNull GenModel genModel) { |
| for (Adapter adapter : genModel.eAdapters()) { |
| if ((adapter instanceof OCLinEcoreStateAdapter) && (((OCLinEcoreStateAdapter)adapter).getGenModelGeneratorAdapter() == this)) { |
| return (OCLinEcoreStateAdapter) adapter; |
| } |
| } |
| return new OCLinEcoreStateAdapter(genModel); |
| } |
| |
| protected boolean hasConstraints(org.eclipse.ocl.pivot.Class pivotClass) { |
| if (pivotClass.getOwnedInvariants().size() > 0) { |
| return true; |
| } |
| for (Operation operation : PivotQueries.getOperations(pivotClass)) { |
| if (operation.getOwnedPreconditions().size() > 0) { |
| return true; |
| } |
| if (operation.getOwnedPostconditions().size() > 0) { |
| return true; |
| } |
| if (operation.getBodyExpression() != null) { |
| return true; |
| } |
| } |
| for (Property property : PivotQueries.getProperties(pivotClass)) { |
| if (property.getOwnedExpression() != null) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Return true if any local GenPackage is for an EPackage that has OCL validation/setting/invocation delegates. |
| */ |
| protected boolean hasDelegates(@NonNull GenModel genModel) { |
| for (GenPackage genPackage : genModel.getAllGenPackagesWithClassifiers()) { |
| EPackage ePackage = genPackage.getEcorePackage(); |
| if ((ePackage != null) && hasDelegates(ePackage)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| protected boolean hasDelegates(@NonNull EPackage ePackage) { |
| List<String> validationDelegates = EcoreUtil.getValidationDelegates(ePackage); |
| for (String validationDelegate : validationDelegates) { |
| if (OCLCommon.isDelegateURI(validationDelegate)) { |
| return true; |
| } |
| } |
| List<String> settingDelegates = EcoreUtil.getSettingDelegates(ePackage); |
| for (String settingDelegate : settingDelegates) { |
| if (OCLCommon.isDelegateURI(settingDelegate)) { |
| return true; |
| } |
| } |
| List<String> invocationDelegates = EcoreUtil.getInvocationDelegates(ePackage); |
| for (String invocationDelegate : invocationDelegates) { |
| if (OCLCommon.isDelegateURI(invocationDelegate)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| } |