blob: 3b22f86353fcf959d5d3fb320221f9fc9172ce94 [file] [log] [blame]
/*******************************************************************************
* 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));
}
}