/******************************************************************************* | |
* Copyright (c) 2004-2010 Gabor Bergmann 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: | |
* Gabor Bergmann - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.viatra2.gtasm.patternmatcher.incremental.simple; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.LinkedList; | |
import java.util.Map; | |
import java.util.Set; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.adapters.GTASMBuildable; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.RetePatternBuildException; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.Stub; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.PVariable; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicdeferred.BaseTypeSafePredicateCheck; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.FlatTuple; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.FunctionInvocation; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.GTPatternCall; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.ModelElementQuery; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Term; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.VariableReference; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPattern; | |
/** | |
* @author Bergmann Gábor | |
* | |
*/ | |
public class GTASMCheckConditionPConstraint<StubHandle> extends | |
BaseTypeSafePredicateCheck<GTPattern, StubHandle> { | |
private Term topTerm; | |
private GTPatternBodyToPSystem<StubHandle, ?> pGraph; | |
private GTASMBuildable<StubHandle, ?> gtBuildable; | |
/** | |
* @param pSystem | |
* @param affectedVariables | |
* @throws RetePatternBuildException | |
*/ | |
public GTASMCheckConditionPConstraint( | |
GTPatternBodyToPSystem<StubHandle, ?> pGraph, GTASMBuildable<StubHandle, ?> gtBuildable, | |
Term topTerm) throws RetePatternBuildException { | |
super(pGraph.pSystem, extractAffectedVariables(pGraph, topTerm)); | |
this.pGraph = pGraph; | |
this.topTerm = topTerm; | |
this.gtBuildable = gtBuildable; | |
} | |
/* (non-Javadoc) | |
* @see org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.DeferredPConstraint#doCheckOn(org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.Stub) | |
*/ | |
@Override | |
protected Stub<StubHandle> doCheckOn(Stub<StubHandle> stub) | |
throws RetePatternBuildException { | |
Map<String, Integer> variableIndices = new HashMap<String, Integer>(); | |
Map<String, String> variableEquivalence = new HashMap<String, String>(); | |
Set<String> variableNames = extractAffectedVariableNames(pGraph, topTerm); | |
for (String name : variableNames) { | |
PVariable pNode = pGraph.getPNode(name); | |
variableEquivalence.put(name, pNode.getName()); | |
variableIndices.put(pNode.getName(), stub.getVariablesIndex().get(pNode)); | |
} | |
return gtBuildable.buildGTASMTermChecker(topTerm, variableIndices, variableEquivalence, null, stub); | |
} | |
/* (non-Javadoc) | |
* @see org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.BasePConstraint#toStringRest() | |
*/ | |
@Override | |
protected String toStringRest() { | |
return new FlatTuple(new ArrayList<PVariable>(getAffectedVariables()).toArray()).toString() + "|=" + topTerm.toString(); | |
} | |
/* (non-Javadoc) | |
* @see org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.BasePConstraint#doReplaceVariable(org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.PVariable, org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.PVariable) | |
*/ | |
@Override | |
protected void doReplaceVariable(PVariable obsolete, PVariable replacement) {} | |
private static <StubHandle> Set<PVariable> extractAffectedVariables(GTPatternBodyToPSystem<StubHandle, ?> pGraph, Term topTerm) | |
throws RetePatternBuildException | |
{ | |
HashSet<PVariable> affected = new HashSet<PVariable>(); | |
Set<String> variableNames = extractAffectedVariableNames(pGraph, topTerm); | |
for (String name : variableNames) { | |
PVariable termNode = pGraph.getPNode(name); | |
affected.add(termNode); | |
} | |
return affected; | |
} | |
private static <StubHandle> Set<String> extractAffectedVariableNames(GTPatternBodyToPSystem<StubHandle, ?> pGraph, Term topTerm) | |
throws RetePatternBuildException | |
{ | |
HashSet<String> affected = new HashSet<String>(); | |
LinkedList<Term> termQueue = new LinkedList<Term>(); | |
termQueue.add(topTerm); | |
while (termQueue.size() > 0) { | |
Term term = termQueue.removeFirst(); | |
if (term instanceof VariableReference) { | |
VariableReference termVar = (VariableReference) term; | |
affected.add(termVar.getVariable().getName()); | |
} else if (term instanceof FunctionInvocation) { | |
FunctionInvocation fi = (FunctionInvocation) term; | |
for (Term paramTerm : fi.getActualParameters()) { | |
termQueue.addFirst(paramTerm); | |
} | |
} else if (term instanceof ModelElementQuery) { | |
ModelElementQuery meq = (ModelElementQuery) term; | |
termQueue.addFirst(meq.getArgument()); | |
} else if (term instanceof GTPatternCall) { | |
GTPatternCall pc = (GTPatternCall) term; | |
String[] errorData = {pc.getCalledPattern().getFqn(), pGraph.gtPattern.getFqn()}; | |
String message = | |
"Offending call to pattern {1} in enclosing pattern {2}. " + | |
"The incremental pattern matcher does not support GT Pattern calls in checks and expressions embedded into GT Patterns;" + | |
" please use a 'find' clause directly in the pattern body."; | |
//pGraph.builder.logger.error(message); | |
throw new RetePatternBuildException(message, errorData, pGraph.gtPattern); | |
// If we did want to handle this case | |
// for (Object o : pc.getActualParameters()) { | |
// termQueue.addFirst((Term) o); | |
// } | |
} | |
} | |
return affected; | |
} | |
} |