| /******************************************************************************* |
| * Copyright (c) 2014, 2017 The University of York and Willink Transformations. |
| * 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: |
| * Horacio Hoyos - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.qvtd.compiler.internal.qvtr2qvtc; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.emf.codegen.ecore.genmodel.GenJDKLevel; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenModel; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenModelFactory; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenPackage; |
| import org.eclipse.emf.common.util.TreeIterator; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.impl.MinimalEObjectImpl; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.xmi.XMLResource; |
| import org.eclipse.emf.importer.ecore.EcoreImporter; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.ocl.pivot.CollectionType; |
| import org.eclipse.ocl.pivot.CompleteClass; |
| import org.eclipse.ocl.pivot.Element; |
| import org.eclipse.ocl.pivot.Import; |
| import org.eclipse.ocl.pivot.Model; |
| import org.eclipse.ocl.pivot.Namespace; |
| import org.eclipse.ocl.pivot.OCLExpression; |
| import org.eclipse.ocl.pivot.Operation; |
| import org.eclipse.ocl.pivot.PivotFactory; |
| import org.eclipse.ocl.pivot.Property; |
| import org.eclipse.ocl.pivot.StandardLibrary; |
| import org.eclipse.ocl.pivot.Type; |
| import org.eclipse.ocl.pivot.TypedElement; |
| import org.eclipse.ocl.pivot.Variable; |
| import org.eclipse.ocl.pivot.VariableDeclaration; |
| import org.eclipse.ocl.pivot.internal.ecore.as2es.AS2Ecore; |
| import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal; |
| import org.eclipse.ocl.pivot.util.DerivedConstants; |
| import org.eclipse.ocl.pivot.utilities.ClassUtil; |
| import org.eclipse.ocl.pivot.utilities.EnvironmentFactory; |
| import org.eclipse.ocl.pivot.utilities.NameUtil; |
| import org.eclipse.ocl.pivot.utilities.TracingOption; |
| import org.eclipse.ocl.pivot.utilities.TreeIterable; |
| import org.eclipse.qvtd.compiler.CompilerChain; |
| import org.eclipse.qvtd.compiler.CompilerChainException; |
| import org.eclipse.qvtd.compiler.CompilerConstants; |
| import org.eclipse.qvtd.compiler.ProblemHandler; |
| import org.eclipse.qvtd.compiler.internal.common.AbstractQVTc2QVTc; |
| import org.eclipse.qvtd.compiler.internal.qvtr2qvtc.trace.RelationalTransformation2TracePackage; |
| import org.eclipse.qvtd.compiler.internal.utilities.CompilerUtil; |
| import org.eclipse.qvtd.pivot.qvtbase.Function; |
| import org.eclipse.qvtd.pivot.qvtbase.Pattern; |
| import org.eclipse.qvtd.pivot.qvtbase.Predicate; |
| import org.eclipse.qvtd.pivot.qvtbase.Transformation; |
| import org.eclipse.qvtd.pivot.qvtbase.TypedModel; |
| import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil; |
| import org.eclipse.qvtd.pivot.qvtcore.BottomPattern; |
| import org.eclipse.qvtd.pivot.qvtcore.CoreDomain; |
| import org.eclipse.qvtd.pivot.qvtcore.CoreModel; |
| import org.eclipse.qvtd.pivot.qvtcore.GuardPattern; |
| import org.eclipse.qvtd.pivot.qvtcore.Mapping; |
| import org.eclipse.qvtd.pivot.qvtcore.QVTcoreFactory; |
| import org.eclipse.qvtd.pivot.qvtcore.RealizedVariable; |
| import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreHelper; |
| import org.eclipse.qvtd.pivot.qvtrelation.DomainPattern; |
| import org.eclipse.qvtd.pivot.qvtrelation.Key; |
| import org.eclipse.qvtd.pivot.qvtrelation.Relation; |
| import org.eclipse.qvtd.pivot.qvtrelation.RelationCallExp; |
| import org.eclipse.qvtd.pivot.qvtrelation.RelationDomain; |
| import org.eclipse.qvtd.pivot.qvtrelation.RelationModel; |
| import org.eclipse.qvtd.pivot.qvtrelation.RelationalTransformation; |
| import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelationHelper; |
| import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelationUtil; |
| import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp; |
| |
| import com.google.common.collect.Iterables; |
| import com.google.common.collect.Lists; |
| |
| public class QVTr2QVTc extends AbstractQVTc2QVTc |
| { |
| public static final @NonNull TracingOption CALL_TREE = new TracingOption(CompilerConstants.PLUGIN_ID, "qvtr2qvtc/callTree"); |
| public static final @NonNull TracingOption SYNTHESIS = new TracingOption(CompilerConstants.PLUGIN_ID, "qvtr2qvtc/synthesis"); |
| public static final @NonNull TracingOption VARIABLES = new TracingOption(CompilerConstants.PLUGIN_ID, "qvtr2qvtc/variables"); |
| |
| public static final class GenPackageComparator implements Comparator<@NonNull GenPackage> |
| { |
| public static final @NonNull GenPackageComparator INSTANCE = new GenPackageComparator(); |
| |
| @Override |
| public int compare(@NonNull GenPackage o1, @NonNull GenPackage o2) { |
| String n1 = String.valueOf(o1.getNSURI()); |
| String n2 = String.valueOf(o2.getNSURI()); |
| return n1.compareTo(n2); |
| } |
| } |
| |
| protected static class CreateVisitor extends AbstractCreateVisitor<@NonNull QVTr2QVTc> |
| { |
| public CreateVisitor(@NonNull QVTr2QVTc context) { |
| super(context); |
| } |
| } |
| |
| public static final class RelationComparator implements Comparator<@NonNull Relation> |
| { |
| private @NonNull Map<@NonNull Relation, @NonNull Set<@NonNull Relation>> relation2overriddens = new HashMap<>(); |
| |
| @Override |
| public int compare(@NonNull Relation r1, @NonNull Relation r2) { |
| // |
| // Top level first |
| // |
| boolean t1 = r1.isIsTopLevel(); |
| boolean t2 = r2.isIsTopLevel(); |
| if (t1 != t2) { |
| return t1 ? -1 : 1; |
| } |
| // |
| // Overriding last |
| // |
| Set<@NonNull Relation> o1 = getOverriddens(r1); |
| Set<@NonNull Relation> o2 = getOverriddens(r2); |
| if (o1.contains(r2)) { |
| assert !o2.contains(r1); |
| return 1; |
| } |
| else if (o2.contains(r1)) { |
| return -1; |
| } |
| // |
| // Alphabetical |
| // |
| String n1 = NameUtil.getSafeName(r1); |
| String n2 = NameUtil.getSafeName(r2); |
| return ClassUtil.safeCompareTo(n1, n2); |
| } |
| |
| private @NonNull Set<@NonNull Relation> getOverriddens(@NonNull Relation relation) { |
| Set<@NonNull Relation> overriddens = relation2overriddens.get(relation); |
| if (overriddens == null) { |
| overriddens = new HashSet<>(); |
| for (Relation overridden = relation; overridden != null; overridden = QVTrelationUtil.basicGetOverridden(overridden)) { |
| if (!overriddens.add(overridden)) { |
| System.err.println("Cyclic override for " + relation + " at " + overridden); |
| break; |
| } |
| } |
| relation2overriddens.put(relation, overriddens); |
| } |
| return overriddens; |
| } |
| } |
| |
| protected static class UpdateVisitor extends AbstractUpdateVisitor<@NonNull QVTr2QVTc> |
| { |
| public UpdateVisitor(@NonNull QVTr2QVTc context) { |
| super(context); |
| } |
| } |
| |
| public static @NonNull String getProjectName(@NonNull URI traceURI) { |
| URI trimFileExtension = traceURI.trimFileExtension(); |
| if (trimFileExtension.isPlatform()) { |
| return trimFileExtension.segment(1); |
| } |
| else { |
| return trimFileExtension.segment(0); |
| } |
| } |
| |
| protected final @NonNull StandardLibrary standardLibrary; |
| private final @NonNull Resource qvtrResource; |
| private final @NonNull Resource qvtcResource; |
| protected final @NonNull QVTrelationHelper rHelper; |
| protected final @NonNull QVTrNameGenerator nameGenerator; |
| |
| /** |
| * Optional configuration of the NsURI of the trace package. |
| */ |
| private @Nullable String traceNsURI = null; |
| private final @NonNull Map<@NonNull Element, @NonNull Element> globalTarget2source = new HashMap<>(); |
| private final @NonNull Map<@NonNull Element, @NonNull List<@NonNull Element>> globalSource2targets = new HashMap<>(); |
| |
| /** |
| * All leaf packages that contribute to the trace. Typically just one leaf package. May be many. |
| */ |
| private final @NonNull List<org.eclipse.ocl.pivot.@NonNull Package> txTracePackages = new ArrayList<>(); |
| // private final @NonNull List<@NonNull Transformation> cTransformations = new ArrayList<@NonNull Transformation>(); |
| |
| /** |
| * Mapping from each key via the TYpedModel in which it is enforced to its corresponding identification constructor function. |
| */ |
| private final @NonNull Map<@NonNull Key, @NonNull Map<@NonNull TypedModel, @NonNull Function>> key2typedModel2function = new HashMap<>(); |
| |
| /** |
| * The Key that identifies each Class. |
| * Multiple keys per class are prohibited by WFRs. See Bug 512532 for rationale. |
| * Singly-derived keys re-use the ancestral key, with a distinct key-class. |
| * Multiply-derived keys are synthesized lazily. |
| * A null value indicates that no key exists. |
| */ |
| private final @NonNull Map<@NonNull CompleteClass, @Nullable Key> completeClass2key = new HashMap<>(); |
| |
| /** |
| * Mapping from each relation to its corresponding trace class. |
| */ |
| private final @NonNull Map<@NonNull Relation, org.eclipse.ocl.pivot.@NonNull Class> relation2traceClass = new HashMap<>(); |
| |
| /** |
| * Mapping from each relation to its corresponding trace class. |
| */ |
| // private final @NonNull Map<@NonNull RelationCallExp, @NonNull List<org.eclipse.ocl.pivot.@NonNull Class>> invocation2traceClasses = new HashMap<>(); |
| |
| /** |
| * Map from each relation to all the expressions that call the relation from a when clause. |
| */ |
| private final @NonNull Map<@NonNull Relation, @Nullable List<@NonNull RelationCallExp>> relation2incomingWhenInvocations = new HashMap<>(); |
| private final @NonNull Map<@NonNull Relation, @Nullable List<@NonNull RelationCallExp>> relation2outgoingWhenInvocations = new HashMap<>(); |
| |
| /** |
| * Map from each relation to all the expressions that call the relation from a where clause. |
| */ |
| private final @NonNull Map<@NonNull Relation, @Nullable List<@NonNull RelationCallExp>> relation2incomingWhereInvocations = new HashMap<>(); |
| private final @NonNull Map<@NonNull Relation, @Nullable List<@NonNull RelationCallExp>> relation2outgoingWhereInvocations = new HashMap<>(); |
| |
| /** |
| * Map from each relation invocation the relation whose where predicate contains the invocation. |
| * @deprecated computable - no cache required |
| */ |
| @Deprecated |
| private final @NonNull Map<@NonNull RelationCallExp, @NonNull Relation> invocation2invokingRelation = new HashMap<>(); |
| |
| private @NonNull CoreModel coreModel; |
| |
| /** |
| * The core Transformation for each RelationalTransformation. |
| */ |
| private @NonNull Map<@NonNull RelationalTransformation, @NonNull Transformation> rTransformation2cTransformation = new HashMap<>(); |
| |
| /** |
| * The trace Package for each RelationalTransformation. |
| */ |
| private @NonNull Map<@NonNull RelationalTransformation, org.eclipse.ocl.pivot.@NonNull Package> rTransformation2tracePackage = new HashMap<>(); |
| |
| private @Nullable RelationalTransformation2TracePackage relationalTransformation2TracePackage = null; |
| |
| /** |
| * The core TypedModel for each Relational TypedModel. |
| */ |
| private @NonNull Map<@NonNull TypedModel, @NonNull TypedModel> relationalTypedModel2coreTypedModel = new HashMap<>(); |
| |
| /** |
| * The lazily created named Core mappings for each transformation. |
| */ |
| private @NonNull Map<@NonNull Transformation, @NonNull Map<@NonNull String, @NonNull Mapping>> transformation2name2mapping = new HashMap<>(); |
| |
| /** |
| * The root variables (in relation call order) of each relation. |
| */ |
| private @NonNull Map<@NonNull Relation, @NonNull List<@NonNull Variable>> relation2rootVariables = new HashMap<>(); |
| |
| /** |
| * Closure of all overriding relations for each relation, or null if not overridden. |
| */ |
| private @NonNull Map<@NonNull Relation, @Nullable Set<@NonNull Relation>> relation2overridingRelations = new HashMap<>(); |
| |
| /** |
| * The per-relation conversions. |
| */ |
| private @NonNull Map<@NonNull Relation, @NonNull AbstractQVTr2QVTcRelations> relation2relation2mapping = new HashMap<>(); |
| |
| private @Nullable Property oclContainerProperty = null; |
| |
| public QVTr2QVTc(@NonNull EnvironmentFactory environmentFactory, @NonNull Resource qvtrResource, @NonNull Resource qvtcResource) { |
| super(environmentFactory); |
| this.standardLibrary = environmentFactory.getStandardLibrary(); |
| this.qvtrResource = qvtrResource; |
| this.qvtcResource = qvtcResource; |
| // this.traceResource = traceResource; |
| this.rHelper = new QVTrelationHelper(environmentFactory); |
| this.nameGenerator = new QVTrNameGenerator(this); |
| this.coreModel = QVTcoreFactory.eINSTANCE.createCoreModel(); |
| |
| // Create a cache of opposite relations and copy imports |
| TreeIterator<EObject> it = qvtrResource.getAllContents(); |
| while (it.hasNext()) { |
| EObject eo = it.next(); |
| if (eo instanceof Key) { |
| analyzeKey((Key)eo); |
| } |
| if (eo instanceof Relation) { |
| Relation relation = (Relation)eo; |
| analyzeInvocations(relation); |
| analyzeRootVariables(relation); |
| for (Relation anOverriddenRelation = relation; anOverriddenRelation != null; anOverriddenRelation = QVTrelationUtil.basicGetOverridden(anOverriddenRelation)) { |
| if ((anOverriddenRelation != relation) && !addOverridingRelation(anOverriddenRelation, relation)) { |
| break; |
| } |
| } |
| } |
| if (eo instanceof Import) { |
| this.coreModel.getOwnedImports().add((Import) EcoreUtil.copy(eo)); |
| } |
| } |
| } |
| |
| private boolean addOverridingRelation(@NonNull Relation overriddenRelation, @NonNull Relation overridingRelation) { |
| assert overridingRelation != overriddenRelation; |
| Set<@NonNull Relation> overridingRelations = relation2overridingRelations.get(overriddenRelation); |
| if (overridingRelations == null) { |
| overridingRelations = new HashSet<>(); |
| relation2overridingRelations.put(overriddenRelation, overridingRelations); |
| } |
| return overridingRelations.add(overridingRelation); |
| } |
| |
| protected void analyzeInvocations(@NonNull Relation callingRelation) { |
| Pattern whenPattern = callingRelation.getWhen(); |
| if (whenPattern != null) { |
| analyzeInvocations(callingRelation, whenPattern, relation2incomingWhenInvocations, relation2outgoingWhenInvocations); |
| } |
| Pattern wherePattern = callingRelation.getWhere(); |
| if (wherePattern != null) { |
| analyzeInvocations(callingRelation, wherePattern, relation2incomingWhereInvocations, relation2outgoingWhereInvocations); |
| } |
| } |
| |
| protected void analyzeInvocations(@NonNull Relation callingRelation, @NonNull Pattern pattern, |
| @NonNull Map<@NonNull Relation, @Nullable List<@NonNull RelationCallExp>> relation2incomingInvocations, |
| @NonNull Map<@NonNull Relation, @Nullable List<@NonNull RelationCallExp>> relation2outgoingInvocations) { |
| for (@NonNull Predicate predicate : QVTrelationUtil.getOwnedPredicates(pattern)) { |
| OCLExpression predicateExpression = predicate.getConditionExpression(); |
| if (predicateExpression instanceof RelationCallExp) { |
| RelationCallExp relationInvocation = (RelationCallExp) predicateExpression; |
| Relation invokedRelation = QVTrelationUtil.getReferredRelation(relationInvocation); |
| List<@NonNull RelationCallExp> incomingInvocations = relation2incomingInvocations.get(invokedRelation); |
| if (incomingInvocations == null) { |
| incomingInvocations = new ArrayList<>(); |
| relation2incomingInvocations.put(invokedRelation, incomingInvocations); |
| } |
| incomingInvocations.add(relationInvocation); |
| Relation invokingRelation = QVTrelationUtil.getContainingRelation(relationInvocation); |
| List<@NonNull RelationCallExp> outgoingInvocations = relation2outgoingInvocations.get(invokingRelation); |
| if (outgoingInvocations == null) { |
| outgoingInvocations = new ArrayList<>(); |
| relation2outgoingInvocations.put(invokingRelation, outgoingInvocations); |
| } |
| outgoingInvocations.add(relationInvocation); |
| invocation2invokingRelation.put(relationInvocation, callingRelation); |
| } |
| } |
| } |
| |
| protected void analyzeKey(@NonNull Key key) { |
| CompleteClass identifies = getCompleteClass(QVTrelationUtil.getIdentifies(key)); |
| completeClass2key.put(identifies, key); |
| } |
| |
| protected void analyzeRootVariables(@NonNull Relation relation) { |
| List<@NonNull Variable> rootVariables = new ArrayList<>(); |
| for (@NonNull RelationDomain rDomain : QVTrelationUtil.getOwnedDomains(relation)) { |
| for (@NonNull DomainPattern rDomainPattern : QVTrelationUtil.getOwnedPatterns(rDomain)) { |
| TemplateExp rRootTemplateExpression = rDomainPattern.getTemplateExpression(); |
| if (rRootTemplateExpression != null) { |
| rootVariables.add(QVTrelationUtil.getBindsTo(rRootTemplateExpression)); |
| } |
| } |
| } |
| relation2rootVariables.put(relation, rootVariables); |
| } |
| |
| public org.eclipse.ocl.pivot.@Nullable Class basicGetSignatureClass(@NonNull Relation rRelation) { |
| return getRelationalTransformation2TracePackage().basicGetSignatureClass(rRelation); |
| } |
| |
| public @Nullable Property basicGetTraceProperty(@NonNull Type aClass, @NonNull VariableDeclaration rVariable) throws CompilerChainException { |
| Property traceProperty = getRelationalTransformation2TracePackage().basicGetTraceProperty(aClass, rVariable); |
| if (traceProperty != null) { |
| return traceProperty; |
| } |
| String name = QVTrelationUtil.getName(rVariable); |
| CompleteClass completeClass = getCompleteClass(aClass); |
| return completeClass.getProperty(name); |
| } |
| |
| public @NonNull CoreDomain createCoreDomain(@NonNull TypedModel typedModel) { |
| CoreDomain coreDomain = QVTcoreFactory.eINSTANCE.createCoreDomain(); |
| coreDomain.setTypedModel(typedModel); |
| coreDomain.setName(QVTrelationUtil.getName(typedModel)); |
| // putTrace(coreDomain, coreRule); |
| GuardPattern guardPattern = QVTcoreFactory.eINSTANCE.createGuardPattern(); |
| coreDomain.setGuardPattern(guardPattern); |
| // putTrace(guardPattern, coreRule); |
| BottomPattern bottomPattern = QVTcoreFactory.eINSTANCE.createBottomPattern(); |
| coreDomain.setBottomPattern(bottomPattern); |
| return coreDomain; |
| } |
| |
| @Override |
| protected @NonNull AbstractCreateVisitor<@NonNull ?> createCreateVisitor() { |
| return new CreateVisitor(this); |
| } |
| |
| public @NonNull String createKeyFunctionName(@NonNull TypedModel rTypedModel, @NonNull Key rKey) { |
| return nameGenerator.createKeyFunctionName(rTypedModel, rKey); |
| } |
| |
| public @NonNull String createKeyedVariableName(@NonNull Variable identifiedVariable) { |
| return nameGenerator.createKeyedVariableName(identifiedVariable); |
| } |
| |
| /** |
| * Create the name Mapping for a cTransformation. |
| */ |
| /*public*/ @NonNull Mapping createMapping(@NonNull Relation relation, @NonNull String name) { |
| RelationalTransformation rt = QVTrelationUtil.getTransformation(relation); |
| @NonNull Transformation cTransformation = getCoreTransformation(rt); |
| Map<@NonNull String, @NonNull Mapping> name2mapping = transformation2name2mapping.get(cTransformation); |
| if (name2mapping == null) { |
| name2mapping = new HashMap<>(); |
| transformation2name2mapping.put(cTransformation, name2mapping); |
| } |
| Mapping coreMapping = name2mapping.get(name); |
| assert (coreMapping == null); |
| coreMapping = helper.createMapping(name); |
| putGlobalTrace(coreMapping, relation); |
| coreMapping.setTransformation(cTransformation); |
| name2mapping.put(name, coreMapping); |
| return coreMapping; |
| } |
| |
| public @NonNull RealizedVariable createRealizedVariable(@NonNull TypedElement typedElement) { |
| return createRealizedVariable(QVTrelationUtil.getName(typedElement), QVTrelationUtil.getType(typedElement)); |
| } |
| |
| public @NonNull RealizedVariable createRealizedVariable(@NonNull String name, @NonNull Type type) { |
| RealizedVariable realizedVariable = QVTcoreFactory.eINSTANCE.createRealizedVariable(); |
| realizedVariable.setName(name); |
| realizedVariable.setType(type); |
| realizedVariable.setIsRequired(true); |
| return realizedVariable; |
| } |
| |
| public @NonNull String createTraceClassName(@NonNull Relation relation) { |
| return nameGenerator.createTraceClassName(relation); |
| } |
| |
| @Override |
| protected @NonNull AbstractUpdateVisitor<@NonNull ?> createUpdateVisitor() { |
| return new UpdateVisitor(this); |
| } |
| |
| // Save the qvtc resource |
| public void dispose() { |
| // What about the trace model? we need to separate them |
| //qvtcSource.getContents().addAll(traceData.getRootOutputELements()); |
| } |
| |
| /* public void execute() throws CompilerChainException { |
| prepare(); |
| transformToTracePackages(); |
| transformToCoreTransformations(); |
| } */ |
| |
| public @NonNull CompleteClass getCompleteClass(@NonNull Type type) { |
| CompleteClass completeClass = environmentFactory.getCompleteModel().getCompleteClass(type); |
| return completeClass; |
| } |
| |
| /*public*/ @NonNull Transformation getCoreTransformation(@NonNull RelationalTransformation rTransformation) { |
| return ClassUtil.nonNullState(rTransformation2cTransformation.get(rTransformation)); |
| } |
| |
| /*public*/ @NonNull TypedModel getCoreTypedModel(@NonNull TypedModel relationTypedModel) { |
| return ClassUtil.nonNullState(relationalTypedModel2coreTypedModel.get(relationTypedModel)); |
| } |
| |
| /* public @NonNull DomainPattern getDomainPattern(@NonNull Domain d) { |
| List<@NonNull DomainPattern> pattern = ClassUtil.nullFree(((RelationDomain) d).getPattern()); |
| assert pattern.size() == 1; |
| DomainPattern domainPattern = pattern.get(0); |
| assert domainPattern != null; |
| return domainPattern; |
| } */ |
| |
| @Override |
| public @NonNull EnvironmentFactory getEnvironmentFactory() { |
| return environmentFactory; |
| } |
| |
| public @Nullable List<@NonNull Element> getGlobalTargets(@NonNull Element element) { |
| return globalSource2targets.get(element); |
| } |
| |
| @Override |
| public @NonNull QVTcoreHelper getHelper() { |
| return helper; |
| } |
| |
| public @Nullable Iterable<@NonNull RelationCallExp> getIncomingWhenInvocationsOf(@NonNull Relation relation) { |
| return relation2incomingWhenInvocations.get(relation); |
| } |
| |
| public @Nullable Iterable<@NonNull RelationCallExp> getIncomingWhereInvocationsOf(@NonNull Relation relation) { |
| return relation2incomingWhereInvocations.get(relation); |
| } |
| |
| /*public*/ @NonNull Relation getInvokingRelation(@NonNull RelationCallExp rInvocation) { |
| Relation rRelation1 = ClassUtil.nonNullState(invocation2invokingRelation.get(rInvocation)); |
| Relation rRelation2 = (Relation) ((Predicate)rInvocation.eContainer()).getPattern().eContainer(); |
| assert rRelation1 == rRelation2; |
| return rRelation1; |
| } |
| |
| /** |
| * Return the Key for completeClass, returning null if none, or an explicit key if defined, |
| * or a synthesized key if singly/multiply inherited. |
| */ |
| public @Nullable Key getKeyForCompleteClass(@NonNull CompleteClass completeClass) { |
| Key key = completeClass2key.get(completeClass); |
| if ((key == null) && !completeClass2key.containsKey(completeClass)) { |
| Set<@NonNull Property> parts = null; |
| for (@NonNull CompleteClass superCompleteClass : completeClass.getProperSuperCompleteClasses()) { |
| Key superKey = getKeyForCompleteClass(superCompleteClass); |
| if (superKey != null) { |
| if (parts == null) { |
| parts = new HashSet<>(); |
| } |
| for (@NonNull Property property : QVTrelationUtil.getOwnedParts(superKey)) { |
| parts.add(property); |
| } |
| for (@NonNull Property property : QVTrelationUtil.getOwnedOppositeParts(superKey)) { |
| parts.add(QVTrelationUtil.getOpposite(property)); |
| } |
| } |
| } |
| if (parts != null) { |
| key = new QVTrelationHelper(environmentFactory).createKey(completeClass.getPrimaryClass(), parts); |
| } |
| completeClass2key.put(completeClass, key); |
| } |
| return key; |
| } |
| |
| public @Nullable Key getKeyForType(@NonNull Type type) { |
| CompleteClass completeClass = getCompleteClass(type); |
| return getKeyForCompleteClass(completeClass); |
| } |
| |
| /*public*/ @NonNull Function getKeyFunction(@NonNull TypedModel rTypedModel, @NonNull Key rKey) throws CompilerChainException { |
| Map<@NonNull TypedModel, @NonNull Function> typedModel2function = key2typedModel2function.get(rKey); |
| if (typedModel2function == null) { |
| typedModel2function = new HashMap<>(); |
| key2typedModel2function.put(rKey, typedModel2function); |
| } |
| Function cKeyFunction = typedModel2function.get(rTypedModel); |
| if (cKeyFunction == null) { |
| Iterable<org.eclipse.ocl.pivot.@NonNull Class> usedClasses = QVTrelationUtil.getUsedClasses(rTypedModel); |
| org.eclipse.ocl.pivot.@NonNull Class identifiedClass = QVTrelationUtil.getIdentifies(rKey); |
| assert (Iterables.contains(usedClasses, identifiedClass)); |
| QVTr2QVTc.SYNTHESIS.println("key " + rKey); |
| KeyToFunctionForIdentification keyToMapping = new KeyToFunctionForIdentification(this, rTypedModel, rKey); |
| cKeyFunction = keyToMapping.transform(); |
| getCoreTransformation(QVTrelationUtil.getContainingTransformation(rTypedModel)).getOwnedOperations().add(cKeyFunction); |
| // } |
| typedModel2function.put(rTypedModel, cKeyFunction); |
| // putTrace(traceClass, r); |
| } |
| return cKeyFunction; |
| } |
| |
| public @NonNull QVTrNameGenerator getNameGenerator() { |
| return nameGenerator; |
| } |
| |
| public @NonNull Property getOclContainerProperty() { |
| Property oclContainerProperty2 = oclContainerProperty; |
| if (oclContainerProperty2 == null) { |
| org.eclipse.ocl.pivot.Class oclElementType = standardLibrary.getOclElementType(); |
| oclContainerProperty2 = NameUtil.getNameable(oclElementType.getOwnedProperties(), "oclContainer"); |
| assert oclContainerProperty2 != null : "OCL Standard Library has no OclElement::oclContainer property"; |
| oclContainerProperty = oclContainerProperty2; |
| } |
| return oclContainerProperty2 ; |
| } |
| |
| public @Nullable Iterable<@NonNull RelationCallExp> getOutgoingWhenInvocationsOf(@NonNull Relation relation) { |
| return relation2outgoingWhenInvocations.get(relation); |
| } |
| |
| public @Nullable Iterable<@NonNull RelationCallExp> getOutgoingWhereInvocationsOf(@NonNull Relation relation) { |
| return relation2outgoingWhereInvocations.get(relation); |
| } |
| |
| public @NonNull Iterable<@NonNull Relation> getOverridingRelations(@NonNull Relation overriddenRelation) { |
| Set<@NonNull Relation> overridingRelations = relation2overridingRelations.get(overriddenRelation); |
| return overridingRelations != null ? overridingRelations : Collections.emptyList(); |
| } |
| |
| public Predicate getPredicateForRelationCallExp(RelationCallExp ri) { |
| // TODO Auto-generated method stub |
| return null; |
| } |
| |
| protected @NonNull Property getProperty(/*@NonNull*/ Type aClass, /*@NonNull*/ String name) throws CompilerChainException { |
| assert (aClass != null) && (name != null); |
| CompleteClass completeClass = getCompleteClass(aClass); |
| Property p = completeClass.getProperty(name); |
| if (p != null) |
| return p; |
| throw new CompilerChainException("No property '" + name + "' in '" + aClass + "::" + "'"); |
| } |
| |
| /** |
| * @return the qvtcSource |
| */ |
| public Resource getQvtcSource() { |
| return qvtcResource; |
| } |
| |
| public @NonNull RelationalTransformation2TracePackage getRelationalTransformation2TracePackage() { |
| return ClassUtil.nonNullState(relationalTransformation2TracePackage); |
| } |
| |
| public @NonNull List<@NonNull Variable> getRootVariables(@NonNull Relation relation) { |
| return ClassUtil.nonNullState(relation2rootVariables.get(relation)); |
| } |
| |
| public org.eclipse.ocl.pivot.@NonNull Class getSignatureClass(@NonNull Relation rRelation) { |
| return getRelationalTransformation2TracePackage().getSignatureClass(rRelation); |
| } |
| |
| // public @NonNull Property getSignatureProperty(@NonNull RelationCallExp rInvocation) { |
| // return getRelationalTransformation2TracePackage().getSignatureProperty(rInvocation); |
| // } |
| |
| /** |
| * Return the trace property that corresponds to rVariable in aClass. |
| */ |
| protected @NonNull Property getSignatureProperty(org.eclipse.ocl.pivot.@NonNull Class aClass, @NonNull VariableDeclaration rVariable) { |
| return getRelationalTransformation2TracePackage().getSignatureProperty(aClass, rVariable); |
| } |
| |
| public @NonNull StandardLibrary getStandardLibrary() { |
| return standardLibrary; |
| } |
| |
| /*public*/ org.eclipse.ocl.pivot.@NonNull Class getTraceClass(@NonNull Relation rRelation) { |
| return getRelationalTransformation2TracePackage().getTraceClass(rRelation); |
| } |
| |
| /*public*/ org.eclipse.ocl.pivot.@NonNull Package getTracePackage(@NonNull RelationalTransformation rTransformation) { |
| return ClassUtil.nonNullState(rTransformation2tracePackage.get(rTransformation)); |
| } |
| |
| /** |
| * Return the trace property of aClass whose name corresponds to rNamedElement. |
| * @throws CompilerChainException if no such property |
| */ |
| protected @NonNull Property getTraceProperty(@NonNull Type aClass, @NonNull VariableDeclaration rVariable) throws CompilerChainException { |
| Property property = getRelationalTransformation2TracePackage().basicGetTraceProperty(aClass, rVariable); |
| if (property != null) { |
| return property; |
| } |
| property = getProperty(aClass, rVariable.getName()); // FIXME above should be non-null to ensure uniquely named property is in use |
| if (rVariable instanceof Property) { |
| assert rVariable == property; |
| } |
| return property; |
| } |
| |
| public @NonNull Property getTraceProperty(@NonNull RelationCallExp rInvocation) { |
| return getRelationalTransformation2TracePackage().getTraceProperty(rInvocation); |
| } |
| |
| private void getUsedGenPackageClosure(@NonNull ProblemHandler problemHandler, @NonNull Map<@NonNull String, @NonNull GenPackage> uri2genPackage, @NonNull Iterable<@NonNull ? extends GenPackage> genPackages) { |
| for (@NonNull GenPackage newGenPackage : genPackages) { |
| String nsURI = newGenPackage.getNSURI(); |
| if (nsURI == null) { |
| problemHandler.addProblem(new CompilerChainException("Null nsURI for " + newGenPackage, newGenPackage)); |
| } |
| else { |
| GenPackage oldGenPackage = uri2genPackage.put(nsURI, newGenPackage); |
| if (oldGenPackage != newGenPackage) { |
| if (oldGenPackage != null) { |
| problemHandler.addProblem(new CompilerChainException("Conflicting " + oldGenPackage + " ignored", oldGenPackage)); |
| } |
| else { |
| GenModel newGenModel = newGenPackage.getGenModel(); |
| Iterable<GenPackage> newUsedGenPackages = ClassUtil.nullFree(newGenModel.getUsedGenPackages()); |
| getUsedGenPackageClosure(problemHandler, uri2genPackage, newUsedGenPackages); |
| } |
| } |
| } |
| } |
| } |
| |
| protected void mapQueries(@NonNull RelationalTransformation rTransformation, @NonNull Transformation cTransformation) { |
| List<@NonNull Operation> cOperations = new ArrayList<>(); |
| for (@NonNull Operation rOperation : QVTbaseUtil.getOwnedOperations(rTransformation)) { |
| Element cOperation = rOperation.accept(createVisitor); |
| if (cOperation instanceof Operation) { |
| cOperations.add((Operation) cOperation); |
| putGlobalTrace(cOperation, rOperation); |
| } |
| } |
| cTransformation.getOwnedOperations().addAll(cOperations); |
| for (@NonNull Operation cOperation : cOperations) { |
| cOperation.accept(updateVisitor); |
| } |
| } |
| |
| /** |
| * Transform the contents of a single rTransformation to populate the already created cTransformation. |
| */ |
| protected void mapTransformation(@NonNull RelationalTransformation rTransformation, @NonNull Transformation cTransformation) throws CompilerChainException { |
| List<@NonNull Relation> rRelations = Lists.newArrayList(QVTrelationUtil.getOwnedRelations(rTransformation)); |
| Collections.sort(rRelations, new RelationComparator()); |
| Variable cThis = QVTbaseUtil.getContextVariable(standardLibrary, cTransformation); |
| Variable rThis = QVTbaseUtil.getContextVariable(standardLibrary, rTransformation); |
| // putGlobalTrace(cThis, rThis); |
| addTrace(rThis, cThis); |
| // UniqueArrayList<@NonNull TypedModel> rEnforceableTypedModels = new UniqueArrayList<>(); // FIXME not used |
| // for (@NonNull Relation rRelation : rRelations) { |
| // for (@NonNull RelationDomain rDomain : QVTrelationUtil.getOwnedDomains(rRelation)) { |
| // if (rDomain.isIsEnforceable()) { |
| // rEnforceableTypedModels.add(QVTrelationUtil.getTypedModel(rDomain)); |
| // } |
| // } |
| // } |
| mapQueries(rTransformation, cTransformation); |
| for (@NonNull Relation rRelation : rRelations) { |
| AbstractQVTr2QVTcRelations relation2mappings; |
| if (rRelation.isIsTopLevel()) { |
| QVTr2QVTc.SYNTHESIS.println("topLevel " + rRelation); |
| relation2mappings = new TopLevelRelationToMappingForEnforcement(this, rRelation); |
| } |
| else { |
| relation2mappings = new InvokedRelationToMappingForEnforcement(this, rRelation); |
| } |
| relation2mappings.analyze(); |
| relation2relation2mapping.put(rRelation, relation2mappings); |
| } |
| for (@NonNull Relation rRelation : rRelations) { |
| AbstractQVTr2QVTcRelations relation2mapping = relation2relation2mapping.get(rRelation); |
| assert relation2mapping != null; |
| relation2mapping.synthesize(); |
| } |
| CompilerUtil.normalizeNameables(QVTbaseUtil.Internal.getOwnedOperationsList(cTransformation)); |
| CompilerUtil.normalizeNameables(QVTbaseUtil.getRule(cTransformation)); |
| } |
| |
| public void addRelation2Mappings(@NonNull AbstractQVTr2QVTcRelations relation2mappings) { |
| Relation rRelation = relation2mappings.getRelation(); |
| relation2relation2mapping.put(rRelation, relation2mappings); |
| } |
| |
| public @NonNull AbstractQVTr2QVTcRelations getRelation2Mappings(@NonNull Relation rRelation) { |
| return ClassUtil.nonNullState(relation2relation2mapping.get(rRelation)); |
| } |
| |
| // Create the top rules, and search the input model for the appropriate types, when possible? |
| public void prepare() { |
| try { |
| qvtrResource.load(null); |
| } catch (IOException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| // EXIT! |
| } finally { |
| // if (qvtrModel.isLoaded()) { |
| //RuleFactory factory = new RuleFactory(); |
| //rules = factory.createTopRules(this); |
| // ruleFactories = new Rule.Factory[] { |
| // RelationalTransformationToMappingTransformation.FACTORY, |
| // RelationToTraceClass.FACTORY |
| // }; |
| // } |
| } |
| } |
| |
| /*public*/ void putCoreTransformation(@NonNull RelationalTransformation relationTransformation, @NonNull Transformation cTransformation) { |
| rTransformation2cTransformation.put(relationTransformation, cTransformation); |
| putGlobalTrace(cTransformation, relationTransformation); |
| } |
| |
| /*private*/ void putGlobalTrace(@NonNull Element coreElement, @NonNull Element relationElement) { |
| // if (relationElement != null) { |
| Element oldRelationElement = globalTarget2source.put(coreElement, relationElement); |
| assert oldRelationElement == null; |
| List<@NonNull Element> targets = globalSource2targets.get(relationElement); |
| if (targets == null) { |
| targets = new ArrayList<> (); |
| globalSource2targets.put(relationElement, targets); |
| } |
| targets.add(coreElement); |
| // } |
| } |
| |
| /* public void putInvocationTrace(@NonNull RelationCallExp rInvocation, org.eclipse.ocl.pivot.@NonNull Class traceClass) { |
| List<org.eclipse.ocl.pivot.@NonNull Class> traceClasses = invocation2traceClasses.get(rInvocation); |
| if (traceClasses == null) { |
| traceClasses = new ArrayList<>(); |
| invocation2traceClasses.put(rInvocation, traceClasses); |
| } |
| assert !traceClasses.contains(traceClass); |
| traceClasses.add(traceClass); |
| // putTrace(traceClass, r); |
| } */ |
| |
| public void putRelationTrace(@NonNull Relation rRelation, org.eclipse.ocl.pivot.@NonNull Class traceClass) { |
| org.eclipse.ocl.pivot.Class oldTraceClass = relation2traceClass.put(rRelation, traceClass); |
| assert oldTraceClass == null; |
| // putTrace(traceClass, r); |
| } |
| |
| public void putTracePackage(@NonNull RelationalTransformation rt, org.eclipse.ocl.pivot.@NonNull Package tracePackage) { |
| org.eclipse.ocl.pivot.Package oldTracePackage = rTransformation2tracePackage.put(rt, tracePackage); |
| assert oldTracePackage == null; |
| // putTrace(tracePackage, rt); |
| } |
| |
| public void putTypedModel(@NonNull TypedModel relationTypedModel, @NonNull TypedModel coreTypedModel) { |
| TypedModel oldTypedModel = relationalTypedModel2coreTypedModel.put(relationTypedModel, coreTypedModel); |
| assert oldTypedModel == null; |
| } |
| |
| public void saveCore(@NonNull Resource asResource, @NonNull Map<?, ?> options) throws IOException { |
| asResource.getContents().add(this.coreModel); |
| // Copy imports |
| |
| for (org.eclipse.ocl.pivot.@NonNull Package asPackage : txTracePackages) { |
| Import asImport = helper.createImport(null, asPackage); |
| coreModel.getOwnedImports().add(asImport); |
| } |
| // -- scan for dangling references if this is really wanted |
| // for (EObject eObject : potentialOrphans) { |
| // if (eObject.eContainer() == null) { |
| // asResource.getContents().add(eObject); |
| // } |
| // } |
| asResource.save(options); |
| } |
| |
| public @NonNull GenModel saveGenModel(@NonNull ProblemHandler problemHandler, @NonNull Resource asResource, @NonNull URI traceURI, @NonNull URI genModelURI, @Nullable Map<@NonNull String, @Nullable String> genModelOptions, @NonNull Map<Object, Object> saveOptions2, @Nullable Collection<@NonNull ? extends GenPackage> usedGenPackages) throws IOException { |
| URI trimFileExtension = traceURI.trimFileExtension(); |
| String projectName = getProjectName(traceURI); |
| Resource genmodelResource = environmentFactory.getResourceSet().createResource(genModelURI); |
| @SuppressWarnings("null")@NonNull GenModel genModel = GenModelFactory.eINSTANCE.createGenModel(); |
| genModel.getForeignModel().add(traceURI.lastSegment()); |
| String copyrightText = genModelOptions != null ? genModelOptions.get(CompilerChain.GENMODEL_COPYRIGHT_TEXT) : null; |
| if (copyrightText != null) { |
| genModel.setCopyrightText(copyrightText); |
| } |
| Map<@NonNull String, @NonNull GenPackage> uri2genPackage = new HashMap<>(); |
| List<@NonNull GenPackage> allUsedGenPackages = new ArrayList<>(); |
| if (usedGenPackages != null) { |
| getUsedGenPackageClosure(problemHandler, uri2genPackage, usedGenPackages); |
| allUsedGenPackages.addAll(uri2genPackage.values()); |
| Collections.sort(allUsedGenPackages, GenPackageComparator.INSTANCE); |
| genModel.getUsedGenPackages().addAll(allUsedGenPackages); |
| } |
| genModel.setModelDirectory("/" + projectName + "/src-gen"); |
| genModel.setModelPluginID(projectName); |
| genModel.setModelName(trimFileExtension.lastSegment()); |
| genModel.setBundleManifest(false); |
| genModel.setUpdateClasspath(false); |
| genModel.setImporterID(new EcoreImporter().getID()); |
| genModel.setComplianceLevel(GenJDKLevel.JDK80_LITERAL); |
| genModel.setCopyrightFields(false); |
| genModel.setOperationReflection(true); |
| genModel.setImportOrganizing(true); |
| genModel.setRootExtendsClass(MinimalEObjectImpl.Container.class.getName()); |
| genModel.setPluginKey(""); |
| genmodelResource.getContents().add(genModel); |
| String basePrefix = genModelOptions != null ? genModelOptions.get(CompilerChain.GENMODEL_BASE_PREFIX) : null; |
| List<GenPackage> genPackages = genModel.getGenPackages(); |
| for (EObject eObject : asResource.getContents()) { |
| if (eObject instanceof Model) { |
| Model asModel = (Model)eObject; |
| for (org.eclipse.ocl.pivot.@NonNull Package asPackage : QVTrelationUtil.getOwnedPackages(asModel)) { |
| GenPackage genPackage = genModel.createGenPackage(); |
| EPackage ePackage = (EPackage) asPackage.getESObject(); |
| genPackage.setEcorePackage(ePackage); |
| genPackage.setPrefix(ePackage.getName()); |
| if (basePrefix != null) { |
| genPackage.setBasePackage(basePrefix); |
| } |
| genPackages.add(genPackage); |
| } |
| Set<org.eclipse.ocl.pivot.@NonNull Package> asPackages = new HashSet<>(); |
| for (EObject element : new TreeIterable(asModel, false)) { |
| if (element instanceof Property) { |
| Property property = (Property)element; |
| Type type = property.getType(); |
| while (type instanceof CollectionType) { |
| type = ((CollectionType)type).getElementType(); |
| } |
| if (type instanceof org.eclipse.ocl.pivot.Class) { |
| org.eclipse.ocl.pivot.Package asPackage = ((org.eclipse.ocl.pivot.Class)type).getOwningPackage(); |
| if (asPackage != null) { |
| asPackages.add(asPackage); |
| } |
| } |
| } |
| } |
| for (@NonNull Import asImport : QVTrelationUtil.getOwnedImports(asModel)) { |
| Namespace asNamespace = asImport.getImportedNamespace(); |
| if (asNamespace instanceof org.eclipse.ocl.pivot.Package) { |
| org.eclipse.ocl.pivot.@NonNull Package asPackage = (org.eclipse.ocl.pivot.Package)asNamespace; |
| asPackages.add(asPackage); |
| } |
| } |
| List<org.eclipse.ocl.pivot.@NonNull Package> asPackageList = new ArrayList<>(asPackages); |
| Collections.sort(asPackageList, NameUtil.NAMEABLE_COMPARATOR); |
| for (org.eclipse.ocl.pivot.@NonNull Package asPackage : asPackageList) { |
| EPackage ePackage = (EPackage) asPackage.getESObject(); |
| if (ePackage != null) { |
| GenPackage genPackage = null; |
| if (allUsedGenPackages != null) { |
| for (@NonNull GenPackage usedGenPackage : allUsedGenPackages) { |
| EPackage ecorePackage = usedGenPackage.getEcorePackage(); |
| if ((ecorePackage != null) && ClassUtil.safeEquals(ecorePackage.getNsURI(), ePackage.getNsURI())) { |
| genPackage = usedGenPackage; |
| break; |
| } |
| } |
| } |
| if (genPackage == null) { |
| genPackage = genModel.createGenPackage(); |
| genPackage.setEcorePackage(ePackage); |
| genPackage.setPrefix(ePackage.getName()); |
| if (basePrefix != null) { |
| genPackage.setBasePackage(basePrefix); |
| } |
| genPackages.add(genPackage); |
| } |
| } |
| } |
| } |
| } |
| genModel.reconcile(); |
| Map<Object, Object> saveOptions = new HashMap<>(saveOptions2); |
| 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); |
| genmodelResource.save(saveOptions); |
| return genModel; |
| } |
| |
| public @NonNull Resource saveTrace(@NonNull Resource asResource, @NonNull URI traceURI, @NonNull URI genModelURI, @Nullable Map<@NonNull String, @Nullable String> traceOptions, @NonNull Map<?, ?> saveOptions) throws IOException { |
| Model root = PivotFactory.eINSTANCE.createModel(); |
| root.setExternalURI(traceURI.toString()); |
| asResource.getContents().add(root); |
| if ((traceNsURI != null) && (txTracePackages.size() == 1)) { |
| txTracePackages.get(0).setURI(traceNsURI); |
| } |
| for (org.eclipse.ocl.pivot.@NonNull Package txTracePackage : txTracePackages) { |
| org.eclipse.ocl.pivot.@NonNull Package rootPackage = txTracePackage; |
| for (EObject eContainer = rootPackage.eContainer(); eContainer instanceof org.eclipse.ocl.pivot.Package; eContainer = eContainer.eContainer()) { |
| rootPackage = (org.eclipse.ocl.pivot.Package)eContainer; |
| } |
| if (!root.getOwnedPackages().contains(rootPackage)) { |
| root.getOwnedPackages().add(rootPackage); |
| } |
| } |
| AS2Ecore as2ecore = new AS2Ecore((EnvironmentFactoryInternal) environmentFactory, traceURI, null); |
| XMLResource ecoreResource = as2ecore.convertResource(asResource, traceURI); |
| ecoreResource.save(saveOptions); |
| return ecoreResource; |
| } |
| |
| public void setTraceNsURI(@Nullable String traceNsURI) { |
| this.traceNsURI = traceNsURI; |
| } |
| |
| public void transformToCoreTransformations() throws CompilerChainException { |
| setDebugSource(qvtrResource); |
| // |
| // Build the corresponding QVTc Model/Package/Transformation hierarchy. |
| // |
| for (@NonNull EObject eObject : qvtrResource.getContents()) { |
| if (eObject instanceof RelationModel) { |
| RelationModel relationModel = (RelationModel)eObject; |
| String externalURI = relationModel.getExternalURI(); |
| if (externalURI.endsWith(".qvtras")) { |
| externalURI = externalURI.replace(".qvtras", ".qvtcas"); |
| } |
| else if (externalURI.endsWith(".qvtr")) { |
| externalURI = externalURI.replace(".qvtr", ".qvtcas"); |
| } |
| coreModel.setExternalURI(externalURI); |
| transformToCoreTransformationHierarchy(QVTrelationUtil.Internal.getOwnedPackagesList(coreModel), QVTrelationUtil.getOwnedPackages(relationModel)); |
| } |
| } |
| List<@NonNull RelationalTransformation> rTransformations = new ArrayList<>(rTransformation2cTransformation.keySet()); |
| Collections.sort(rTransformations, NameUtil.NAMEABLE_COMPARATOR); |
| for (@NonNull RelationalTransformation rTransformation : rTransformations) { |
| Transformation cTransformation = getCoreTransformation(rTransformation); |
| pushScope(cTransformation); |
| mapTransformation(rTransformation, cTransformation); |
| popScope(); |
| } |
| /* for (@NonNull Transformation cTransformation : rTransformation2cTransformation.values()) { |
| List<DebugTraceBack> debugTraceBacks = cTransformation.getOwnedDebugTraceBacks(); |
| for (@NonNull Element target : target2source.keySet()) { |
| if (QVTbaseUtil.getContainingTransformation(target) == cTransformation) { |
| DebugTraceBack traceBack = QVTbaseFactory.eINSTANCE.createDebugTraceBack(); |
| traceBack.setTarget(target); |
| // FIXME true source URI traceBack.getSources().add(target2source.get(target)); |
| debugTraceBacks.add(traceBack); |
| } |
| } |
| // CompilerUtil.normalizeNameables(debugTraceBacks); |
| } */ |
| } |
| |
| /** |
| * Descend the relationPackages hierarchy to establish a QVTc transformation object for each QVTr transformation object with a corresponding package hierarchy in corePackages. |
| */ |
| private void transformToCoreTransformationHierarchy(@NonNull List<org.eclipse.ocl.pivot.@NonNull Package> corePackages, @NonNull Iterable<org.eclipse.ocl.pivot.@NonNull Package> relationPackages) { |
| for (org.eclipse.ocl.pivot.@NonNull Package relationPackage : relationPackages) { |
| String name = relationPackage.getName(); |
| assert name != null; |
| org.eclipse.ocl.pivot.@NonNull Package corePackage = helper.createPackage(name, relationPackage.getNsPrefix(), relationPackage.getURI()); |
| corePackages.add(corePackage); |
| // |
| // Transform the transformations to establish callable names. |
| // |
| for (org.eclipse.ocl.pivot.@NonNull Class relationClass : QVTrelationUtil.getOwnedClasses(relationPackage)) { |
| if (relationClass instanceof RelationalTransformation) { |
| RelationalTransformationToMappingTransformation rTransformationToMappingTransformation = new RelationalTransformationToMappingTransformation(this); |
| Transformation cTransformation = rTransformationToMappingTransformation.doRelationalTransformationToMappingTransformation((RelationalTransformation)relationClass); |
| corePackage.getOwnedClasses().add(cTransformation); |
| // CompilerUtil.normalizeNameables(QVTrelationUtil.getRule(cTransformation))); |
| } |
| } |
| CompilerUtil.normalizeNameables(QVTrelationUtil.Internal.getOwnedClassesList(corePackage)); |
| // |
| // Recurse to establish callable names in nested packages. |
| // |
| transformToCoreTransformationHierarchy(QVTrelationUtil.Internal.getOwnedPackagesList(corePackage), QVTrelationUtil.getOwnedPackages(relationPackage)); |
| } |
| } |
| |
| public void transformToTracePackages() throws CompilerChainException { |
| List<org.eclipse.ocl.pivot.@NonNull Package> rootTracePackages = null; |
| for (@NonNull EObject eObject : qvtrResource.getContents()) { |
| if (eObject instanceof RelationModel) { |
| List<org.eclipse.ocl.pivot.@NonNull Package> tracePackages = transformToTracePackageHierarchy(QVTrelationUtil.getOwnedPackages((RelationModel)eObject)); |
| if (tracePackages != null) { |
| if (rootTracePackages == null) { |
| rootTracePackages = new ArrayList<>(); |
| } |
| rootTracePackages.addAll(tracePackages); |
| } |
| } |
| } |
| if (rootTracePackages != null) { |
| CompilerUtil.normalizeNameables(rootTracePackages); |
| } |
| } |
| |
| private @Nullable List<org.eclipse.ocl.pivot.@NonNull Package> transformToTracePackageHierarchy(@NonNull Iterable<org.eclipse.ocl.pivot.@NonNull Package> relationPackages) throws CompilerChainException { |
| List<org.eclipse.ocl.pivot.@NonNull Package> nestingTracePackages = null; |
| for (org.eclipse.ocl.pivot.@NonNull Package relationPackage : relationPackages) { |
| List<org.eclipse.ocl.pivot.@NonNull Package> nestedTracePackages = null; |
| for (org.eclipse.ocl.pivot.@NonNull Class relationClass : QVTrelationUtil.getOwnedClasses(relationPackage)) { |
| if (relationClass instanceof RelationalTransformation) { |
| relationalTransformation2TracePackage = new RelationalTransformation2TracePackage(this, (RelationalTransformation)relationClass); |
| org.eclipse.ocl.pivot.Package nestedTracePackage = relationalTransformation2TracePackage.transform(); |
| txTracePackages.add(nestedTracePackage); |
| if (nestedTracePackages == null) { |
| nestedTracePackages = new ArrayList<>(); |
| } |
| nestedTracePackages.add(nestedTracePackage); |
| } |
| } |
| List<org.eclipse.ocl.pivot.@NonNull Package> nestedTracePackages2 = transformToTracePackageHierarchy(QVTrelationUtil.Internal.getOwnedPackagesList(relationPackage)); |
| if (nestedTracePackages2 != null) { |
| if (nestedTracePackages == null) { |
| nestedTracePackages = new ArrayList<>(); |
| } |
| nestedTracePackages.addAll(nestedTracePackages2); |
| } |
| if (nestedTracePackages != null) { |
| CompilerUtil.normalizeNameables(nestedTracePackages); |
| // String uri = relationPackage.getURI(); // FIXME replicate tx package hierarchy |
| // if (uri == null) { |
| // StringBuilder s = new StringBuilder(); |
| // getURI(relationPackage, s); |
| // uri = s.toString(); |
| // } |
| // org.eclipse.ocl.pivot.Package nestingTracePackage = helper.createPackage(ClassUtil.nonNull(relationPackage.getName()), relationPackage.getNsPrefix(), uri); |
| // nestingTracePackage.getOwnedPackages().addAll(nestedTracePackages); |
| if (nestingTracePackages == null) { |
| nestingTracePackages = new ArrayList<>(); |
| } |
| // nestingTracePackages.add(nestingTracePackage); |
| nestingTracePackages.addAll(nestedTracePackages); |
| } |
| } |
| return nestingTracePackages; |
| } |
| } |