/** * */ package agg.xt_basis; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Vector; import agg.attribute.AttrContext; import agg.attribute.handler.AvailableHandlers; import agg.attribute.impl.CondMember; import agg.attribute.impl.CondTuple; import agg.attribute.impl.ValueMember; import agg.attribute.impl.ValueTuple; import agg.attribute.impl.VarMember; import agg.attribute.impl.VarTuple; import agg.ruleappl.ObjectFlow; import agg.util.Pair; /** * Construct a concurrent rule based on two source rules * and already computed dependency critical pair of these rules. * Additionally used, the inverse rule of rule1 * and two help isomorphisms: * isoLeft1: LHS of rule1 --> LHScopy which can be done by rule1.getLeft().isomorphicCopy(), * isoRight1: RHS of rule1 --> RHScopy which can be done by rule1.getRight().isomorphicCopy(). * * NOT implemented jet: Shift of General ACs from from rule1 and rule2 to the concurrent rule. * * @author olga * */ public class ConcurrentRule { //TODO shift of General ACs // embeddingLeft1: L1 -> Lcr protected OrdinaryMorphism embLr1ToLcr; // to compute // embeddingRight1: R1 -> Rcr protected OrdinaryMorphism embRr1ToRcr; // to compute // embeddingLeft2: L2 -> Lcr protected OrdinaryMorphism embLr2ToLcr; // to compute // embeddingRight2: R2 -> Rcr protected OrdinaryMorphism embRr2ToRcr; // to compute protected Object source1, source2; // given : Rule | ConcurrentRule protected int indx1=-1, indx2=-1; protected OrdinaryMorphism overlap1, overlap2; // given protected Object source1Concurrent, source2Concurrent; // given protected Rule concurrentRule; // to compute protected int depth; protected boolean enableEqualVariableNameOfAttrMapping; protected boolean disjoint; // protected final Hashtable<GraphObject, GraphObject> // reflectedObjectFlow = new Hashtable<GraphObject, GraphObject>(); // output -> input protected final Hashtable<GraphObject, GraphObject> reflectedObjectFlowOI = new Hashtable<GraphObject, GraphObject>(); // source output -> other input protected final Hashtable<GraphObject, GraphObject> reflectedObjectFlowIO = new Hashtable<GraphObject, GraphObject>(); // source input -> other output -> // (otherRule, ObjectFlow)| ObjectFlow: otherRule.RHS.GraphObject -> this.rule.LHS.GraphObject protected final Hashtable<Object, ObjectFlow> inputObjectFlow = new Hashtable<Object, ObjectFlow>(4); // (otherRule, ObjectFlow)| ObjectFlow: this.rule.RHS.GraphObject -> otherRule.LHS.GraphObject protected final Hashtable<Object, ObjectFlow> outputObjectFlow = new Hashtable<Object, ObjectFlow>(4); protected int sizeOfInputObjectFlow; protected boolean injective = true; private final List<OrdinaryMorphism> failedApplConds = new Vector<OrdinaryMorphism>(); public long freeM, usedM; /** * Construct a concurrent rule based on two source rules * and already computed dependency critical pair of these rules. * Additionally used, the inverse rule of rule1 * and two help isomorphisms: * isoLeft1: LHS of rule1 --> LHScopy of rule1 which can be done by rule1.getLeft().isomorphicCopy(), * isoLeft1: RHS of rule1 --> RHScopy of rule1 which can be done by rule1.getRight().isomorphicCopy(). * The target graph of the morphism isoLeft1 is the left graph of the inverse rule, * The target graph of the morphism isoRight1 is the right graph of the inverse rule, */ public ConcurrentRule( final Rule rule1, final Rule inverseRule1, final Rule rule2, final OrdinaryMorphism isoLeft1, final OrdinaryMorphism isoRight1, final OrdinaryMorphism overlapping1, final OrdinaryMorphism overlapping2) { this.injective = true; this.source1 = rule1; this.source2 = rule2; this.overlap1 = overlapping1; this.overlap2 = overlapping2; this.concurrentRule = makeRule(rule1, inverseRule1, rule2, isoLeft1, isoRight1, overlapping1, overlapping2); if (this.concurrentRule != null) { this.depth++; this.concurrentRule.notApplicable = this.concurrentRule.notApplicable || rule1.isNotApplicable() || rule2.isNotApplicable(); } } /** * Create disjoint concurrent (parallel) rule based on given rules. * @param rule1 * @param rule2 */ public ConcurrentRule(final Rule rule1, final Rule rule2) { this.injective = true; this.source1 = rule1; this.source2 = rule2; this.concurrentRule = makeRuleByDisjointUnion(rule1, rule2); if (this.concurrentRule != null) { this.depth++; this.concurrentRule.notApplicable = this.concurrentRule.notApplicable || rule1.isNotApplicable() || rule2.isNotApplicable(); } } public ConcurrentRule( final ConcurrentRule rule1, final Rule inverseRule1, final Rule rule2, final OrdinaryMorphism isoLeft1, final OrdinaryMorphism isoRight1, final OrdinaryMorphism overlapping1, final OrdinaryMorphism overlapping2) { this.injective = true; this.source1 = rule1.getRule(); this.source2 = rule2; this.source1Concurrent = rule1; this.overlap1 = overlapping1; this.overlap2 = overlapping2; this.concurrentRule = makeRule(rule1.getRule(), inverseRule1, rule2, isoLeft1, isoRight1, this.overlap1, this.overlap2); if (this.concurrentRule != null) { this.depth++; this.depth = this.depth + rule1.depth; this.concurrentRule.notApplicable = this.concurrentRule.notApplicable || rule1.getRule().isNotApplicable() || rule2.isNotApplicable(); } } /** * Make a concurrent rule by disjoint union of rule1 and rul2. * @param rule1 * @param rule2 */ public ConcurrentRule( final ConcurrentRule rule1, final Rule rule2) { this.injective = true; this.source1 = rule1.getRule(); this.source2 = rule2; this.source1Concurrent = rule1; this.concurrentRule = makeRuleByDisjointUnion(rule1.getRule(), rule2); if (this.concurrentRule != null) { this.depth++; this.depth = this.depth + rule1.depth; this.concurrentRule.notApplicable = this.concurrentRule.notApplicable || rule1.getRule().isNotApplicable() || rule2.isNotApplicable(); } } public ConcurrentRule( final Rule rule1, final ConcurrentRule rule2) { this.injective = true; this.source1 = rule1; this.source2 = rule2.getRule(); this.source2Concurrent = rule2; this.concurrentRule = makeRuleByDisjointUnion(rule1, rule2.getRule()); if (this.concurrentRule != null) { this.depth++; this.depth = this.depth + rule2.depth; this.concurrentRule.notApplicable = this.concurrentRule.notApplicable || rule2.getRule().isNotApplicable() || rule1.isNotApplicable(); } } /* private Hashtable<GraphObject, GraphObject> getReflectedObjectFlowToRule( final Rule r, final List<ObjectFlow> list) { Hashtable<GraphObject, GraphObject> objmap = new Hashtable<GraphObject, GraphObject>(); for (int i=0; i<list.size(); i++) { Hashtable<Object,Object> map = list.get(i).getMapping(); Enumeration<Object> objs1 = map.keys(); while (objs1.hasMoreElements()) { GraphObject obj1 = (GraphObject) objs1.nextElement(); GraphObject obj2 = (GraphObject) map.get(obj1); if (obj2.getContext() == r.getLeft()) { GraphObject out = this.getRightEmbedding(obj1); if (out != null) { objmap.put(out, obj2); } } } } return objmap; } */ /** * The given Rule <code>r</code> is a pre-rule of this rule * and the ObjectFlow list contains all its output-input relations.<br> * Collects all output-input relations * where the output is an object of <code>r.RHS</code> * and the input is an Object of <code>this.getRule().LHS</code>.<br> * * @param r * @param list * @return map of collected output-input object pairs */ public Hashtable<GraphObject, GraphObject> getReflectedInputObjectFlowFromRule( final Rule r, final List<ObjectFlow> list) { Hashtable<GraphObject, GraphObject> objmap = new Hashtable<GraphObject, GraphObject>(); for (int i=0; i<list.size(); i++) { Hashtable<Object,Object> map = list.get(i).getMapping(); Enumeration<Object> objs1 = map.keys(); while (objs1.hasMoreElements()) { GraphObject obj1 = (GraphObject) objs1.nextElement(); GraphObject obj2 = (GraphObject) map.get(obj1); // obj1.getContext().getName(); if (obj1.getContext() == r.getRight()) { // output of pre rule GraphObject in = this.getLeftEmbedding(obj2); // input for this rule if (in != null) { objmap.put(obj1, in); } } } } return objmap; } public Hashtable<GraphObject, GraphObject> getReflectedInputObjectFlowFromGraph( final Graph g, final List<ObjectFlow> list) { Hashtable<GraphObject, GraphObject> objmap = new Hashtable<GraphObject, GraphObject>(); for (int i=0; i<list.size(); i++) { Hashtable<Object,Object> map = list.get(i).getMapping(); Enumeration<Object> objs1 = map.keys(); while (objs1.hasMoreElements()) { GraphObject obj1 = (GraphObject) objs1.nextElement(); GraphObject obj2 = (GraphObject) map.get(obj1); // obj1.getContext().getName(); if (obj1.getContext() == g) { // output of graph GraphObject in = this.getLeftEmbedding(obj2); // input for this rule if (in != null) { objmap.put(obj1, in); } } } } return objmap; } public int getSizeOfReflectedInputObjectFlow() { return this.sizeOfInputObjectFlow; } public void setInjectiveMatchProperty(boolean b) { this.injective = b; } public boolean hasInjectiveMatchProperty() { return this.injective; } public Hashtable<GraphObject, GraphObject> applyReflectedObjectFlowToMatchMap( final Graph graph) { Hashtable<GraphObject, GraphObject> map = new Hashtable<GraphObject, GraphObject>(); Enumeration<GraphObject> keys = this.reflectedObjectFlowIO.keys(); while (keys.hasMoreElements()) { GraphObject input = keys.nextElement(); GraphObject output = this.reflectedObjectFlowIO.get(input); if (output.getContext() == graph) { GraphObject ownInput1 = this.embLr1ToLcr.getImage(input); if (ownInput1 != null) { map.put(ownInput1, output); } else { GraphObject ownInput2 = this.embLr2ToLcr.getImage(input); if (ownInput2 != null) { map.put(ownInput2, output); } else { // second source rule is ConcurrentRule if (this.source2Concurrent instanceof ConcurrentRule) { ownInput2 = ((ConcurrentRule) this.source2Concurrent).getFirstLeftEmbedding().getImage(input); if (ownInput2 != null) { map.put(ownInput2, output); } else { ownInput2 = ((ConcurrentRule) this.source2Concurrent).getSecondLeftEmbedding().getImage(input); if (ownInput2 != null) { map.put(ownInput2, output); } } } } } } else { //TODO // if (this.source1 instanceof Rule // && output.getContext() == ((Rule)this.source1).getRight()) { // if (((Rule)this.source1).getInverseImage(output).hasMoreElements()) { // GraphObject obj = ((Rule)this.source1).getInverseImage(output).nextElement(); // //TODO // } // } else if (this.source2 instanceof Rule // && output.getContext() == ((Rule)this.source2).getRight()) { // if (((Rule)this.source2).getInverseImage(output).hasMoreElements()) { // GraphObject obj = ((Rule)this.source2).getInverseImage(output).nextElement(); // //TODO // } // } } } return map; } public boolean reflectObjectFlow(final List<ObjectFlow> objFlowOfSource) { if (objFlowOfSource == null || objFlowOfSource.isEmpty()) { return true; } final Iterator<ObjectFlow> iterator = objFlowOfSource.iterator(); while (iterator.hasNext()) { ObjectFlow objFlow = iterator.next(); Hashtable<Object, Object> map = objFlow.getMapping(); Enumeration<Object> outputs = map.keys(); while (outputs.hasMoreElements()) { Object output = outputs.nextElement(); Object input = map.get(output); GraphObject input_cr = null; GraphObject output_cr = null; // if (this.source1Concurrent instanceof ConcurrentRule) { // //TODO ??? // } else if (this.source1 instanceof Rule) { input_cr = this.embLr1ToLcr.getImage((GraphObject) input); if (input_cr != null){ this.reflectedObjectFlowIO.put((GraphObject) input, (GraphObject) output); this.sizeOfInputObjectFlow++; } else { output_cr = this.embRr1ToRcr.getImage((GraphObject) output); if (output_cr != null) this.reflectedObjectFlowOI.put((GraphObject) output, (GraphObject)input); } } if (this.source2Concurrent instanceof ConcurrentRule) { input_cr = ((ConcurrentRule) this.source2Concurrent).getFirstLeftEmbedding().getImage((GraphObject) input); if (this.embLr2ToLcr.getImage(input_cr) != null) { this.reflectedObjectFlowIO.put(input_cr, (GraphObject) output); this.sizeOfInputObjectFlow++; } else { input_cr = ((ConcurrentRule) this.source2Concurrent).getSecondLeftEmbedding().getImage((GraphObject) input); if (this.embLr2ToLcr.getImage(input_cr) != null) { this.reflectedObjectFlowIO.put(input_cr, (GraphObject) output); this.sizeOfInputObjectFlow++; } } } else if (this.source2 instanceof Rule) { input_cr = this.embLr2ToLcr.getImage((GraphObject) input); if (input_cr != null){ if (((Rule)this.source1).getTarget().isElement((GraphObject) output) && this.embLr1ToLcr.getInverseImage(input_cr).hasMoreElements()) { } else { this.reflectedObjectFlowIO.put((GraphObject) input, (GraphObject) output); this.sizeOfInputObjectFlow++; } } else { output_cr = this.embRr2ToRcr.getImage((GraphObject) output); if (output_cr != null) this.reflectedObjectFlowOI.put((GraphObject) output, (GraphObject)input); } } } } return true; } /* private void connectOwnInputToOtherOutput(final Object input, final Object output) { this.reflectedObjectFlowIO.put((GraphObject) input, (GraphObject) output); } private GraphObject getKeyOfValue( final Hashtable<GraphObject, GraphObject> map, final GraphObject val) { final Enumeration<GraphObject> keys = map.keys(); while (keys.hasMoreElements()) { GraphObject key = keys.nextElement(); if (map.get(key) == val) return key; } return null; } */ public void setFirstSourceConcurrentRule(final ConcurrentRule cr) { this.source1Concurrent = cr; this.depth = this.depth + cr.depth; } public ConcurrentRule getFirstSourceConcurrentRule() { if (this.source1Concurrent instanceof ConcurrentRule) return (ConcurrentRule) this.source1Concurrent; return null; } public Rule getFirstSourceRule() { if (this.source1 instanceof Rule) return (Rule) this.source1; return null; } public void setIndexOfFirstSourceRule(int indx) { this.indx1 = indx; } public int getIndexOfFirstSourceRule() { return this.indx1; } public void setSecondSourceConcurrentRule(final ConcurrentRule cr) { this.source2Concurrent = cr; this.depth = this.depth + cr.depth; } public ConcurrentRule getSecondSourceConcurrentRule() { if (this.source2Concurrent instanceof ConcurrentRule) return (ConcurrentRule) this.source2Concurrent; return null; } public Rule getSecondSourceRule() { if (this.source2 instanceof Rule) return (Rule) this.source2; return null; } public void setIndexOfSecondSourceRule(int indx) { this.indx2 = indx; } public int getIndexOfSecondSourceRule() { return this.indx2; } public Rule getLastSecondSourceRule() { if (this.source2Concurrent != null) { ConcurrentRule cr = (ConcurrentRule) this.source2Concurrent; while (cr.getSecondSourceConcurrentRule() != null) { cr = cr.getSecondSourceConcurrentRule(); } return cr.getSecondSourceRule(); } return (Rule) this.source2; } public OrdinaryMorphism getSecondOverlappingOfDependencyPair() { return this.overlap2; } /** * Returns a list with overlapping objects of the second rule (LHS) */ public List<GraphObject> getOverlappingObjectsOfSecondRule() { if (this.overlap1 == null || this.overlap2 == null) return null; List<GraphObject> list = new Vector<GraphObject>(); Iterator<?> elems = this.overlap1.getTarget().getNodesSet().iterator(); while (elems.hasNext()) { GraphObject go = (GraphObject) elems.next(); if (this.overlap1.getInverseImage(go).hasMoreElements() && this.overlap2.getInverseImage(go).hasMoreElements()) { list.add(this.overlap2.getInverseImage(go).nextElement()); } } elems = this.overlap1.getTarget().getArcsSet().iterator(); while (elems.hasNext()) { GraphObject go = (GraphObject) elems.next(); if (this.overlap1.getInverseImage(go).hasMoreElements() && this.overlap2.getInverseImage(go).hasMoreElements()) { list.add(this.overlap2.getInverseImage(go).nextElement()); } } return list; } /** * Returns a list with overlapping objects of the first rule (RHS) */ public List<GraphObject> getOverlappingObjectsOfFirstRule() { if (this.overlap1 == null || this.overlap2 == null) return null; List<GraphObject> list = new Vector<GraphObject>(); Iterator<?> elems = this.overlap1.getTarget().getNodesSet().iterator(); while (elems.hasNext()) { GraphObject go = (GraphObject) elems.next(); if (this.overlap1.getInverseImage(go).hasMoreElements() && this.overlap2.getInverseImage(go).hasMoreElements()) { list.add(this.overlap1.getInverseImage(go).nextElement()); } } elems = this.overlap1.getTarget().getArcsSet().iterator(); while (elems.hasNext()) { GraphObject go = (GraphObject) elems.next(); if (this.overlap1.getInverseImage(go).hasMoreElements() && this.overlap2.getInverseImage(go).hasMoreElements()) { list.add(this.overlap1.getInverseImage(go).nextElement()); } } return list; } /** * Returns a map with overlapping pair (RHS1 object, LHS2 object) */ public Hashtable<GraphObject, GraphObject> getOverlappingObjects() { if (this.overlap1 == null || this.overlap2 == null) return null; Hashtable<GraphObject, GraphObject> map = new Hashtable<GraphObject,GraphObject>(); Iterator<?> elems = this.overlap1.getTarget().getNodesSet().iterator(); while (elems.hasNext()) { GraphObject go = (GraphObject) elems.next(); if (this.overlap1.getInverseImage(go).hasMoreElements() && this.overlap2.getInverseImage(go).hasMoreElements()) { map.put(this.overlap1.getInverseImage(go).nextElement(), this.overlap2.getInverseImage(go).nextElement()); } } elems = this.overlap1.getTarget().getArcsSet().iterator(); while (elems.hasNext()) { GraphObject go = (GraphObject) elems.next(); if (this.overlap1.getInverseImage(go).hasMoreElements() && this.overlap2.getInverseImage(go).hasMoreElements()) { map.put(this.overlap1.getInverseImage(go).nextElement(), this.overlap2.getInverseImage(go).nextElement()); } } return map; } public GraphObject getLeftEmbedding(final GraphObject obj) { GraphObject go = this.embLr1ToLcr.getImage(obj); if (go == null) { go = this.embLr2ToLcr.getImage(obj); if (go == null) { if (this.source2Concurrent != null) { GraphObject go1 = ((ConcurrentRule) this.source2Concurrent).getLeftEmbedding(obj); if (go1 != null) go = this.getLeftEmbedding(go1); } } } return go; } public GraphObject getRightEmbedding(final GraphObject obj) { GraphObject go = this.embRr1ToRcr.getImage(obj); if (go == null) { go = this.embRr2ToRcr.getImage(obj); if (go == null) { if (this.source2Concurrent != null) { GraphObject go1 = ((ConcurrentRule) this.source2Concurrent).getRightEmbedding(obj); if (go1 != null) go = this.getRightEmbedding(go1); } } } return go; } public OrdinaryMorphism getFirstLeftEmbedding() { return this.embLr1ToLcr; } public OrdinaryMorphism getSecondLeftEmbedding() { return this.embLr2ToLcr; } public OrdinaryMorphism getFirstRightEmbedding() { return this.embRr1ToRcr; } public OrdinaryMorphism getSecondRightEmbedding() { return this.embRr2ToRcr; } /** * Returns constructed concurrent rule. * @return concurrent rule */ public Rule getRule() { return this.concurrentRule; } public boolean isReadyToTransform() { if (this.concurrentRule != null) { boolean result = true; BaseFactory.theFactory().unsetAllTransientAttrValuesOfRule(this.concurrentRule); result = result && this.concurrentRule.isReadyToTransform(); return result; } return false; } public int getDepth() { return this.depth; } public void enableEqualVariableNameOfAttrMapping(boolean enable) { this.enableEqualVariableNameOfAttrMapping = enable; } /** * Forwards match mappings from the first plain source rule to the concurrent rule. * * @param map match mapping of the first source rule * @return true if all mappings forwarded successfully, otherwise false */ public boolean forwardMatchMappingOfFirstSourceRule( final Hashtable<GraphObject, GraphObject> map, final Graph g) { boolean result = false; Match m = BaseFactory.theFactory().createMatch(this.concurrentRule, g); if (m != null) { this.concurrentRule.setMatch(m); Enumeration<GraphObject> objs = map.keys(); while (objs.hasMoreElements()) { final GraphObject obj = objs.nextElement(); if (obj.isNode()) { final GraphObject img = map.get(obj); if (this.embLr1ToLcr != null && obj.getContext() == this.embLr1ToLcr.getSource()) { final GraphObject obj_cr = this.embLr1ToLcr.getImage(obj); if (obj_cr != null) { try { m.addMapping(obj_cr, img); result = true; } catch (BadMappingException ex) { return false; } } } } } objs = map.keys(); while (objs.hasMoreElements()) { final GraphObject obj = objs.nextElement(); if (obj.isArc()) { final GraphObject img = map.get(obj); if (this.embLr1ToLcr != null && obj.getContext() == this.embLr1ToLcr.getSource()) { final GraphObject obj_cr = this.embLr1ToLcr.getImage(obj); if (obj_cr != null) { try { m.addMapping(obj_cr, img); result = true; } catch (BadMappingException ex) { return false; } } } } } } return result; } /** * Constructs a concurrent rule based on given rules rule1, rule2. * This concurrent rule is like a parallel rule: * its LHS is the disjoint union of rule1.LHS and rule2.LHS, * its RHS is the disjoint union of rule1.RHS and rule2.RHS. * * @param rule1 the first source rule of concurrent rule * @param rule2 the second source rule of concurrent rule * * @return constructed concurrent rule */ private Rule makeRuleByDisjointUnion( final Rule rule1, final Rule rule2) { // System.out.println("ConcurrentRule.makeRuleByDisjointUnion "+rule1.getName()+" + "+rule2.getName()); this.failedApplConds.clear(); Rule cr = null; this.disjoint = true; // make left and right graphs OrdinaryMorphism lhs1ToLHS = rule1.getLeft().isomorphicCopy(); if (lhs1ToLHS == null) { return null; } OrdinaryMorphism rhs1ToRHS = rule1.getRight().isomorphicCopy(); if (rhs1ToRHS == null) { lhs1ToLHS.dispose(); lhs1ToLHS = null; return null; } OrdinaryMorphism lhs2ToLHS = null; try { lhs2ToLHS = BaseFactory.theFactory().extendGraphByGraph(lhs1ToLHS.getTarget(), rule2.getLeft()); // lhs1ToLHS.getTarget() == lhs2ToLHS.getTarget() } catch (Exception e) { lhs1ToLHS.dispose(); lhs1ToLHS = null; rhs1ToRHS.dispose(); rhs1ToRHS = null; return null; } if (lhs2ToLHS != null) { OrdinaryMorphism rhs2ToRHS = null; try { rhs2ToRHS = BaseFactory.theFactory().extendGraphByGraph(rhs1ToRHS.getTarget(), rule2.getRight()); // rhs1ToRHS.getTarget() == rhs2ToRHS.getTarget() } catch (Exception e) { lhs1ToLHS.dispose(); lhs1ToLHS = null; rhs1ToRHS.dispose(); rhs1ToRHS = null; return null; } if (rhs2ToRHS != null) { boolean ok = true; // get graphs final Graph lhs = lhs2ToLHS.getTarget(); final Graph rhs = rhs2ToRHS.getTarget(); // create morphism final OrdinaryMorphism morphCR = BaseFactory.theFactory().createMorphism(lhs, rhs); // add morphism mapping over rule1 // add morphism mapping over rule2 if (morphCR.completeDiagram(lhs1ToLHS, rule1, rhs1ToRHS) && morphCR.completeDiagram(lhs2ToLHS, rule2, rhs2ToRHS)) { // make concurrent rule cr = BaseFactory.theFactory().constructRuleFromMorph(morphCR); cr.setName(rule1.getName()+"+"+rule2.getName()); // store help data this.embLr1ToLcr = lhs1ToLHS; this.embRr1ToRcr = rhs1ToRHS; this.embLr2ToLcr = lhs2ToLHS; this.embRr2ToRcr = rhs2ToRHS; // handle PACs and NACs this.shiftCondsOfRuleOverEmbMorph(cr, rule1, this.embLr1ToLcr, true); this.shiftCondsOfRuleOverEmbMorph(cr, rule2, this.embLr2ToLcr, true); OrdinaryMorphism rhs1ToE = rule1.getRight().isomorphicCopy(); try { OrdinaryMorphism lhs2ToE = BaseFactory.theFactory().extendGraphByGraph( rhs1ToE.getTarget(), rule2.getLeft()); OrdinaryMorphism left = BaseFactory.theFactory().createMorphism(lhs, lhs2ToE.getTarget()); if (left.completeDiagram(lhs1ToLHS, rule1, rhs1ToE) && left.completeDiagram2(this.embLr2ToLcr, lhs2ToE)) { // left: L1+L2 -> R1+L2 this.shiftCondsOfRuleOverMorphAndLeft(cr, rule2, lhs2ToE, left, this.embLr2ToLcr, true); } else ok = false; } catch (Exception e) { ok = false; } if (ok) { OrdinaryMorphism rhs2ToE = rule2.getRight().isomorphicCopy(); try { OrdinaryMorphism lhs1ToE = BaseFactory.theFactory().extendGraphByGraph( rhs2ToE.getTarget(), rule1.getLeft()); OrdinaryMorphism left = BaseFactory.theFactory().createMorphism(lhs, lhs1ToE.getTarget()); if (left.completeDiagram(lhs2ToLHS, rule2, rhs2ToE) && left.completeDiagram2(this.embLr1ToLcr, lhs1ToE)) { // left: L1+L2 -> R2+L1 this.shiftCondsOfRuleOverMorphAndLeft(cr, rule1, lhs1ToE, left, this.embLr1ToLcr, true); } else ok = false; } catch (Exception e) { ok = false; } } removeIsomorphicMorph(cr.getNACsList()); removeIsomorphicMorph(cr.getPACsList()); // add attribute conditions addAttrConditionFromTo(rule1, cr); addAttrConditionFromTo(rule2, cr); addUndeclaredVariableOfExpression(cr); BaseFactory.theFactory().unsetAllTransientAttrValuesOfRule(cr); // test this.adjustUnsetAttrsAboveMorph(this.embLr1ToLcr); this.adjustUnsetAttrsAboveMorph(this.embLr2ToLcr); cr.removeUnusedVariableOfAttrContext(); setInputParameterIfNeeded(cr); cr.isReadyToTransform(); // ((VarTuple)cr.getAttrContext().getVariables()).showVariables(); // ((VarTuple)cr.getLeft().getAttrContext().getVariables()).showVariables(); // ((VarTuple)cr.getRight().getAttrContext().getVariables()).showVariables(); // System.out.println("ConcurrentRule.makeRuleByDisjointUnion ===> "+cr.getName()+" DONE ( " +cr.getErrorMsg()); } morphCR.dispose(); } else { lhs1ToLHS.dispose(); lhs1ToLHS = null; rhs1ToRHS.dispose(); rhs1ToRHS = null; lhs2ToLHS.dispose(); lhs2ToLHS = null; } } BaseFactory.theFactory().unsetAllTransientAttrValuesOfRule(rule1); BaseFactory.theFactory().unsetAllTransientAttrValuesOfRule(rule2); return cr; } /** * Constructs a concurrent rule based on given parameters. * * @param rule1 the first source rule of concurrent rule * @param inverseRule1 inverse rule of the first source rule * @param rule2 the second source rule of concurrent rule * @param isoLeft1 isomorphism: rule1.LHS --> inverseRule1.RHS * @param isoRight1 isomorphism: rule1.RHS --> inverseRule1.LHS * @param overlapping1 : inverseRule1.LHS -> graph * @param overlapping2 : rule2.LHS -> graph * * @return constructed concurrent rule */ private Rule makeRule( final Rule rule1, final Rule inverseRule1, final Rule rule2, final OrdinaryMorphism isoLeft1, final OrdinaryMorphism isoRight1, final OrdinaryMorphism overlapping1, final OrdinaryMorphism overlapping2) { // System.out.println("ConcurrentRule.makeRule "+rule1.getName()+" & "+rule2.getName()); this.failedApplConds.clear(); Rule cr = null; this.disjoint = false; // graphE is the overlapping graph final Graph graphE = overlapping1.getTarget(); // create isom of the overlapping graph graphE final OrdinaryMorphism iso1 = graphE.isomorphicCopy(); if (iso1 == null) return null; // first create morphism of concurrent rule final OrdinaryMorphism crMorph = iso1.getTarget().isomorphicCopy(); if (crMorph == null) { iso1.dispose(); return null; } final Graph leftCR = crMorph.getSource(); final Graph rightCR = crMorph.getTarget(); // match1: inverseRule1.LHS -> leftCR == iso1.target final Match match1 = constructMatch1(leftCR, inverseRule1, overlapping1, iso1); // match2: rule2.LHS -> rightCR == iso1.target == iso2.source final Match match2 = constructMatch2(rightCR, rule2, overlapping2, iso1, crMorph); final OrdinaryMorphism lhs1ToLHS = constructLHSbyPO(match1); // lhs1ToLHS: inverseRule1.LHS -> leftCR == iso1.target == iso2.source boolean failed = (lhs1ToLHS == null); if (!failed) { final OrdinaryMorphism rhs2ToRHS = constructRHSbyPO(match2/*, crMorph*/); // rhs2ToRHS: rule2.RHS -> rightCR == iso2.target failed = (rhs2ToRHS == null); if (!failed) { // make concurrent rule cr = BaseFactory.theFactory().constructRuleFromMorph(crMorph); cr.setName(rule1.getName()+"+"+rule2.getName()); // save help data this.embLr1ToLcr = isoLeft1.compose(lhs1ToLHS); this.embRr1ToRcr = isoRight1.compose(overlapping1).compose(iso1).compose(crMorph); this.embLr2ToLcr = overlapping2.compose(iso1); this.embRr2ToRcr = rhs2ToRHS; // System.out.println("******* Concurrent rule: "+cr.getName()); boolean includedPACs = true; // if (checkCorrespondingAttrsOfPACs(rule1)) { // extend LHS of concurrent rule by PACs of rule1 // includedPACs = extendLeftRightGraphsByPACsOfRule(cr, rule1, this.embLr1ToLcr); // } // System.out.println("******* try add NACs (PACs)"); // extend concurrent rule by NACs and PACs of its first source rule1 // this.embLr1ToLcr is n1: LHS_r1 --> LHS_rc // if add of a PAC of first rule failed, the concurrent rule is not applicable! cr.notApplicable = !shiftCondsOfRuleOverEmbMorph(cr, rule1, this.embLr1ToLcr, includedPACs); includedPACs = true; // if (checkCorrespondingAttrsOfPACs(rule2)) { // extend LHS of concurrent rule by PACs of rule2 // includedPACs = extendLeftRightGraphsByPACsOfRule(cr, rule2, this.embLr2ToLcr); // } // if add of PAC of second rule failed, the concurrent rule is not applicable! cr.notApplicable = !shiftCondsOfRuleOverMorphAndRight( cr, rule2, overlapping2, iso1, this.embLr2ToLcr, includedPACs); removeIsomorphicMorph(cr.getNACsList()); removeIsomorphicMorph(cr.getPACsList()); // add attribute conditions addAttrConditionFromTo(rule1, cr); addAttrConditionFromTo(rule2, cr); final OrdinaryMorphism rule1LHS2leftCR = isoLeft1.compose(lhs1ToLHS); // adjust attr expressions and conditions adjustLeftMappedAttrs(cr, rule1, rule1LHS2leftCR); setAttrExpressionOfConcurrentRule(match2.getRule(), match2, rhs2ToRHS, cr); addUndeclaredVariableOfExpression(cr); BaseFactory.theFactory().unsetAllTransientAttrValuesOfRule(cr); cr.removeUnusedVariableOfAttrContext(); // test this.adjustUnsetAttrsAboveMorph(this.embLr1ToLcr); setInputParameterIfNeeded(cr); cr.isReadyToTransform(); // System.out.println("ConcurrentRule.makeRule ===> "+cr.getName()+" DONE ( " +cr.getErrorMsg()); rule1LHS2leftCR.dispose(); } } BaseFactory.theFactory().unsetAllTransientAttrValuesOfRule(rule1); BaseFactory.theFactory().unsetAllTransientAttrValuesOfRule(rule2); return cr; } /** * Constructs the first match to produce the left graph of the concurrent rule by PO1. * * @param leftCR left graph of the concurrent rule * @param inverseRule1 inverse rule1 to apply at the left graph on the constructed match * @param m1 the first morphism of the used dependency critical pair * @param iso1 isomorphism from the overlapping graph of the used dependency critical pair * to a copy of this graph * * @return the first match */ private Match constructMatch1( final Graph leftCR, final Rule inverseRule1, final OrdinaryMorphism m1, final OrdinaryMorphism iso1) { // here: // m1 = criticalPair.first; // iso1 = graphE.isomorphicCopy(); // graphE = criticalPair.first.getTarget(); boolean failed = false; // restore match1 to apply inverseRule1 on Graph leftCR Match match1 = BaseFactory.theFactory().createMatch(inverseRule1, leftCR, true); match1.setCompletionStrategy(new Completion_InjCSP()); match1.getTarget().setCompleteGraph(false); // set mappings of match1 similar to m1 Enumeration<GraphObject> dom1 = m1.getDomain(); while (dom1.hasMoreElements() && !failed) { GraphObject obj = dom1.nextElement(); try { match1.addMapping(obj, iso1.getImage(m1.getImage(obj))); } catch (Exception ex) { // System.out.println("ConcurrentRule.constructMatch1:: match1 FAILED! "+ex.getMessage()); failed = true; } } return match1; } /** * Computes the left graph of the concurrent rule by PO * via the specified match. * @param match the match to apply * * @return the co-match if PO exists, otherwise null */ private OrdinaryMorphism constructLHSbyPO(final Match match) { // here: //match: inverseRule.LHS -> concurrent.LHS // apply match to get LHS graph of concurrent rule OrdinaryMorphism comatch = null; try { comatch = (OrdinaryMorphism) TestStep.execute(match, true, this.enableEqualVariableNameOfAttrMapping); } catch (Exception ex) { // System.out.println("ConcurrentRule.constructLHSbyPO:: comatch FAILED! "+ex.getMessage()); } return comatch; } /** * Constructs the second match to produce the right graph of the concurrent rule by PO2. * * @param rightCR right graph of the concurrent rule * @param rule2 rule to apply at the right graph on the constructed match * @param m2 the second morphism of the used dependency critical pair * @param iso1 isomorphism from the overlapping graph of the used dependency critical pair * to a copy of this graph. The target graph of the morphism iso1 is the left graph of the concurrent rule * @param iso2 isomorphism from the target graph of the morphism iso1 * to a copy of this graph. The target graph of the morphism iso2 is the right graph of the concurrent rule * * @return the first match */ private Match constructMatch2( final Graph rightCR, final Rule rule2, final OrdinaryMorphism m2, final OrdinaryMorphism iso1, final OrdinaryMorphism iso2) { // here: // m2 = criticalPair.second; // iso1 = graphE.isomorphicCopy(); // iso2 = iso1.getTarget().isomorphicCopy(); // graphE = criticalPair.first.getTarget(); boolean failed = false; // restore match2 to apply rule2 on Graph rightCR Match match2 = BaseFactory.theFactory().createMatch(rule2, rightCR, true); match2.setCompletionStrategy(new Completion_InjCSP()); match2.getTarget().setCompleteGraph(false); // set mappings of match2 similar to m2 Enumeration<GraphObject> dom2 = m2.getDomain(); while (!failed && dom2.hasMoreElements()) { GraphObject obj = dom2.nextElement(); // System.out.println("*** m2.getImage(obj): "+m2.getImage(obj)); try { match2.addMapping(obj, iso2.getImage(iso1.getImage(m2.getImage(obj)))); } catch (BadMappingException ex) { // System.out.println("ConcurrentRule.constructMatch2:: match2 FAILED! "+ex.getMessage()); failed = true; } } // System.out.println("****** match2: "+match2); return match2; } /** * Computes the right graph of the concurrent rule by PO * via the specified match. * @param match the match to apply * * @return the co-match if PO exists, otherwise null */ private OrdinaryMorphism constructRHSbyPO(final Match match/*, final OrdinaryMorphism concurrentMorph*/) { // here: // match2: rule2.LHS -> concurrentRule.RHS // apply match2 to get RHS graph of concurrent rule OrdinaryMorphism comatch = null; try { comatch = (OrdinaryMorphism) TestStep.execute(match, true, this.enableEqualVariableNameOfAttrMapping); // setAttrExpressionOfConcurrentRule(match.getRule(), match, comatch, concurrentMorph); } catch (Exception ex) { // System.out.println("ConcurrentRule.constructRHSbyPO:: comatch FAILED! "+ex.getMessage()); } return comatch; } /** * Shift NACs and PACs of the rule over morphism * lhs11ToLHS: rule1.LHS -> cr.LHS. * * @param cr the concurrent rule * @param rule the a source rule * @param lhsToLHS the morphism: rule.LHS --> cr.LHS * * @return false, if construction of at least one PAC failed, otherwise return true. */ private boolean shiftCondsOfRuleOverEmbMorph( final Rule cr, final Rule rule, final OrdinaryMorphism lhsToLHS, boolean alsoPACs) { boolean ok = true; if (alsoPACs && rule.getPACs().hasMoreElements()) { List<OrdinaryMorphism> condList = shiftPACsOverEmbMorph(cr, rule, rule.getPACs(), lhsToLHS); if (cr.notApplicable) { return false; } if (condList != null && !condList.isEmpty()) { removeIsomorphicMorph(condList); for (int l=0; l<condList.size(); l++) { OrdinaryMorphism condCR = condList.get(l); condCR.getImage().setAttrContext(cr.getLeft().getAttrContext()); condCR.setAttrContext(cr.getLeft().getAttrContext()); BaseFactory.theBaseFactory.declareVariable(condCR.getTarget(), (VarTuple)cr.getAttrContext().getVariables()); if (!condCR.isRightTotal() || !condCR.doesIgnoreAttrs()) { cr.addPAC(condCR); } } } } if (ok && rule.getNACs().hasMoreElements()) { List<OrdinaryMorphism> condList = shiftNACsOverEmbMorph(rule, rule.getNACs(), lhsToLHS); if (condList != null && !condList.isEmpty()) { removeIsomorphicMorph(condList); for (int l=0; l<condList.size(); l++) { OrdinaryMorphism condCR = condList.get(l); condCR.getImage().setAttrContext(cr.getLeft().getAttrContext()); condCR.setAttrContext(cr.getLeft().getAttrContext()); BaseFactory.theBaseFactory.declareVariable(condCR.getTarget(), (VarTuple)cr.getAttrContext().getVariables()); if (!condCR.isRightTotal() || !condCR.doesIgnoreAttrs()) { cr.addNAC(condCR); // condCR.setName(condCR.getName()+"-EM-"+rule.getName()); } } } } return ok; } private void removeIsomorphicMorph(List<OrdinaryMorphism> list) { if (list.size() >= 2) { List<OrdinaryMorphism> list1 = new Vector<OrdinaryMorphism>(list); for (int i=0; i<list1.size(); i++) { OrdinaryMorphism m1 = list1.get(i); if (list.contains(m1)) { for (int j=0; j<list.size(); j++) { OrdinaryMorphism m = list.get(j); if (m != m1) { OrdinaryMorphism iso = m1.getTarget().getIsomorphicWith(m.getTarget()); if (iso != null) { if (m1.isCommutative(m, iso)) { list.remove(j); j--; } iso.dispose(); } } } } } } } @SuppressWarnings("unused") private boolean extendLeftRightGraphsByPACsOfRule( final Rule concurRule, final Rule rule, final OrdinaryMorphism leftRuleToLeftCR) { boolean ok = true; final List<OrdinaryMorphism> pacs = rule.getPACsList(); for(int i=0; i<pacs.size() && ok; i++) { OrdinaryMorphism pac = pacs.get(i); // extend left graph of concurrent rule OrdinaryMorphism pacGraph2concurRuleLHS = this.extendTargetGraph(leftRuleToLeftCR, pac, concurRule); // extend right graph of concurrent rule, // add morphism mapping Hashtable<Node, Node> tmp = new Hashtable<Node, Node>(5); final Iterator<Node> en = pac.getTarget().getNodesSet().iterator(); while (en.hasNext() && ok) { GraphObject o = en.next(); if (!pac.getInverseImage(o).hasMoreElements()) { Node lhsNode = (Node) pacGraph2concurRuleLHS.getImage(o); try { Node rhsNode = concurRule.getRight().copyNode(lhsNode); rhsNode.setContextUsage(o.hashCode()); tmp.put(lhsNode, rhsNode); try { concurRule.addMapping(lhsNode, rhsNode); } catch (BadMappingException exc) {ok = false;} } catch (TypeException ex) {ok = false;} } } final Iterator<Arc> ea = pac.getTarget().getArcsSet().iterator(); while (ea.hasNext() && ok) { GraphObject o = ea.next(); if (!pac.getInverseImage(o).hasMoreElements()) { Arc lhsArc = (Arc) pacGraph2concurRuleLHS.getImage(o); // here src, tar of lhsArc must be preserved! // TODO: allow src, tar to be deleted if (lhsArc != null && concurRule.getImage(lhsArc.getSource()) != null && concurRule.getImage(lhsArc.getTarget()) != null) { Node src = (Node) concurRule.getImage(lhsArc.getSource()); Node tar = (Node) concurRule.getImage(lhsArc.getTarget()); if (src != null && tar != null) { try { Arc rhsArc = concurRule.getRight().copyArc(lhsArc, src, tar); try { concurRule.addMapping(lhsArc, rhsArc); } catch (BadMappingException exc) {ok = false;} } catch (TypeException ex) {ok = false;} } } else { ok = false; } } } } return ok; } @SuppressWarnings("unused") private boolean checkCorrespondingAttrsOfPACs(final Rule rule) { boolean ok = true; final List<OrdinaryMorphism> pacs = rule.getPACsList(); for(int i=0; i<pacs.size() && ok; i++) { OrdinaryMorphism pac = pacs.get(i); ok = checkCorrespondingAttrsOfApplCondition(rule, pac); } return ok; } /** * Check whether each attribute member of an object in the LHS of the given rule and * its corresponding attribute member of the mapped object of the given * application condition (e.g. PAC) * do contain equal value or one of them is not set. * * @param rule * A rule to check * @param applCond * An application condition to check * * @return * <code>true</code> if check was successful, otherwise - <code>false</code> */ private boolean checkCorrespondingAttrsOfApplCondition(final Rule rule, final OrdinaryMorphism applCond) { boolean ok = true; final Enumeration<GraphObject> dom = applCond.getDomain(); while (dom.hasMoreElements() && ok) { GraphObject lhsObj = dom.nextElement(); GraphObject acObj = applCond.getImage(lhsObj); if (acObj != null && acObj.getAttribute() != null) { final ValueTuple acVal = (ValueTuple) acObj.getAttribute(); final ValueTuple lhsVal = (ValueTuple) lhsObj.getAttribute(); for (int i=0; i<lhsVal.getNumberOfEntries(); i++) { ValueMember lhsMem = lhsVal.getEntryAt(i); ValueMember acMem = acVal.getEntryAt(lhsMem.getName()); if (!lhsMem.isSet() || (acMem != null && !acMem.isSet()) || lhsMem.getExprAsText().equals(acMem.getExprAsText())) { continue; } ok = false; break; } } } return ok; } /** * Constructs and adds NACs and PACs to the concurrent rule based on NACs and PACs of the rule. * * @param cr the concurrent rule * @param rule the source rule * @param morph the second morphism of the used dependency pair * @param right isomorphism of the target graph of the used dependency pair * @param embMorph left embedding morphism of the rule into concurrent rule * @param alsoPACs consider PACs or not * * @return <true>, if construction was successful, otherwise return <code>false</code>. */ private boolean shiftCondsOfRuleOverMorphAndRight( final Rule cr, final Rule rule, final OrdinaryMorphism morph, final OrdinaryMorphism right, final OrdinaryMorphism embMorph, boolean alsoPACs) { boolean ok = true; if (alsoPACs) { List<OrdinaryMorphism> condList = shiftPACsOverMorphAndRight(cr, rule, rule.getPACs(), morph, right, embMorph); if (cr.notApplicable) { return false; } if (condList != null && !condList.isEmpty()) { removeIsomorphicMorph(condList); for (int l=0; l<condList.size(); l++) { OrdinaryMorphism condCR = condList.get(l); condCR.getImage().setAttrContext(cr.getLeft().getAttrContext()); condCR.setAttrContext(cr.getLeft().getAttrContext()); BaseFactory.theBaseFactory.declareVariable(condCR.getTarget(), (VarTuple)cr.getAttrContext().getVariables()); if (!condCR.isRightTotal() || !condCR.doesIgnoreAttrs()) { cr.addPAC(condCR); } } } } if (ok) { List<OrdinaryMorphism> condList = shiftNACsOverMorphAndRight(cr, rule, rule.getNACs(), morph, right, embMorph); if (condList != null && !condList.isEmpty()) { removeIsomorphicMorph(condList); for (int l=0; l<condList.size(); l++) { OrdinaryMorphism condCR = condList.get(l); condCR.getImage().setAttrContext(cr.getLeft().getAttrContext()); condCR.setAttrContext(cr.getLeft().getAttrContext()); BaseFactory.theBaseFactory.declareVariable(condCR.getTarget(), (VarTuple)cr.getAttrContext().getVariables()); if (!condCR.isRightTotal() || !condCR.doesIgnoreAttrs()) { cr.addNAC(condCR); } } } } return ok; } private boolean shiftCondsOfRuleOverMorphAndLeft( final Rule cr, final Rule rule, final OrdinaryMorphism morph, final OrdinaryMorphism left, final OrdinaryMorphism embMorph, boolean alsoPACs) { boolean ok = true; if (alsoPACs) { List<OrdinaryMorphism> condList = shiftPACsOverMorphAndLeft(cr, rule, rule.getPACs(), morph, left, embMorph); if (cr.notApplicable) { return false; } if (condList != null && !condList.isEmpty()) { removeIsomorphicMorph(condList); for (int l=0; l<condList.size(); l++) { OrdinaryMorphism condCR = condList.get(l); condCR.getImage().setAttrContext(cr.getLeft().getAttrContext()); condCR.setAttrContext(cr.getLeft().getAttrContext()); BaseFactory.theBaseFactory.declareVariable(condCR.getTarget(), (VarTuple)cr.getAttrContext().getVariables()); if (!condCR.isRightTotal() || !condCR.doesIgnoreAttrs()) { cr.addPAC(condCR); } } } } if (ok) { List<OrdinaryMorphism> condList = shiftNACsOverMorphAndLeft(cr, rule, rule.getNACs(), morph, left, embMorph); if (condList != null && !condList.isEmpty()) { removeIsomorphicMorph(condList); for (int l=0; l<condList.size(); l++) { OrdinaryMorphism condCR = condList.get(l); condCR.getImage().setAttrContext(cr.getLeft().getAttrContext()); condCR.setAttrContext(cr.getLeft().getAttrContext()); BaseFactory.theBaseFactory.declareVariable(condCR.getTarget(), (VarTuple)cr.getAttrContext().getVariables()); if (!condCR.isRightTotal() || !condCR.doesIgnoreAttrs()) { cr.addNAC(condCR); // condCR.setName(condCR.getName()+"-LEFT-"+rule.getName()); } } } } return ok; } private List<OrdinaryMorphism> shiftPACsOverEmbMorph( final Rule cr, final Rule rule, final Enumeration<OrdinaryMorphism> conds, final OrdinaryMorphism morph) { List<OrdinaryMorphism> result = new Vector<OrdinaryMorphism>(); while (conds.hasMoreElements()) { OrdinaryMorphism cond = conds.nextElement(); if (cond.getSize() > 0) { // morphism mapping exists // here: LHS -> cond is not empty List<OrdinaryMorphism> list = shiftCondOverEmbMorph(cond, morph); if (list != null && list.size() > 0) { for (int i=0; i<list.size(); i++) { OrdinaryMorphism lc = list.get(i); filterCondL(cond, lc, morph); this.filterNotNeededObjs(lc, morph); if (lc.getTarget().getSize() >= cond.getTarget().getSize() && !this.isFalseCond(cond, lc, morph)) { this.adjustUnsetAttrsAboveMorphs(cond, morph, lc); result.add(lc); } else { list.remove(lc); i--; } } if (list.size() > 1) { for (int i=1; i<list.size(); i++) { OrdinaryMorphism lc = list.get(i); lc.setName(lc.getName().concat("(OR)")); } cr.addShiftedPAC(list); } } else { // shift failed, so the concurRule is not applicable because of failed PAC cr.notApplicable = true; result.clear(); result = null; break; } } else { // cond is global OrdinaryMorphism lc = shiftGlobalRuleCond1(rule, cond, morph); if (lc != null) { this.adjustUnsetAttrsAboveMorphs(cond, morph, lc); result.add(lc); } } } return result; } private List<OrdinaryMorphism> shiftNACsOverEmbMorph( final Rule rule, final Enumeration<OrdinaryMorphism> conds, final OrdinaryMorphism morph) { final List<OrdinaryMorphism> result = new Vector<OrdinaryMorphism>(); while (conds.hasMoreElements()) { OrdinaryMorphism cond = conds.nextElement(); if (cond.getSize() > 0) { // here: LHS -> cond mapping not empty List<OrdinaryMorphism> list = shiftCondOverEmbMorph(cond, morph); if (list != null && list.size() > 0) { for (int i=0; i<list.size(); i++) { OrdinaryMorphism lc = list.get(i); filterCondL(cond, lc, morph); this.filterNotNeededObjs(lc, morph); if (lc.getTarget().getSize() >= cond.getTarget().getSize() && !this.isFalseCond(cond, lc, morph)) { this.adjustUnsetAttrsAboveMorphs(cond, morph, lc); result.add(lc); } } list.clear(); } } else { // cond is global OrdinaryMorphism lc = shiftGlobalRuleCond1(rule, cond, morph); if (lc != null) { this.adjustUnsetAttrsAboveMorphs(cond, morph, lc); result.add(lc); } } } return result; } private List<OrdinaryMorphism> shiftPACsOverMorphAndRight( final Rule cr, final Rule rule, final Enumeration<OrdinaryMorphism> conds, final OrdinaryMorphism morph, final OrdinaryMorphism right, final OrdinaryMorphism embMorph) { List<OrdinaryMorphism> result = new Vector<OrdinaryMorphism>(); while (conds.hasMoreElements()) { OrdinaryMorphism cond = conds.nextElement(); if (cond.getSize() > 0) { // here: LHS -> cond mapping is not empty List<OrdinaryMorphism> list = shiftCondOverMorph(rule, cond, morph); List<OrdinaryMorphism> list2 = null; if (list != null && list.size() > 0) { list2 = new Vector<OrdinaryMorphism>(); for (int i=0; i<list.size(); i++) { OrdinaryMorphism c = list.get(i); // shift c left OrdinaryMorphism lc = BaseFactory.theBaseFactory.createMorphism(right.getTarget(), c.getTarget()); Enumeration<GraphObject> dom = c.getDomain(); while (dom.hasMoreElements()) { GraphObject go = dom.nextElement(); GraphObject go1 = c.getImage(go); GraphObject go2 = right.getImage(go); if (go2 != null) { try { lc.addMapping(go2, go1); } catch (BadMappingException ex) { System.out.println("########### Shift Left FAILED! Rule: " +rule.getName()+" AC: "+cond.getName()+" cr: "+cr.getName()); } } } if (lc.getTarget().getSize() >= cond.getTarget().getSize() && !this.isFalseCond(cond, lc, embMorph)) { lc.setName(c.getName()); lc.setEnabled(cond.isEnabled()); this.adjustUnsetAttrsAboveMorphs(cond, embMorph, lc); list2.add(lc); } } } if (list2 != null && list2.size() > 0) { result.addAll(list2); if (list2.size() > 1) { cr.addShiftedPAC(list2); } } else { // shift failed, so the concurRule is not applicable because of failed PAC cr.notApplicable = true; result.clear(); result = null; break; } } else { // cond is global OrdinaryMorphism lc = shiftGlobalRuleCond1(rule, cond, morph.compose(right)); if (lc != null) { this.adjustUnsetAttrsAboveMorphs(cond, embMorph, lc); result.add(lc); } } } return result; } private List<OrdinaryMorphism> shiftNACsOverMorphAndRight( final Rule cr, final Rule rule, final Enumeration<OrdinaryMorphism> conds, final OrdinaryMorphism morph, final OrdinaryMorphism right, final OrdinaryMorphism embMorph) { List<OrdinaryMorphism> result = new Vector<OrdinaryMorphism>(); while (conds.hasMoreElements()) { OrdinaryMorphism cond = conds.nextElement(); if (cond.getSize() > 0) { // morphism mapping exists // here: LHS -> cond is not empty List<OrdinaryMorphism> list = shiftCondOverMorph(rule, cond, morph); List<OrdinaryMorphism> list2 = new Vector<OrdinaryMorphism>(); for (int i=0; i<list.size(); i++) { OrdinaryMorphism c = list.get(i); // shift c left OrdinaryMorphism lc = BaseFactory.theBaseFactory.createMorphism(right.getTarget(), c.getTarget()); // set mapping Enumeration<GraphObject> dom = c.getDomain(); while (dom.hasMoreElements()) { GraphObject go = dom.nextElement(); GraphObject go1 = c.getImage(go); GraphObject go2 = right.getImage(go); if (go2 != null) { try { lc.addMapping(go2, go1); } catch (BadMappingException ex) { System.out.println("########### Shift Left FAILED! Rule: " +rule.getName()+" AC: "+cond.getName()+" cr: "+cr.getName()); } } } if (lc.getTarget().getSize() >= cond.getTarget().getSize() && !this.isFalseCond(cond, lc, embMorph)) { lc.setName(c.getName()); lc.setEnabled(cond.isEnabled()); this.adjustUnsetAttrsAboveMorphs(cond, embMorph, lc); list2.add(lc); } } if (list2 != null && list2.size() > 0) { result.addAll(list2); } } else { // cond is global OrdinaryMorphism lc = shiftGlobalRuleCond1(rule, cond, morph.compose(right)); if (lc != null) { this.adjustUnsetAttrsAboveMorphs(cond, embMorph, lc); result.add(lc); } } } return result; } private List<OrdinaryMorphism> shiftPACsOverMorphAndLeft( final Rule cr, final Rule rule, final Enumeration<OrdinaryMorphism> conds, final OrdinaryMorphism morph, final OrdinaryMorphism left, final OrdinaryMorphism embMorph) { List<OrdinaryMorphism> result = new Vector<OrdinaryMorphism>(); while (conds.hasMoreElements()) { OrdinaryMorphism cond = conds.nextElement(); if (cond.getSize() > 0) { // here: LHS -> cond mapping is not empty List<OrdinaryMorphism> list = shiftCondOverMorph(rule, cond, morph); List<OrdinaryMorphism> list2 = null; if (list != null && list.size() > 0) { list2 = new Vector<OrdinaryMorphism>(); for (int i=0; i<list.size(); i++) { OrdinaryMorphism c = list.get(i); // shift c left OrdinaryMorphism lc = BaseFactory.theBaseFactory.shiftApplCondLeft(c, left); //TEST filterCondL(cond, lc, embMorph); this.filterNotNeededObjs(lc, embMorph); // if (lc.getTarget().getSize() >= cond.getTarget().getSize() && !this.isFalseCond(cond, lc, embMorph)) { lc.setName(c.getName()); lc.setEnabled(cond.isEnabled()); this.adjustUnsetAttrsAboveMorphs(cond, embMorph, lc); list2.add(lc); } } } if (list2 != null && list2.size() > 0) { result.addAll(list2); if (list2.size() > 1) { for (int i=1; i<list2.size(); i++) { OrdinaryMorphism lc = list2.get(i); lc.setName(lc.getName().concat("(OR)")); } cr.addShiftedPAC(list2); } } else { // shift failed, so the concurRule is not applicable because of failed PAC cr.notApplicable = true; result.clear(); result = null; break; } } else { // cond is global OrdinaryMorphism lc = this.shiftGlobalRuleCond2(rule, cond, left); if (lc != null) { this.adjustUnsetAttrsAboveMorphs(cond, embMorph, lc); result.add(lc); } } } return result; } private List<OrdinaryMorphism> shiftNACsOverMorphAndLeft( final Rule cr, final Rule rule, final Enumeration<OrdinaryMorphism> conds, final OrdinaryMorphism morph, final OrdinaryMorphism left, final OrdinaryMorphism embMorph) { List<OrdinaryMorphism> result = new Vector<OrdinaryMorphism>(); while (conds.hasMoreElements()) { OrdinaryMorphism cond = conds.nextElement(); if (cond.getSize() > 0) { // here: LHS -> cond is not empty List<OrdinaryMorphism> list = shiftCondOverMorph(rule, cond, morph); List<OrdinaryMorphism> list2 = new Vector<OrdinaryMorphism>(); for (int i=0; i<list.size(); i++) { OrdinaryMorphism c = list.get(i); // shift c left OrdinaryMorphism lc = BaseFactory.theBaseFactory.shiftApplCondLeft(c, left); //TEST filterCondL(cond, lc, embMorph); this.filterNotNeededObjs(lc, embMorph); // if (lc.getTarget().getSize() >= cond.getTarget().getSize() && !this.isFalseCond(cond, lc, embMorph)) { lc.setName(c.getName()); lc.setEnabled(cond.isEnabled()); this.adjustUnsetAttrsAboveMorphs(cond, embMorph, lc); list2.add(lc); } } if (list2 != null && list2.size() > 0) { result.addAll(list2); } } else { // cond is global OrdinaryMorphism lc = this.shiftGlobalRuleCond2(rule, cond, left); if (lc != null) { this.adjustUnsetAttrsAboveMorphs(cond, embMorph, lc); result.add(lc); } } } return result; } private void filterNotNeededObjs( final OrdinaryMorphism cond, final OrdinaryMorphism iL) { List<GraphObject> delete = new Vector<GraphObject>(); // delete mapped arcs final Iterator<Arc> arcs = cond.getTarget().getArcsSet().iterator(); while (arcs.hasNext()) { Arc arc = arcs.next(); Enumeration<GraphObject> inv = cond.getInverseImage(arc); if (inv.hasMoreElements()) { GraphObject lgo = inv.nextElement(); if (!iL.getInverseImage(lgo).hasMoreElements()) { if (similarAttribute(lgo, arc)) delete.add(arc); } } } for (int i=0; i<delete.size(); i++) { Arc arc = (Arc) delete.get(i); try { cond.removeMapping(arc); try { cond.getTarget().destroyArc(arc, false, false); } catch (TypeException ex) {} } catch (BadMappingException ex1) {} } delete.clear(); // delete mapped free nodes final Iterator<Node> nodes = cond.getTarget().getNodesSet().iterator(); while (nodes.hasNext()) { Node node = nodes.next(); if (!node.getOutgoingArcs().hasNext() && !node.getIncomingArcs().hasNext()) { Enumeration<GraphObject> inv = cond.getInverseImage(node); if (inv.hasMoreElements()) { GraphObject lgo = inv.nextElement(); if (!iL.getInverseImage(lgo).hasMoreElements()) { if (similarAttribute(lgo, node)) delete.add(node); } } } } for (int i=0; i<delete.size(); i++) { Node node = (Node) delete.get(i); try { cond.removeMapping(node); try { cond.getTarget().destroyNode(node, false, false); } catch (TypeException ex) {} } catch (BadMappingException ex1) {} } delete.clear(); delete = null; } private boolean similarAttribute(final GraphObject go1, final GraphObject go2) { if (go1.getAttribute() != null && go2.getAttribute() != null) { final ValueTuple val1 = (ValueTuple) go1.getAttribute(); final ValueTuple val2 = (ValueTuple) go2.getAttribute(); for (int i=0; i<val2.getNumberOfEntries(); i++) { ValueMember vm2 = val2.getValueMemberAt(i); ValueMember vm1 = val1.getValueMemberAt(vm2.getName()); if (vm2.isSet()) { // mem2 is set, check mem1 if (vm1 != null && vm1.isSet()) { if (//!vm2.isTransient() && !vm2.isTransient() && !vm2.getExprAsText().equals(vm1.getExprAsText())) { // mem1 is set by another value return false; } } else { // mem1 does not exist or unset return false; } } else if (vm1.isSet()) { return false; } } } return true; } private OrdinaryMorphism shiftGlobalRuleCond1( final Rule rule, final OrdinaryMorphism cond, final OrdinaryMorphism morph) { final OrdinaryMorphism condIsom = cond.getTarget().isomorphicCopy(); if (condIsom == null) return null; final OrdinaryMorphism condCR = BaseFactory.theBaseFactory .createMorphism(morph.getTarget(), condIsom.getTarget()); condCR.setName(cond.getName()); condCR.setEnabled(cond.isEnabled()); return condCR; } private OrdinaryMorphism shiftGlobalRuleCond2( final Rule rule, final OrdinaryMorphism cond, final OrdinaryMorphism morph) { final OrdinaryMorphism condIsom = cond.getTarget().isomorphicCopy(); if (condIsom == null) return null; final OrdinaryMorphism condCR = BaseFactory.theBaseFactory .createMorphism(morph.getSource(), condIsom.getTarget()); condCR.setName(cond.getName()); condCR.setEnabled(cond.isEnabled()); return condCR; } /** * Try to shift the specified application condition <code>cond</code> * over the embedding morphism <code>morph</code>. For * given morphisms must hold: cond.getSource() == morph.getSource(). * * @return list of application condition on the graph * <code>morph.getTarget()</code> */ private List<OrdinaryMorphism> shiftCondOverEmbMorph( final OrdinaryMorphism cond, final OrdinaryMorphism morph) { final List<OrdinaryMorphism> list = new Vector<OrdinaryMorphism>(); // make an iso-copy of the rule LHS final OrdinaryMorphism condSrcIsom = cond.getSource().isomorphicCopy(); if (condSrcIsom == null) { return null; } // extend the target graph of condSrcIsom by elements of the target // graph of cond // final OrdinaryMorphism condExt = BaseFactory.theBaseFactory.extendTargetGraph1ByTargetGraph2(condSrcIsom, cond); // get the extended result graph final Graph dCondGraph = condSrcIsom.getTarget(); final Vector<GraphObject> condDom = condSrcIsom.getDomainObjects(); final List<Object> requiredObjs = new Vector<Object>(condDom.size()); final Hashtable<Object, Object> objmap = new Hashtable<Object, Object>( condDom.size()); // fill a map with objects required // for the graph overlappings of dCondGraph and morph.getTarget() for (int j = 0; j < condDom.size(); j++) { GraphObject go = condDom.get(j); GraphObject go1 = condSrcIsom.getImage(go); GraphObject go2 = morph.getImage(go); if (go1 != null && go2 != null) { requiredObjs.add(go1); objmap.put(go1, go2); } } // make graph overlappings above required objects Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> overlaps = BaseFactory.theBaseFactory .getOverlappingByPartialPredefinedIntersection(dCondGraph, morph.getTarget(), requiredObjs, objmap, true); // false); // add created conditions to the list while (overlaps.hasMoreElements()) { Pair<OrdinaryMorphism, OrdinaryMorphism> p = overlaps.nextElement(); if (!p.second.getTarget().isEmpty()) { // get an application condition after shifting OrdinaryMorphism c = p.second; c.setEnabled(cond.isEnabled()); c.setName(cond.getName()); c.shifted = true; list.add(c); } } return (list.isEmpty())? null: list; } private List<OrdinaryMorphism> shiftCondOverMorph( final Rule rule, final OrdinaryMorphism cond, final OrdinaryMorphism morph) { // first check: // for all x from rule.lhs with cond.getImage(x) != null also morph.getImage(x) != null final Enumeration<GraphObject> dom = cond.getDomain(); while (dom.hasMoreElements()) { GraphObject go = dom.nextElement(); if (morph.getImage(go) == null) { this.failedApplConds.add(cond); return null; } } final OrdinaryMorphism condIsom = cond.getTarget().isomorphicCopy(); if (condIsom == null) { this.failedApplConds.add(cond); return null; } final OrdinaryMorphism leftToCond = cond.compose(condIsom); final Vector<GraphObject> condDom = cond.getDomainObjects(); final List<Object> requiredObjs = new Vector<Object>(condDom.size()); final Hashtable<Object,Object> objmap = new Hashtable<Object,Object>(condDom.size()); for (int j=0; j<condDom.size(); j++) { GraphObject go = condDom.get(j); GraphObject go1 = leftToCond.getImage(go); GraphObject go2 = morph.getImage(go); if (go1 != null && go2 != null) { requiredObjs.add(go1); objmap.put(go1, go2); } } final Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> overlaps = BaseFactory.theBaseFactory.getOverlappingByPartialPredefinedIntersection( condIsom.getTarget(), morph.getTarget(), requiredObjs, objmap, true); final List<OrdinaryMorphism> list = new Vector<OrdinaryMorphism>(); while (overlaps.hasMoreElements()) { Pair<OrdinaryMorphism, OrdinaryMorphism> p = overlaps.nextElement(); OrdinaryMorphism condCR = p.second; if (!p.second.getTarget().isEmpty()) { filterObjsOfRightRuleCond(rule, cond, condIsom, p.first, condCR, morph); condCR.setName(cond.getName().concat(String.valueOf(list.size()))); condCR.setEnabled(cond.isEnabled()); condCR.shifted = true; list.add(condCR); } } if (list.isEmpty()) { this.failedApplConds.add(cond); } return list; } private boolean filterObjsOfRightRuleCond( final Rule r, final OrdinaryMorphism condL, final OrdinaryMorphism condIsom, final OrdinaryMorphism condTargetToCondCR, final OrdinaryMorphism condCR, final OrdinaryMorphism leftEmbeddingMorph) { boolean ok = true; // delete arc to be created or without a mapping // from its pre-image into the condL List<GraphObject> todelete = new Vector<GraphObject>(); final Iterator<Arc> arcs = condCR.getTarget().getArcsSet().iterator(); while (arcs.hasNext()) { Arc go_condCR = arcs.next(); Arc goInv_condCR = null; if (condCR.getInverseImage(go_condCR).hasMoreElements()) { if (condTargetToCondCR.getInverseImage(go_condCR).hasMoreElements()) goInv_condCR = (Arc) condTargetToCondCR.getInverseImage(go_condCR).nextElement(); if (goInv_condCR == null) { todelete.add(go_condCR); continue; } if (!condIsom.getInverseImage(goInv_condCR).hasMoreElements()) { todelete.add(go_condCR); continue; } Arc go_leftCR = (Arc) condCR.getInverseImage(go_condCR).nextElement(); if (r == this.source2) { if (this.embLr2ToLcr.getInverseImage(go_leftCR).hasMoreElements()) { Arc go_left2 = (Arc)this.embLr2ToLcr.getInverseImage(go_leftCR).nextElement(); if (condL.getImage(go_left2) == null) { condCR.removeMapping(go_condCR); } } else if (this.embLr1ToLcr.getInverseImage(go_leftCR).hasMoreElements()) { todelete.add(go_condCR); } } else if (r == this.source1) { if (this.embLr1ToLcr.getInverseImage(go_leftCR).hasMoreElements()) { Arc go_left1 = (Arc)this.embLr1ToLcr.getInverseImage(go_leftCR).nextElement(); if (condL.getImage(go_left1) == null) { condCR.removeMapping(go_condCR); } } else if (this.embLr2ToLcr.getInverseImage(go_leftCR).hasMoreElements()) { todelete.add(go_condCR); } } } } for (int i=0; i<todelete.size(); i++) { try { condCR.getTarget().destroyArc((Arc)todelete.get(i), false, false); } catch (TypeException ex) {} } todelete.clear(); // delete node to be created or without a mapping // from its pre-image into the condL final Iterator<Node> nodes = condCR.getTarget().getNodesSet().iterator(); while (nodes.hasNext()) { Node go_condCR = nodes.next(); Node goInv_condCR = null; if (condCR.getInverseImage(go_condCR).hasMoreElements()) { if (condTargetToCondCR.getInverseImage(go_condCR).hasMoreElements()) goInv_condCR = (Node) condTargetToCondCR.getInverseImage(go_condCR).nextElement(); if (goInv_condCR == null) { todelete.add(go_condCR); continue; } if (!condIsom.getInverseImage(goInv_condCR).hasMoreElements()) { todelete.add(go_condCR); continue; } Node go_leftCR = (Node) condCR.getInverseImage(go_condCR).nextElement(); if (r == this.source2) { if (this.embLr2ToLcr.getInverseImage(go_leftCR).hasMoreElements()) { Node go_left2 = (Node)this.embLr2ToLcr.getInverseImage(go_leftCR).nextElement(); if (condL.getImage(go_left2) == null) { condCR.removeMapping(go_condCR); } } else if (this.embLr1ToLcr.getInverseImage(go_leftCR).hasMoreElements()) { todelete.add(go_condCR); } } else if (r == this.source1) { if (this.embLr1ToLcr.getInverseImage(go_leftCR).hasMoreElements()) { Node go_left1 = (Node)this.embLr1ToLcr.getInverseImage(go_leftCR).nextElement(); if (condL.getImage(go_left1) == null) { condCR.removeMapping(go_condCR); } } else if (this.embLr2ToLcr.getInverseImage(go_leftCR).hasMoreElements()) { todelete.add(go_condCR); } } } } for (int i=0; i<todelete.size(); i++) { try { condCR.getTarget().destroyNode((Node) todelete.get(i), false, false); } catch (TypeException ex) {} } return ok; } /** * Extends the target graph of the specified morphism isom by the graph elements * of the target graph of the specified morphism cond. * * @param isom isomorphism of a graph * @param cond is a NAC resp. PAC, * where the source graph is the source graph of the isom * * @return morphism, where the source graph is the target graph of the condition * and the target graph is the target graph of the isom */ private OrdinaryMorphism extendTargetGraph( final OrdinaryMorphism isom, final OrdinaryMorphism cond, final Rule concurRule) { Graph extTarget = isom.getTarget(); OrdinaryMorphism morph = BaseFactory.theFactory().createMorphism( cond.getTarget(), extTarget); Hashtable<Node, Node> tmp = new Hashtable<Node, Node>(5); final Iterator<Node> en = cond.getTarget().getNodesSet().iterator(); while (en.hasNext()) { GraphObject o = en.next(); if (!cond.getInverseImage(o).hasMoreElements()) { try { Node n = extTarget.copyNode((Node) o); n.setContextUsage(o.hashCode()); tmp.put((Node) o, n); try { morph.addMapping(o, n); } catch (BadMappingException exc) {} } catch (TypeException ex) {} } else if (isom.getImage(cond.getInverseImage(o).nextElement()) != null) { try { Node n = (Node) isom.getImage(cond .getInverseImage(o).nextElement()); n.setObjectName(o.getObjectName()); this.adjustAttrsFromTo(o, n, concurRule); morph.addMapping(o, isom.getImage(cond .getInverseImage(o).nextElement())); } catch (BadMappingException exc) {} } } final Iterator<Arc> ea = cond.getTarget().getArcsSet().iterator(); while (ea.hasNext()) { GraphObject o = ea.next(); if (!cond.getInverseImage(o).hasMoreElements()) { Node src = tmp.get(((Arc) o).getSource()); if (src == null) { src = (Node) isom.getImage(cond.getInverseImage( ((Arc) o).getSource()).nextElement()); } Node tar = tmp.get(((Arc) o).getTarget()); if (tar == null) { tar = (Node) isom.getImage(cond.getInverseImage( ((Arc) o).getTarget()).nextElement()); } try { Arc a = extTarget.copyArc((Arc) o, src, tar); a.setContextUsage(o.hashCode()); try { morph.addMapping(o, a); } catch (BadMappingException exc) {} } catch (TypeException ex) {} } else if (isom.getImage(cond.getInverseImage(o).nextElement()) != null) { try { Arc a = (Arc) isom.getImage(cond .getInverseImage(o).nextElement()); a.setObjectName(o.getObjectName()); this.adjustAttrsFromTo(o, a, concurRule); morph.addMapping(o, isom.getImage( cond.getInverseImage(o).nextElement())); } catch (BadMappingException exc) {} } } return morph; } private void adjustAttrsFromTo( final GraphObject from, final GraphObject to, final OrdinaryMorphism morph) { if (to != null) { if (from.getAttribute() != null) { ValueTuple vt_from = (ValueTuple) from.getAttribute(); ValueTuple vt_to = (ValueTuple) to.getAttribute(); for (int i=0; i<vt_from.getNumberOfEntries(); i++) { ValueMember vm = vt_from.getValueMemberAt(i); if (vm.isSet()) { if (vm.getExpr().isVariable()) { if (((VarTuple) morph.getAttrContext().getVariables()) .getVarMemberAt(vm.getExprAsText()) == null) { ((VarTuple) morph.getAttrContext().getVariables()) .getTupleType().addMember(vm.getHandler(), vm.getDeclaration().getTypeName(), vm.getExprAsText()); ((VarTuple) morph.getAttrContext().getVariables()).getVarMemberAt(vm.getExprAsText()).setTransient(false); } } ValueMember vm_to = vt_to.getValueMemberAt(vm.getName()); if (vm_to != null) { vm_to.setExprAsText(vm.getExprAsText()); vm_to.setTransient(false); } } } } } } private void adjustUnsetAttrsAboveMorph(final OrdinaryMorphism morph) { Enumeration<GraphObject> dom = morph.getDomain(); while (dom.hasMoreElements()) { final GraphObject from = dom.nextElement(); final GraphObject to = morph.getImage(from); if (from.getAttribute() != null && to.getAttribute() != null) { ValueTuple vt_from = (ValueTuple) from.getAttribute(); ValueTuple vt_to = (ValueTuple) to.getAttribute(); for (int i=0; i<vt_from.getNumberOfEntries(); i++) { ValueMember vm_from = vt_from.getValueMemberAt(i); if (!vm_from.isSet()) { ValueMember vm_to = vt_to.getValueMemberAt(vm_from.getName()); if (vm_to != null && vm_to.isSet()) { vm_to.setExpr(null); vm_to.setTransient(false); } } // else { // if (vm_from.getExpr().isVariable()) { // if (((VarTuple) morph.getAttrContext().getVariables()) // .getVarMemberAt(vm_from.getExprAsText()) == null) { // ((VarTuple) morph.getAttrContext().getVariables()) // .getTupleType().addMember(vm_from.getHandler(), vm_from.getDeclaration().getTypeName(), vm_from.getExprAsText()); // ((VarTuple) morph.getAttrContext().getVariables()).getVarMemberAt(vm_from.getExprAsText()).setTransient(false); // } // } // ValueMember vm_to = vt_to.getValueMemberAt(vm_from.getName()); // if (vm_to != null) { // vm_to.setExprAsText(vm_from.getExprAsText()); // vm_to.setTransient(false); // } // } } } } } private void adjustUnsetAttrsAboveMorphs( final OrdinaryMorphism cond, final OrdinaryMorphism morph, final OrdinaryMorphism shifted) { Enumeration<GraphObject> dom = morph.getDomain(); while (dom.hasMoreElements()) { final GraphObject obj = dom.nextElement(); final GraphObject img = morph.getImage(obj); final GraphObject from = cond.getImage(obj); final GraphObject to = shifted.getImage(img); if (from != null && to != null) { if (from.getAttribute() != null && to.getAttribute() != null) { ValueTuple vt_from = (ValueTuple) from.getAttribute(); ValueTuple vt_to = (ValueTuple) to.getAttribute(); for (int i=0; i<vt_from.getNumberOfEntries(); i++) { ValueMember vm_from = vt_from.getValueMemberAt(i); if (!vm_from.isSet()) { ValueMember vm_to = vt_to.getValueMemberAt(vm_from.getName()); if (vm_to != null && vm_to.isSet()) { vm_to.setExpr(null); vm_to.setTransient(false); } } // else { // if (vm_from.getExpr().isVariable()) { // if (((VarTuple) morph.getAttrContext().getVariables()) // .getVarMemberAt(vm_from.getExprAsText()) == null) { // ((VarTuple) morph.getAttrContext().getVariables()) // .getTupleType().addMember(vm_from.getHandler(), vm_from.getDeclaration().getTypeName(), vm_from.getExprAsText()); // ((VarTuple) morph.getAttrContext().getVariables()).getVarMemberAt(vm_from.getExprAsText()).setTransient(false); // } // } // ValueMember vm_to = vt_to.getValueMemberAt(vm_from.getName()); // if (vm_to != null) { // vm_to.setExprAsText(vm_from.getExprAsText()); // vm_to.setTransient(false); // } // } } } } } } private void addAttrConditionFromTo(final Rule fromRule, final Rule toRule) { CondTuple condsFrom = (CondTuple) fromRule.getAttrContext().getConditions(); if (condsFrom.isEmpty()) return; CondTuple conds = (CondTuple) toRule.getAttrContext().getConditions(); for (int i=0; i<condsFrom.getNumberOfEntries(); i++) { CondMember cond = condsFrom.getCondMemberAt(i); if (this.isAttrCondRelevant(fromRule, cond)) { conds.addCondition(cond.getExprAsText()); } } } private boolean isAttrCondRelevant(final Rule r, final CondMember cond) { Vector<String> condvars = cond.getAllVariables(); for (int i=0; i<this.failedApplConds.size(); i++) { OrdinaryMorphism morph = this.failedApplConds.get(i); if (r.getLeft() == morph.getSource()) { Vector<String> vars = morph.getTarget().getVariableNamesOfAttributes(); for (int j=0; j<condvars.size(); j++) { if (vars.contains(condvars.get(j))) return false; } } } return true; } private List<String> adjustLeftMappedAttrs( final Rule cr, final Rule rule, final OrdinaryMorphism ruleLeftt2leftCR) { // System.out.println("ConcurrentRule.adjustLeftMappedAttrs:: "+cr.getName()+" "+rule.getName()); List<String> varToDelete = new Vector<String>(); Enumeration<GraphObject> dom1 = rule.getDomain(); while (dom1.hasMoreElements()) { GraphObject obj = dom1.nextElement(); if (obj.getAttribute() != null) { GraphObject img = rule.getImage(obj); ValueTuple vt = (ValueTuple) obj.getAttribute(); for (int i=0; i<vt.getNumberOfEntries(); i++) { ValueMember vm = vt.getValueMemberAt(i); if (vm.isSet() && vm.getExpr().isVariable()) { ValueMember vmImg = ((ValueTuple) img.getAttribute()).getValueMemberAt(vm.getName()); if (vmImg != null && vmImg.isSet() && vmImg.getExpr().isVariable() && vm.getExprAsText().equals(vmImg.getExprAsText())) { // System.out.println(vm.getExprAsText()+" == "+vmImg.getExprAsText()); GraphObject crLeftObj = ruleLeftt2leftCR.getImage(obj); if (crLeftObj != null) { // System.out.println("crLeftObj found"); GraphObject crRightObj = cr.getImage(crLeftObj); if (crRightObj != null) { // System.out.println("crRightObj found"); ValueMember vm_crLeftObj = ((ValueTuple) crLeftObj.getAttribute()).getValueMemberAt(vm.getName()); ValueMember vm_crRightObj = ((ValueTuple) crRightObj.getAttribute()).getValueMemberAt(vm.getName()); if (vm_crLeftObj.isSet() && vm_crLeftObj.getExpr().isVariable() && vm_crRightObj.isSet() && vm_crRightObj.getExpr().isVariable() && !vm_crLeftObj.getExprAsText().equals(vm_crRightObj.getExprAsText())) { // System.out.println(vm_crLeftObj.getExprAsText()+" ?= "+vm_crRightObj.getExprAsText()); // if (!varToDelete.contains(vm_crLeftObj.getExprAsText())) { // varToDelete.add(vm_crLeftObj.getExprAsText()); // } vm_crLeftObj.setExpr(null); vm_crLeftObj.setExprAsText(vm_crRightObj.getExprAsText()); if (!vm_crLeftObj.isTransient()) vm_crLeftObj.setTransient(vm_crRightObj.isTransient()); // NEW } } } } } } } } return varToDelete; } /** * Adjusts attribute expressions of the RHS of the concurrent rule * and also its attribute conditions according the second rule. * * @param rule2 the second rule of the concurrent rule * @param match2 match of PO2 * @param comatch2 co-match of PO2 * @param concurrentMorph morphism to be a concurrent rule morphism */ private void setAttrExpressionOfConcurrentRule( final Rule rule2, final OrdinaryMorphism match2, final OrdinaryMorphism comatch2, final OrdinaryMorphism concurrentMorph) { doSetAttrExpressionOfConcurrentRule(rule2, match2, comatch2, concurrentMorph, match2.getSource().getNodesSet().iterator()); doSetAttrExpressionOfConcurrentRule(rule2, match2, comatch2, concurrentMorph, match2.getSource().getArcsSet().iterator()); } private void doSetAttrExpressionOfConcurrentRule( final Rule rule2, final OrdinaryMorphism match2, final OrdinaryMorphism comatch2, final OrdinaryMorphism concurrentMorph, Iterator<?> elems) { while (elems.hasNext()) { GraphObject obj = (GraphObject) elems.next(); GraphObject img = match2.getImage(obj); if (img != null) { if (obj.getAttribute() != null) { ValueTuple vt = (ValueTuple) obj.getAttribute(); for (int i=0; i<vt.getNumberOfEntries(); i++) { ValueMember vm = vt.getValueMemberAt(i); if (vm.isSet() && vm.getExpr().isVariable()) { ValueTuple vtImg = (ValueTuple) img.getAttribute(); ValueMember vmImg = vtImg.getValueMemberAt(vm.getName()); if (vmImg != null && vmImg.isSet() && vmImg.getExpr().isVariable()) { // System.out.println("**** "+vmImg.getExprAsText()+" ?= "+vm.getExprAsText()); if (!vmImg.getExprAsText().equals(vm.getExprAsText())) { // System.out.println("**** setAttrExpressionOfConcurrentRule:: "+vm.getExprAsText()+" replace by "+ vmImg.getExprAsText()); replaceVariable(vm.getExprAsText(), vmImg.getExprAsText(), rule2, comatch2, concurrentMorph); } } } } } } } } private void replaceVariable(final String from, final String to, final Rule rule2, final OrdinaryMorphism comatch2, final OrdinaryMorphism concurrentMorph) { doReplaceVariable(from, to, concurrentMorph.getAttrContext(), concurrentMorph.getTarget().getNodesSet().iterator()); doReplaceVariable(from, to, concurrentMorph.getAttrContext(), concurrentMorph.getTarget().getArcsSet().iterator()); BaseFactory.theFactory().renameVariableOfCondition( concurrentMorph.getAttrContext(), (CondTuple)concurrentMorph.getAttrContext().getConditions(), from, to); removeVariableOfAttrContext(concurrentMorph.getAttrContext(), from); } private void doReplaceVariable( final String from, final String to, final AttrContext ac, final Iterator<?> elems) { while (elems.hasNext()) { GraphObject obj = (GraphObject) elems.next(); if (obj.getAttribute() != null) { ValueTuple vt = (ValueTuple) obj.getAttribute(); for (int i=0; i<vt.getNumberOfEntries(); i++) { ValueMember vm = vt.getValueMemberAt(i); if (vm.isSet()) { if (vm.getExpr().isVariable()) { if (vm.getExprAsText().equals(from)) { vm.setExpr(null); vm.setExprAsText(to); // System.out.println("attr variable after replace variable: "+vm.getExprAsText()); VarMember var = addVariableToAttrContext(ac, from, to); if (!vm.isTransient() && var != null) vm.setTransient(true); } } else if (vm.getExpr().isComplex()) { Vector<String> v = new Vector<String>(); vm.getExpr().getAllVariables(v); if (v.contains(from)) { BaseFactory.theFactory().renameVariableOfExpression(ac, vt, from, to); // System.out.println("attr expression after replace variable: "+vm.getExprAsText()); addVariableToAttrContext(ac, from, to); } } } } } } } private void addUndeclaredVariableOfExpression(final OrdinaryMorphism concurrentMorph) { doAddUndeclaredVariableOfExpression( concurrentMorph, concurrentMorph.getTarget().getNodesSet().iterator()); doAddUndeclaredVariableOfExpression( concurrentMorph, concurrentMorph.getTarget().getArcsSet().iterator()); } private void doAddUndeclaredVariableOfExpression( final OrdinaryMorphism concurrentMorph, final Iterator<?> elems) { final VarTuple vars = (VarTuple) concurrentMorph.getAttrContext().getVariables(); while (elems.hasNext()) { GraphObject obj = (GraphObject) elems.next(); if (obj.getAttribute() != null) { ValueTuple vt = (ValueTuple) obj.getAttribute(); for (int i=0; i<vt.getNumberOfEntries(); i++) { ValueMember vm = vt.getValueMemberAt(i); if (vm.isSet()) { if (vm.getExpr().isComplex()) { Vector<String> v = new Vector<String>(); vm.getExpr().getAllVariables(v); for (int j=0; j<v.size(); j++) { if (vars.getVarMemberAt(v.get(j)) == null) { addVariableToAttrContext(concurrentMorph.getAttrContext(), null, v.get(j)); } } } } } } } } private VarMember addVariableToAttrContext(final AttrContext attrContext, final String from, final String to) { VarTuple vars = (VarTuple) attrContext.getVariables(); VarMember v = null; if (vars.getVarMemberAt(to) == null) { if (from != null) { vars.getTupleType().addMember(vars.getVarMemberAt(from).getDeclaration().getHandler(), vars.getVarMemberAt(from).getDeclaration().getTypeName(), to); } else { vars.getTupleType().addMember(AvailableHandlers.newInstances()[0], "String", to); } v = vars.getVarMemberAt(to); v.setTransient(true); } return v; } private void removeVariableOfAttrContext( final AttrContext attrContext, final String var) { if (this.concurrentRule != null) { VarTuple vars = (VarTuple) attrContext.getVariables(); if (vars.getVarMemberAt(var) != null) { if (!this.concurrentRule.getLeft().getVariableNamesOfAttributes().contains(var)) { if (!this.concurrentRule.getRight().getVariableNamesOfAttributes().contains(var)) { if (!isUsedInGraph(this.concurrentRule.getNACs(), var)) { if (!isUsedInGraph(this.concurrentRule.getPACs(), var)) { vars.getTupleType().deleteMemberAt(var); // System.out.println("ConcurrentRule.removeVariableOfAttrContext:: removed: "+var); } } } } } } } public boolean isDisjoint() { return this.disjoint; } private void setInputParameterIfNeeded(final Rule concurRule) { // final Hashtable<Graph, Vector<String>> // graph2Varnames = new Hashtable<Graph, Vector<String>>(); VarTuple vars = (VarTuple) concurRule.getAttrContext().getVariables(); Vector<String> varNamesRHS = concurRule.getTarget().getVariableNamesOfAttributes(); Vector<String> varNamesLHS = concurRule.getSource().getVariableNamesOfAttributes(); for (int i=0; i<vars.getNumberOfEntries(); i++) { VarMember var = vars.getVarMemberAt(i); if (varNamesRHS.contains(var.getName())) { boolean found = false; if (varNamesLHS.contains(var.getName())) { found = true; } else if (!var.isTransient()) { if (!found) { var.setInputParameter(true); } /* final List<OrdinaryMorphism> nacs = concurRule.getNACsList(); for(int j=0; j<nacs.size() && !found; j++) { OrdinaryMorphism morph = nacs.get(j); if (graph2Varnames.get(morph.getTarget()) == null) { graph2Varnames.put(morph.getTarget(), morph.getTarget().getVariableNamesOfAttributes()); } Vector<String> varNames = graph2Varnames.get(morph.getTarget()); if (varNames.contains(var.getName())) { found = true; } } if (!found) { final List<OrdinaryMorphism> pacs = concurRule.getPACsList(); for(int j=0; j<pacs.size() && !found; j++) { OrdinaryMorphism morph = pacs.get(j); if (graph2Varnames.get(morph.getTarget()) == null) { graph2Varnames.put(morph.getTarget(), morph.getTarget().getVariableNamesOfAttributes()); } Vector<String> varNames = graph2Varnames.get(morph.getTarget()); if (varNames.contains(var.getName())) { found = true; } } } */ } } } } private boolean isUsedInGraph(Enumeration<OrdinaryMorphism> list, String varName) { while (list.hasMoreElements()) { Graph g = list.nextElement().getTarget(); if (g.getVariableNamesOfAttributes().contains(varName)) { // System.out.println(g.getName()+" uses "+varName); return true; } } return false; } private boolean isFalseCond( final OrdinaryMorphism cond, final OrdinaryMorphism condL, final OrdinaryMorphism leftEmbMorph) { Iterator<Node> iter = cond.getSource().getNodesSet().iterator(); while (iter.hasNext()) { GraphObject go = iter.next(); GraphObject go1 = leftEmbMorph.getImage(go); if (cond.getImage(go) == null && condL.getImage(go1) != null) { return true; } } Iterator<Arc> iter2 = cond.getSource().getArcsSet().iterator(); while (iter2.hasNext()) { GraphObject go = iter2.next(); GraphObject go1 = leftEmbMorph.getImage(go); if (cond.getImage(go) == null && condL.getImage(go1) != null) { return true; } } return false; } private void filterCondL( final OrdinaryMorphism cond, final OrdinaryMorphism condL, final OrdinaryMorphism leftEmbMorph) { Vector<GraphObject> del = new Vector<GraphObject>(); Iterator<Arc> iter2 = cond.getSource().getArcsSet().iterator(); while (iter2.hasNext()) { GraphObject go = iter2.next(); GraphObject go1 = leftEmbMorph.getImage(go); GraphObject go2 = condL.getImage(go1); if (cond.getImage(go) == null && go2 != null) { if (similarAttribute(go2, go1)) { del.add(go2); } } } Iterator<Node> iter = cond.getSource().getNodesSet().iterator(); while (iter.hasNext()) { GraphObject go = iter.next(); GraphObject go1 = leftEmbMorph.getImage(go); GraphObject go2 = condL.getImage(go1); if (cond.getImage(go) == null && go2 != null) { if (similarAttribute(go2, go1)) { del.add(go2); } } } for (int i=0; i<del.size(); i++) { GraphObject go = del.get(i); if (go.isArc()) { try { condL.removeMapping(go); try { condL.getTarget().destroyArc((Arc)go, false, false); } catch (TypeException ex) {} } catch (BadMappingException ex1) {} } else { try { condL.removeMapping(go); try { condL.getTarget().destroyNode((Node)go, false, false); } catch (TypeException ex) {} } catch (BadMappingException ex1) {} } } del.clear(); } }