blob: 560d2b109637e86bca01ecccfe8fb53f4d537b34 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2018 The University of York.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Dimitrios Kolovos - initial API and implementation
* Sina Madani - refactoring, utility methods, short-circuiting
******************************************************************************/
package org.eclipse.epsilon.evl.execute.context;
import java.util.*;
import java.util.stream.Collectors;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.erl.execute.context.IErlContext;
import org.eclipse.epsilon.evl.IEvlModule;
import org.eclipse.epsilon.evl.dom.Constraint;
import org.eclipse.epsilon.evl.execute.UnsatisfiedConstraint;
import org.eclipse.epsilon.evl.trace.ConstraintTrace;
public interface IEvlContext extends IErlContext {
Set<UnsatisfiedConstraint> getUnsatisfiedConstraints();
ConstraintTrace getConstraintTrace();
/**
* @since 1.6
*/
public static final String
OPTIMIZE_CONSTRAINT_TRACE = "optimizeConstraintTrace",
SHORT_CIRCUIT = "shortCircuit";;
/**
* Return true if the constraint results cache is optimized. When optimized, constraint results
* will only be cached during satisfies operation executions, that is, results will only be
* cached if required. If false, constraint results will always be cached.
* <p>
* The default value is false;
* @return The value of the flag.
* @since 1.6
*/
boolean isOptimizeConstraintTrace();
/**
* Set the flag for using optimized contraint result caching.
* @see #isOptimizeConstraintTrace()
* @param use Set to true to use optimzied contraint caching.
* @since 1.6
*/
void setOptimizeConstraintTrace(boolean optimized);
/**
* Option allowing validation to terminate early when any invariant is unsatisfied.
*
* @return Whether validation will stop once an UnsatisfiedConstraint is found.
* @since 1.6
*/
boolean isShortCircuiting();
/**
* Sets whether short-circuited validation is enabled.
*
* @param shortCircuit The new value for the flag.
* @since 1.6
*/
void setShortCircuit(boolean shortCircuit);
/**
* Checks whether the condition for short-circuiting is met, either by previous invocation returning
* true or if there are unsatisfied constraints and the
* {@link #isShortCircuiting()} flag is enabled, or if the specified module element has been annotated
* with a termination criteria and an unsatisfied constraint containing the type is already present.
*
* @param Constraint The rule with the termination annotation.
* @return Whether termination should be suspended.
* @throws EolRuntimeException
* @throws IllegalArgumentException If the rule parameter is not an appropriate type.
* @since 1.6
*/
default boolean shouldShortCircuit(Constraint constraint) throws EolRuntimeException {
if (isShortCircuiting() && !getUnsatisfiedConstraints().isEmpty()) {
return true;
}
if (constraint.getBooleanAnnotationValue("terminate", this)) {
return getUnsatisfiedConstraints()
.stream()
.map(UnsatisfiedConstraint::getConstraint)
.filter(constraint::equals)
.findAny()
.isPresent();
}
return false;
}
/**
* @since 1.6
* @return
*/
default boolean hasFixes() {
return getUnsatisfiedConstraints()
.stream()
.map(UnsatisfiedConstraint::getFixes)
.anyMatch(fixes -> !fixes.isEmpty());
}
/**
* @return A mapping from a Constraint to all of its unsatisfied instances.
* @since 1.6
*/
default Map<Constraint, Set<Object>> sortUnsatisfiedConstraints() {
return getUnsatisfiedConstraints()
.stream()
.collect(Collectors.groupingBy(
UnsatisfiedConstraint::getConstraint,
LinkedHashMap::new,
Collectors.mapping(UnsatisfiedConstraint::getInstance, Collectors.toSet())
));
}
/**
* @return A sorted entry of Constraints with the number of unsatisfied instances, in descending order.
* @since 1.6
*/
default Map<Constraint, Integer> getUnsatisfiedConstraintsBySize() {
return sortUnsatisfiedConstraints()
.entrySet()
.stream()
.map(entry -> new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue().size()))
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.collect(Collectors.toMap(
Map.Entry::getKey, Map.Entry::getValue, (a, b) -> b, LinkedHashMap::new)
);
}
/**
*
* @return
* @since 1.6
*/
default Set<Constraint> getConstraintsDependedOn() {
return getModule().getConstraints()
.stream()
.filter(Constraint::isDependedOn)
.collect(Collectors.toSet());
}
/**
* Casts the IModule to IEvlModule
* @see org.eclipse.epsilon.eol.execute.context.IEolContext#getModule()
* @since 1.6
*/
@Override
default IEvlModule getModule() {
return (IEvlModule) ((IEolContext)this).getModule();
}
}