blob: 8119a575a24324a77337d6315726cc75405ca3f2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017, 2019 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink - Initial API and implementation
*******************************************************************************/
package org.eclipse.qvtd.umlx.umlx2qvtr;
import java.io.IOException;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.ExpressionInOCL;
import org.eclipse.ocl.pivot.InvalidType;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.internal.messages.PivotMessagesInternal;
import org.eclipse.ocl.pivot.internal.scoping.EnvironmentView;
import org.eclipse.ocl.pivot.internal.scoping.ScopeView;
import org.eclipse.ocl.pivot.resource.ASResource;
import org.eclipse.ocl.pivot.resource.CSResource;
import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
import org.eclipse.ocl.pivot.utilities.Nameable;
import org.eclipse.ocl.pivot.utilities.ParserException;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.ocl.pivot.utilities.StringUtil;
import org.eclipse.ocl.xtext.base.attributes.PivotableElementCSAttribution;
import org.eclipse.ocl.xtext.base.cs2as.CS2AS;
import org.eclipse.ocl.xtext.base.cs2as.CS2ASConversion;
import org.eclipse.ocl.xtext.base.utilities.AbstractExtendedParserContext;
import org.eclipse.ocl.xtext.base.utilities.BaseCSResource;
import org.eclipse.ocl.xtext.basecs.ElementCS;
import org.eclipse.ocl.xtext.essentialocl.cs2as.ImplicitSourceTypeIterator;
import org.eclipse.ocl.xtext.essentialoclcs.ContextCS;
import org.eclipse.ocl.xtext.essentialoclcs.EssentialOCLCSPackage;
import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil;
import org.eclipse.qvtd.pivot.qvtrelation.RelationalTransformation;
import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelationUtil;
import org.eclipse.qvtd.xtext.qvtrelation.cs2as.QVTrelationCS2AS;
import org.eclipse.qvtd.xtext.qvtrelation.cs2as.QVTrelationCSLeft2RightVisitor;
/**
* UMLXParserContext supervises parsing a textual OCL expression embedded within a UMLX model element
* to yield an OCL expression tree for use within a corresponding QVTr model.
*
* The standard Essential OCL expression parser is overridden to use the QVTr parser and so to support
* QVTr extensions such as RelationCallExp. THe QVTr parser is in turn overridden to support resolution of
* name lookups and iterator implicit sources within the embedding QVTr model.
*/
class UMLXParserContext extends AbstractExtendedParserContext
{
protected class ContextCSAttribution extends PivotableElementCSAttribution
{
@Override
public @Nullable ScopeView computeLookup(@NonNull EObject target, @NonNull EnvironmentView environmentView, @NonNull ScopeView scopeView) {
ScopeView computeLookup = super.computeLookup(target, environmentView, scopeView);
//
// Last, last alternative. If nothing found get the UMLXParserContext to help out.
//
if (!environmentView.hasFinalResult()) {// && ((computeLookup == null) || (computeLookup.getTarget() == null))) {
return UMLXParserContext.this.computeLookup(target, environmentView, scopeView);
}
return computeLookup;
}
}
protected class UMLXCS2AS extends QVTrelationCS2AS
{
protected UMLXCS2AS(@NonNull BaseCSResource csResource, @NonNull ASResource asResource) {
super(UMLXParserContext.this.environmentFactory, csResource, asResource);
}
@Override
protected @NonNull QVTrelationCSLeft2RightVisitor createLeft2RightVisitor(@NonNull CS2ASConversion converter) {
return new UMLXCSLeft2RightVisitor(converter);
}
}
protected class UMLXCSLeft2RightVisitor extends QVTrelationCSLeft2RightVisitor
{
protected UMLXCSLeft2RightVisitor(@NonNull CS2ASConversion context) {
super(context);
}
@Override
protected ImplicitSourceTypeIterator createImplicitSourceTypeIterator(@NonNull ElementCS csElement) {
return new ImplicitSourceTypeIterator(csElement)
{
@Override
protected boolean doNext(@NonNull ElementCS csParent, @NonNull ElementCS csChild) {
if (csParent instanceof ContextCS) {
setNext(contextVariable);
return DONE; // no more parents
}
else {
return super.doNext(csParent, csChild);
}
}
};
}
}
protected final @NonNull EObject contextElement;
protected final @NonNull VariableDeclaration contextVariable;
public UMLXParserContext(@NonNull EnvironmentFactory environmentFactory, @NonNull EObject contextElement) {
super(environmentFactory, null); //ClassUtil.nonNullEMF(URI.createURI(EcoreUtil.generateUUID() + ".qvtr")));
this.contextElement = contextElement;
RelationalTransformation transformation = QVTrelationUtil.getContainingTransformation(contextElement);
this.contextVariable = QVTbaseUtil.getContextVariable(environmentFactory.getStandardLibrary(), transformation);
addAttribution(EssentialOCLCSPackage.Literals.CONTEXT_CS, new ContextCSAttribution());
}
private @Nullable ScopeView computeLookup(@NonNull EObject target, @NonNull EnvironmentView environmentView, @NonNull ScopeView scopeView) {
EObject pivot = contextElement;
if ((pivot instanceof Element) && (pivot.eResource() != null) && !(pivot instanceof InvalidType)) {
environmentView.computeLookups((Element) pivot, null); //PivotUtil.getPivot(Element.class, scopeView.getChild());
}
if (!environmentView.hasFinalResult()) {
return scopeView.getParent();
}
return scopeView.getParent();
}
@Override
public @Nullable CS2AS createCS2AS(@NonNull BaseCSResource csResource, @NonNull ASResource asResource) {
return new UMLXCS2AS(csResource, asResource);
}
public @NonNull OCLExpression parseExpression(@NonNull EObject owner, @NonNull String expression) throws ParserException, IOException {
CSResource resource = createBaseResource(expression);
String childName = owner instanceof Nameable ? ((Nameable)owner).getName() : "<unknown>";
EObject eContainer = owner.eContainer();
String parentName = eContainer instanceof Nameable ? ((Nameable)eContainer).getName() : "<unknown>";
PivotUtil.checkResourceErrors(StringUtil.bind(PivotMessagesInternal.ValidationConstraintIsInvalid_ERROR_, parentName, childName, expression.trim()), resource);
ASResource asResource = resource.getASResource();
assert asResource.getContents().size() == 1;
ExpressionInOCL asExpression = (ExpressionInOCL) asResource.getContents().get(0);
return PivotUtil.getOwnedBody(asExpression);
}
}