blob: a0ef9be9f32e4f966d9dd7c0da5543d1ba0ff1d3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004-2008 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.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
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.helpers.LayoutHelper;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.PSystem;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.PVariable;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicdeferred.Equality;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicdeferred.ExportedParameter;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicdeferred.Inequality;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicdeferred.NegativePatternCall;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicdeferred.PatternMatchCounter;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicenumerables.Containment;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicenumerables.Generalization;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicenumerables.Instantiation;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicenumerables.PositivePatternCall;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicenumerables.TypeBinary;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicenumerables.TypeTernary;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.basicenumerables.TypeUnary;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.matcher.IPatternMatcherContext.EdgeInterpretation;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.FlatTuple;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.Tuple;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Variable;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.ContainmentMode;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.ValueKind;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Constant;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.GTPatternCall;
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.ContainmentConstraint;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTMatchCounter;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPattern;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPatternBody;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.NonInjectivityConstraint;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.PatternVariable;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.PatternVariableAssignment;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.ElementReference;
import org.eclipse.viatra2.gtasmmodel.vpm.editmodel.Entity;
import org.eclipse.viatra2.gtasmmodel.vpm.editmodel.ModelElement;
import org.eclipse.viatra2.gtasmmodel.vpm.editmodel.Relation;
import org.eclipse.viatra2.gtasmmodel.vpm.editmodel.Relationship;
import org.eclipse.viatra2.gtasmmodel.vpm.editmodel.SupertypeOf;
import org.eclipse.viatra2.gtasmmodel.vpm.editmodel.TypeOf;
class GTPatternBodyToPSystem<StubHandle, Collector> {
protected GTPattern gtPattern;
protected GTPatternBody body;
protected SimpleReteBuilder<StubHandle, Collector> builder;
protected GTASMBuildable<StubHandle, Collector> buildable;
protected Entity graphEntity;
protected PSystem<GTPattern, StubHandle, Collector> pSystem;
// /**
// * pNodes are pattern variables, indexed by their names.
// *
// * VariableAssignments are already taken care of by variableEquivalence,
// * pNodes are equivalence groups.
// */
// protected Map<String, PVariable> pNodeByName = new HashMap<String, PVariable>();
// //protected Map<String, PatternEdge> pEdgeByName = new HashMap<String, PatternEdge>();
// /**
// * pEdges are the pattern constraints / hyperedges
// */
// protected Collection<PatternEdge> pEdges = new LinkedList<PatternEdge>();
// protected Map<PVariable, Collection<PatternEdge>> edgeList = new HashMap<PVariable, Collection<PatternEdge>>();
// // protected Set<PVariable> boundNodes = new HashSet<PVariable>();
//
// protected int nextVirtualNodeID = 0;
//
// /**
// * contains the equivalence classes induced by variableassignments the
// * factor set corresponds to the set of pNodes pNodes are named after
// * equivalence class representatives
// */
// protected UnionFind<String> variableEquivalence = new UnionFind<String>();
// /**
// * Valid in shareable patterns.
// *
// * For each pNode, this structure contains the set of pNodes against which
// * it is explicitly tested for inequality during the injectivity check phase.
// *
// * For virtual nodes, it should always contain null, reflecting that
// * virtual nodes are permitted to be equal with anything.
// *
// * For regular nodes, it symmetrically gathers explicity inequality assertions.
// */
// protected Map<PVariable, Set<PVariable>> explicitInequality = new HashMap<PVariable, Set<PVariable>>();
//
// /**
// * For each pNode, this structure contains the set of pNodes against which
// * it is NOT tested for inequality during the injectivity check phase.
// *
// * For injective (distinct) patterns, it overrides the default injectivity check.
// * For shareable patterns, it overrides explicit inequality checking.
// *
// * For virtual nodes, it should always contain null, reflecting that
// * virtual nodes are permitted to be equal with anything.
// *
// * For regular nodes, it always contains identity.
// * Furthermore, parameters of a positive pattern call of an injective pattern
// * MAY be included in each others permittableEquality sets to avoid double-checking,
// * but only under conditions that if it is safe.
// */
// protected Map<PVariable, Set<PVariable>> permittableEquality = new HashMap<PVariable, Set<PVariable>>();
/**
* contains the values of constant nodes
*/
protected Map<PVariable, Object> constantValues = new HashMap<PVariable, Object>();
/**
* contains the edit models in the pattern graph
*/
protected Map<PVariable, Set<ModelElement>> sourceEditModelElements = new HashMap<PVariable, Set<ModelElement>>();
/**
* @param gtPattern
* @param body
*/
public GTPatternBodyToPSystem(GTPattern gtPattern, GTPatternBody body,
SimpleReteBuilder<StubHandle, Collector> builder,
GTASMBuildable<StubHandle, Collector> buildable) {
super();
this.gtPattern = gtPattern;
this.body = body;
this.builder = builder;
this.buildable = buildable;
graphEntity = body.getPatternGraph();
}
public PSystem<GTPattern, StubHandle, Collector> toPSystem() throws RetePatternBuildException {
if (this.pSystem == null) {
this.pSystem = new PSystem<GTPattern, StubHandle, Collector>(builder.getContext(), buildable, gtPattern);
preProcessAssignments();
preProcessPVariables();
gatherInequalityAssertions();
gatherContainmentConstraints();
gatherRelationsAndContainments();
gatherRelationships();
gatherPositivePatternCalls();
gatherCheckExpressions();
// expressTypeChecks();
gatherNegativePatternCalls(); // should go last to have node.isTouched
// ready
//touchQuantifiedVariables();
// connectPEdges();
// countTypeRestrictions();
}
return pSystem;
}
public PVariable[] symbolicParameterArray() throws RetePatternBuildException {
toPSystem();
EList<PatternVariable> symParameters = gtPattern.getSymParameters();
int arity = symParameters.size();
PVariable[] result = new PVariable[arity];
for (int i=0; i<arity; ++i) result[i] = getPNode(symParameters.get(i));
return result;
}
protected PVariable getPNode(String name) {
return pSystem.getOrCreateVariableByName(name);
}
protected PVariable getPNode(Variable variable) {
return getPNode(variable.getName());
}
protected PVariable getPNode(ModelElement element) {
return getPNode(element.getName());
}
/**
* @return the graphEntity
*/
protected Entity getGraphEntity() {
return graphEntity;
}
/**
* @return true iff correspondence is new
*/
protected boolean traceVariableToEditModel(PVariable pVar, ModelElement editModelElement) {
Set<ModelElement> sources = sourceEditModelElements.get(pVar);
if (sources == null) {
sources = new HashSet<ModelElement>();
sourceEditModelElements.put(pVar, sources);
}
return sources.add(editModelElement);
}
protected Set<ModelElement> traceBackVariable(PVariable pVar) {
Set<ModelElement> sources = sourceEditModelElements.get(pVar);
if (sources == null) return Collections.emptySet();
else return sources;
}
protected void preProcessAssignments() {
for (Object o : body.getVariableAssignments()) {
PatternVariableAssignment assignment = (PatternVariableAssignment) o;
String lName = assignment.getLeftValue().getVariable().getName();
String rName = assignment.getRightValue().getVariable().getName();
new Equality<GTPattern, StubHandle>(pSystem, getPNode(lName), getPNode(rName));
}
LayoutHelper.unifyVariablesAlongEqualities(pSystem);
}
protected void preProcessPVariables()
throws RetePatternBuildException {
for (PatternVariable o : gtPattern.getSymParameters()) {
preProcessPVariableVariables(o);
new ExportedParameter<GTPattern, StubHandle>(pSystem, getPNode(o), o.getName());
}
for (PatternVariable o : body.getLocalVariables()) {
preProcessPVariableVariables(o);
}
preProcessPVariableEntities(graphEntity.getComponents());
}
protected void preProcessPVariableVariables(PatternVariable variable) {
// makes sure the PVariable is created
getPNode(variable);
/*
* Collection elements = variable.getElementInPattern(); boolean
* isRelation = (!elements.isEmpty() && elements.iterator().next()
* instanceof Relation);
*/
// String name = variable.getName();
//// if (pNode.getDirectUnifiedInto() == null) // only if this is the
//// // representative of an
//// // equivalence class
// // THERE WILL BE DUPLICATES BECAUSE OF UNIFICATION? BUT THIS PART IS IDEMPOTENT
// {
//
//// pNodeByName.put(name, pNode);
////
//// edgeList.put(pNode, new LinkedList<PatternEdge>());
//
// HashSet<PVariable> permitted = new HashSet<PVariable>();
// permitted.add(pNode);
// permittableEquality.put(pNode, permitted);
// explicitInequality.put(pNode, new HashSet<PVariable>());
// }
}
protected void preProcessPVariableEntities(Collection<Entity> entities)
throws RetePatternBuildException {
for (Entity entity : entities) {
String name = entity.getName();
PVariable pNode = getPNode(name);
traceVariableToEditModel(pNode, entity);
// new PatternEdge(this, entity);
preProcessPVariableEntities(entity.getComponents());
}
}
protected PVariable newConstant(Constant constant) throws RetePatternBuildException {
Object value;
if (constant.getKind().getValue() == ValueKind.MODELELEMENT) {
value = builder.context.resolveConstant(constant.getValue());
} else
value = constant.getValue();
return pSystem.newConstantVariable(value);
}
protected PVariable newConstant(ElementReference reference) throws RetePatternBuildException {
String fqn = ((Constant) reference.getArgument()).getValue();
return newConstant(fqn);
}
protected PVariable newConstant(String fqn) throws RetePatternBuildException {
Object value = builder.context.resolveConstant(fqn);
return pSystem.newConstantVariable(value);
}
// public PVariable substituteTerm(Term term)
// throws RetePatternBuildException {
// PVariable pNode = pSystem.newVirtualVariable();
// pEdges.add(new PatternEdge(this, term, pNode));
// return pNode;
// }
// protected void instantiationIndirect(PVariable type, PVariable instance) {
// PVariable virtual = pSystem.newVirtualVariable();
// new Generalization<GTPattern, StubHandle>(pSystem, type, virtual, true);
// new Instantiation<GTPattern, StubHandle>(pSystem, virtual, instance, false);
//// pEdges.add(new PatternEdge(this, type, virtual,
//// HyperEdgeClass.GENERALIZATION_TRANSITIVE));
//// pEdges.add(new PatternEdge(this, virtual, instance,
//// HyperEdgeClass.INSTANTIATION_DIRECT));
// }
// void touchQuantifiedVariables() {
// for (Object o : gtPattern.getSymParameters())
// getPNode((PatternVariable) o).isTouched = true;
// for (PatternEdge edge : pEdges)
// edge.touchQuantifiedNodes();
// }
//PRE: quantified nodes have been touched
// void connectPEdges() {
// for (PatternEdge edge : pEdges)
// edge.connectNodes();
// }
/**
* PRE: there are no virtual PVariables yet.
* @throws RetePatternBuildException
*/
protected void gatherInequalityAssertions() throws RetePatternBuildException {
if (gtPattern.isDistinctMatching()) {
/**
* For each pNode, this structure contains the set of pNodes against which
* it is NOT tested for inequality during the injectivity check phase.
*
* // For virtual nodes, it should always contain null, reflecting that
* // virtual nodes are permitted to be equal with anything.
*
* For regular nodes, it always contains identity.
* Furthermore, parameters of a positive pattern call of an injective pattern
* MAY be included in each others permittableEquality sets to avoid double-checking,
* but only if called pattern never asserts explicit equality between them.
* Finally, scalar values (results of match counting) are completely exempt.
*/
Map<PVariable, Set<PVariable>> permittableEquality = new HashMap<PVariable, Set<PVariable>>();
Set<PVariable> uniqueVariables = pSystem.getUniqueVariables();
for (PVariable pNode : uniqueVariables) {
permittableEquality.put(pNode, new HashSet<PVariable>(Collections.singleton(pNode)));
}
for (GTPatternCall call : body.getCalledPatterns()) {
GTMatchCounter matchCounter = call.getMatchCounter();
if (matchCounter == null && call.getCalledPattern().isDistinctMatching()) {
PVariable[] parameters = extractPatternCallParameterArray(call);
HashMap<PatternVariable, PVariable> symParamToPVariable = new HashMap<PatternVariable, PVariable>();
int k = 0;
for (PatternVariable variable : call.getCalledPattern().getSymParameters())
symParamToPVariable.put(variable, parameters[k++]);
Map<PVariable, Set<PVariable>> localPermittableEquality = new HashMap<PVariable, Set<PVariable>>();
for (PVariable pNode : parameters) {
localPermittableEquality.put(pNode, new HashSet<PVariable>(Arrays.asList(parameters)));
}
for (GTPatternBody body: call.getCalledPattern().getPatternBodies()) {
for (PatternVariableAssignment varAss: body.getVariableAssignments()) {
PVariable left = symParamToPVariable.get(varAss.getLeftValue().getVariable());
PVariable right = symParamToPVariable.get(varAss.getRightValue().getVariable());
if (left != null && right != null) {
localPermittableEquality.get(left).remove(right);
localPermittableEquality.get(right).remove(left);
}
}
}
for (PVariable pNode : parameters) {
permittableEquality.get(pNode).addAll(localPermittableEquality.get(pNode));
}
}
if (matchCounter != null) {
PVariable resultVar = getPNode(matchCounter.getVariableReference().getVariable());
permittableEquality.get(resultVar).addAll(uniqueVariables);
for (PVariable pNode : uniqueVariables) permittableEquality.get(pNode).add(resultVar);
}
}
for (PVariable pNode1 : uniqueVariables) if (!pNode1.isVirtual()) {
for (PVariable pNode2 : uniqueVariables) {
if (
!pNode2.isVirtual() &&
!permittableEquality.get(pNode1).contains(pNode2) &&
pNode1.getName().compareTo(pNode2.getName()) < 0 // avoid asserting symmetric inequalities
) new Inequality<GTPattern, StubHandle>(pSystem, pNode1, pNode2, true); // WEAK
}
}
}
// else // practically in case of shareable patterns
for(Object o: body.getNonInjectivityConstraints()) {
NonInjectivityConstraint nic = (NonInjectivityConstraint)o;
PVariable left = getPNode(nic.getLeftValue().getVariable());
PVariable right = getPNode(nic.getRightValue().getVariable());
new Inequality<GTPattern, StubHandle>(pSystem, left, right); // STRONG
}
}
protected void gatherRelationsAndContainments() {
// using queue to protect against concurrentModificationException for created virtual nodes +
// Relations can be added back after being gathered
LinkedList<PVariable> nodeQueue = new LinkedList<PVariable>(pSystem.getUniqueVariables());
//Set<PVariable> processed = new HashSet<PVariable>();
for (Object rel : body.getDanglingRelations()) // dangling relations cannot be collected otherwise
gatherRelation((Relation) rel, nodeQueue);
while (!nodeQueue.isEmpty()) {
PVariable pNode = nodeQueue.removeFirst();
//if (!processed.add(pNode)) continue; // skip if already processed
for (ModelElement source : traceBackVariable(pNode)) {
for (Object o : source.getRelationsFrom()) {
Relation rel = (Relation) o;
gatherRelation(rel, nodeQueue);
}
for (Object o : source.getRelationsTo()) {
Relation rel = (Relation) o;
gatherRelation(rel, nodeQueue);
}
if (source instanceof Entity) {
Entity entity = (Entity) source;
for (Object o : entity.getComponents()) {
new Containment<GTPattern, StubHandle>(pSystem, pNode, getPNode((Entity) o), false);
}
}
}
}
}
// idempotent
protected void gatherRelation(Relation rel, Queue<PVariable> nodeQueue) {
PVariable pNode = getPNode(rel);
if (traceVariableToEditModel(pNode, rel)) {
// new PatternEdge(this, rel);
nodeQueue.add(pNode);
}
}
protected void gatherRelationships()
throws RetePatternBuildException {
// against concurrentModificationException for created virtual nodes
//Collection<PVariable> nodes = new ArrayList<PVariable>(pNodeByName.values());
Collection<Relationship> relationships = new LinkedHashSet<Relationship>(body.getDanglingRelationships());
try {
for (PVariable pNode : pSystem.getUniqueVariables()) {
for (ModelElement source : traceBackVariable(pNode)) {
List<String> typeNames = new ArrayList<String>();
for (Object o : source.getSubRelationships()) relationships.add((Relationship) o);
for (Object o : source.getSuperRelationships()) {
Relationship rship = (Relationship) o;
if (rship instanceof TypeOf
&& rship.getSupplier()!=null
&& rship.getSupplier().getRealElement() != null
&& !rship.getSupplier().getRealElement().equals(""))
{
//String supplierName = rship.getSupplier().getName(); // LOL what a coincidence
String supplierName = rship.getSupplier().getRealElement();
typeNames.add(supplierName);
}
else relationships.add(rship);
}
if (typeNames.isEmpty()) typeNames.add(null); // default entity / relation global supertype
expressTypesOnPNode(pNode, source, typeNames);
}
}
for (Relationship rship : relationships) gatherRelationship(rship);
} catch (RetePatternBuildException e) {
e.setPatternDescription(gtPattern);
throw e;
}
}
protected void expressTypesOnPNode(PVariable pNode, ModelElement source,
List<String> typeNames) throws RetePatternBuildException {
if (source instanceof Relation) {
Relation relation = (Relation) source;
PVariable fromPNode = getPNode(relation.getFromStr());
PVariable toPNode = getPNode(relation.getToStr());
if (builder.context.edgeInterpretation() == EdgeInterpretation.TERNARY) {
for (String supplierName : typeNames) {
Object typeObject = supplierName == null ? null : builder.context.retrieveTernaryEdgeType(supplierName);
new TypeTernary<GTPattern, StubHandle>(pSystem, builder.getContext(), pNode, fromPNode, toPNode, typeObject);
}
} else {
for (String supplierName : typeNames) {
Object typeObject = supplierName == null ? null : builder.context.retrieveBinaryEdgeType(supplierName);
new TypeBinary<GTPattern, StubHandle>(pSystem, builder.getContext(), fromPNode, toPNode, typeObject);
}
}
} else { // source instanceof Entity
for (String supplierName : typeNames) {
Object typeObject = supplierName == null ? null : builder.context.retrieveUnaryType(supplierName);
new TypeUnary<GTPattern, StubHandle>(pSystem, pNode, typeObject);
}
}
}
// not idempotent, unique invocation required
protected void gatherRelationship(Relationship rship) throws RetePatternBuildException {
String clientName = rship.getClientStr();
PVariable clientNode = getPNode(clientName);
if (clientNode == null) clientNode = newConstant(clientName);
String supplierName = rship.getSupplierStr();
PVariable supplierNode = getPNode(supplierName);
if (supplierNode == null) {
//if (rship instanceof TypeOf)
supplierNode = newConstant(supplierName);
}
// HyperEdgeClass edgeClass;
if (rship instanceof TypeOf) {
// instantiationIndirect(supplierNode, clientNode);
new Instantiation<GTPattern, StubHandle>(pSystem, supplierNode, clientNode, true);
} else if (rship instanceof SupertypeOf) {
new Generalization<GTPattern, StubHandle>(pSystem, supplierNode, clientNode, true);
} else {
String[] args = {rship.eClass().getName(), supplierName, clientName, gtPattern.getFqn()};
String msg = "Unsupported VPM Relationship type: {1} encountered between {2} and {3} in pattern {4}";
throw new RetePatternBuildException(msg, args, gtPattern);
}
}
// /**
// * Implies that relation type typeObj and all supertypes are implicitly checked for the owner pNode of impliedTypes
// * @param typeObj
// * @param impliedTypes
// */
// private void implyTypes(Object typeObj, Set<Object> impliedTypes) {
// if (Options.calcImpliedTypes && typeObj!=null && impliedTypes.add(typeObj)) {
// for (Object superType: builder.context.enumerateDirectSupertypes(typeObj)) {
// implyTypes(superType, impliedTypes);
// }
// }
// }
// /**
// * Implies that relation type typeObj and all supertypes are implicitly checked for the owner pNode of impliedTypes
// * @param typeObj
// * @param impliedTypes
// */
// private void implyRelationTypes(Object typeObj, Set<Object> impliedTypes) {
// if (impliedTypes.add(typeObj)) {
// for (Object superType: builder.context.enumerateDirectRelationSupertypes(typeObj)) {
// implyRelationTypes(superType, impliedTypes);
// }
// }
// }
// /**
// * Implies that reference type typeObj and all supertypes are implicitly checked for the owner pNode of impliedTypes
// * @param typeObj
// * @param impliedTypes
// */
// private void implyReferenceTypes(Object typeObj, Set<Object> impliedTypes) {
// if (impliedTypes.add(typeObj)) {
// for (Object superType: builder.context.enumerateDirectReferenceSupertypes(typeObj)) {
// implyReferenceTypes(superType, impliedTypes);
// }
// }
// }
// protected void expressTypeChecks() {
// for (PVariable pNode : pSystem.getUniqueVariables()) {
// for (Object assertedType: pNode.assertedTypes) {
// if (pNode.source instanceof Relation)
// pEdges.add(new PatternEdge(this, (Relation) pNode.source, assertedType));
// // entity optimization by implied types
// else if (assertedType==null && pNode.impliedTypes.isEmpty() ||
// assertedType!=null && !pNode.impliedTypes.contains(assertedType))
// pEdges.add(new PatternEdge(this, (Entity) pNode.source, assertedType));
// else {
// // Object o = 2*15; // No need to assert type, already implied!
// }
// }
// }
// }
protected void gatherContainmentConstraints()
throws RetePatternBuildException
{
for (Object o : body.getContainmentConstraints()) {
ContainmentConstraint cc = (ContainmentConstraint) o;
PVariable child = getPNode(cc.getVariable());
boolean transitive = cc.getMode().equals(ContainmentMode.BELOW_LITERAL);
// HyperEdgeClass relationshipClass = transitive ? HyperEdgeClass.CONTAINMENT_TRANSITIVE
// : HyperEdgeClass.CONTAINMENT_DIRECT;
PVariable parent;
if (cc.getParent() instanceof VariableReference) {
VariableReference parentVar = (VariableReference) cc.getParent();
parent = getPNode(parentVar.getVariable());
} else if (cc.getParent() instanceof Constant) {
parent = newConstant((Constant) cc.getParent());
} else if (cc.getParent() instanceof ElementReference) {
parent = newConstant((ElementReference) cc.getParent());
} else {
// parent = substituteTerm(cc.getParent());
throw new RetePatternBuildException(
"Incremental matcher incompatible with containment parent {1} of {2}.",
new String[]{cc.getParent().toString(), child.toString()}, gtPattern);
// // ???
// hu.bme.mit.viatra.gtasmmodel.gtasm.metamodel.modelmanagement
// .queryFunctions.impl.ElementReferenceImpl
//
// builder.logger.warning(
// "ContainmentConstraint parent must be a variable or constant or element reference instead of "
// + cc.getParent().toString() );
// //throw new RetePatternBuildException();
}
new Containment<GTPattern, StubHandle>(pSystem, parent, child, transitive);
}
}
protected void gatherPositivePatternCalls() throws RetePatternBuildException {
for (Object o : body.getCalledPatterns()) {
GTPatternCall call = (GTPatternCall) o;
GTPattern calledPattern = call.getCalledPattern();
Tuple parameters = extractPatternCallParameterTuple(call);
GTMatchCounter matchCounter = call.getMatchCounter();
if (matchCounter == null) {
new PositivePatternCall<GTPattern, StubHandle>(pSystem, parameters, calledPattern);
} else {
PVariable resultVariable = getPNode(matchCounter.getVariableReference().getVariable());
new PatternMatchCounter<GTPattern, StubHandle>(pSystem, parameters, calledPattern, resultVariable);
}
}
}
protected void gatherNegativePatternCalls() throws RetePatternBuildException {
for (Object o : body.getNegativePatterns()) {
GTPatternCall call = (GTPatternCall) o;
GTPattern calledPattern = call.getCalledPattern();
Tuple parameters = extractPatternCallParameterTuple(call);
new NegativePatternCall<GTPattern, StubHandle>(pSystem, parameters, calledPattern);
}
}
/**
* @param call
* @return
* @throws RetePatternBuildException
*/
protected Tuple extractPatternCallParameterTuple(GTPatternCall call)
throws RetePatternBuildException {
PVariable[] nodes = extractPatternCallParameterArray(call);
Tuple parameters = new FlatTuple(nodes);
return parameters;
}
/**
* @param call
* @return
* @throws RetePatternBuildException
*/
protected PVariable[] extractPatternCallParameterArray(GTPatternCall call)
throws RetePatternBuildException {
int paramNum = call.getActualParameters().size();
PVariable[] nodes = new PVariable[paramNum];
for (int i = 0; i < paramNum; ++i) {
Object actualParam = call.getActualParameters().get(i);
if (actualParam instanceof VariableReference) {
VariableReference paramVar = (VariableReference) actualParam;
PVariable paramNode = getPNode(paramVar.getVariable());
nodes[i] = paramNode;
} else if (actualParam instanceof Constant) {
Constant constant = (Constant) actualParam;
PVariable paramNode = newConstant(constant);
nodes[i] = paramNode;
} else if (actualParam instanceof ElementReference) {
ElementReference reference = (ElementReference) actualParam;
PVariable paramNode = newConstant(reference);
nodes[i] = paramNode;
} else {
throw new RetePatternBuildException(
"Incremental matcher incompatible with parameter {3} of the pattern call of {2}: unsupported expression term {1}.",
new String[]{actualParam.toString(), call.getCalledPattern().getFqn(), Integer.toString(i)}, gtPattern);
// Term term = (Term) actualParam;
// PVariable paramNode = substituteTerm(term);
//
// nodes[i] = paramNode;
}
}
return nodes;
}
protected void gatherCheckExpressions()
throws RetePatternBuildException {
for (Object o : body.getCheckExpressions()) {
final Term topTerm = (Term) o;
new GTASMCheckConditionPConstraint<StubHandle>(this, buildable, topTerm);
}
}
// public void countTypeRestrictions() {
// for (PatternEdge e: pEdges)
// for (int index : e.conveysTypeInformationIndices()) {
// PVariableBase node = e.nodes.get(index);
// node.lingeringTypeInfoCounter++;
// for (PatternEdge f: edgeList.get(node))
// f.totalLingeringTypeInfoCounter++;
// }
//
// }
// protected void addEdge(PatternEdge edge)
// {
// if (edge.relMe!=null)
// {
// String name = edge.relMe.getName();
// PVariable pNode = pNodeByName.get(name);
// if (pNode != null)
// {
// //pNodeByName.remove(name);
// edgeList.remove(pNode);
// pEdgeByName.put(name, edge);
// }
// }
// }
}