/******************************************************************************* * Copyright (c) 2008, 2014 Borland Software Corporation 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: * Borland Software Corporation - initial API and implementation * Christopher Gerking - bugs 302594, 310991 * Alex Paperno - bugs 416584 *******************************************************************************/ package org.eclipse.m2m.internal.qvt.oml.ast.env; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl; import org.eclipse.m2m.internal.qvt.oml.ast.parser.IntermediateClassFactory; import org.eclipse.m2m.internal.qvt.oml.ast.parser.QvtOperationalUtil; import org.eclipse.m2m.internal.qvt.oml.expressions.DirectionKind; import org.eclipse.m2m.internal.qvt.oml.expressions.ModelParameter; import org.eclipse.m2m.internal.qvt.oml.expressions.ModelType; import org.eclipse.m2m.internal.qvt.oml.expressions.Module; import org.eclipse.m2m.internal.qvt.oml.expressions.OperationalTransformation; import org.eclipse.ocl.ecore.EcoreFactory; import org.eclipse.ocl.expressions.Variable; import org.eclipse.ocl.lpg.ProblemHandler; import org.eclipse.ocl.options.ProblemOption; public class QvtOperationalModuleEnv extends QvtOperationalEnv { private Module myContextModule; private QvtOperationalFileEnv myFileParent; QvtOperationalModuleEnv(EPackage.Registry registry, Resource resource) { super(registry, resource != null ? resource : new EcoreResourceFactoryImpl().createResource(URI.createURI("qvto.env.module"))); //$NON-NLS-1$ // Eliminate parsing warning on "" occurrences, used in model types URIs, etc. // TODO - solve in QVT grammar setOption(ProblemOption.ELEMENT_NAME_QUOTE_ESCAPE, ProblemHandler.Severity.OK); setOption(ProblemOption.STRING_CASE_CONVERSION, ProblemHandler.Severity.OK); setOption(ProblemOption.STRING_SINGLE_QUOTE_ESCAPE, ProblemHandler.Severity.OK); setOption(ProblemOption.CONCEPTUAL_OPERATION_NAME, ProblemHandler.Severity.OK); } @Override protected void addedVariable(String name, Variable<EClassifier, EParameter> elem, boolean isExplicit) { super.addedVariable(name, elem, isExplicit); if(name != null && name.equals(THIS)) { if(myContextModule != null) { myContextModule.getOwnedVariable().add((org.eclipse.ocl.ecore.Variable)elem); } } } @Override protected void removedVariable(String name, Variable<EClassifier, EParameter> variable, boolean isExplicit) { super.removedVariable(name, variable, isExplicit); if(name != null && name.equals(THIS)) { if(myContextModule != null) { myContextModule.getOwnedVariable().remove((org.eclipse.ocl.ecore.Variable)variable); } } } public void setContextModule(Module module) { if (myContextModule != module) { deleteElement(THIS); myContextModule = null; if(module != null) { myContextModule = module; org.eclipse.ocl.ecore.Variable thisVar = EcoreFactory.eINSTANCE.createVariable(); thisVar.setName(THIS); thisVar.setType(module); addElement(THIS, thisVar, false); // confine module in resource getTypeResolver().getResource().getContents().add(module); } } if(module instanceof OperationalTransformation) { registerModelParameters((OperationalTransformation)module); } } public ModelParameter lookupModelParameter(String name, DirectionKind directionKind) { if(name == null) { return null; } List<ModelParameter> myModelParameters = getModelParameters(); for (ModelParameter modelParam : myModelParameters) { if (directionKind != DirectionKind.IN) { if (modelParam.getKind() == DirectionKind.IN) { continue; } } String nextParamName = modelParam.getName(); if (nextParamName != null) { if (nextParamName.equals(name)) { return modelParam; } } } return null; } /** * Get names of all available extents of given direction kind in this * environments. * * @param directionKind * filtering condition to be satisfied by returned extents or * <code>null</code> if all kinds are acceptable * @return list of corresponding model parameter names */ public List<String> getAllExtentNames(DirectionKind directionKind) { List<ModelParameter> modelParameters = getModelParameters(); List<String> result = new ArrayList<String>(modelParameters.size()); for (ModelParameter modelParam : modelParameters) { if (directionKind != DirectionKind.IN) { if (modelParam.getKind() == DirectionKind.IN) { continue; } } String nextParam = modelParam.getName(); if(nextParam != null && nextParam.length() > 0) { result.add(nextParam); } } return Collections.unmodifiableList(result); } public ModelParameter resolveModelParameter(EClassifier type, DirectionKind directionKind) { if (!isMayBelongToExtent(type)) { return null; } return findModelParameter(type, directionKind, getModelParameters()); } public ModelParameter resolveModelParameterDeprecated(EClassifier type, DirectionKind directionKind) { if (!isMayBelongToExtent(type)) { return null; } return findModelParameterDeprecated(type, directionKind, getModelParameters()); } static ModelParameter findModelParameter(EClassifier type, DirectionKind directionKind, Collection<ModelParameter> modelParameters) { EObject rootContainer = EcoreUtil.getRootContainer(type); // lookup explicit extent for (ModelParameter modelParam : modelParameters) { if (directionKind != DirectionKind.IN) { if (modelParam.getKind() == DirectionKind.IN) { continue; } } ModelType modelType = QvtOperationalUtil.getModelType(modelParam); if(modelType != null) { List<EPackage> metamodels = modelType.getMetamodel(); if (!metamodels.isEmpty() && rootContainer == metamodels.get(0)) { return modelParam; } } } // lookup implicit extent for (ModelParameter modelParam : modelParameters) { if (directionKind != DirectionKind.IN) { if (modelParam.getKind() == DirectionKind.IN) { continue; } } return modelParam; } return null; } static ModelParameter findModelParameterDeprecated(EClassifier type, DirectionKind directionKind, Collection<ModelParameter> modelParameters) { EObject rootContainer = EcoreUtil.getRootContainer(type); // lookup explicit extent for (ModelParameter modelParam : modelParameters) { if (directionKind == DirectionKind.OUT) { if (modelParam.getKind() == DirectionKind.IN) { continue; } } ModelType modelType = QvtOperationalUtil.getModelType(modelParam); if(modelType != null) { List<EPackage> metamodels = modelType.getMetamodel(); if (!metamodels.isEmpty() && rootContainer == metamodels.get(0)) { return modelParam; } } } // lookup implicit extent for (ModelParameter modelParam : modelParameters) { if (directionKind == DirectionKind.OUT) { if (modelParam.getKind() == DirectionKind.IN) { continue; } } return modelParam; } return null; } @Override public final Module getModuleContextType() { return myContextModule; } @Override public String toString() { if(myContextModule != null && myContextModule.getName() != null) { return "Module env: <" + myContextModule.getName() + ">@" + Integer.toHexString(System.identityHashCode(this)); //$NON-NLS-1$ //$NON-NLS-2$ } return super.toString(); } private List<ModelParameter> getModelParameters() { if(getModuleContextType() instanceof OperationalTransformation == false) { return Collections.emptyList(); } OperationalTransformation transformation = (OperationalTransformation) getModuleContextType(); List<ModelParameter> myModelParameters = transformation.getModelParameter(); return myModelParameters; } public boolean isMayBelongToExtent(EClassifier myType) { return myType != null && !IntermediateClassFactory.isIntermediateClass(myType) && getOCLStandardLibrary().getOclVoid() != myType && getOCLStandardLibrary().getOclInvalid() != myType; } private void registerModelParameters(OperationalTransformation module) { for (ModelParameter modelParam : module.getModelParameter()) { addElement(modelParam.getName(), modelParam, true); } } public QvtOperationalFileEnv getFileParent() { return myFileParent; } public void setFileParent(QvtOperationalFileEnv parentEnv) { myFileParent = parentEnv; } }