/** * */ package agg.parser; import java.util.Collection; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; import java.util.Vector; import agg.attribute.AttrType; import agg.attribute.impl.ValueMember; import agg.attribute.impl.ValueTuple; import agg.attribute.impl.VarMember; import agg.attribute.impl.VarTuple; import agg.util.Pair; import agg.xt_basis.Arc; import agg.xt_basis.BadMappingException; import agg.xt_basis.BaseFactory; import agg.xt_basis.Graph; import agg.xt_basis.GraphObject; import agg.xt_basis.Match; import agg.xt_basis.OrdinaryMorphism; import agg.xt_basis.Rule; import agg.xt_basis.TestStep; import agg.xt_basis.TypeException; /** * This class computes critical matches of two rules at a concrete graph. * The two rules and a concret host graph graph are specified * by the class constructor. * In case of rule application conflicts * a vector with pairs of tables with critical matches will be computed. * The first table contains the match mappings from the LHS * of the first rule into the graph and * the second table contains the mappings from the LHS * of the second rule into the same graph. * @author olga * */ public class CriticalRulePairAtGraph extends ExcludePair { private Rule rule1, rule2; private Graph graph; final private Vector<Hashtable<GraphObject, GraphObject>> r1Matches = new Vector<Hashtable<GraphObject, GraphObject>>(); final private Vector<Hashtable<GraphObject, GraphObject>> r2Matches = new Vector<Hashtable<GraphObject, GraphObject>>(); private Hashtable<Vector<GraphObject>, Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> jointlyMatches; public CriticalRulePairAtGraph( final Rule r1, final Rule r2, final Graph g) { this.rule1 = r1; this.rule2 = r2; this.graph = g; // if (!this.rule1.isReadyToTransform()) // System.out.println(this.rule1.getName()+" is not ready to transform!"); // if (!this.rule2.isReadyToTransform()) // System.out.println(this.rule2.getName()+" is not ready to transform!"); } /** * Computes critical matches of two rules at a concrete graph. * Two rules and a concret host graph graph are specified * by the class constructor. * In case of rule application conflicts * returns a vector with pairs of tables with critical matches. * The first table contains the match mappings from the LHS * of the first rule into the graph and * the second table contains the mappings from the LHS * of the second rule into the same graph. * Returns null, if the specified two rules can be applied at the host graph * without any conflicts. * @return a vector with pairs of tables or null */ public Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> isCriticalAtGraph() { // System.out.println("CriticalRulePairAtGraph.isCriticalAtGraph "); if (this.essential) { // disable Type Multiplicity, Graph Constraints and NACs checking this.disableConstraints(); } // check global NACs of r2 before all other checks // if LHS of r1 satisfy a global NAC of r2, // where the NAC contains nodes with attrs are not set, // then this rule pair is non-critical! if (!checkGlobalNACsOfRule2(this.rule1, this.rule2)) { // System.out.println("CriticalRulePairAtGraph.isExclude:: a global NAC of rule2 FAILED!"); System.out.println("*** CriticalRulePairAtGraph.getCriticalForGraph:: [ " + this.rule1.getName() + ", " + this.rule2.getName() + " ] non-critical."); return null; } // Prepare and perform rule analysis // fill typesTG_L2 with types used in LHS of r2 fillTypeSubset(this.rule2.getLeft(), this.typesTG_L2); // fill typesTG_PAC2 with types from typesTG_L2 // and types used in PACs of r2 if (this.withPACs) getTypeSubsetLeft_PACs(this.rule2, this.typesTG_L2, this.typesTG_PAC2); // fill typesTG_NAC2 with types from typesTG_L2 // and types used in NACs of r2 if (this.withNACs) getTypeSubsetLeft_NACs(this.rule2, this.typesTG_L2, this.typesTG_NAC2); // compute left context, boundary, preserved and delete of r1 if (this.withPACs) computeLeftC_B_K(this.rule1, this.contextC1_L1, this.boundB1_L1, this.preservedK1_L1, this.delete, this.typesTG_PAC2); else computeLeftC_B_K(this.rule1, this.contextC1_L1, this.boundB1_L1, this.preservedK1_L1, this.delete, this.typesTG_L2); // compute right context, boundary, preserved and produce of r1 if (this.withNACs) computeRightC_B_K(this.rule1, this.contextC1_R1, this.boundB1_R1, this.preservedK1_R1, this.produce, this.typesTG_NAC2); else computeRightC_B_K(this.rule1, this.contextC1_R1, this.boundB1_R1, this.preservedK1_R1, this.produce, this.typesTG_L2); findValidMatches(this.rule1, this.graph, this.r1Matches); findValidMatches(this.rule2, this.graph, this.r2Matches); // System.out.println("### r1Matches: "+r1Matches.size()); // System.out.println("### r2Matches: "+r2Matches.size()); boolean canOverlapLHS1withLHS2 = canMatchConstantAttributeLHS1intoLHS2(this.rule1, this.rule2); final Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> resultOverlappings = new Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>>(); // check delete-use conflicts Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> deleteUseOverlappings = null; if (!this.contextC1_L1.isEmpty() && canOverlapLHS1withLHS2 && !this.stop) { deleteUseOverlappings = getDeleteUseConflictsAtGraph(this.rule1, this.rule2); if (deleteUseOverlappings != null) { for (int i = 0; i < deleteUseOverlappings.size(); i++) resultOverlappings.add(deleteUseOverlappings.elementAt(i)); } } // check produce-forbid conflicts Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> produceForbidOverlappings = null; if (this.withNACs && (this.complete || resultOverlappings.isEmpty()) && !this.contextC1_R1.isEmpty() && !this.stop) { produceForbidOverlappings = getProduceForbidConflictsAtGraph(this.rule1, this.rule2); if (produceForbidOverlappings != null) { for (int i = 0; i < produceForbidOverlappings.size(); i++) resultOverlappings.add(produceForbidOverlappings.elementAt(i)); } } // check attribute conflicts Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> changeAttributeOverlappings = null; if ((this.complete || resultOverlappings.isEmpty()) // && canOverlapLHS1withLHS2 && !this.stop) { final Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>> changedAttrsL1 = new Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>>(); // fill preservedChanged vector ruleChangesAttributes(this.rule1, this.rule2, this.contextC1_L1, this.boundB1_L1, this.preservedK1_L1, changedAttrsL1, this.typesTG_NAC2); final Vector<GraphObject> preservedL2_K2 = new Vector<GraphObject>(5); final Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>> changedAttrsL2 = new Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>>(); ruleChangesAttributes(this.rule2, preservedL2_K2, changedAttrsL2); if (ruleRestrictsAttributes(true, this.rule2, changedAttrsL2, changedAttrsL1)) { changeAttributeOverlappings = getChangeAttributeConflictsAtGraph( this.rule1, this.rule2, changedAttrsL1, changedAttrsL2); if (changeAttributeOverlappings != null) { for (int i = 0; i < changeAttributeOverlappings.size(); i++) resultOverlappings.add(changeAttributeOverlappings.elementAt(i)); } } } if (this.essential) { // enable Type Multiplicity, Graph Constraints and NACs checking this.enableConstraints(); } return resultOverlappings; } private void findValidMatches( final Rule r, final Graph g, final Vector<Hashtable<GraphObject, GraphObject>> ruleMatches) { // System.out.println("### findValidMatches: "+r.getName()); Match m = BaseFactory.theFactory().createMatch(r, g); m.setCompletionStrategy(super.strategy, true); // super.strategy.showProperties(); // ((VarTuple)m.getAttrContext().getVariables()).showVariables(); // ((CondTuple)m.getAttrContext().getConditions()).showConditions(); while (m.nextCompletion()) { if (m.isValid()) { Hashtable<GraphObject, GraphObject> mTable = new Hashtable<GraphObject, GraphObject>(); Enumeration<GraphObject> dom = m.getDomain(); while (dom.hasMoreElements()) { GraphObject o = dom.nextElement(); mTable.put(o, m.getImage(o)); } ruleMatches.add(mTable); } else { // System.out.println("### match failed: "+m.getErrorMsg()); } } } /* * Should be used to check Delete-Use conflicts only. * Key is all jointly GraphObjects, * Pair contains mappings of match1 and match2. */ private Hashtable<Vector<GraphObject>, Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> getJointlyMatches( final Vector<Hashtable<GraphObject, GraphObject>> ruleMatches1, final Vector<Hashtable<GraphObject, GraphObject>> ruleMatches2) { Hashtable<Vector<GraphObject>, Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> result = new Hashtable<Vector<GraphObject>, Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>>(); for (int i=0; i<ruleMatches1.size(); i++) { Hashtable<GraphObject, GraphObject> m1 = ruleMatches1.get(i); for (int j=0; j<ruleMatches2.size(); j++) { Hashtable<GraphObject, GraphObject> m2 = ruleMatches2.get(j); Vector<GraphObject> jointlyObjs = new Vector<GraphObject>(); Enumeration<GraphObject> keys1 = m1.keys(); while (keys1.hasMoreElements()) { GraphObject o1 = keys1.nextElement(); GraphObject i1 = m1.get(o1); Collection<GraphObject> values2 = m2.values(); if (values2.contains(i1)) { jointlyObjs.add(i1); } } if (!jointlyObjs.isEmpty()) { Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>> p = new Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>(m1, m2); result.put(jointlyObjs, p); } } } return result; } /* private boolean setMapping( final OrdinaryMorphism morph, final Hashtable<GraphObject, GraphObject> map) { Enumeration<GraphObject> keys = map.keys(); while (keys.hasMoreElements()) { GraphObject o = keys.nextElement(); GraphObject i = map.get(o); try { if (i.isArc()) { morph.addMapping(((Arc)o).getSource(), ((Arc)i).getSource()); morph.addMapping(((Arc)o).getTarget(), ((Arc)i).getTarget()); } morph.addMapping(o, i); } catch (BadMappingException ex) { return false; } } return true; } */ private boolean setMapping( final OrdinaryMorphism morph, final OrdinaryMorphism isoG, final Hashtable<GraphObject, GraphObject> map) { Enumeration<GraphObject> keys = map.keys(); while (keys.hasMoreElements()) { GraphObject o = keys.nextElement(); GraphObject img = isoG.getImage(map.get(o)); if (img != null) { try { if (img.isArc()) { morph.addMapping(((Arc)o).getSource(), ((Arc)img).getSource()); morph.addMapping(((Arc)o).getTarget(), ((Arc)img).getTarget()); } morph.addMapping(o, img); } catch (BadMappingException ex) { // System.out.println(ex.getLocalizedMessage()); return false; } } else return false; } return true; } /* * Returns Delete-Use conflicts of the rule pair (r1, r2). */ private Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> getDeleteUseConflictsAtGraph( final Rule r1, final Rule r2) { // System.out.println("CriticalRulePairAtGraph.getDeleteUseConflictsAtGraph...("+r1.getName()+", "+r2.getName()+")"); // System.out.println("### to delete: "+super.delete); this.jointlyMatches = getJointlyMatches(this.r1Matches, this.r2Matches); // System.out.println("### jointlyMatches: "+jointlyMatches.size()); if (!this.jointlyMatches.isEmpty()) { Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> result = new Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>>(); Enumeration<Vector<GraphObject>> jointly = this.jointlyMatches.keys(); while (jointly.hasMoreElements()) { Vector<GraphObject> jointlyObjs = jointly.nextElement(); Hashtable<GraphObject, GraphObject> m1 = this.jointlyMatches.get(jointlyObjs).first; Hashtable<GraphObject, GraphObject> m2 = this.jointlyMatches.get(jointlyObjs).second; for (int i=0; i<jointlyObjs.size(); i++) { GraphObject o = jointlyObjs.get(i); GraphObject go = getOriginalOfImage(o, m1); if (super.delete.contains(go)) { o.setCritical(true); // System.out.println("### Critical: "+o); Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>> p = new Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>( m1, m2); result.add(p); break; } } } // System.out.println("### result: "+result.size()); return result; } return null; } private GraphObject getOriginalOfImage(GraphObject img, Hashtable<GraphObject, GraphObject> map) { Enumeration<GraphObject> keys = map.keys(); while (keys.hasMoreElements()) { GraphObject o = keys.nextElement(); GraphObject i = map.get(o); if (i == img) return o; } return null; } /* * Returns Produce-Forbid conflicts of the rule pair (r1, r2). */ private Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> getProduceForbidConflictsAtGraph( final Rule r1, final Rule r2) { Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> result = new Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>>(); for (int i=0; i<this.r1Matches.size(); i++) { OrdinaryMorphism isoG = this.graph.isomorphicCopy(); if (isoG == null) { result = null; return null; } Hashtable<GraphObject, GraphObject> m1Map = this.r1Matches.get(i); Match m1 = BaseFactory.theFactory().createMatch(r1, isoG.getTarget()); if (setMapping(m1, isoG, m1Map)) { // make test step (r1,m1) OrdinaryMorphism com1 = null; try { com1 = (OrdinaryMorphism) TestStep.execute(m1); } catch (TypeException ex) { m1.dispose(); m1 = null; continue; } for (int j=0; j<this.r2Matches.size(); j++) { Hashtable<GraphObject, GraphObject> m2Map = this.r2Matches.get(j); Match m2 = BaseFactory.theFactory().createMatch(r2, isoG.getTarget()); if (setMapping(m2, isoG, m2Map)) { if (m2.areTotalIdentDanglSatisfied()) { final List<OrdinaryMorphism> nacs2 = r2.getNACsList(); for (int l=0; l<nacs2.size(); l++) { final OrdinaryMorphism nac2 = nacs2.get(l); final OrdinaryMorphism nac2Star = (OrdinaryMorphism) m2.checkNAC(nac2); if (nac2Star != null) { boolean critical = false; final Enumeration<GraphObject> nac2StarCodom = nac2Star.getCodomain(); while (nac2StarCodom.hasMoreElements()) { final GraphObject o = nac2StarCodom.nextElement(); final Enumeration<GraphObject> preimgR1 = com1.getInverseImage(o); if (preimgR1.hasMoreElements()) { final GraphObject preimg = preimgR1.nextElement(); if (!r1.getInverseImage(preimg).hasMoreElements()) { o.setCritical(true); critical = true; } } // oder so: // Enumeration<GraphObject> com1Codom = com1.getCodomain(); // while (com1Codom.hasMoreElements()) { // GraphObject go = com1Codom.nextElement(); // if (go == o) { // GraphObject preimg = com1.getInverseImage(go).nextElement(); // if (!r1.getInverseImage(preimg).hasMoreElements()) { // o.setCritical(true); // critical = true; // } // } // } } if (critical) { final Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>> p = new Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>( m1Map, m2Map); result.add(p); } } } } } } } } if (!result.isEmpty()) { result.trimToSize(); return result; } result = null; return null; } /* * Returns Change-Use-Attribute conflict of the rule pair (r1, r2). */ private Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>> getChangeUseAttributeConflictAtGraph( final Rule r1, final Rule r2, final Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>> changedAttrsL1, // final Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>> changedAttrsL2, final Hashtable<GraphObject, GraphObject> m1map, // final OrdinaryMorphism isoG, // final Match m1test, final OrdinaryMorphism com1test, final Match m2) { if (this.jointlyMatches == null) this.jointlyMatches = getJointlyMatches(this.r1Matches, this.r2Matches); if (!this.jointlyMatches.isEmpty()) { // System.out.println("### getChangeUseAttributeConflictAtGraph..."); Enumeration<Vector<GraphObject>> jointly = this.jointlyMatches.keys(); while (jointly.hasMoreElements()) { Vector<GraphObject> jointlyObjs = jointly.nextElement(); Hashtable<GraphObject, GraphObject> m1Map = this.jointlyMatches.get(jointlyObjs).first; if (m1Map != m1map) continue; Hashtable<GraphObject, GraphObject> m2Map = this.jointlyMatches.get(jointlyObjs).second; boolean critical = false; for (int i=0; i<jointlyObjs.size(); i++) { GraphObject o = jointlyObjs.get(i); GraphObject go1 = getOriginalOfImage(o, m1Map); if (super.preservedChanged.contains(go1)) { // check attrs GraphObject go2 = getOriginalOfImage(o, m2Map); GraphObject img2 = m2.getImage(go2); GraphObject img1changed = com1test.getImage(r1.getImage(go1)); // System.out.println("### img2: "+img2); // System.out.println("### img1changed: " +img1changed); if (!checkChangeUseAttribute(img2, img1changed, changedAttrsL1)) { o.setCritical(true); // System.out.println("### Critical host graph obj: \n"+o); critical = true; } } } if (critical) { Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>> p = new Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>( m1Map, m2Map); return p; } } } return null; } /* * Returns Change-Forbid-Attribute conflict of the rule pair (r1, r2). */ private Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>> getChangeForbidAttributeConflictAtGraph( final Rule r1, final Rule r2, final Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>> changedAttrsL1, // final Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>> changedAttrsL2, final Hashtable<GraphObject, GraphObject> m1map, final Hashtable<GraphObject, GraphObject> m2map, // final OrdinaryMorphism isoG, // final Match m1test, final OrdinaryMorphism com1test, final Match m2) { // System.out.println("### getChangeForbidAttributeConflictAtGraph... "+r1.getName()+" && "+r2.getName()); // now check change-forbid attribute after apply r1 final List<OrdinaryMorphism> nacs2 = r2.getNACsList(); for (int i=0; i<nacs2.size(); i++) { final OrdinaryMorphism nac2 = nacs2.get(i); final OrdinaryMorphism nac2Star = (OrdinaryMorphism) m2.checkNAC(nac2); // System.out.println("### nac: "+ nac2.getName()+" nac2Star: "+nac2Star); if (nac2Star != null) { // System.out.println("### nac NOT satisfied! "+nac2.getName()); boolean critical = false; final Enumeration<GraphObject> nac2StarCodom = nac2Star.getCodomain(); while (nac2StarCodom.hasMoreElements()) { final GraphObject o = nac2StarCodom.nextElement(); final Enumeration<GraphObject> preimgR1 = com1test.getInverseImage(o); if (preimgR1.hasMoreElements()) { final GraphObject preimg = preimgR1.nextElement(); final Enumeration<GraphObject> preimgL1 = r1.getInverseImage(preimg); if (preimgL1.hasMoreElements()) { // final GraphObject prepreimg1 = preimgL1.nextElement(); // check attrs final GraphObject nac2go = nac2Star.getInverseImage(o).nextElement(); if (checkChangeForbidAttribute(nac2go, o, changedAttrsL1)) { o.setCritical(true); critical = true; } } } } if (critical) { // System.out.println("### Critical NAC: "+nac2.getName()); final Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>> p = new Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>( m1map, m2map); return p; } } } return null; } /* * Returns Change-Attribute conflicts of the rule pair (r1, r2). */ private Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> getChangeAttributeConflictsAtGraph( final Rule r1, final Rule r2, final Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>> changedAttrsL1, final Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>> changedAttrsL2) { // System.out.println("### getChangeAttributeConflictsAtGraph... ("+r1.getName()+", "+r2.getName()+")"); // System.out.println("### to change: "+super.preservedChanged); Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>> result = new Vector<Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>>>(); for (int i=0; i<this.r1Matches.size(); i++) { OrdinaryMorphism isoG = this.graph.isomorphicCopy(); if (isoG == null) { result = null; return null; } Hashtable<GraphObject, GraphObject> m1Map = this.r1Matches.get(i); Match m1 = BaseFactory.theFactory().createMatch(r1, isoG.getTarget()); if (setMapping(m1, isoG, m1Map)) { // make test step (r1,m1) OrdinaryMorphism com1 = null; try { com1 = (OrdinaryMorphism) TestStep.execute(m1); } catch (TypeException ex) { m1.dispose(); m1 = null; continue; } for (int j=0; j<this.r2Matches.size(); j++) { Hashtable<GraphObject, GraphObject> m2Map = this.r2Matches.get(j); Match m2 = BaseFactory.theFactory().createMatch(r2, isoG.getTarget()); if (setMapping(m2, isoG, m2Map)) { if (m2.areTotalIdentDanglSatisfied()) { // check change-use attribute after apply r1 Pair<Hashtable<GraphObject, GraphObject>, Hashtable<GraphObject, GraphObject>> p = this.getChangeUseAttributeConflictAtGraph( r1, r2, changedAttrsL1, // changedAttrsL2, m1Map, // isoG, m1, com1, m2); if (p != null) result.add(p); // check change-forbid attribute after apply r1 p = this.getChangeForbidAttributeConflictAtGraph( r1, r2, changedAttrsL1, // changedAttrsL2, m1Map, m2Map, // isoG, m1, com1, m2); if (p != null) result.add(p); } } } } } if (!result.isEmpty()) { result.trimToSize(); return result; } result = null; return null; } private boolean checkChangeForbidAttribute( final GraphObject other, final GraphObject changed, final Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>> changedAttrs) { ValueTuple otherAttr = (ValueTuple) other.getAttribute(); if (otherAttr == null) return true; Vector<Pair<ValueMember, ValueMember>> vec = changedAttrs.get(changed.getType().getAttrType()); if (vec == null) return true; for (int i=0; i<vec.size(); i++) { Pair<ValueMember, ValueMember> p = vec.get(i); ValueMember vmLeft = p.first; // ValueMember vmRight = p.second; ValueMember vmChanged = ((ValueTuple) changed.getAttribute()).getValueMemberAt(vmLeft.getName()); ValueMember vmOther = otherAttr.getValueMemberAt(vmLeft.getName()); if (vmOther.isSet()) { if (vmOther.getExpr().isVariable()) { String varValue = getValueOfVariable(this.rule2, vmOther.getExprAsText()); if (varValue != null && !varValue.equals(vmChanged.getExprAsText())) return false; } else if (vmOther.getExpr().isConstant()) { if (!vmOther.getExprAsText().equals(vmChanged.getExprAsText())) return false; } } } return true; } private boolean checkChangeUseAttribute( final GraphObject other, final GraphObject changed, final Hashtable<AttrType, Vector<Pair<ValueMember, ValueMember>>> changedAttrs) { ValueTuple otherAttr = (ValueTuple) other.getAttribute(); if (otherAttr == null) return true; Vector<Pair<ValueMember, ValueMember>> vec = changedAttrs.get(changed.getType().getAttrType()); if (vec == null) return true; for (int i=0; i<vec.size(); i++) { Pair<ValueMember, ValueMember> p = vec.get(i); ValueMember vmLeft = p.first; // ValueMember vmRight = p.second; ValueMember vmChanged = ((ValueTuple) changed.getAttribute()).getValueMemberAt(vmLeft.getName()); ValueMember vmOther = otherAttr.getValueMemberAt(vmLeft.getName()); if (vmOther.isSet()) { if (vmOther.getExpr().isVariable()) { String varValue = getValueOfVariable(this.rule2, vmOther.getExprAsText()); if (varValue != null && !varValue.equals(vmChanged.getExprAsText())) return false; } else if (vmOther.getExpr().isConstant()) { if (!vmOther.getExprAsText().equals(vmChanged.getExprAsText())) return false; } } } return true; } private String getValueOfVariable(Rule r, String varName) { VarTuple vars = (VarTuple) r.getAttrContext().getVariables(); VarMember var = vars.getVarMemberAt(varName); if (var.isSet()) return var.getExprAsText(); return null; } }