/******************************************************************************* * Copyright (c) 2012, 2015 Willink Transformations 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 - initial API and implementation *******************************************************************************/ package org.eclipse.ocl.pivot.internal.context; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.pivot.ExpressionInOCL; import org.eclipse.ocl.pivot.NamedElement; import org.eclipse.ocl.pivot.OCLExpression; import org.eclipse.ocl.pivot.Operation; import org.eclipse.ocl.pivot.Parameter; import org.eclipse.ocl.pivot.PivotFactory; import org.eclipse.ocl.pivot.Property; 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.utilities.AbstractConversion; import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal; import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal; import org.eclipse.ocl.pivot.utilities.ClassUtil; import org.eclipse.ocl.pivot.utilities.NameUtil; import org.eclipse.ocl.pivot.utilities.PivotUtil; /** * AbstractBase2ASConversion provides the Xtext independent support for Concrete Syntax * to Pivot conversion. */ public abstract class AbstractBase2ASConversion extends AbstractConversion implements Base2ASConversion { /** * Set of all expression nodes whose type involves an UnspecifiedType. These are * created during the left2right pass and are finally resolved to * minimize invalidity. */ private HashSet<TypedElement> underspecifiedTypedElements = null; protected AbstractBase2ASConversion(@NonNull EnvironmentFactoryInternal environmentFactory) { super(environmentFactory); } protected void addUnderspecifiedTypedElement(@NonNull TypedElement pivotElement) { if (underspecifiedTypedElements == null) { underspecifiedTypedElements = new HashSet<TypedElement>(); } underspecifiedTypedElements.add(pivotElement); } public void refreshName(@NonNull NamedElement pivotNamedElement, @Nullable String newName) { String oldName = pivotNamedElement.getName(); if ((newName != oldName) && ((newName == null) || !newName.equals(oldName))) { pivotNamedElement.setName(newName); } } public void refreshNsURI(org.eclipse.ocl.pivot.@NonNull Package pivotPackage, String newNsURI) { String oldNsURI = pivotPackage.getURI(); if ((newNsURI != oldNsURI) && ((newNsURI == null) || !newNsURI.equals(oldNsURI))) { pivotPackage.setURI(newNsURI); } } public void setBehavioralType(@NonNull TypedElement targetElement, @NonNull TypedElement sourceElement) { if (!sourceElement.eIsProxy()) { Type type = PivotUtilInternal.getBehavioralType(sourceElement); if ((type != null) && type.eIsProxy()) { type = null; } boolean isRequired = sourceElement.isIsRequired(); setType(targetElement, type, isRequired); } } @Override public void setContextVariable(@NonNull ExpressionInOCL pivotSpecification, @NonNull String selfVariableName, @Nullable Type contextType, @Nullable Type contextInstance) { Variable contextVariable = pivotSpecification.getOwnedContext(); if (contextVariable == null) { @NonNull Variable nonNullContextVariable = PivotFactory.eINSTANCE.createVariable(); contextVariable = nonNullContextVariable; pivotSpecification.setOwnedContext(contextVariable); } refreshName(contextVariable, selfVariableName); setType(contextVariable, contextType, contextVariable.isIsRequired(), contextInstance); } @Override public void setClassifierContext(@NonNull ExpressionInOCL pivotSpecification, @NonNull Type contextType) { Variable contextVariable = pivotSpecification.getOwnedContext(); if (contextVariable != null) { if (contextType.eIsProxy()) { setType(contextVariable, null, false); } else { setType(contextVariable, contextType, true); } } } public void setOperationContext(@NonNull ExpressionInOCL pivotSpecification, @NonNull Operation contextOperation, @Nullable String resultName) { Variable contextVariable = pivotSpecification.getOwnedContext(); // pivotSpecification.getParameterVariable().clear(); if ((contextVariable != null) && !contextOperation.eIsProxy()) { setType(contextVariable, contextOperation.getOwningClass(), true); setParameterVariables(pivotSpecification, ClassUtil.nonNullEMF(contextOperation.getOwnedParameters())); } if (resultName != null) { setResultVariable(pivotSpecification, contextOperation, resultName); } } @Override public void setParameterVariables(@NonNull ExpressionInOCL pivotSpecification, @NonNull List<Parameter> parameters) { List<Variable> oldVariables = new ArrayList<Variable>(pivotSpecification.getOwnedParameters()); List<Variable> newVariables = new ArrayList<Variable>(); for (Parameter parameter : parameters) { String name = parameter.getName(); Variable param = NameUtil.getNameable(oldVariables, name); if (param != null) { oldVariables.remove(param); } else { param = PivotFactory.eINSTANCE.createVariable(); param.setName(name); } setBehavioralType(param, parameter); param.setRepresentedParameter(parameter); newVariables.add(param); } refreshList(ClassUtil.nonNullModel(pivotSpecification.getOwnedParameters()), newVariables); } @Override public void setParameterVariables(@NonNull ExpressionInOCL pivotSpecification, @NonNull Map<String, Type> parameters) { List<Variable> oldVariables = new ArrayList<Variable>(pivotSpecification.getOwnedParameters()); List<Variable> newVariables = new ArrayList<Variable>(); for (String name : parameters.keySet()) { Type type = parameters.get(name); Variable param = NameUtil.getNameable(oldVariables, name); if (param != null) { oldVariables.remove(param); } else { param = PivotFactory.eINSTANCE.createVariable(); param.setName(name); } setType(param, type, param.isIsRequired()); // param.setRepresentedParameter(parameter); newVariables.add(param); } refreshList(ClassUtil.nonNullModel(pivotSpecification.getOwnedParameters()), newVariables); } public void setPropertyContext(@NonNull ExpressionInOCL pivotSpecification, @NonNull Property contextProperty) { Variable contextVariable = pivotSpecification.getOwnedContext(); if ((contextVariable != null) && !contextProperty.eIsProxy()) { setType(contextVariable, contextProperty.getOwningClass(), true); } } @Override public void setResultVariable(@NonNull ExpressionInOCL pivotSpecification, @NonNull Operation contextOperation, @NonNull String resultName) { Type returnType = contextOperation.getType(); if (returnType != null) { // FIXME BUG 385711 Use OclVoid rather than null Variable resultVariable = pivotSpecification.getOwnedResult(); if (resultVariable == null) { resultVariable = PivotFactory.eINSTANCE.createVariable(); } resultVariable.setName(resultName); setBehavioralType(resultVariable, contextOperation); pivotSpecification.setOwnedResult(resultVariable); } else { pivotSpecification.setOwnedResult(null); } } /** * Set the type and so potentially satisfy some TypeOfDependency. This method ensures that * type is not set to null. */ @Deprecated public void setType(@NonNull TypedElement pivotElement, Type type) { setType(pivotElement, type, pivotElement.isIsRequired()); } public void setType(@NonNull OCLExpression pivotElement, Type type, boolean isRequired, @Nullable Type typeValue) { setType(pivotElement, type, isRequired); Type primaryTypeValue = typeValue != null ? metamodelManager.getPrimaryType(typeValue) : null; if (primaryTypeValue != pivotElement.getTypeValue()) { pivotElement.setTypeValue(primaryTypeValue); } } public void setType(@NonNull VariableDeclaration pivotElement, Type type, boolean isRequired, @Nullable Type typeValue) { setType(pivotElement, type, isRequired); Type primaryTypeValue = typeValue != null ? metamodelManager.getPrimaryType(typeValue) : null; if (primaryTypeValue != pivotElement.getTypeValue()) { pivotElement.setTypeValue(primaryTypeValue); } } public void setType(@NonNull TypedElement pivotElement, Type type, boolean isRequired) { Type primaryType = type != null ? metamodelManager.getPrimaryType(type) : null; if (primaryType != pivotElement.getType()) { pivotElement.setType(primaryType); } boolean wasRequired = pivotElement.isIsRequired(); if (wasRequired != isRequired) { pivotElement.setIsRequired(isRequired); } if (primaryType != null) { PivotUtil.debugWellContainedness(primaryType); } } }