| /******************************************************************************* |
| * 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;
|
| }
|
| }
|