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