blob: 692c7e13e948d5add0cc7926dba8c323aa62b668 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2018 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.ocl.pivot.library;
import java.util.Iterator;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CallExp;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment;
import org.eclipse.ocl.pivot.evaluation.Evaluator;
import org.eclipse.ocl.pivot.evaluation.Executor;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.CollectionValue;
import org.eclipse.ocl.pivot.values.IterableValue;
/**
* AbstractEvaluatorIterationManager supervises a collection iteration evaluation for which the iteration context is
* maintained in the executor's evaluationEnvironment for access by the body expression evaluation.
*
* As soon as the API ripple is acceptable, this collection-only variant of AbstractEvaluatorIterableIterationManager
* should be replaced by the generic collection/map capability.
*/
public abstract class AbstractEvaluatorIterationManager extends AbstractIterationManager
{
protected static class ValueIterator
{
private final EvaluationEnvironment evaluationEnvironment;
private final @NonNull CollectionValue collectionValue;
private final @NonNull TypedElement variable;
private Iterator<? extends Object> javaIter;
private Object value; // 'null' is a valid value so 'this' is used as end of iteration
/** @deprecated use Executor */
@Deprecated
public ValueIterator(@NonNull Evaluator evaluator, @NonNull CollectionValue collectionValue, @NonNull TypedElement variable) {
this(ValueUtil.getExecutor(evaluator), collectionValue, variable);
}
/**
* @since 1.1
*/
public ValueIterator(@NonNull Executor executor, @NonNull CollectionValue collectionValue, @NonNull TypedElement variable) {
this.evaluationEnvironment = executor.getEvaluationEnvironment();
this.collectionValue = collectionValue;
this.variable = variable;
reset();
}
public @Nullable Object get() {
return value;
}
public boolean hasCurrent() {
return value != this;
}
public @Nullable Object next() {
if (!javaIter.hasNext()) {
value = this;
}
else {
value = javaIter.next();
evaluationEnvironment.replace(variable, value);
// System.out.println(name + " = " + value);
}
return value;
}
public Object reset() {
javaIter = collectionValue.iterator();
return next();
}
@Override
public String toString() {
return String.valueOf(variable) + " = " + (value != this ? String.valueOf(value) : "<<END>>");
}
}
/** @deprecated use Executor */
@Deprecated
protected static @NonNull ValueIterator @Nullable [] createIterators(@NonNull TypedElement @NonNull [] referredIterators, @NonNull Evaluator evaluator, @NonNull CollectionValue collectionValue) {
return createIterators(referredIterators, ValueUtil.getExecutor(evaluator), collectionValue);
}
/**
* @since 1.1
*/
protected static @NonNull ValueIterator @Nullable [] createIterators(@NonNull TypedElement @NonNull [] referredIterators, @NonNull Executor executor, @NonNull CollectionValue collectionValue) {
int iMax = referredIterators.length;
@NonNull ValueIterator @Nullable [] iterators = new @NonNull ValueIterator[iMax];
for (int i = 0; i < iMax; i++) {
TypedElement referredIterator = referredIterators[i];
ValueIterator valueIterator = new ValueIterator(executor, collectionValue, referredIterator);
if (!valueIterator.hasCurrent()) {
return null;
}
iterators[i] = valueIterator;
}
return iterators;
}
protected final @NonNull CollectionValue collectionValue;
/**
* @since 1.1
*/
protected final /*@NonNull*/ CallExp callExp; // Null at root or when calling context unknown
protected final @NonNull OCLExpression body;
protected final @Nullable TypedElement accumulatorVariable;
private @Nullable Object accumulatorValue;
/** deprecated supply a callExp */
@Deprecated
public AbstractEvaluatorIterationManager(@NonNull Evaluator evaluator, @NonNull OCLExpression body, @NonNull CollectionValue collectionValue,
@Nullable TypedElement accumulatorVariable, @Nullable Object accumulatorValue) {
this(ValueUtil.getExecutor(evaluator), null, body, collectionValue, accumulatorVariable, accumulatorValue);
}
/**
* @since 1.1
*/
protected AbstractEvaluatorIterationManager(@NonNull Executor executor, /*@NonNull*/ CallExp callExp, @NonNull OCLExpression body, @NonNull CollectionValue collectionValue,
@Nullable TypedElement accumulatorVariable, @Nullable Object accumulatorValue) {
super(executor);
this.collectionValue = collectionValue;
this.callExp = callExp;
this.body = body;
this.accumulatorVariable = accumulatorVariable;
this.accumulatorValue = accumulatorValue;
if (accumulatorVariable != null) {
getEvaluationEnvironment().add(accumulatorVariable, accumulatorValue);
}
this.executor.pushEvaluationEnvironment(body, (Object)callExp);
}
public AbstractEvaluatorIterationManager(@NonNull AbstractEvaluatorIterationManager iterationManager, @NonNull CollectionValue collectionValue) {
super(iterationManager.executor);
this.callExp = iterationManager.callExp;
this.body = iterationManager.body;
this.collectionValue = collectionValue;
this.accumulatorValue = iterationManager.accumulatorValue;
this.accumulatorVariable = iterationManager.accumulatorVariable;
this.executor.pushEvaluationEnvironment(body, (Object)callExp);
}
@Override
public void dispose() {
executor.popEvaluationEnvironment();
}
@Override
public @Nullable Object evaluateBody() {
return executor.evaluate(body);
}
@Override
public @Nullable Object getAccumulatorValue() {
return accumulatorValue;
}
public @NonNull CollectionValue getCollectionValue() {
return collectionValue;
}
public @NonNull EvaluationEnvironment getEvaluationEnvironment() {
return executor.getEvaluationEnvironment();
}
@Override
public @NonNull CollectionValue getSourceCollection() {
return collectionValue;
}
/**
* @since 1.6
*/
@Override
public @NonNull IterableValue getSourceIterable() {
return collectionValue;
}
@Override
public String toString() {
// return body.eContainer().toString();
return body.toString();
}
@Override
public @Nullable Object updateAccumulator(Object newValue) {
this.accumulatorValue = newValue;
TypedElement accumulatorVariable2 = accumulatorVariable;
if (accumulatorVariable2 != null) {
getEvaluationEnvironment().replace(accumulatorVariable2, accumulatorValue);
}
return null; // carry on
}
}