| /******************************************************************************* |
| * Copyright (c) 2008, 2015 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 |
| *******************************************************************************/ |
| package org.eclipse.m2m.internal.qvt.oml.evaluator.iterators; |
| |
| import java.util.Collection; |
| import java.util.List; |
| |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EParameter; |
| import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEvaluationEnv; |
| import org.eclipse.m2m.internal.qvt.oml.ast.parser.QvtOperationalUtil; |
| import org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.BreakingResult; |
| import org.eclipse.ocl.EvaluationEnvironment; |
| import org.eclipse.ocl.EvaluationVisitor; |
| import org.eclipse.ocl.expressions.OCLExpression; |
| import org.eclipse.ocl.expressions.Variable; |
| import org.eclipse.ocl.types.InvalidType; |
| import org.eclipse.ocl.types.VoidType; |
| |
| /** |
| * @author aigdalov |
| * Created on Sep 25, 2008 |
| */ |
| public abstract class QvtImperativeIteratorTemplate<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> |
| extends QvtIterationTemplate<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> { |
| |
| protected QvtImperativeIteratorTemplate(EvaluationVisitor<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> v) { |
| super(v); |
| } |
| |
| // override this method for different iterator behaviors |
| protected abstract Object evaluateResult(List<Variable<C, PM>> iterators, String resultName, OCLExpression<EClassifier> conditionExp, Object bodyVal, boolean isOne); |
| |
| @Override |
| protected Object evaluateResultTemplate(List<Variable<C, PM>> iterators, |
| Variable<EClassifier, EParameter> target, |
| String resultName, OCLExpression<C> condition, |
| OCLExpression<C> body, boolean isOne) { |
| // evaluate the body of the expression in this environment |
| Object bodyVal = null; |
| if (body != null) { |
| bodyVal = getEvaluationVisitor().visitExpression(body); |
| } |
| else if (iterators.size() == 1) { |
| bodyVal = getEvalEnvironment().getValueOf(iterators.get(0).getName()); |
| } |
| |
| if(bodyVal instanceof BreakingResult) { |
| // Control flow was broken (break, continue, return); propagate this. |
| return bodyVal; |
| } |
| |
| advanceTarget(target, bodyVal); |
| |
| // get the new result value |
| @SuppressWarnings("unchecked") |
| Object resultVal = evaluateResult(iterators, resultName, (OCLExpression<EClassifier>) condition, bodyVal, isOne); |
| return resultVal; |
| } |
| |
| protected Boolean isConditionOk(OCLExpression<EClassifier> conditionExp, Object bodyVal) { |
| // evaluate the condition of the expression in this environment |
| Object conditionVal = conditionExp.accept(getEvaluationVisitor()); |
| if (conditionVal instanceof Boolean) { |
| return (Boolean) conditionVal; |
| } else if (conditionVal instanceof EClassifier){ |
| QvtOperationalEvaluationEnv env = (QvtOperationalEvaluationEnv) getEvalEnvironment(); |
| return oclIsKindOf(bodyVal, (EClassifier) conditionVal, env); |
| } else { |
| setDone(true); |
| return null; |
| } |
| } |
| |
| |
| protected Object returnCheckedEvaluationResult(Object addedElement, boolean isOne, String resultName) { |
| // If the body result is invalid then the entire expression's value |
| // is invalid, because OCL does not permit OclInvalid in a collection |
| if (addedElement == getInvalid()) { |
| setDone(true); |
| return getInvalid(); |
| } |
| if (isOne) { |
| setDone(true); |
| return addedElement; |
| } |
| @SuppressWarnings("unchecked") |
| Collection<Object> resultingCollection = (Collection<Object>) getEvalEnvironment().getValueOf(resultName); |
| resultingCollection.add(addedElement); |
| return resultingCollection; |
| } |
| |
| |
| /* TODO Moved these bits from QvtOperationalUtil |
| * Why OCL iskindof, istypeof is not sufficient? |
| */ |
| private Boolean oclIsKindOf(Object value, EClassifier type, QvtOperationalEvaluationEnv env) { |
| // regardless of the source value, if the type is undefined, then so |
| // is oclIsTypeOf |
| if (type == null) { |
| return null; |
| } |
| |
| // OclVoid and Invalid conform to all classifiers but their instances |
| // aren't actually useful as any type but their own. So, check for |
| // exact type match in these cases |
| if (isUndefined(value)) { |
| return oclIsTypeOf(value, type); |
| } |
| |
| return Boolean.valueOf(env.isKindOf(value, type)); |
| } |
| |
| private boolean isUndefined(Object value) { |
| return QvtOperationalUtil.isUndefined(value, getEvalEnvironment()); |
| } |
| |
| private Boolean oclIsTypeOf(Object value, EClassifier type) { |
| // regardless of the source value, if the type is undefined, then so |
| // is oclIsTypeOf |
| if (type == null) { |
| return null; |
| } |
| |
| // the type of null is OclVoid |
| // FIXME - may change in OCL 3.0 |
| if (value == null) { |
| return Boolean.valueOf(type instanceof VoidType<?>); |
| } |
| |
| // the type of OclInvalid is Invalid |
| if (QvtOperationalUtil.isInvalid(value, getEvalEnvironment())) { |
| return Boolean.valueOf(type instanceof InvalidType<?>); |
| } |
| |
| // FIXME |
| @SuppressWarnings("unchecked") |
| EvaluationEnvironment<EClassifier, ?, ?, ?, ?> evalEnv = (EvaluationEnvironment<EClassifier, ?, ?, ?, ?>) getEvalEnvironment(); |
| return Boolean.valueOf(evalEnv.isTypeOf(value, type)); |
| } |
| } |