blob: 8102b7aef90e7ed861763bd07b5392b6c5e2d7bc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009-2010, Akos horvath and Daniel Varro
* 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:
* Akos Horvath - initial API and implementation
*******************************************************************************/
package org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.viatra2.core.IEntity;
import org.eclipse.viatra2.core.IModelElement;
import org.eclipse.viatra2.core.IModelManager;
import org.eclipse.viatra2.gtasm.interpreter.exception.ViatraTransformationException;
import org.eclipse.viatra2.gtasm.patternmatcher.ExecutionMode;
import org.eclipse.viatra2.gtasm.patternmatcher.IMatching;
import org.eclipse.viatra2.gtasm.patternmatcher.ParameterMode;
import org.eclipse.viatra2.gtasm.patternmatcher.PatternCallSignature;
import org.eclipse.viatra2.gtasm.patternmatcher.Scope;
import org.eclipse.viatra2.gtasm.patternmatcher.exceptions.PatternMatcherCompileTimeException;
import org.eclipse.viatra2.gtasm.patternmatcher.exceptions.PatternMatcherRuntimeException;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.callgraph.FlattenedPattern;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.DummyOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.SearchPlanOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.term.ITermHandler;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.ContainmentMode;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPattern;
import org.eclipse.viatra2.logger.Logger;
public class HackedPatternMatcher extends PatternMatcher {
FlattenedPattern[] flattenedPatterns = null;
public HackedPatternMatcher(GTPattern pattern, Logger logger,
IModelManager manager, ITermHandler termHandler)
throws PatternMatcherCompileTimeException {
super(pattern, logger, manager, termHandler);
flattenedPatterns = root.getFlattenedPatterns();
}
@Override
//TODO: Can only be used when there is no Recursive call!!
public IMatching match(Object[] inputMapping,
PatternCallSignature[] signature) throws ViatraTransformationException {
for(FlattenedPattern pattern: flattenedPatterns){
IMatching frame = internalMatch(inputMapping, signature, pattern);
if(frame != null)
{// Checking IN/BELOW constraints on the result
//TODO: Can be possible that it does not fulfil the Containment Constraints on the input parameters --> Use with caution with containment constraints!
boolean constraintsFulfilled = true;
for (int i = 0; constraintsFulfilled && i < signature.length; i++)
{
if (signature[i].getParameterMode() == ParameterMode.OUTPUT) {
Scope s = signature[i].getParameterScope();
IEntity container = (IEntity) s.getParent();
Object obj = frame.lookup(i);
if (obj instanceof IModelElement) {
IModelElement me = (IModelElement) obj;
if (s.getContainmentMode() == ContainmentMode.IN) {
constraintsFulfilled = me.getNamespace().compareTo(container) == 0;
} else if (s.getContainmentMode() == ContainmentMode.BELOW) {
constraintsFulfilled = me.isBelowNamespace(container);
}
} else {
// TODO Akos Horvath: what happens, if a formal parameter is a String, integer and it has a container constraint?
}
}
}
if (constraintsFulfilled)
return frame;
}
}
return null;
}
//TODO: truehybrid approach does not work with the current version of the hackedpatternmacther-> do not know exactly why
// but does not generate the IncrementalRemote goal while it generates the incrementalpatternNode.
private IMatching internalMatch(Object[] inputMapping,
PatternCallSignature[] signature,
FlattenedPattern flattenedPattern) throws ViatraTransformationException {
for (int i = 0; i < signature.length; i++) {
if (signature[i].getExecutionMode() == ExecutionMode.MULTIPLE_RESULTS) {
logger.debug("The method match(Object[], PatternCallSignature[] has been invoked in MULTIPLE_RESULTS execution mode.");
return null;
}
}
Integer[] quantificationOrder = new Integer[signature.length];
for (int i = 0; i < quantificationOrder.length; i++) {
quantificationOrder[i] = i;
}
// Key generator preparation based on the variables with forall quantifier
if (signature.length != quantificationOrder.length) {
String[] context = {root.getPattern().getName()};
throw new PatternMatcherRuntimeException(
PatternMatcherErrorStrings.INTERNAL_QUANTIFICATION_AND_SIGNATURES_PARAMETER_MISMATCH
,context
,root.getPattern());
}
int multipleUpperBound = 0;
Vector<Integer> vector = new Vector<Integer>();
for (int i = 0; i < quantificationOrder.length; i++) {
Integer index = quantificationOrder[i];
if (index < signature.length) {
if (signature[index].getExecutionMode() == ExecutionMode.MULTIPLE_RESULTS) {
if (i <= multipleUpperBound) {
vector.add(index);
multipleUpperBound++;
} else {
String[] context = {root.getPattern().getName()};
throw new PatternMatcherRuntimeException(
PatternMatcherErrorStrings.INTERNAL_QUANTIFICATION_ORDER
,context
,root.getPattern());
}
}
} else {
String[] context = {root.getPattern().getName()};
throw new PatternMatcherRuntimeException(
PatternMatcherErrorStrings.INTERNAL_QUANTIFICATION_ORDER
,context
,root.getPattern());
}
}
final Integer[] keys = new Integer[vector.size()];
vector.toArray(keys);
/* IKeyGenerator<MatchingKey, MatchingFrame> resultKeyGenerator =
new IKeyGenerator<MatchingKey, MatchingFrame>() {
public MatchingKey calculateKey(MatchingFrame value) {
Object[] matchingKey = new Object[keys.length];
for (int i = 0; i < keys.length; i++) {
matchingKey[i] = value.getValue(keys[i]);
}
return new MatchingKey(matchingKey);
}
public int size() {
return keys.length;
}
};*/
// // Matching table initalization
MatchingFrame frame = new MatchingFrame(flattenedPattern);
// Initialization (IN/BELOW constraint processing)
final Boolean[] adornment = new Boolean[signature.length];
Vector<Object> vec = new Vector<Object>();
for (int i = 0; i < signature.length; i++) {
if (signature[i].getParameterMode() == ParameterMode.INPUT) {
adornment[i] = true;
vec.add(inputMapping[i]);
frame.setValue(i, inputMapping[i]);
} else {
adornment[i] = false;
}
}
int strongestConstraint = 0;
if (vec.size() == 0) {
int largestDistance = 0;
boolean hasInConstraint = false;
for (int i = 0; i < signature.length; i++) {
Scope s = signature[i].getParameterScope();
int distance = 0;
IEntity parent = (IEntity) s.getParent();
for (distance = 0; !parent.equals(manager.getRoot()); distance++) {
parent = parent.getParent();
}
if (s.getContainmentMode() == ContainmentMode.IN) {
if (hasInConstraint && distance > largestDistance) {
largestDistance = distance;
strongestConstraint = i;
} else if (!hasInConstraint) {
hasInConstraint = true;
largestDistance = distance;
strongestConstraint = i;
}
} else if (s.getContainmentMode() == ContainmentMode.BELOW) {
if (!hasInConstraint && distance > largestDistance) {
largestDistance = distance;
strongestConstraint = i;
}
}
}
adornment[strongestConstraint] = true;
}
SearchPlanOperation[] t = new SearchPlanOperation[1];
List<SearchPlanOperation> operations = flattenedPattern.generateSearchPlan(adornment, manager);
operations.add(new DummyOperation()); //some funky legacy code from Gergely Varro to be able to separate searchplan along recursive code
SearchPlan searchPlan = new SearchPlan(operations.toArray(t));
// no input parameter, have to create an iterator of possible choices
if (vec.size() == 0) {
Scope s = signature[strongestConstraint].getParameterScope();
IEntity parent = (IEntity) s.getParent();
Iterator<IModelElement> i = (s.getContainmentMode() == ContainmentMode.IN
? parent.getElementsInNamespace().iterator()
: parent.getAllElementsInNamespace().iterator());
for (; i.hasNext();) {
MatchingFrame framenoBound = new MatchingFrame(flattenedPattern);
framenoBound.setValue(strongestConstraint, i.next());
if(searchPlan.execute(framenoBound))
return framenoBound;
}
}
else //there is a bound input parameter*/
if(searchPlan.execute(frame))
return frame;
else
return null;
return null;
}
}