package agg.xt_basis; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Vector; import java.util.Hashtable; import agg.attribute.AttrInstance; import agg.attribute.AttrConditionTuple; import agg.attribute.AttrVariableTuple; import agg.attribute.AttrContext; import agg.attribute.AttrMapping; import agg.attribute.impl.AttrTupleManager; import agg.attribute.impl.DeclMember; import agg.attribute.impl.DeclTuple; import agg.attribute.impl.VarTuple; import agg.attribute.impl.VarMember; import agg.attribute.impl.ValueTuple; import agg.attribute.impl.ValueMember; import agg.attribute.impl.CondTuple; import agg.attribute.impl.CondMember; import agg.cons.AtomConstraint; import agg.cons.Convert; import agg.cons.AtomApplCond; import agg.cons.EvalSet; import agg.cons.Evaluable; import agg.cons.Formula; import agg.util.XMLHelper; import agg.util.XMLObject; import agg.util.Pair; import agg.xt_basis.agt.RuleScheme; import agg.xt_basis.csp.CompletionPropertyBits; /** * At the moment, AGG implements the DPO approach by switching on the * dangling-edge condition by default. Switching off the dangling condition allows * AGG to simulate the SPO approach. (SG, Aug.1999) * * @version $Id: Rule.java,v 1.121 2010/12/16 17:31:39 olga Exp $ * @author $Author: olga $ */ public class Rule extends OrdinaryMorphism implements XMLObject { protected Formula itsFormula = new Formula(true); protected String formStr = "true"; protected String formReadStr = "true"; final protected Vector<OrdinaryMorphism> itsACs = new Vector<OrdinaryMorphism>(); final protected Vector<OrdinaryMorphism> itsNACs = new Vector<OrdinaryMorphism>(); final protected Vector<OrdinaryMorphism> itsPACs = new Vector<OrdinaryMorphism>(); // containers for PostApplicationConditions transient protected boolean generatePostConstraints; protected Vector<AtomConstraint> itsUsedAtomics; protected Vector<Formula> itsUsedFormulas; transient protected Vector<String> constraintNameSet; transient protected Vector<Formula> constraints; transient protected Vector<EvalSet> atom_conditions; protected Vector<ShiftedPAC> itsShiftedPACs; transient protected boolean applicable; protected boolean parallelMatching; protected boolean randomCSPDomain; protected boolean startParallelMatchByFirstCSPVar; protected int layer; protected int priority; protected boolean triggerOfLayer; transient protected boolean isReady; transient protected boolean isDeleting, isNodeDeleting, isCreating, isChanging, hasEnabledGACs; transient protected List<GraphObject> preserved; transient protected List<GraphObject> created; transient protected List<GraphObject> deleted; transient protected List<GraphObject> forbiden; transient protected Hashtable<GraphObject, GraphObject> changedPreserved; transient protected List<String> typesWhichNeedMultiplicityCheck; protected Hashtable<Node, Type> abstractType2childType; protected Match itsMatch; protected boolean notApplicable, waitBeforeApply; private InverseRuleConstructData invConstruct; /** * Create myself. */ protected Rule() { super(); this.itsName = "Rule"; this.itsOrig.setName("Left"); this.itsOrig.setKind(GraphKind.LHS); this.itsImag.setName("Right"); this.itsImag.setKind(GraphKind.RHS); this.itsAttrContext = this.itsAttrManager.newContext(AttrMapping.PLAIN_MAP); this.itsOrig.setAttrContext(this.itsAttrManager.newLeftContext(this.itsAttrContext)); this.itsImag.setAttrContext(this.itsAttrManager.newRightContext(this.itsAttrContext)); this.generatePostConstraints = true; this.applicable = true; } /** * Create myself. */ protected Rule(TypeSet types) { super(BaseFactory.theFactory().createGraph(types), BaseFactory.theFactory().createGraph(types)); this.itsName = "Rule"; this.itsOrig.setName("Left"); this.itsOrig.setKind(GraphKind.LHS); this.itsImag.setName("Right"); this.itsImag.setKind(GraphKind.RHS); this.itsAttrContext = this.itsAttrManager.newContext(AttrMapping.PLAIN_MAP); this.itsOrig.setAttrContext(this.itsAttrManager.newLeftContext(this.itsAttrContext)); this.itsImag.setAttrContext(this.itsAttrManager.newRightContext(this.itsAttrContext)); this.generatePostConstraints = true; this.applicable = true; } /** * Create myself. * * @param left * my left graph. * @param right * my right graph. */ protected Rule(Graph left, Graph right) { super(left, right); this.itsName = "Rule"; this.itsOrig.setName("Left"); this.itsOrig.setKind(GraphKind.LHS); this.itsImag.setName("Right"); this.itsImag.setKind(GraphKind.RHS); this.itsAttrContext = this.itsAttrManager.newContext(AttrMapping.PLAIN_MAP); this.itsOrig.setAttrContext(this.itsAttrManager.newLeftContext(this.itsAttrContext)); this.itsImag.setAttrContext(this.itsAttrManager.newRightContext(this.itsAttrContext)); this.generatePostConstraints = true; this.applicable = true; } protected Rule(Graph left, Graph right, AttrContext cont) { super(left, right, cont); this.itsName = "Rule"; this.itsOrig.setName("Left"); this.itsOrig.setKind(GraphKind.LHS); this.itsImag.setName("Right"); this.itsImag.setKind(GraphKind.RHS); this.itsAttrContext = cont; this.itsOrig.setAttrContext(this.itsAttrManager.newLeftContext(cont)); this.itsImag.setAttrContext(this.itsAttrManager.newRightContext(cont)); this.generatePostConstraints = true; this.applicable = true; } public void disposeSuper() { super.dispose(); this.itsMatch = null; this.typesWhichNeedMultiplicityCheck = null; this.changed = false; } public void dispose() { super.dispose(); while (!this.itsNACs.isEmpty()) { this.itsNACs.get(0).dispose(false, true); this.itsNACs.remove(0); } this.itsNACs.trimToSize(); while (!this.itsPACs.isEmpty()) { this.itsPACs.get(0).dispose(false, true); this.itsPACs.remove(0); } this.itsPACs.trimToSize(); while (!this.itsACs.isEmpty()) { this.itsACs.get(0).dispose(false, true); this.itsACs.remove(0); } this.itsACs.trimToSize(); this.disposeInverseConstruct(); this.itsOrig.dispose(); this.itsImag.dispose(); this.itsMatch = null; this.typesWhichNeedMultiplicityCheck = null; this.changed = false; // System.out.println("Rule.dispose:: DONE "+this.hashCode()); } public void finalize() { // System.out.println("Rule.finalize() called "+this.hashCode()); } public void setName(String n) { this.itsName = n; this.itsFormula.setName("Formula.".concat(n)); } /** * Returns its name */ public String getQualifiedName() { return super.getName(); } public boolean hasChanged() { return this.changed || this.itsOrig.hasChanged() || this.itsImag.hasChanged(); } private void disposeMatch() { if (this.itsMatch != null) { this.itsMatch.dispose(); this.itsMatch = null; } } public void clearRule() { disposeMatch(); while (!this.itsNACs.isEmpty()) { this.itsNACs.get(0).dispose(false, true); this.itsNACs.remove(0); } while (!this.itsPACs.isEmpty()) { this.itsPACs.get(0).dispose(false, true); this.itsPACs.remove(0); } while (!this.itsACs.isEmpty()) { this.itsACs.get(0).dispose(false, true); this.itsACs.remove(0); } super.clear(); this.changed = false; this.itsOrig.clear(); this.itsImag.clear(); if (this.typesWhichNeedMultiplicityCheck != null) { this.typesWhichNeedMultiplicityCheck.clear(); this.typesWhichNeedMultiplicityCheck = null; } } public void disposeResultsOfNestedACs() { for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); ac.disposeResults(); } // System.gc(); } /** * Checks if the specified graph is its LHS, RHS, * target of a NAC, target of a PAC graph. */ public boolean isElement(Graph g) { if (this.itsOrig == g || this.itsImag == g) { return true; } for (int i = 0; i < this.itsNACs.size(); i++) { OrdinaryMorphism om = this.itsNACs.get(i); if (om.getTarget() == g) { return true; } } for (int i = 0; i < this.itsPACs.size(); i++) { OrdinaryMorphism om = this.itsPACs.get(i); if (om.getTarget() == g) { return true; } } for (int i = 0; i < this.itsACs.size(); i++) { OrdinaryMorphism om = this.itsACs.get(i); if (om.getTarget() == g) { return true; } } return false; } /** Returns its left graph. */ public final Graph getLeft() { return this.itsOrig; } /** Returns its right graph. */ public final Graph getRight() { return this.itsImag; } public boolean isNotApplicable() { return this.notApplicable; } /** * Returns the value which is set after <code>setApplicable(boolean appl)</code> called. */ public boolean isApplicable() { return !this.notApplicable && this.applicable; } /** * Checks whether this rule is applicable at the specified graph by the * specified matching strategy or not. * * <b>Pre:</b> check <code>isReadyToTransform()</code> should be done before * */ public boolean isApplicable(Graph g, MorphCompletionStrategy strategy) { return isApplicable(g, strategy, false); } /** * Checks whether this rule is applicable at the specified graph by the * specified matching strategy or not. */ public boolean isApplicable( final Graph g, final MorphCompletionStrategy strategy, final boolean doCheckIfReadyToTransform) { boolean result = this.enabled; //true; if (result && doCheckIfReadyToTransform) { result = this.isReadyToTransform(); } if (result) { result = false; Match m = BaseFactory.theFactory().createMatch(this, g); if (m != null) { m.setCompletionStrategy(strategy, true); m.enableInputParameter(false); // ((VarTuple) this.getAttrContext().getVariables()).showVariables(); // ((VarTuple) m.getAttrContext().getVariables()).showVariables(); if (m.nextCompletion()) { result = true; } // else { // System.out.println("Rule.isApplicable:: ERROR: "+m.getErrorMsg()+" "+this.errorMsg); // } m.dispose(); } } return result; } public void enableInputParameter(final boolean enable) { VarTuple vars = (VarTuple) this.getAttrContext().getVariables(); for (int i=0; i<vars.getNumberOfEntries(); i++) { VarMember vm = vars.getVarMemberAt(i); if (vm.isInputParameter()) { vm.setEnabled(enable); enableAttrConditionWithInputParameter(vm.getName(), enable); } } } private void enableAttrConditionWithInputParameter(final String ipName, final boolean enable) { CondTuple conds = (CondTuple) this.getAttrContext().getConditions(); for (int i=0; i<conds.getNumberOfEntries(); i++) { CondMember cond = conds.getCondMemberAt(i); if (cond.getAllVariables().contains(ipName)) { cond.setEnabled(enable); } } } /** * Checks whether the LHS of this rule is applicable at the specified graph by the * specified matching strategy. */ public boolean isLeftApplicable( final Graph g, final MorphCompletionStrategy strategy, final boolean doCheckIfReadyToTransform) { boolean result = true; if (doCheckIfReadyToTransform) { result = this.isReadyToTransform(); } if (result) { result = false; Hashtable<OrdinaryMorphism, Boolean> applcond2enable = new Hashtable<OrdinaryMorphism, Boolean>( this.itsNACs.size()+this.itsPACs.size()+this.itsACs.size()); // store nac.isEnabled() setting and disable nac for (int i = 0; i < this.itsNACs.size(); i++) { OrdinaryMorphism nac = this.itsNACs.get(i); applcond2enable.put(nac, Boolean.valueOf(nac.isEnabled())); nac.setEnabled(false); } // store pac.isEnabled() setting and disable nac for (int i = 0; i < this.itsPACs.size(); i++) { OrdinaryMorphism pac = this.itsPACs.get(i); applcond2enable.put(pac, Boolean.valueOf(pac.isEnabled())); pac.setEnabled(false); } // store ac.isEnabled() setting and disable ac for (int i = 0; i < this.itsACs.size(); i++) { OrdinaryMorphism ac = this.itsACs.get(i); applcond2enable.put(ac, Boolean.valueOf(ac.isEnabled())); ac.setEnabled(false); } Match m = BaseFactory.theFactory().createMatch(this, g); if (m != null) { m.setCompletionStrategy(strategy); while (m.nextCompletion()) { result = true; break; } } BaseFactory.theFactory().destroyMatch(m); // restore enable setting for (int i = 0; i < this.itsNACs.size(); i++) { this.itsNACs.get(i).setEnabled(applcond2enable.get(this.itsNACs.get(i)).booleanValue()); } for (int i = 0; i < this.itsPACs.size(); i++) { this.itsPACs.get(i).setEnabled(applcond2enable.get(this.itsPACs.get(i)).booleanValue()); } for (int i = 0; i < this.itsACs.size(); i++) { this.itsACs.get(i).setEnabled(applcond2enable.get(this.itsACs.get(i)).booleanValue()); } } return result; } public void enableNACs(boolean enable) { for (int i = 0; i < this.itsNACs.size(); i++) { this.itsNACs.get(i).setEnabled(enable); } } public void enablePACs(boolean enable) { for (int i = 0; i < this.itsPACs.size(); i++) { this.itsPACs.get(i).setEnabled(enable); } } public void setApplicable(boolean appl) { this.applicable = appl; } public TypeSet getTypeSet() { return getLeft().getTypeSet(); } // private Graph createCondGraph(final TypeSet types) { // return types.isArcDirected()? new Graph(types): new UndirectedGraph(types); // } /** * Creates and adds a new (nested) application condition (GAC). * Note, because a new morphism is empty and the LHS graph is not, * it is not a morphism in terms of theory, * which demands an application condition to be a total morphism. * * @return an empty morphism <code>ac</code> with * <code>ac.getOriginal() == this.getOriginal()</code>. */ public NestedApplCond createNestedAC() { final NestedApplCond ac = new NestedApplCond( getLeft(), BaseFactory.theFactory().createGraph(getRight().getTypeSet()), getRight().getAttrContext()); this.itsACs.add(ac); AttrContext acContext = ac.getAttrContext(); //getLeft().getAttrContext(); ac.getImage().setAttrContext(acContext); ac.getImage().setKind(GraphKind.AC); return ac; } /** * Creates and adds a new (nested) application condition (GAC). * The target graph of the new GAC is constructed due to RHS of this rule. */ public NestedApplCond createNestedACDuetoRHS() { final NestedApplCond nac = createNestedAC(); makeACDuetoRHS(nac); return nac; } /** * Adds the specified morphism representing a nested application condition. * <b>Pre:</b> <code>ac.getOriginal() == this.getOriginal()</code>. */ public boolean addNestedAC(final OrdinaryMorphism ac) { return this.addNestedAC(-1, ac); } /** * Adds the specified morphism representing a nested application condition * in the list at the specified index. * <b>Pre:</b> <code>ac.getOriginal() == this.getOriginal()</code>. */ public boolean addNestedAC(int indx, final OrdinaryMorphism ac) { if (!this.itsACs.contains(ac)) { ac.getTarget().setKind(GraphKind.AC); if (indx >= 0 && indx < this.itsACs.size()) this.itsACs.add(indx, ac); else this.itsACs.add(ac); this.changed = true; return true; } return false; } public void enableNestedAC(boolean enable) { for (int i = 0; i < this.itsACs.size(); i++) { this.itsACs.get(i).setEnabled(enable); } } /** * Destroys the specified application condition. * The image graph of the <code>ac</code> * morphism would be destroyed, too. */ public void destroyNestedAC(final OrdinaryMorphism ac) { this.itsACs.removeElement(ac); ac.getImage().dispose(); } /** * Returns true, if it contains nested application conditions. */ public boolean hasNestedACs() { return !this.itsACs.isEmpty(); } /** * Return an enumeration of nested application conditions. * An element is of type <code>OrdinaryMorphism</code>. */ public Enumeration<OrdinaryMorphism> getNestedACs() { return this.itsACs.elements(); } public List<NestedApplCond> getEnabledACs() { List<NestedApplCond> list = new Vector<NestedApplCond>(this.itsACs.size()); for (int i = 0; i < this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); if (ac.isEnabled()) list.add(ac); } return list; } public List<OrdinaryMorphism> getNestedACsList() { return this.itsACs; } public List<Evaluable> getEnabledGeneralACsAsEvaluable() { List<Evaluable> list = new Vector<Evaluable>(this.itsACs.size()); for (int i = 0; i < this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); if (ac.isEnabled()) list.add(ac); } return list; } /** * Returns an OrdinaryMorphism representing * a nested application condition with the specified name. */ public OrdinaryMorphism getNestedAC(String name) { for (int i = 0; i < this.itsACs.size(); i++) { OrdinaryMorphism ac = this.itsACs.get(i); if (ac.getName().equals(name)) return ac; } return null; } public OrdinaryMorphism getNestedAC(int indx) { if (indx >= 0 && indx < this.itsACs.size()) return this.itsACs.get(indx); else return null; } /** * Removes the specified application condition. * * @return <code>false</code> if <code>ac</code> is not found, * otherwise - <code>true</code>. */ public final boolean removeNestedAC(OrdinaryMorphism ac) { boolean enAC = ac.isEnabled(); if (this.itsACs.removeElement(ac)) { if (enAC) { this.itsFormula.patchOutEvaluable((NestedApplCond) ac, true); this.refreshFormula(new Vector<Evaluable>(this.getEnabledACs())); } return true; } return false; } public boolean nestedACIsUsingVariable( final VarMember var, final AttrConditionTuple act) { for (int i=0; i<this.itsACs.size(); i++) { final OrdinaryMorphism ac = this.itsACs.get(i); if (ac.getTarget().isUsingVariable(var)) { return true; } Vector<String> acVars = ac.getTarget() .getVariableNamesOfAttributes(); for (int j = 0; j < acVars.size(); j++) { String varName = acVars.get(j); for (int k = 0; k < act.getNumberOfEntries(); k++) { CondMember cond = (CondMember) act.getMemberAt(k); Vector<String> condVars = cond.getAllVariables(); if (condVars.contains(varName) && condVars.contains(var.getName())) { return true; } } } } return false; } /** * Creates a new negative application condition (NAC) and add it to its NACs. * Note, because a new morphism is empty and the LHS graph is not, * it is not a morphism in terms of theory, * which demands a NAC to be a total morphism. * * @return an empty morphism <code>nac</code> with * <code>nac.getOriginal() == this.getOriginal()</code>. */ public OrdinaryMorphism createNAC() { final OrdinaryMorphism nac = new OrdinaryMorphism( getLeft(), BaseFactory.theFactory().createGraph(getRight().getTypeSet()), getRight().getAttrContext()); this.itsNACs.addElement(nac); AttrContext nacContext = nac.getAttrContext(); //getLeft().getAttrContext(); nac.getImage().setAttrContext(nacContext); nac.getImage().setKind(GraphKind.NAC); return nac; } /** * Creates a new negative application condition (NAC) and add it to its NACs. * The target graph of the new NAC is constructed due to RHS of this rule. */ public OrdinaryMorphism createNACDuetoRHS() { final OrdinaryMorphism nac = createNAC(); makeACDuetoRHS(nac); return nac; } public void makeACDuetoRHS(final OrdinaryMorphism morph) { HashMap<Node,Node> map = new HashMap<Node,Node>(); Iterator<Node> nodes = this.itsImag.getNodesSet().iterator(); while (nodes.hasNext()) { Node nr = nodes.next(); Enumeration<GraphObject> l = this.getInverseImage(nr); if (l.hasMoreElements()) { Node nl = (Node)l.nextElement(); try { Node n = morph.getTarget().copyNode(nl); try { morph.addMapping(nl, n); while (l.hasMoreElements()) { morph.addMapping((Node)l.nextElement(), n); } map.put(nr, n); } catch (BadMappingException ex) {} } catch (TypeException e) {} } else { try { Node n = morph.getTarget().copyNode(nr); if (n.getAttribute() != null) ((agg.attribute.impl.ValueTuple)n.getAttribute()).unsetValueAsExpr(); map.put(nr, n); } catch (TypeException e) {} } } Iterator<Arc> arcs = this.itsImag.getArcsSet().iterator(); while (arcs.hasNext()) { Arc ar = arcs.next(); Enumeration<GraphObject> l = this.getInverseImage(ar); if (l.hasMoreElements()) { Arc al = (Arc) l.nextElement(); try { Arc a = morph.getTarget().copyArc(al, (Node)morph.getImage(al.getSource()), (Node)morph.getImage(al.getTarget())); try { morph.addMapping(al, a); while (l.hasMoreElements()) { morph.addMapping(l.nextElement(), a); } } catch (BadMappingException ex) {} } catch (TypeException e) {} } else { try { Node s = (Node)map.get(ar.getSource()); Node t = (Node)map.get(ar.getTarget()); Arc a = morph.getTarget().copyArc(ar, s, t); if (a.getAttribute() != null) ((agg.attribute.impl.ValueTuple)a.getAttribute()).unsetValueAsExpr(); } catch (TypeException e) {} } } map.clear(); map = null; } /** * Adds the specified morphism representing a negative application condition (NAC). * <p> * <b>Pre:</b> <code>nac.getOriginal() == this.getOriginal()</code>. */ public boolean addNAC(final OrdinaryMorphism nac) { return this.addNAC(-1, nac); } /** * Adds the specified morphism representing a negative application condition (NAC) * to the list at the specified index. * <p> * <b>Pre:</b> <code>nac.getOriginal() == this.getOriginal()</code>. */ public boolean addNAC(int indx, final OrdinaryMorphism nac) { if (!this.itsNACs.contains(nac)) { nac.getTarget().setKind(GraphKind.NAC); if (indx >= 0 && indx < this.itsNACs.size()) this.itsNACs.add(indx, nac); else this.itsNACs.add(nac); this.changed = true; return true; } return false; } /** * Destroys the specified NAC from my NACs. * The image graph of the nac morphism would be destroyed, too. */ public void destroyNAC(OrdinaryMorphism nac) { this.itsNACs.removeElement(nac); nac.getImage().dispose(); } /** * Returns true if it contains a NAC. */ public boolean hasNACs() { return !this.itsNACs.isEmpty(); } /** * Returns an enumeration of my NACs. */ public Enumeration<OrdinaryMorphism> getNACs() { return this.itsNACs.elements(); } /** * @deprecated replaced by <code>getNACsList()</code> */ public Vector<OrdinaryMorphism> getNACsVector() { return this.itsNACs; } public List<OrdinaryMorphism> getNACsList() { return this.itsNACs; } /** * Returns an OrdinaryMorphism representing a NAC with the specified name. */ public OrdinaryMorphism getNAC(String name) { for (int i = 0; i < this.itsNACs.size(); i++) { OrdinaryMorphism nac = this.itsNACs.get(i); if (nac.getName().equals(name)) return nac; } return null; } /** * Returns an OrdinaryMorphism representing a NAC at the specified index. */ public OrdinaryMorphism getNAC(int indx) { if (indx >= 0 && indx < this.itsNACs.size()) return this.itsNACs.get(indx); else return null; } /** * Returns an OrdinaryMorphism representing a NAC with the target as specified graph. */ public OrdinaryMorphism getNAC(final Graph g) { for (int i = 0; i < this.itsNACs.size(); i++) { OrdinaryMorphism ac = this.itsNACs.get(i); if (ac.getTarget() == g) return ac; } return null; } /** * Returns true if the specified Graph g is the target graph * of an OrdinaryMorphism representing a NAC. */ public boolean hasNAC(final Graph g) { for (int i = 0; i < this.itsNACs.size(); i++) { OrdinaryMorphism ac = this.itsNACs.get(i); if (ac.getTarget() == g) return true; } return false; } /** * Removes a negative application condition. * * @return <code>false</code> if <code>nac</code> is not found, * otherwise - <code>true</code>. */ public final boolean removeNAC(OrdinaryMorphism nac) { if (this.itsNACs.removeElement(nac)) { return true; } return false; } /** * Creates a new positive application condition (PAC) and add it to its PACs. * Note, because a new morphism is empty and the LHS is not, * it is not a morphism in terms of theory, * which demands a PAC to be a total morphism. * * @return an empty morphism <code>pac</code> with * <code>pac.getOriginal() == this.getOriginal()</code>. */ public OrdinaryMorphism createPAC() { final OrdinaryMorphism pac = new OrdinaryMorphism( getLeft(), BaseFactory.theFactory().createGraph(getRight().getTypeSet()), getRight().getAttrContext()); this.itsPACs.addElement(pac); AttrContext pacContext = pac.getAttrContext(); //getLeft().getAttrContext(); pac.getImage().setAttrContext(pacContext); pac.getImage().setKind(GraphKind.PAC); return pac; } /** * Adds the specified morphism representing a positive application condition (PAC). * <b>Pre:</b> <code>pac.getOriginal() == this.getOriginal()</code>. */ public boolean addPAC(final OrdinaryMorphism pac) { return this.addPAC(-1, pac); } /** * Adds the specified morphism representing a positive application condition (PAC) * in the list at the specified index. * <b>Pre:</b> <code>pac.getOriginal() == this.getOriginal()</code>. */ public boolean addPAC(int indx, final OrdinaryMorphism pac) { if (!this.itsPACs.contains(pac)) { pac.getTarget().setKind(GraphKind.PAC); if (indx >= 0 && indx < this.itsPACs.size()) this.itsPACs.add(indx, pac); else this.itsPACs.add(pac); this.changed = true; return true; } return false; } public void addShiftedPAC(final List<OrdinaryMorphism> list) { final ShiftedPAC shiftedPAC = new ShiftedPAC(list); if (this.itsShiftedPACs == null) itsShiftedPACs = new Vector<ShiftedPAC>(); this.itsShiftedPACs.add(shiftedPAC); } public List<ShiftedPAC> getShiftedPACs() { return this.itsShiftedPACs; } public boolean isShiftedPAC(final OrdinaryMorphism pac) { if (this.itsShiftedPACs == null) return false; for (int i=0; i<this.itsShiftedPACs.size(); i++) { if (this.itsShiftedPACs.get(i).contains(pac)) return true; } return false; } /** * Destroys the specified pac from my set of PACs. * The image graph of the pac * morphism would be destroyed, too. */ public void destroyPAC(final OrdinaryMorphism pac) { this.itsPACs.removeElement(pac); pac.getImage().dispose(); } /** * Returns true, if its contains a PAC. */ public boolean hasPACs() { return !this.itsPACs.isEmpty(); } /** * Return an enumeration of my PACs with elements of type * <code>OrdinaryMorphism</code>. */ public Enumeration<OrdinaryMorphism> getPACs() { return this.itsPACs.elements(); } /** * @deprecated replaced by <code>getPACsList()</code> * * Return the Vector of my PACs with elements of type * <code>OrdinaryMorphism</code>. */ public Vector<OrdinaryMorphism> getPACsVector() { return this.itsPACs; } public List<OrdinaryMorphism> getPACsList() { return this.itsPACs; } /** * Returns an OrdinaryMorphism representing a PAC with the specified name. */ public OrdinaryMorphism getPAC(String name) { for (int i = 0; i < this.itsPACs.size(); i++) { OrdinaryMorphism pac = this.itsPACs.get(i); if (pac.getName().equals(name)) return pac; } return null; } /** * Returns an OrdinaryMorphism representing a PAC at the specified index. */ public OrdinaryMorphism getPAC(int indx) { if (indx >= 0 && indx < this.itsPACs.size()) return this.itsPACs.get(indx); else return null; } /** * Returns an OrdinaryMorphism representing a PAC with target as specified Graph. */ public OrdinaryMorphism getPAC(final Graph g) { for (int i = 0; i < this.itsPACs.size(); i++) { OrdinaryMorphism ac = this.itsPACs.get(i); if (ac.getTarget() == g) return ac; } return null; } /** * Returns true if the specified Graph g is the target graph * of an OrdinaryMorphism representing a PAC. */ public boolean hasPAC(final Graph g) { for (int i = 0; i < this.itsPACs.size(); i++) { OrdinaryMorphism ac = this.itsPACs.get(i); if (ac.getTarget() == g) return true; } return false; } /** * Removes the specified positive application condition. * * @return <code>false</code> if <code>pac</code> is not found, * otherwise - <code>true</code>. */ public final boolean removePAC(OrdinaryMorphism pac) { if (this.itsPACs.removeElement(pac)) { return true; } return false; } // ///////////////////////////////////// /** * Returns FALSE if the specified nodeType is an abstract type and * used in the RHS to create a node, * otherwise - TRUE. */ public boolean checkCreateAbstractNode(Type nodeType) { Iterator<Node> en = getTarget().getNodesSet().iterator(); while (en.hasNext()) { Node n = en.next(); if (n.getType().equals(nodeType)) { if (!this.getInverseImage(n).hasMoreElements()) return false; } } return true; } public TypeError checkNewNodeRequiresArc() { final Iterator<Node> elems = this.getRight().getNodesSet().iterator(); while (elems.hasNext()) { final GraphObject obj = elems.next(); if (!this.getInverseImage(obj).hasMoreElements()) { List<String> list = this.getRight().getTypeSet().nodeRequiresArc((Node) obj); if (list != null && !list.isEmpty()) { TypeError actError = new TypeError(TypeError.TO_LESS_ARCS, "Node type " + "\""+obj.getType().getName()+ "\" \n" + "requires edge(s) of type: \n" + list.toString(), obj.getType()); actError.setContainingGraph(this.getRight()); return actError; } } } return null; } /** * Try to destroy all graph objects of the specified type from its graphs * (LHS, RHS, NACs, PACs, graph constraints). */ public boolean destroyObjectsOfType(Type t) { if (getLeft().destroyObjectsOfType(t)) { if (getRight().destroyObjectsOfType(t)) { for (int j = 0; j < this.itsNACs.size(); j++) { OrdinaryMorphism nac = this.itsNACs.get(j); if (!nac.getTarget().destroyObjectsOfType(t)) return false; } for (int j = 0; j < this.itsPACs.size(); j++) { OrdinaryMorphism pac = this.itsPACs.get(j); if (!pac.getTarget().destroyObjectsOfType(t)) return false; } for (int j = 0; j < this.itsACs.size(); j++) { OrdinaryMorphism ac = this.itsACs.get(j); if (!ac.getTarget().destroyObjectsOfType(t)) return false; } // delete from rule application conditions Vector<EvalSet> atom_conds = getAtomApplConds(); for (int i = 0; i < atom_conds.size(); i++) { Vector<?> v = atom_conds.get(i).getSet(); for (int j = 0; j < v.size(); j++) { Vector<?> v1 = ((EvalSet) v.get(j)).getSet(); for (int k = 0; k < v1.size(); k++) { agg.cons.AtomApplCond aac = (agg.cons.AtomApplCond) v1 .get(k); OrdinaryMorphism cond = aac.getPreCondition(); OrdinaryMorphism tm = aac.getT(); OrdinaryMorphism qm = aac.getQ(); cond.getSource().destroyObjectsOfType(t); cond.getTarget().destroyObjectsOfType(t); tm.getTarget().destroyObjectsOfType(t); qm.getSource().destroyObjectsOfType(t); } } } } } return true; } /** * Try to destroy all graph objects of the specified types from its graphs * (LHS, RHS, NACs, PACs, graph constraints). * Returns names of the failed types. */ public Vector<String> destroyObjectsOfTypes(Vector<Type> types) { Vector<String> failed = new Vector<String>(5); for (int i = 0; i < types.size(); i++) { Type t = types.get(i); if (!destroyObjectsOfType(t)) { String s = "Rule: " + getName() + " Type: " + t.getName(); failed.add(s); } } return failed; } /** * Returns a copy of this rule by using its types. */ public Rule getClone() { return BaseFactory.theFactory().cloneRule(this); } /** * Returns a copy of this rule by using the specified types. */ public Rule getClone(TypeSet types) { return BaseFactory.theFactory().cloneRule(this, types, true); } /** * Return its morphism between the left and right graphs. */ public final OrdinaryMorphism getMorphism() { return this; } /** * Returns its graph constraints * which can be converted to the post application constraints. */ public Vector<Formula> getConstraints() { return (this.constraints != null) ? this.constraints : new Vector<Formula>(0); } /** * Checks the type compatibility of two graph objects. * The first object should belong to the LHS, the second - to the RHS, * to be used for a mapping of the rule morphism. */ protected boolean checkType(Type orig, Type image) { return orig.compareTo(image); } public void createAttrInstanceWhereNeeded() { this.itsOrig.createAttrInstanceWhereNeeded(); this.itsImag.createAttrInstanceWhereNeeded(); for (int i=0; i<this.itsNACs.size(); i++) { this.itsNACs.get(i).getTarget().createAttrInstanceWhereNeeded(); } for (int i=0; i<this.itsPACs.size(); i++) { this.itsPACs.get(i).getTarget().createAttrInstanceWhereNeeded(); } for (int i=0; i<this.itsACs.size(); i++) { this.itsACs.get(i).getTarget().createAttrInstanceWhereNeeded(); } } public void createAttrInstanceOfTypeWhereNeeded(final Type t) { this.itsOrig.createAttrInstanceOfTypeWhereNeeded(t); this.itsImag.createAttrInstanceOfTypeWhereNeeded(t); for (int i=0; i<this.itsNACs.size(); i++) { this.itsNACs.get(i).getTarget().createAttrInstanceOfTypeWhereNeeded(t); } for (int i=0; i<this.itsPACs.size(); i++) { this.itsPACs.get(i).getTarget().createAttrInstanceOfTypeWhereNeeded(t); } for (int i=0; i<this.itsACs.size(); i++) { this.itsACs.get(i).getTarget().createAttrInstanceOfTypeWhereNeeded(t); } } /** * Generates rule post application conditions from its constraints(formulas). * Returns error message if something gone wrong, otherwise - empty. */ public String convertUsedFormulas() { if (this.itsUsedAtomics != null && this.itsUsedAtomics.size() > 0 && this.itsUsedFormulas != null && this.itsUsedFormulas.size() > 0) { String msg = ""; Vector<EvalSet> fin = new Vector<EvalSet>(); Vector<String> names = new Vector<String>(); // clear Post Appl. Conditions if (this.constraints == null) constraints = new Vector<Formula>(); else this.constraints.clear(); setAtomApplConds(null, null); final Hashtable<AtomConstraint,EvalSet> atomic2set = new Hashtable<AtomConstraint,EvalSet>(); final Hashtable<String,String> failedAtomic2error = new Hashtable<String,String>(); int tgLevel = this.getTypeSet().getLevelOfTypeGraphCheck(); if (tgLevel > TypeSet.ENABLED_MAX) this.getTypeSet().setLevelOfTypeGraph(TypeSet.ENABLED_MAX); for (int j = 0; j < this.itsUsedAtomics.size(); j++) { AtomConstraint a = this.itsUsedAtomics.elementAt(j); if (!a.isValid()) { msg = "Atomic \"" + a.getAtomicName() + "\" is not valid. <br>"; this.itsUsedAtomics.clear(); this.itsUsedFormulas.clear(); return msg; } ((AttrTupleManager) AttrTupleManager.getDefaultManager()) .setVariableContext(true); Convert conv = new Convert(this, a); Vector<Object> v = conv.convert(); ((AttrTupleManager) AttrTupleManager.getDefaultManager()) .setVariableContext(false); final EvalSet set = new EvalSet(v); fin.add(set); names.add(a.getAtomicName()); if (!v.isEmpty()) { atomic2set.put(a, set); } if (!"".equals(conv.getErrorMsg())) { failedAtomic2error.put(a.getAtomicName(), conv.getErrorMsg()); } } this.getTypeSet().setLevelOfTypeGraph(tgLevel); if (!failedAtomic2error.isEmpty()) { msg = "Error(s) during creating Post Application Condition : <br>"; } for (int j = 0; j < this.itsUsedFormulas.size(); j++) { Formula f = this.itsUsedFormulas.elementAt(j); if (!f.isEnabled()) { continue; } Vector<Evaluable> v = new Vector<Evaluable>(); String s = f.getAsString(v); // System.out.println(s); // System.out.println(v); // In v the atomics used in f are noted. // In fin the set of _all_new atomics are noted // (though they are real formulas now) in the original order. // This means, we need a translation. // I.e. we build a new vector as the source of a new formula // only containing the base formulas // corresponding to the atomic at that index. boolean formulaOK = true; Vector<Evaluable> v2 = new Vector<Evaluable>(); for (int k = 0; k < v.size(); k++) { Object e = v.get(k); boolean convertOK = false; int k2; for (k2 = 0; k2 < this.itsUsedAtomics.size(); k2++) { if (this.itsUsedAtomics.get(k2) == e) { final String atomicName = this.itsUsedAtomics.get(k2).getAtomicName(); // System.out.println(atomicName)); Evaluable set = atomic2set.get(e); if (set != null) { v2.add(set); convertOK = true; break; } int indx = names.indexOf(atomicName); fin.remove(indx); names.remove(indx); } } if (!convertOK) { formulaOK = false; break; } } if (formulaOK) { Formula f2 = new Formula(v2, s); this.constraints.add(f2); } } if (fin.isEmpty()) { this.itsUsedAtomics.clear(); this.itsUsedFormulas.clear(); } else { this.setAtomApplConds(fin, names); } deleteTransientContextVariables(getSource()); deleteTransientContextVariables(getTarget()); this.removeUnusedVariableOfAttrContext(); String msg1 = "Cannot convert atomic(s) :\n"; String msg2 = ""; final Enumeration<String> failedAtomic = failedAtomic2error.keys(); while (failedAtomic.hasMoreElements()) { String name = failedAtomic.nextElement(); String error = failedAtomic2error.get(name); msg2 = msg2.concat(" - ").concat(name).concat(" - ").concat("\n"); msg2 = msg2.concat(error).concat("\n"); } if (!"".equals(msg2)) { msg1 = msg1.concat(msg2); msg = msg.concat(msg1); } return msg; } else { return "Cannot create post application conditions. There isn't any formula selected. <br>"; } } /** * Set a vector of atomic graph constraints used for generating post * application conditions. Elements of the usedAtomic are of the type * agg.cons.AtomConstraint . * * private void setUsedAtomics(Vector usedAtomics) { itsUsedAtomics = * usedAtomics; } */ /** * Set its constraints (formulas) which will be used for generating its post * application conditions. */ public void setUsedFormulas(List<Formula> formulasToUse) { if (!formulasToUse.isEmpty()) { if (this.itsUsedFormulas == null) itsUsedFormulas = new Vector<Formula>(); else this.itsUsedFormulas.clear(); if (this.itsUsedAtomics == null) itsUsedAtomics = new Vector<AtomConstraint>(); else this.itsUsedAtomics.clear(); this.itsUsedFormulas.addAll(formulasToUse); for (int i = 0; i < this.itsUsedFormulas.size(); i++) { Formula f = this.itsUsedFormulas.get(i); Vector<Evaluable> vec = new Vector<Evaluable>(); String form = f.getAsString(vec); for (int j = 0; j < vec.size(); j++) { if (vec.get(j) instanceof AtomConstraint) { AtomConstraint ac = (AtomConstraint) vec.get(j); this.itsUsedAtomics.addElement(ac); } else { System.out .println("Rule.setUsedFormulas(Vector<Formula> usedFormulas): formula: " + form + " FAILED!"); } } } } } /** * Return a vector of atomic graph constraints used for generating post * application conditions. Elements of the usedAtomic are of the type * agg.cons.AtomConstraint . */ public Vector<AtomConstraint> getUsedAtomics() { return (this.itsUsedAtomics != null) ? this.itsUsedAtomics : new Vector<AtomConstraint>(0); } /** * Return the vector of constraints (formulas) used for generating post * application conditions. Elements of the usedFormulas are of the type * agg.cons.Formula . */ public Vector<Formula> getUsedFormulas() { return (this.itsUsedFormulas != null) ? this.itsUsedFormulas : new Vector<Formula>(0); } /** * Clears its lists of graph constraints only if the specified * atomic graph constraint belongs to its constraints. */ public void clearConstraints(AtomConstraint ac) { if (this.itsUsedAtomics != null && this.itsUsedAtomics.contains(ac)) { this.clearConstraints(); } } /** * Clears its lists of graph constraints only if the specified * graph constraint belongs to its constraints. */ public void clearConstraints(Formula f) { if (this.itsUsedFormulas != null && this.itsUsedFormulas.contains(f)) { this.clearConstraints(); } } /** * Clears lists of its graph constraints. */ public void clearConstraints() { if (this.itsUsedAtomics != null) this.itsUsedAtomics.clear(); if (this.itsUsedFormulas != null) this.itsUsedFormulas.clear(); if (this.constraints != null) this.constraints.clear(); setAtomApplConds(null, null); } /** * Set the specified post application conditions to its conditions. */ public void setAtomApplConds(Vector<EvalSet> v, Vector<String> names) { if (this.atom_conditions == null) atom_conditions = new Vector<EvalSet>(); else this.atom_conditions.clear(); if (this.constraintNameSet == null) constraintNameSet = new Vector<String>(); else this.constraintNameSet.clear(); if (v != null) this.atom_conditions.addAll(v); if (names != null) this.constraintNameSet.addAll(names); if (this.constraintNameSet.size() < this.atom_conditions.size()) { for (int i = this.constraintNameSet.size(); i < this.atom_conditions.size(); i++) this.constraintNameSet.add("Unknown Name " + i); } } public Vector<EvalSet> getAtomApplConds() { return (this.atom_conditions != null) ? this.atom_conditions : new Vector<EvalSet>(0); } public Vector<String> getConstraintNames() { return (this.constraintNameSet != null) ? this.constraintNameSet : new Vector<String>(0); } /** * Removes the specified application condition from its * post application conditions. */ public void removeConstraint(EvalSet constraint) { if (this.atom_conditions != null && this.atom_conditions.contains(constraint)) { int i = this.atom_conditions.indexOf(constraint); this.atom_conditions.removeElement(constraint); this.constraintNameSet.removeElementAt(i); } } /** * Removes the specified atomic application condition from its * post application conditions. */ public void removeAtomApplCond(AtomApplCond atom) { if (this.atom_conditions != null) { int i = 0; while (i < this.atom_conditions.size()) { Vector<?> v = this.atom_conditions.get(i).getSet(); int j = 0; while (j < v.size()) { Vector<?> v1 = ((EvalSet) v.get(j)).getSet(); int k = 0; while (k < v1.size()) { AtomApplCond aac = (AtomApplCond) v1.get(k); if (atom.equals(aac)) { v1.removeElement(atom); // System.out.println("AtomApplCond: DONE"); k = v1.size(); } else k++; } if (v1.size() == 0) { v.removeElementAt(j); j = v.size(); } else j++; } if (v.size() == 0) { this.atom_conditions.removeElementAt(i); this.constraintNameSet.removeElementAt(i); i = this.atom_conditions.size(); } else i++; } } } /** * Clears its application constraints. */ public void removeApplConditions() { clearConstraints(); } // /** // * Enable or disable this rule to make it usable during graph // transformation. // */ // public void setEnabled(boolean enable) { // enabled = enable; // // System.out.println("Rule.setEnabled "+enabled); // } // // /** // * Returns TRUE if this rule is usable during graph transformation // otherwise FALSE. // */ // public boolean isEnabled() { // return enabled; // } /** * Set this rule to be a trigger rule of its layer. That means: This rule * will be the first rule to apply on its layer. It can be applyed one time * only. All other rules on this layer can be applyed so long as possible. * * @param trigger */ public void setTriggerForLayer(boolean trigger) { this.triggerOfLayer = trigger; } /** Checks if this rule is a trigger rule of its layer. */ public boolean isTriggerOfLayer() { return this.triggerOfLayer; } /** * Returns its layer. The layer will be used by layered grammar. */ public int getLayer() { return this.layer; } /** * Sets its layer. The layer is used by layered grammar. */ public void setLayer(int l) { this.layer = l; } /** * Returns my priority. The priority cann be used during graph * transformation. */ public int getPriority() { return this.priority; } /** * Sets my priority. The priority cann be used during graph transformation. */ public void setPriority(int p) { this.priority = p; } /** * Trims the capacity of used vectors to be the vector's current * size. */ public void trimToSize() { super.trimToSize(); this.itsNACs.trimToSize(); for (int i = 0; i < this.itsNACs.size(); i++) { this.itsNACs.elementAt(i).trimToSize(); } this.itsPACs.trimToSize(); for (int i = 0; i < this.itsPACs.size(); i++) { this.itsPACs.elementAt(i).trimToSize(); } this.itsACs.trimToSize(); for (int i = 0; i < this.itsACs.size(); i++) { this.itsACs.elementAt(i).trimToSize(); } if (this.itsUsedAtomics != null) { this.itsUsedAtomics.trimToSize(); for (int i = 0; i < this.itsUsedAtomics.size(); i++) { this.itsUsedAtomics.get(i).trimToSize(); } } if (this.itsUsedFormulas != null) { this.itsUsedFormulas.trimToSize(); for (int i = 0; i < this.itsUsedFormulas.size(); i++) { this.itsUsedFormulas.trimToSize(); } } if (this.constraints != null) { this.constraints.trimToSize(); for (int i = 0; i < this.constraints.size(); i++) { this.constraints.trimToSize(); } } if (this.atom_conditions != null) this.atom_conditions.trimToSize(); if (this.constraintNameSet != null) this.constraintNameSet.trimToSize(); if (this.itsShiftedPACs != null) this.itsShiftedPACs.trimToSize(); } public void refreshAttributed() { getLeft().refreshAttributed(); getRight().refreshAttributed(); for (int i = 0; i < this.itsNACs.size(); i++) { this.itsNACs.elementAt(i).getTarget().refreshAttributed(); } for (int i = 0; i < this.itsPACs.size(); i++) { this.itsPACs.elementAt(i).getTarget().refreshAttributed(); } for (int i = 0; i < this.itsACs.size(); i++) { this.itsACs.elementAt(i).getTarget().refreshAttributed(); } } /** Returns true if this rule, its NACs or PACs are using the specified type * which is an element (node or edge) of a type graph. */ public boolean isUsingType(GraphObject typeObj) { if (getLeft().isUsingType(typeObj)) return true; if (getRight().isUsingType(typeObj)) return true; for (int i = 0; i < this.itsNACs.size(); i++) { if (this.itsNACs.elementAt(i).getTarget().isUsingType(typeObj)) return true; } for (int i = 0; i < this.itsPACs.size(); i++) { if (this.itsPACs.elementAt(i).getTarget().isUsingType(typeObj)) return true; } for (int i = 0; i < this.itsACs.size(); i++) { this.itsACs.elementAt(i).getTarget().refreshAttributed(); } return false; } public void removeUnusedVariableOfAttrContext() { DeclTuple vars = ((VarTuple) this.getAttrContext().getVariables()).getTupleType(); for (int i=0; i<vars.getNumberOfEntries(); i++) { DeclMember vm = (DeclMember) vars.getMemberAt(i); String var = vm.getName(); if (!this.getSource().getVariableNamesOfAttributes().contains(var)) { if (!this.getRight().getVariableNamesOfAttributes().contains(var)) { if (!isUsedInTargetGraph(this.getNACs(), var)) { if (!isUsedInTargetGraph(this.getPACs(), var)) { if (!isUsedInNestedGraphs(this.getNestedACs(), var)) { vars.getTupleType().deleteMemberAt(var); // System.out.println("Rule.removeVariableOfAttrContext:: removed: "+var); i--; } } } } } } } private boolean isUsedInTargetGraph(Enumeration<OrdinaryMorphism> list, String varName) { while (list.hasMoreElements()) { Graph g = list.nextElement().getTarget(); if (g.getVariableNamesOfAttributes().contains(varName)) { return true; } } return false; } private boolean isUsedInNestedGraphs(Enumeration<OrdinaryMorphism> list, String varName) { while (list.hasMoreElements()) { OrdinaryMorphism m = list.nextElement(); if (m.getTarget().getVariableNamesOfAttributes().contains(varName)) { return true; } if (m instanceof NestedApplCond) { Vector<OrdinaryMorphism> nl = new Vector<OrdinaryMorphism>(); for (int i=0; i<((NestedApplCond)m).getNestedACs().size(); i++) { nl.add(((NestedApplCond)m).getNestedACs().get(i)); } if (isUsedInNestedGraphs(nl.elements(), varName)) return true; } } return false; } public void setWaitBeforeApplyEnabled(boolean b) { this.waitBeforeApply = b; } public boolean isWaitBeforeApplyEnabled() { return this.waitBeforeApply; } /* * Create and return a new subrule. It is automatically added to my set of * subrules. The new subrule, the subrule's set of NACs, and its left and * right-hand side graphs which are newly created are initially empty. * <p> * Note that the newly created left and right side subgraphs are not * automatically removed when the subrule itself is destroyed. * * @see agg.xt_basis.Rule#getSubRules */ // public final SubRule createSubRule() { // SubRule sr = new SubRule(this, getLeft().createSubGraph(), getRight() // .createSubGraph()); // if (itsSubRules == null) // itsSubRules = new Vector<SubRule>(5, 1); // itsSubRules.addElement(sr); // return sr; // } /** * Create and return a new subrule. It is automatically added to my set of * subrules. The new subrule's left and right-hand side graphs are set to be * <code>left</code> and <code>right</code>, respectively. The subrule * is filled so that it maps all the objects of <code>left</code> in the * same way I do. The set of NACs of the new subrule is initially empty. * <p> * <b>Pre:</b> * <ol> * <li> <code>left</code> is subgraph of <code>this.getLeft()</code>. * <li> <code>right</code> is subgraph of <code>this.getRight()</code>. * </ol> * * @see agg.xt_basis.Rule#getSubRules * @see agg.xt_basis.Rule#getLeft * @see agg.xt_basis.Rule#getRight */ // public final SubRule createSubRule(SubGraph left, SubGraph right) { // SubRule sr = new SubRule(this, left, right); // if (itsSubRules == null) // itsSubRules = new Vector<SubRule>(5, 1); // itsSubRules.addElement(sr); // return sr; // // } // // public final SubRule createSubRule(SubGraGra sgg) { // SubRule sr = new SubRule(this, new SubGraph(this.getLeft()), // new SubGraph(this.getRight())); // itsSubRules.addElement(sr); // if (sgg != null) // sgg.addRule(sr); // return sr; // } /** * Remove a subrule from my set of subrules. * * @return <code>false</code> iff <code>sr</code> was not an element of * my set of subrules. */ // public final boolean destroySubRule(SubRule sr) { // if (sr != null) { // if (itsSubRules.remove(sr)) { // sr.dispose(); // return true; // } // } // return false; // } /** * Return an Enumeration of all of my subrules (not including myself). * Enumeration elements are of type <code>SubRule</code>. */ // public final Enumeration<SubRule> getSubRules() { // return itsSubRules.elements(); // } /** * Implements the interface of XMLObject */ public void XwriteObject(XMLHelper h) { this.changed = false; h.openNewElem("Rule", this); h.addAttr("name", this.itsName); if (!"".equals(this.formStr)) h.addAttr("formula", this.formStr); if (!this.enabled) h.addAttr("enabled", "false"); if (this.triggerOfLayer) h.addAttr("trigger", "true"); if (this.parallelMatching) h.addAttr("parallel", "true"); if (this.startParallelMatchByFirstCSPVar) h.addAttr("parallelByFirst", "true"); if (this.waitBeforeApply) h.addAttr("waitBeforeApply", "true"); AttrContext context = getAttrContext(); h.addObject("", context.getVariables(), true); getSource().setKind(GraphKind.LHS); h.addObject("", getSource(), true); getSource().setKind(GraphKind.RHS); h.addObject("", getTarget(), true); // String namestr = this.getName(); writeMorphism(h); // NACs Enumeration<OrdinaryMorphism> nacs = getNACs(); // PACs Enumeration<OrdinaryMorphism> pacs = getPACs(); // nested ACs Enumeration<OrdinaryMorphism> nested = getNestedACs(); // Attr context conditions AttrConditionTuple condt = context.getConditions(); int num = condt.getNumberOfEntries(); if (nested.hasMoreElements() || nacs.hasMoreElements() || pacs.hasMoreElements() || (num > 0) || (this.itsUsedAtomics != null && this.itsUsedAtomics.size() > 0)) { h.openSubTag("ApplCondition"); // NACs while (nacs.hasMoreElements()) { OrdinaryMorphism m = nacs.nextElement(); m.getTarget().setKind(GraphKind.NAC); h.openSubTag("NAC"); if (!m.isEnabled()) h.addAttr("enabled", "false"); h.addObject("", m.getTarget(), true); m.writeMorphism(h); h.close(); } // PACs while (pacs.hasMoreElements()) { OrdinaryMorphism m = pacs.nextElement(); m.getTarget().setKind(GraphKind.PAC); h.openSubTag("PAC"); if (!m.isEnabled()) h.addAttr("enabled", "false"); h.addObject("", m.getTarget(), true); m.writeMorphism(h); h.close(); } // nested ACs while (nested.hasMoreElements()) { OrdinaryMorphism m = nested.nextElement(); m.getTarget().setKind(GraphKind.AC); h.openSubTag("NestedAC"); if (!m.isEnabled()) h.addAttr("enabled", "false"); h.addObject("", m.getTarget(), true); m.writeMorphism(h); ((NestedApplCond) m).writeNestedApplConds(h); h.close(); } // Attr context conditions if (num > 0) { h.openSubTag("AttrCondition"); h.addObject("", condt, true); h.close(); } // Post Application Constraints if ((this.itsUsedAtomics != null && this.itsUsedAtomics.size() > 0) && (this.itsUsedFormulas != null && this.itsUsedFormulas.size() > 0)) { h.openSubTag("PostApplicationCondition"); // save formulas for (int i = 0; i < this.itsUsedFormulas.size(); i++) { Formula f = this.itsUsedFormulas.elementAt(i); h.openSubTag("FormulaRef"); h.addObject("f", f, false); h.close(); } h.close(); } h.close(); // ApplCondition } // TaggedValue layer h.openSubTag("TaggedValue"); h.addAttr("Tag", "layer"); h.addAttr("TagValue", this.layer); h.close(); // TaggedValue priority h.openSubTag("TaggedValue"); h.addAttr("Tag", "priority"); h.addAttr("TagValue", this.priority); h.close(); h.close(); } /** * Implements the interface of XMLObject */ public void XreadObject(XMLHelper h) { if (h.isTag("Rule", this)) { String attrStr = h.readAttr("formula"); if (!"".equals(attrStr)) this.formStr = attrStr; else this.formStr = "true"; this.setTextualComment("Formula: ".concat(this.formStr)); attrStr = h.readAttr("enabled"); if (attrStr != null && attrStr.equals("false")) this.enabled = false; else this.enabled = true; attrStr = h.readAttr("trigger"); if (attrStr != null && attrStr.equals("true")) this.triggerOfLayer = true; else this.triggerOfLayer = false; attrStr = h.readAttr("parallel"); if (attrStr != null && attrStr.equals("true")) this.parallelMatching = true; else this.parallelMatching = false; attrStr = h.readAttr("parallelByFirst"); if (attrStr != null && attrStr.equals("true")) this.startParallelMatchByFirstCSPVar = true; else this.startParallelMatchByFirstCSPVar = false; attrStr = h.readAttr("waitBeforeApply"); if (attrStr != null && attrStr.equals("true")) this.waitBeforeApply = true; else this.waitBeforeApply = false; h.enrichObject(getAttrContext().getVariables()); h.getObject("", getSource(), true); h.getObject("", getTarget(), true); readMorphism(h); this.itsOrig.setName("LeftOf_" + getName()); this.itsOrig.setKind(GraphKind.LHS); this.itsOrig.setHelpInfo(this.getName()); this.itsImag.setName("RightOf_" + getName()); this.itsImag.setKind(GraphKind.RHS); this.itsImag.setHelpInfo(this.getName()); Vector<Formula> tmpFormulas = new Vector<Formula>(); // of PostApplicationCondition // Vector<NestedApplCond> nacs = new Vector<NestedApplCond>(); // Vector<NestedApplCond> pacs = new Vector<NestedApplCond>(); // boolean needConvertToFormula = false; if (h.readSubTag("ApplCondition")) { while (h.readSubTag("NAC")) { boolean nacEnabled = true; Object nacattr_enabled = h.readAttr("enabled"); if ((nacattr_enabled != null) && ((String) nacattr_enabled).equals("false")) nacEnabled = false; OrdinaryMorphism nac = createNAC(); // NestedApplCond nac = createNestedAC(); // nacs.add(nac); // needConvertToFormula = true; nac.getTarget().setHelpInfo(this.getName()); nac.getTarget().xyAttr = this.getLeft().xyAttr; h.getObject("", nac.getTarget(), true); nac.readMorphism(h); h.close(); nac.setEnabled(nacEnabled); nac.getTarget().setHelpInfo(""); } while (h.readSubTag("PAC")) { boolean pacEnabled = true; Object pacattr_enabled = h.readAttr("enabled"); if ((pacattr_enabled != null) && ((String) pacattr_enabled).equals("false")) pacEnabled = false; OrdinaryMorphism pac = createPAC(); // NestedApplCond pac = createNestedAC(); // pacs.add(pac); // needConvertToFormula = true; pac.getTarget().setHelpInfo(this.getName()); pac.getTarget().xyAttr = this.getLeft().xyAttr; h.getObject("", pac.getTarget(), true); pac.readMorphism(h); h.close(); pac.setEnabled(pacEnabled); pac.getTarget().setHelpInfo(""); } while (h.readSubTag("NestedAC")) { // needConvertToFormula = false; boolean acEnabled = true; Object acattr_enabled = h.readAttr("enabled"); if ((acattr_enabled != null) && ((String) acattr_enabled).equals("false")) acEnabled = false; NestedApplCond ac = createNestedAC(); ac.getTarget().setHelpInfo(this.getName()); ac.getTarget().xyAttr = this.getLeft().xyAttr; h.getObject("", ac.getTarget(), true); ac.readMorphism(h); ac.readNestedApplConds(h); h.close(); ac.setEnabled(acEnabled); ac.getTarget().setHelpInfo(""); } if (h.readSubTag("AttrCondition")) { AttrConditionTuple condt = getAttrContext().getConditions(); if (condt != null) h.enrichObject(condt); h.close(); } // read Post Application Constraints if (h.readSubTag("PostApplicationCondition")) { // System.out.println("PostApplicationCondition"); // read formulas while (h.readSubTag("FormulaRef")) { Formula f = new Formula(true); f.setName(""); Formula f1 = (Formula) h.getObject("f", null, false); // System.out.println("Formula: "+f1); if (f1 != null) tmpFormulas.addElement(f1); h.close(); } h.close(); // generatePostConstraints = true; // setUsedFormulas(tmpFormulas); // convertUsedFormulas(); } h.close(); } // read layer if (h.readSubTag("TaggedValue")) { int v = 0; String t = h.readAttr("Tag"); // read old attribute int v1 = h.readIAttr("Value"); // read new attribute int v2 = h.readIAttr("TagValue"); if (v1 > 0) v = v1; else if (v2 > 0) v = v2; if (t.equals("layer")) this.layer = v; h.close(); } // read priority if (h.readSubTag("TaggedValue")) { int v = 0; String t = h.readAttr("Tag"); // read old attribute int v1 = h.readIAttr("Value"); // read new attribute int v2 = h.readIAttr("TagValue"); if (v1 > 0) v = v1; else if (v2 > 0) v = v2; if (t.equals("priority")) this.priority = v; h.close(); } /* * alte Variante : NOT MORE USED! / read Post Application * Constraints generatePostConstraints = false; * if(h.readSubTag("TaggedValue")) { String t = h.readAttr("Tag"); * int v = h.readIAttr("Value"); if(t.equals("post_constraints")) { * if(v != 0) generatePostConstraints = true; } h.close(); } */ h.close(); this.applicable = true; setUsedFormulas(tmpFormulas); this.itsOrig.setHelpInfo(""); this.itsImag.setHelpInfo(""); // if ( needConvertToFormula && "true".equals(this.formStr)) { // convertToFormula(pacs, nacs); // } // else this.setFormula(this.formStr); } } @SuppressWarnings("unused") private boolean convertToFormula( final List<NestedApplCond> pacs, final List<NestedApplCond> nacs) { final List<Evaluable> vars = new Vector<Evaluable>(this.itsACs.size()); if (this.itsACs.size() == 0) { this.formStr = "true"; this.formReadStr = this.formStr; return true; } String tmp = ""; int indx = -1; for (int i=0; i<pacs.size(); i++) { NestedApplCond ac = pacs.get(i); if (ac.isEnabled()) { indx++; vars.add(ac); if (vars.size() == 1) tmp = tmp.concat(String.valueOf(indx+1)); else tmp = tmp.concat("&").concat(String.valueOf(indx+1)); } } for (int i=0; i<nacs.size(); i++) { NestedApplCond ac = nacs.get(i); if (ac.isEnabled()) { indx++; vars.add(ac); if (vars.size() == 1) tmp = tmp.concat("!".concat(String.valueOf(indx+1))); else tmp = tmp.concat("&!").concat(String.valueOf(indx+1)); } } if ("".equals(tmp)) { this.formStr = "true"; this.formReadStr = this.formStr; return true; } if (this.itsFormula.setFormula(vars, tmp)) { this.formStr = this.itsFormula.getAsString(vars); this.formReadStr = this.formStr; // System.out.println("Rule: "+this.getName()+" formula: "+this.formStr); return true; } return false; } // ------ additional methods according to Gabi's new AGG design --------- // ----------- attention: yet untested! (SG, Aug.1999) ------------------ /** * Returns an inverted rule. This rule has to be injective, * otherwise - returns null. * The attribute mappings are NOT inverted, thus: the resulting left and * right-hand side graphs are not attributed anymore. */ public Rule invertSimplex() { if (!this.isInjective()) { return (null); } Rule inverse = new Rule(); Graph lgraph = this.getLeft(); Graph rgraph = this.getRight(); Graph linverse = inverse.getLeft(); Graph rinverse = inverse.getRight(); OrdinaryMorphism lmorph = new OrdinaryMorphism(lgraph, rinverse); OrdinaryMorphism rmorph = new OrdinaryMorphism(rgraph, linverse); Iterator<Node> rnodes = rgraph.getNodesSet().iterator(); while (rnodes.hasNext()) { Node rNode = rnodes.next(); Node linverseNode = null; try { linverseNode = linverse.createNode(rNode.getType()); } catch (TypeException e) { // if the old rule was well typed, the new // rule should be also well typed e.printStackTrace(); } rmorph.addMapping(rNode, linverseNode); } Iterator<Node> lnodes = lgraph.getNodesSet().iterator(); while (lnodes.hasNext()) { Node lNode = lnodes.next(); Node rinverseNode = null; try { rinverseNode = rinverse.createNode(lNode.getType()); } catch (TypeException e) { // if the old rule was well typed, the new // rule should be also well typed e.printStackTrace(); } lmorph.addMapping(lNode, rinverseNode); GraphObject rn = this.getImage(lNode); if (rn != null) { inverse.addMapping(rmorph.getImage(rn), rinverseNode); } } Iterator<Arc> rarcs = rgraph.getArcsSet().iterator(); while (rarcs.hasNext()) { Arc rArc = rarcs.next(); Node linverseSource = (Node) rmorph.getImage(rArc.getSource()); Node linverseTarget = (Node) rmorph.getImage(rArc.getTarget()); Arc linverseArc = null; try { linverseArc = linverse.createArc(rArc.getType(), linverseSource, linverseTarget); rmorph.addMapping(rArc, linverseArc); } catch (TypeException ex) { } } Iterator<Arc> larcs = lgraph.getArcsSet().iterator(); while (larcs.hasNext()) { Arc lArc = larcs.next(); Node rinverseSource = (Node) lmorph.getImage(lArc.getSource()); Node rinverseTarget = (Node) lmorph.getImage(lArc.getTarget()); Arc rinverseArc = null; try { rinverseArc = rinverse.createArc(lArc.getType(), rinverseSource, rinverseTarget); lmorph.addMapping(lArc, rinverseArc); } catch (TypeException ex) {} GraphObject ra = this.getImage(lArc); if (ra != null) { inverse.addMapping(rmorph.getImage(ra), rinverseArc); } } return (inverse); } /** * Tries to invert this rule. The rule has to be injective. * The attribute mappings are NOT inverted, thus the resulting * left and right-hand side graphs are not attributed anymore. * * Returns the pair with an inverted rule as the first element * and a help pair of two graph morphisms as the second element. * The first morphism is between the LHS of this * and the RHS of the inverted rule, * the second morphism is between the RHS of this * and the LHS of the inverted rule. * If this rule is not injective - returns null. */ public Pair<Rule, Pair<OrdinaryMorphism, OrdinaryMorphism>> invertComplex() { if (!this.isInjective()) { return (null); } Rule inverse = new Rule(); Graph lgraph = this.getLeft(); Graph rgraph = this.getRight(); Graph linverse = inverse.getLeft(); Graph rinverse = inverse.getRight(); OrdinaryMorphism lmorph = new OrdinaryMorphism(lgraph, rinverse); OrdinaryMorphism rmorph = new OrdinaryMorphism(rgraph, linverse); Iterator<Node> rnodes = rgraph.getNodesSet().iterator(); while (rnodes.hasNext()) { Node rNode = rnodes.next(); Node linverseNode = null; try { linverseNode = linverse.createNode(rNode.getType()); } catch (TypeException e) { // if the old rule was well typed, the new // rule should be also well typed e.printStackTrace(); } rmorph.addMapping(rNode, linverseNode); } Iterator<Node> lnodes = lgraph.getNodesSet().iterator(); while (lnodes.hasNext()) { Node lNode = lnodes.next(); Node rinverseNode = null; try { rinverseNode = rinverse.createNode(lNode.getType()); } catch (TypeException e) { // if the old rule was well typed, the new // rule should be also well typed e.printStackTrace(); } lmorph.addMapping(lNode, rinverseNode); GraphObject rn = this.getImage(lNode); if (rn != null) { inverse.addMapping(rmorph.getImage(rn), rinverseNode); } } Iterator<Arc> rarcs = rgraph.getArcsSet().iterator(); while (rarcs.hasNext()) { Arc rArc = rarcs.next(); Node linverseSource = (Node) rmorph.getImage(rArc.getSource()); Node linverseTarget = (Node) rmorph.getImage(rArc.getTarget()); Arc linverseArc = null; try { linverseArc = linverse.createArc(rArc.getType(), linverseSource, linverseTarget); rmorph.addMapping(rArc, linverseArc); } catch (TypeException ex) {} } Iterator<Arc> larcs = lgraph.getArcsSet().iterator(); while (larcs.hasNext()) { Arc lArc = larcs.next(); Node rinverseSource = (Node) lmorph.getImage(lArc.getSource()); Node rinverseTarget = (Node) lmorph.getImage(lArc.getTarget()); Arc rinverseArc = null; try { rinverseArc = rinverse.createArc(lArc.getType(), rinverseSource, rinverseTarget); lmorph.addMapping(lArc, rinverseArc); } catch (TypeException ex) {} GraphObject ra = this.getImage(lArc); if (ra != null) { inverse.addMapping(rmorph.getImage(ra), rinverseArc); } } Pair<OrdinaryMorphism, OrdinaryMorphism> information = new Pair<OrdinaryMorphism, OrdinaryMorphism>( lmorph, rmorph); return (new Pair<Rule, Pair<OrdinaryMorphism, OrdinaryMorphism>>( inverse, information)); } /** * A plain rule returns null.<br> * Its subclasses <code>KernelRule</code>, * <code>MultiRule</code>, <code>RuleScheme</code>, * <code>AmalgamatedRule</code> overide this method * to return its <code>RuleScheme</code>. */ public RuleScheme getRuleScheme() { return null; } /** Returns my current match */ public Match getMatch() { return this.itsMatch; } /** * Compares attribute value of the specified objects due to * constant value of the first object. * Failed attribute value of the second object will be unset. * Checks all members of the attribute tuple. * * @param src first object (an object of the LHS of a rule) * @param tgt second object (an object of a NAC, PAC of a rule) * @return true if attribute value is equal, otherwise false */ public boolean compareConstantAttributeValue( final GraphObject src, final GraphObject tgt) { boolean result = true; if (src.getAttribute() != null && tgt.getAttribute() != null) { final ValueTuple tgtValue = (ValueTuple) tgt.getAttribute(); final ValueTuple srcValue = (ValueTuple) src.getAttribute(); for (int i=0; i<srcValue.getNumberOfEntries(); i++) { final ValueMember lhsvm = srcValue.getValueMemberAt(i); final ValueMember tgtvm = tgtValue.getValueMemberAt(lhsvm.getName()); if (lhsvm.isSet() && lhsvm.getExpr().isConstant() && tgtvm != null && tgtvm.isSet() && !lhsvm.getExprAsText().equals(tgtvm.getExprAsText())) { result = false; tgtvm.setExpr(null); } } } return result; } /** * Compares attribute value of the specified objects due to * constant value of the first object. * Failed attribute value of the second object will be unset. * The check broken after at least one attribute failed. * * @param src first object (an object of the LHS of a rule) * @param tgt second object (an object of a NAC, PAC of a rule) * @return true if attribute value is equal, otherwise false */ public boolean compareConstAttrValueOfMapObjs( final GraphObject src, final GraphObject tgt) { if (src.getAttribute() != null && tgt.getAttribute() != null) { final ValueTuple tgtValue = (ValueTuple) tgt.getAttribute(); final ValueTuple srcValue = (ValueTuple) src.getAttribute(); for (int i=0; i<srcValue.getNumberOfEntries(); i++) { final ValueMember srcvm = srcValue.getValueMemberAt(i); final ValueMember tgtvm = tgtValue.getValueMemberAt(srcvm.getName()); if (srcvm.isSet() && srcvm.getExpr().isConstant() && tgtvm.isSet() && !srcvm.getExprAsText().equals(tgtvm.getExprAsText())) { tgtvm.setExpr(null); return false; } } } return true; } /** * Compares its LHS, RHS, morphism, NACs, PACs and attribute context * to the appropriate elements of the specified rule. * Returns true if all elements are equal. */ public boolean compareTo(Rule r) { // System.out.println("Rule.compareTo"); Pair<Boolean,String> errMsgHolder = null; // compare rule morphism if (!((OrdinaryMorphism) this).compareTo(r)) { // System.out.println("Rule: "+getName()+" :: Mapping failed!"); errMsgHolder = new Pair<Boolean,String>(Boolean.valueOf(true), "Rule content is different."); return false; } // compare NACs errMsgHolder = compareApplConds(this.getNACsList(), r.getNACsList(), "NAC"); if (errMsgHolder != null) return false; // compare PACs errMsgHolder = compareApplConds(this.getPACsList(), r.getPACsList(), "PAC"); if (errMsgHolder != null) return false; // compare nested ACs errMsgHolder = compareApplConds(this.getNestedACsList(), r.getNestedACsList(), "nested AC"); if (errMsgHolder != null) return false; // compare rule context VarTuple var = (VarTuple) getAttrContext().getVariables(); VarTuple varOther = (VarTuple) r.getAttrContext().getVariables(); if (!var.compareTo(varOther)) { errMsgHolder = new Pair<Boolean,String>(Boolean.valueOf(true), "Variable rule context is different."); return false; } CondTuple cond = (CondTuple) getAttrContext().getConditions(); CondTuple condOther = (CondTuple) r.getAttrContext().getConditions(); if (!cond.compareTo(condOther)) { errMsgHolder = new Pair<Boolean,String>(Boolean.valueOf(true), "Conditional rule context is different."); return false; } return true; } private Pair<Boolean,String> compareApplConds( final List<OrdinaryMorphism> applConds, final List<OrdinaryMorphism> otherApplConds, String what) { // compare ACs Vector<OrdinaryMorphism> another = new Vector<OrdinaryMorphism>(); another.addAll(otherApplConds); if (applConds.size() != another.size()) { // System.out.println("Rule: "+getName()+" NACs discrepancy!"); Pair<Boolean,String> errMsgHolder = new Pair<Boolean,String>( Boolean.valueOf(true), "Number of "+what+"s is different."); return errMsgHolder; } OrdinaryMorphism ac = null; for (int i = 0; i < applConds.size(); i++) { ac = applConds.get(i); for (int j = another.size() - 1; j >= 0; j--) { OrdinaryMorphism ac1 = another.elementAt(j); if (ac.compareTo(ac1)) { another.remove(ac1); break; } } } if (another.size() != 0 && ac != null) { Pair<Boolean,String> errMsgHolder = new Pair<Boolean,String>( Boolean.valueOf(true), what+": " + ac.getName()+ " is different."); return errMsgHolder; } return null; } public List<GraphObject> getInputParameterObjectsLeft(final List<String> inputParams) { return getInputParameterObjects(this.getLeft(), inputParams); } public List<GraphObject> getInputParameterObjectsRight(final List<String> inputParams) { return getInputParameterObjects(this.getRight(), inputParams); } private List<GraphObject> getInputParameterObjects(final Graph g, final List<String> inputParams) { List<GraphObject> goIP = new Vector<GraphObject>(); Enumeration<GraphObject> elems = g.getElements(); while (elems.hasMoreElements()) { GraphObject go = elems.nextElement(); if (go.getAttribute() != null) { ValueTuple val = (ValueTuple)go.getAttribute(); for (int i=0; i<val.getNumberOfEntries(); i++) { ValueMember mem = val.getEntryAt(i); if (mem.isSet() && mem.getExpr().isVariable()) { if (inputParams.contains(mem.getExprAsText())) { goIP.add(go); } } } } } return goIP; } public List<GraphObject> getLeftInputParameterObjects() { List<GraphObject> list = new Vector<GraphObject>(); VarTuple var = (VarTuple) getAttrContext().getVariables(); Enumeration<GraphObject> elems = this.itsOrig.getElements(); while (elems.hasMoreElements()) { GraphObject go = elems.nextElement(); if (go.getAttribute() != null) { ValueTuple val = (ValueTuple) go.getAttribute(); for (int i=0; i<val.getNumberOfEntries(); i++) { ValueMember mem = val.getValueMemberAt(i); if (mem.isSet() && mem.getExpr().isVariable()) { if (var.getVarMemberAt(mem.getExprAsText()) != null && var.getVarMemberAt(mem.getExprAsText()).isInputParameter()) { list.add(go); } } } } } // System.out.println(list); return list; } public List<GraphObject> getRightInputParameterObjects() { List<GraphObject> list = new Vector<GraphObject>(); VarTuple var = (VarTuple) getAttrContext().getVariables(); Enumeration<GraphObject> elems = this.itsImag.getElements(); while (elems.hasMoreElements()) { GraphObject go = elems.nextElement(); if (go.getAttribute() != null) { ValueTuple val = (ValueTuple) go.getAttribute(); for (int i=0; i<val.getNumberOfEntries(); i++) { ValueMember mem = val.getValueMemberAt(i); if (mem.isSet() && mem.getExpr().isVariable()) { if (var.getVarMemberAt(mem.getExprAsText()) != null && var.getVarMemberAt(mem.getExprAsText()).isInputParameter()) { list.add(go); } } } } } return list; } public Vector<String> getInputParameterNames() { Vector<String> inputParams = new Vector<String>(1); VarTuple var = (VarTuple) getAttrContext().getVariables(); for (int i = 0; i < var.getNumberOfEntries(); i++) { VarMember varm = var.getVarMemberAt(i); if (varm.isInputParameter()) inputParams.add(varm.getName()); } return inputParams; } /** * Returns variables of the attribute context of this rule * which are used as input parameter for the rule application. */ public Vector<VarMember> getInputParameters() { Vector<VarMember> inputParams = new Vector<VarMember>(1); VarTuple var = (VarTuple) getAttrContext().getVariables(); for (int i = 0; i < var.getNumberOfEntries(); i++) { VarMember varm = var.getVarMemberAt(i); if (varm.isInputParameter()) inputParams.addElement(varm); } return inputParams; } public Vector<VarMember> getInputParametersLeft() { Vector<VarMember> inputParams = new Vector<VarMember>(1); VarTuple var = (VarTuple) getAttrContext().getVariables(); for (int i = 0; i < var.getNumberOfEntries(); i++) { VarMember vm = var.getVarMemberAt(i); if (vm.isInputParameter() && vm.getMark() == VarMember.LHS) { inputParams.addElement(vm); } } return inputParams; } public Vector<VarMember> getInputParametersRight() { Vector<VarMember> inputParams = new Vector<VarMember>(1); VarTuple var = (VarTuple) getAttrContext().getVariables(); for (int i = 0; i < var.getNumberOfEntries(); i++) { VarMember vm = var.getVarMemberAt(i); if (vm.isInputParameter() && (vm.getMark() == VarMember.RHS || vm.getMark() == VarMember.NAC)) { inputParams.addElement(vm); } } return inputParams; } /** * Returns variables of the attribute context of this rule * which are used by attributes of the specified graph object * as an input parameter for the rule application. */ public Vector<VarMember> getInputParametersOfGraphObject(final GraphObject go, final VarTuple var) { if (go.getAttribute() == null) return new Vector<VarMember>(); Vector<VarMember> inputParams = new Vector<VarMember>(1); ValueTuple attrVal = (ValueTuple)go.getAttribute(); for (int i = 0; i < attrVal.getNumberOfEntries(); i++) { ValueMember vm = attrVal.getValueMemberAt(i); if (vm.isSet() && vm.getExpr().isVariable()) { VarMember varm = var.getVarMemberAt(vm.getExprAsText()); if (varm != null && varm.isInputParameter()) inputParams.addElement(varm); } } return inputParams; } public Vector<VarMember> getNonInputParametersOfNewGraphObjects() { VarTuple var = (VarTuple) getAttrContext().getVariables(); Vector<VarMember> params = new Vector<VarMember>(1); final Enumeration<GraphObject> objs = this.itsImag.getElements(); while (objs.hasMoreElements()) { GraphObject go = objs.nextElement(); if (go.getAttribute() == null || this.itsCodomObjects.contains(go)) continue; ValueTuple attrVal = (ValueTuple)go.getAttribute(); for (int i = 0; i < attrVal.getNumberOfEntries(); i++) { ValueMember vm = attrVal.getValueMemberAt(i); if (vm.isSet() && vm.getExpr().isVariable()) { VarMember varm = var.getVarMemberAt(vm.getExprAsText()); if (varm != null && !varm.isInputParameter()) params.addElement(varm); } } } return params; } public Vector<VarMember> getNonInputParameters() { VarTuple var = (VarTuple) getAttrContext().getVariables(); Vector<VarMember> params = new Vector<VarMember>(1); for (int i = 0; i < var.getNumberOfEntries(); i++) { VarMember v = var.getVarMemberAt(i); if (!v.isInputParameter()) params.addElement(v); } return params; } /** * always returns TRUE. It is not yet implemented! */ public boolean areNACsValid() { // for (int i = 0; i < itsNACs.size(); i++) { // OrdinaryMorphism nac = itsNACs.get(i); // if (!isNACValid(nac) { // return false; // } // } return true; } // public boolean isGlobalNAC(OrdinaryMorphism nac) { // return nac.isEmpty(); // } // // public boolean isGlobalPAC(OrdinaryMorphism pac) { // return pac.isEmpty(); // } /** * always returns TRUE. It is not yet implemented! */ public boolean isNACValid(OrdinaryMorphism nac) { return true; } /** * Shift of an application condition is not possible when it may cause a dangling edge. */ public boolean isACShiftPossible(OrdinaryMorphism ac) { Iterator<Arc> arcs = ac.getTarget().getArcsCollection().iterator(); while (arcs.hasNext()) { Arc a = arcs.next(); if (!ac.getInverseImage(a).hasMoreElements()) { if (ac.getInverseImage(a.getSource()).hasMoreElements()) { if (this.getImage(ac.getInverseImage(a.getSource()).nextElement()) == null) return false; } if (ac.getInverseImage(a.getTarget()).hasMoreElements()) { if (this.getImage(ac.getInverseImage(a.getTarget()).nextElement()) == null) return false; } } } return true; } /** * Checks dangling edges of the given pac. * Returns true if no dangling edge exists, otherwise false. */ public boolean isPACValid(OrdinaryMorphism ac) { if (ac.isEnabled()) { final Iterator<Node> objects = this.itsOrig.getNodesSet().iterator(); while (objects.hasNext()) { final Node x = objects.next(); if (this.getImage(x) == null) { final Node y = (Node) ac.getImage(x); if (y != null && x.getNumberOfArcs() != y.getNumberOfArcs()) { this.setErrorMsg(ac.getName()+" - PAC failed (dangling edge)"); // this.setErrorMsg(this.getName()+": "+ac.getName()+" - PAC failed (dangling edge)"); return false; } } } } return true; } /** * Checks dangling edges of the its pacs. * Returns true if no dangling edge exists, otherwise false. */ public boolean arePACsValid() { for (int i=0; i<this.itsPACs.size(); i++) { OrdinaryMorphism ac = this.itsPACs.get(i); if (!this.isPACValid(ac)) { return false; } } return true; } /** * Checks dangling edges of the given general application condition ac. * Returns true if no dangling edge exists, otherwise false. */ public boolean isGACValid(NestedApplCond ac) { if (ac.isEnabled()) { return ac.isValid(); } return true; } /** * Checks dangling edges of the its general application conditions. * Returns true if no dangling edge exists, otherwise false. */ public boolean areGACsValid() { for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); if (!this.isGACValid(ac)) { return false; } } return true; } /** * Checks dangling edges of the its pacs and general acs. * Returns true if no dangling edge exists, otherwise false. */ public boolean areApplCondsValid() { for (int i=0; i<this.itsPACs.size(); i++) { OrdinaryMorphism ac = this.itsPACs.get(i); if (!this.isPACValid(ac)) { return false; } } for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond)this.itsACs.get(i); if (!ac.isValid()) { return false; } } return true; } public boolean extendByPacs() { for (int i=0; i<this.itsPACs.size(); i++) { OrdinaryMorphism pac = this.itsPACs.get(i); if (pac.isEnabled()) { extendByPac(pac); pac.setEnabled(false); } } return true; } private boolean extendByPac(OrdinaryMorphism pac) { Hashtable<Node,Node> n2n = new Hashtable<Node,Node>(); Iterator<Node> nodes = pac.getTarget().getNodesCollection().iterator(); while (nodes.hasNext()) { Node pn = nodes.next(); Enumeration<GraphObject> en = pac.getInverseImage(pn); if (!en.hasMoreElements()) { try { Node nln = this.itsOrig.copyNode(pn); n2n.put(pn, nln); Node nrn = this.itsImag.copyNode(pn); n2n.put(nln, nrn); try { this.addMapping(nln, nrn); } catch (BadMappingException ex1) { return false; } } catch (TypeException ex) { return false; } } else { while (en.hasMoreElements()) { Node ln = (Node) en.nextElement(); n2n.put(pn, ln); Node rn = (Node) this.getImage(ln); if (rn != null) { n2n.put(ln, rn); } break; } } } Iterator<Arc> arcs = pac.getTarget().getArcsCollection().iterator(); while (arcs.hasNext()) { Arc pa = arcs.next(); Enumeration<GraphObject> en = pac.getInverseImage(pa); if (!en.hasMoreElements()) { try { Node srcl = n2n.get(pa.getSource()); Node tarl = n2n.get(pa.getTarget()); if (srcl != null && tarl != null) { Arc nla = this.getOriginal().copyArc(pa, srcl, tarl); Node srcr = n2n.get(srcl); Node tarr = n2n.get(tarl); if (srcr != null && tarr != null) { Arc nra = this.getImage().copyArc(pa, srcr, tarr); if (nla != null && nra != null) { try { this.addMapping(nla, nra); } catch (BadMappingException ex1) { return false; } } } } } catch (TypeException ex) { return false; } } } return true; } /** * Checks existing variables of the attribute context against the attribute * context of its current match and adjusts the attribute context of its match, * if needed. */ public void adjustAttrContextOfMatch(boolean inputParameterOnly) { if (this.itsMatch != null) { this.itsMatch.adjustAttrInputParameter(inputParameterOnly); this.itsMatch.adjustAttrCondition(); } } /** * Set the value of variables of rule attribute context to null. */ public void unsetValueOfContextVariable(boolean inputParameterOnly) { VarTuple vt = (VarTuple) getAttrContext().getVariables(); for (int i = 0; i < vt.getNumberOfEntries(); i++) { VarMember vm = vt.getVarMemberAt(i); if (inputParameterOnly) { if (vm.isInputParameter()) vm.setExpr(null); } else vm.setExpr(null); } } /** * Attribute context variable which is an input parameter is no more input parameter * after this method applied. */ public void unsetInputParameter() { AttrVariableTuple avt = getAttrContext().getVariables(); for (int i = 0; i < avt.getNumberOfEntries(); i++) { VarMember vm = (VarMember) avt.getMemberAt(i); if (vm.isInputParameter()) vm.setInputParameter(false); } } /** * Returns the name of an input parameter whithout value, otherwise - null. */ public String getInputParameterWithoutValue() { AttrVariableTuple avt = getAttrContext().getVariables(); for (int i = 0; i < avt.getNumberOfEntries(); i++) { VarMember vm = (VarMember) avt.getMemberAt(i); if (vm.isInputParameter() && !vm.isSet()) return vm.getName(); } return null; } /** * Returns name(s) of the variables of the attribute context which are used * as input parameter(s) of this rule and they are not set. * If the specified parameter is TRUE then the LHS * (NACs, PACs) with an input parameter for matching are taken in account. * If the specified parameter is FALSE then the RHS * (NACs, PACs) with an input parameter for matching are taken in acount. * * Returns null if all input parameter are set. */ public String getInputParameterWithoutValue(boolean left) { AttrVariableTuple avt = getAttrContext().getVariables(); for (int i = 0; i < avt.getNumberOfEntries(); i++) { VarMember vm = (VarMember) avt.getMemberAt(i); if (vm.isInputParameter() && !vm.isSet()) { if (left) { Vector<String> vars = getLeft().getVariableNamesOfAttributes(); for (int j = 0; j < vars.size(); j++) { if (vars.get(j).equals(vm.getName())) return vm.getName(); } } else { Vector<String> vars = getRight().getVariableNamesOfAttributes(); for (int j = 0; j < vars.size(); j++) { if (vars.get(j).equals(vm.getName())) return vm.getName(); } } for (int j = 0; j < this.itsNACs.size(); j++) { OrdinaryMorphism nac = this.itsNACs.get(j); Vector<String> vars = nac.getTarget() .getVariableNamesOfAttributes(); for (int k = 0; k < vars.size(); k++) { if (vars.get(k).equals(vm.getName())) return vm.getName(); } } for (int j = 0; j < this.itsPACs.size(); j++) { OrdinaryMorphism pac = this.itsPACs.get(j); Vector<String> vars = pac.getTarget() .getVariableNamesOfAttributes(); for (int k = 0; k < vars.size(); k++) { if (vars.get(k).equals(vm.getName())) return vm.getName(); } } for (int j = 0; j < this.itsACs.size(); j++) { OrdinaryMorphism ac = this.itsACs.get(j); Vector<String> vars = ac.getTarget() .getVariableNamesOfAttributes(); for (int k = 0; k < vars.size(); k++) { if (vars.get(k).equals(vm.getName())) return vm.getName(); } } } } return null; } /** * Checks attribute setting of RHS, variable declarations and attribute * conditions. * If all checks successful, it prepares infos about this rule. * The method getErrorMessage() gives more information about fails. */ public boolean isReadyToTransform() { this.isReady = true; if (!this.enabled) return true; // check usage of abstract types of the RHS final Vector<String> abstractTypesOfRHS = new Vector<String>(1); Iterator<Node> enumer = this.itsImag.getNodesSet().iterator(); while (enumer.hasNext()) { GraphObject o = enumer.next(); Enumeration<GraphObject> inverse = getInverseImage(o); if (!inverse.hasMoreElements() && o.getType().isAbstract()) { abstractTypesOfRHS.add(o.getType().getName()); } } this.isReady = abstractTypesOfRHS.isEmpty(); if (!this.isReady) { this.errorMsg = this.errorMsg.concat("RHS: creating abstract nodes not allowed! ").concat(abstractTypesOfRHS.toString()); return false; } // check PAC is valid: check dangling edge of nodes to delete which are used in a PAC for (int l=0; l<this.itsPACs.size(); l++) { this.isReady = this.isPACValid(this.itsPACs.get(l)); if (!this.isReady) { return false; } } // check attributes if (!isAttributed()) { return true; } this.applyDefaultAttrValuesOfTypeGraph(this.itsImag); AttrVariableTuple avt = this.itsAttrContext.getVariables(); AttrConditionTuple act = this.itsAttrContext.getConditions(); this.errorMsg = ""; // get used variable and its declaration: (type, name) Vector<Pair<String, String>> varDecls = getVariableDeclarations(); // add vars of NACs to varDecls for (int l=0; l<this.itsNACs.size(); l++) { addVarDecl(this.itsNACs.get(l).getImage(), varDecls); } // add vars of PACs to varDecls for (int l=0; l<this.itsPACs.size(); l++) { addVarDecl(this.itsPACs.get(l).getImage(), varDecls); } // add vars of nested ACs to varDecls for (int l=0; l<this.itsACs.size(); l++) { addVarDecl(this.itsACs.get(l).getImage(), varDecls); } // check: same variable name , different type :: should not happen! this.isReady = checkDoubleVarDecl(varDecls); if (!this.isReady) { return false; } // check used variables this.isReady = checkUsedVariables(avt, varDecls); if (!this.isReady) { return false; } // mark used variables: RHS, NAC, PAC, LHS markUsedVariables(avt); // check and mark the attr. conditions this.isReady = markAttrConditions(avt, act); if (!this.isReady) { return false; } // find objects: to preserve, to delete, to create, to change, // also types which need to be checked due to multiplicity this.prepareRuleInfo(); // adjust the attribute conditions (mark, enabled) // of my match, if it exists if (this.itsMatch != null) { if (this.itsMatch.getRule() == this) this.itsMatch.adjustAttrCondition(); else { this.itsMatch.dispose(); this.itsMatch = null; } } // check attribute settings of the new objects this.isReady = this.checkAttributesOfNewObjects(avt); if (!this.isReady) { return false; } return this.isReady; } public boolean nacIsUsingVariable( final VarMember var, final AttrConditionTuple act) { for (int i=0; i<this.itsNACs.size(); i++) { final OrdinaryMorphism nac = this.itsNACs.get(i); if (nac.getTarget().isUsingVariable(var)) { return true; } Vector<String> nacVars = nac.getTarget() .getVariableNamesOfAttributes(); for (int j = 0; j < nacVars.size(); j++) { String varName = nacVars.get(j); for (int k = 0; k < act.getNumberOfEntries(); k++) { CondMember cond = (CondMember) act.getMemberAt(k); Vector<String> condVars = cond.getAllVariables(); if (condVars.contains(varName) && condVars.contains(var.getName())) { return true; } } } } return false; } public boolean pacIsUsingVariable( final VarMember var, final AttrConditionTuple act) { for (int i=0; i<this.itsPACs.size(); i++) { final OrdinaryMorphism pac = this.itsPACs.get(i); if (pac.getTarget().isUsingVariable(var)) { return true; } Vector<String> pacVars = pac.getTarget() .getVariableNamesOfAttributes(); for (int j = 0; j < pacVars.size(); j++) { String varName = pacVars.get(j); for (int k = 0; k < act.getNumberOfEntries(); k++) { CondMember cond = (CondMember) act.getMemberAt(k); Vector<String> condVars = cond.getAllVariables(); if (condVars.contains(varName) && condVars.contains(var.getName())) { return true; } } } } return false; } protected void applyDefaultAttrValuesOfTypeGraph( final Graph g, final Iterator<?> iter) { boolean right = g == this.getRight(); while (iter.hasNext()) { GraphObject o = (GraphObject)iter.next(); if (o.getAttribute() == null) { if ((o.getType().getAttrType() != null) && (o.getType().getAttrType().getNumberOfEntries() != 0)) { o.createAttributeInstance(); } else continue; } if (right && !this.getInverseImage(o).hasMoreElements()) { if (o.isNode()) g.applyDefaultAttrValuesOfTypeGraph((Node)o, null); else g.applyDefaultAttrValuesOfTypeGraph((Arc)o, null); } } } /* * Use the attribute values of the nodes and edges of the Type Graph as default values * for the attributes of the specified graph. */ public void applyDefaultAttrValuesOfTypeGraph(final Graph g) { this.applyDefaultAttrValuesOfTypeGraph(g, g.getNodesSet().iterator()); this.applyDefaultAttrValuesOfTypeGraph(g, g.getArcsSet().iterator()); } protected boolean isAttributed() { boolean attributed = this.itsOrig.isAttributed() || this.itsImag.isAttributed(); for (int l=0; !attributed && l<this.itsNACs.size() ; l++) { attributed = this.itsNACs.get(l).getImage().isAttributed(); } for (int l=0; !attributed && l<this.itsPACs.size(); l++) { attributed = this.itsPACs.get(l).getImage().isAttributed(); } for (int l=0; !attributed && l<this.itsACs.size(); l++) { attributed = this.itsACs.get(l).getImage().isAttributed(); } return attributed; } private void addVarDecl(final Graph g, final Vector<Pair<String, String>> varDecls) { addVarDecl(g.getNodesSet().iterator(), varDecls); addVarDecl(g.getArcsSet().iterator(), varDecls); } private void addVarDecl(final Iterator<?>elems, final Vector<Pair<String, String>> varDecls) { while (elems.hasNext()) { GraphObject o = (GraphObject) elems.next(); if (o.getAttribute() != null) { AttrInstance attr = o.getAttribute(); ValueTuple vt = (ValueTuple) attr; for (int k = 0; k < vt.getSize(); k++) { ValueMember vm = vt.getValueMemberAt(k); if (vm.isSet() && vm.getExpr().isVariable()) { String n = vm.getExprAsText(); String t = vm.getDeclaration().getTypeName(); // System.out.println(o.getContext().getName()+" "+n+" "+t); Pair<String, String> p = new Pair<String, String>(t, n); boolean found = false; for (int j = 0; j < varDecls.size(); j++) { Pair<String, String> pj = varDecls.elementAt(j); if (t.equals(pj.first) && n.equals(pj.second)) { found = true; break; } } if (!found) { varDecls.addElement(p); } } } } } } private boolean checkDoubleVarDecl(final Vector<Pair<String, String>> varDecls) { boolean result = true; // check: same variable name , different type :: should not happen! for (int j = 0; result && j < varDecls.size(); j++) { Pair<String, String> pj = varDecls.elementAt(j); for (int jj = j + 1; result && jj < varDecls.size(); jj++) { Pair<String, String> pjj = varDecls.elementAt(jj); if (pj.second.equals(pjj.second) && !pj.first.equals(pjj.first)) { if (!("Object".equals(pj.first) || "java.lang.Object".equals(pj.first)) && !("Object".equals(pjj.first) || "java.lang.Object".equals(pjj.first))) { this.errorMsg = "Variable has multiple declaration : ".concat(pj.second); result = false; } } } } return result; } /** * All attributes of the elements of the RHS to create * have to be set. */ private boolean checkAttributesOfNewObjects(final AttrVariableTuple avt) { return checkAttrsOfNewObjs(avt, this.itsImag.getNodesSet().iterator()) && checkAttrsOfNewObjs(avt, this.itsImag.getArcsSet().iterator()); } private boolean checkAttrsOfNewObjs( final AttrVariableTuple avt, final Iterator<?> elems) { final boolean result = true; while (elems.hasNext()) { final GraphObject o = (GraphObject) elems.next(); if (this.itsCodomObjects.contains(o)) { continue; } if (o.getAttribute() == null) { if ((o.getType().getAttrType() != null) && (o.getType().getAttrType().getNumberOfEntries() != 0)) { this.errorMsg = "Type: <".concat(o.getType().getName()).concat("> - attribute not set."); return false; } continue; } final AttrInstance attr = o.getAttribute(); ValueTuple typeObjectAttr = null; if (o instanceof Node) { final Node typeNode = o.getType().getTypeGraphNodeObject(); if (typeNode != null) { typeObjectAttr = (ValueTuple) typeNode.getAttribute(); } } else { final Arc typeEdge = o.getType().getTypeGraphArcObject(((Arc)o).getSourceType(), ((Arc)o).getTargetType()); if (typeEdge != null) { typeObjectAttr = (ValueTuple) typeEdge.getAttribute(); } } final ValueTuple vt = (ValueTuple) attr; for (int k = 0; k < vt.getSize(); k++) { final ValueMember vm = vt.getValueMemberAt(k); if (vm.isSet()) { if (vm.getExpr().isVariable()) { final VarMember var = avt.getVarMemberAt(vm.getExprAsText()); if (var == null) { this.errorMsg = "Variable : "; this.errorMsg = this.errorMsg.concat(vm.getExprAsText()); this.errorMsg = this.errorMsg.concat(" is not declared."); return false; } if (!var.isInputParameter() && vm.getExpr() == null) { final Vector<String> leftVars = this.itsOrig.getVariableNamesOfAttributes(); if (!leftVars.contains(var.getName())) { this.errorMsg = "Variable : "; this.errorMsg = this.errorMsg.concat(var.getName()); this.errorMsg = this.errorMsg.concat(" in the RHS of the rule should be an input parameter"); this.errorMsg = this.errorMsg.concat("\nor already declared in the LHS."); return false; } } } else if (vm.getExpr().isComplex()) { if (!vm.isValid()) { this.errorMsg = "Not all attributes of the RHS are correct.\nPlease check expression : "; this.errorMsg = this.errorMsg.concat(vm.getExprAsText()); return false; } final Vector<String> vec = vm.getAllVariableNamesOfExpression(); final Vector<String> vecLeft = this.itsOrig.getVariableNamesOfAttributes(); for (int l = 0; l < vec.size(); l++) { final String n = vec.elementAt(l); boolean found = false; for (int ll = 0; ll < vecLeft.size(); ll++) { String nn = vecLeft.elementAt(ll); if (n.equals(nn)) { found = true; } } if (!found) { final VarMember m = avt.getVarMemberAt(n); if (m != null && !m.isSet() && !m.isInputParameter()) { this.errorMsg = "Not all attributes in the RHS of the rule are correct."; this.errorMsg = this.errorMsg.concat("\nPlease check variable : "); this.errorMsg = this.errorMsg.concat(n); return false; } } } } } else //if (!getInverseImage(o).hasMoreElements()) { // look for default attr value in the type graph boolean failed = true; if (typeObjectAttr != null) { final ValueMember tnvm = typeObjectAttr.getValueMemberAt(vm.getName()); if (tnvm != null && tnvm.isSet()) { vm.setExprAsText(tnvm.getExprAsText()); if (vm.isSet()) { failed = false; } } } if (failed) { if (vm.getDeclaration().getType() == null) { vm.setExprAsText("null"); } else if (!this.getTypeSet().isEmptyAttrAllowed()) { this.errorMsg = "Not all attributes in the RHS of the rule are set."; return false; } } } } } return result; } private boolean checkUsedVariables( final AttrVariableTuple avt, final Vector<Pair<String, String>>varDecls) { boolean result = true; for (int i = 0; i < varDecls.size(); i++) { final Pair<String, String> p = varDecls.elementAt(i); String typeName1 = p.first; boolean isClass1 = false; final String className1 = isClassName(typeName1); if (className1 != null) { isClass1 = true; } boolean isClass2 = false; String className2 = null; String typeName2 = ""; final String varName = p.second; VarMember varm = ((VarTuple) avt).getVarMemberAt(varName); if (varm == null) { className2 = isClassName(varName); if (className2 != null) { typeName2 = className2; } } else if (varm.getDeclaration() == null) { this.errorMsg = "Variable: ".concat(varName).concat(" isn't declared!"); return false; } else { typeName2 = varm.getDeclaration().getTypeName(); className2 = isClassName(typeName2); } if (className2 != null) { isClass2 = true; } if (className1 != null && className2 != null) { if (!className1.equals(className2)) { if (!className1.equals("java.lang.Object") && !className2.equals("java.lang.Object")) { this.errorMsg = "Variable: " + varName + " has wrong type." + "\nIt should be : " + className1 + " ."; return false; } } else if (!typeName1.equals(typeName2)) { final String packageName = className1.substring(0, className1.lastIndexOf(".")); if (packageName.equals("java.lang") && varm != null) { varm.getDeclaration().setType(typeName1); } else { this.errorMsg = "Variable: " + varName + " has wrong type." + "\nIt should be : " + typeName1 + " ."; return false; } } } else if (!isClass1 && !isClass2 && !typeName1.equals(typeName2)) { this.errorMsg = "Variable: " + varName + " has wrong type." + "\nIt should be : " + typeName1 + " ."; return false; } } return result; } private boolean markAttrConditions( final AttrVariableTuple avt, final AttrConditionTuple act) { boolean result = true; // check and mark the attr. conditions for (int k = 0; k < ((CondTuple) act).getSize(); k++) { final CondMember cm = ((CondTuple) act).getCondMemberAt(k); if (cm.getExpr() == null) { this.errorMsg = "Condition: " + cm + " is not defined."; return false; } else if (!cm.isValid()) { this.errorMsg = "Condition: " + cm + " is not valid.\nPlease check variables of it."; return false; } final Vector<String> vars = cm.getAllVariables(); if (!vars.isEmpty()) { boolean mixedNAC = false; boolean mixedPAC = false; boolean mixed = false; String name0 = vars.elementAt(0); if (((VarTuple) avt).isDeclared(name0)) { final VarMember var0 = avt.getVarMemberAt(vars.elementAt(0)); int mark = var0.getMark(); for (int j = 1; j < vars.size(); j++) { final String name = vars.elementAt(j); if (((VarTuple) avt).isDeclared(name)) { final VarMember var = avt.getVarMemberAt(name); if (mark == VarMember.LHS) { if (var.getMark() == VarMember.NAC) { mixedNAC = true; } else if (var.getMark() == VarMember.PAC) { mixedPAC = true; } } else if (mark == VarMember.NAC) { if (var.getMark() == VarMember.LHS) { mixedNAC = true; } else if (var.getMark() == VarMember.PAC) { mixed = true; } } else if (mark == VarMember.PAC) { if (var.getMark() == VarMember.LHS) { mixedPAC = true; } else if (var.getMark() == VarMember.NAC) { mixed = true; } } } else { if(isClassName(name) == null) { this.errorMsg = "Variable: " + name + "\nof condition: " + cm.getExprAsText() + "\nis not declared."; return false; } } } if (mixedNAC && mixedPAC) { cm.setMark(CondMember.NAC_PAC_LHS); } else if (mixedNAC) { cm.setMark(CondMember.NAC_LHS); } else if (mixedPAC) { cm.setMark(CondMember.PAC_LHS); } else if (mixed) { cm.setMark(CondMember.NAC_PAC); } else if (mark == VarMember.NAC) { cm.setMark(CondMember.NAC); } else if (mark == VarMember.PAC) { cm.setMark(CondMember.PAC); } else if (mark == VarMember.RHS) { cm.setMark(CondMember.RHS); } else { cm.setMark(CondMember.LHS); } } else { if(isClassName(name0) == null) { this.errorMsg = "Variable: " + name0 + "\nof condition: " + cm.getExprAsText() + "\nis not declared."; return false; } } } } return result; } private void markUsedVariables(final AttrVariableTuple avt) { // mark used variables: // inside RHS markUsedVars(this.itsImag.getNodesSet().iterator(), this.itsImag.getArcsSet().iterator(), avt, VarMember.RHS); // inside NACs for (int l=0; l<this.itsNACs.size(); l++) { Graph g = this.itsNACs.get(l).getImage(); markUsedVars(g.getNodesSet().iterator(), g.getArcsSet().iterator(), avt, VarMember.NAC); } // inside PACs for (int l=0; l<this.itsPACs.size(); l++) { Graph g = this.itsPACs.get(l).getImage(); markUsedVars(g.getNodesSet().iterator(), g.getArcsSet().iterator(), avt, VarMember.PAC); } // inside nested AC markUsedVarsOfNestedACs(this.itsACs, avt); // for (int l=0; l<this.itsACs.size(); l++) { // Graph g = this.itsACs.get(l).getImage(); // markUsedVars(g.getNodesSet().iterator(), // g.getArcsSet().iterator(), // avt, VarMember.PAC); // // } // finally inside LHS markUsedVars(this.itsOrig.getNodesSet().iterator(), this.itsOrig.getArcsSet().iterator(), avt, VarMember.LHS); } private void markUsedVarsOfNestedACs(List<?> nestedACs, AttrVariableTuple avt) { for (int i=0; i<nestedACs.size(); i++) { OrdinaryMorphism nestAC = (OrdinaryMorphism) nestedACs.get(i); Graph g = nestAC.getImage(); markUsedVars(g.getNodesSet().iterator(), g.getArcsSet().iterator(), avt, VarMember.PAC); markUsedVarsOfNestedACs(((NestedApplCond)nestAC).getNestedACs(), avt); } } private void markUsedVars( final Iterator<Node> nodes, final Iterator<Arc> arcs, final AttrVariableTuple avt, int mark) { while (nodes.hasNext()) { final GraphObject o = nodes.next(); if (o.getAttribute() != null) { final ValueTuple vt = (ValueTuple) o.getAttribute(); for (int k = 0; k < vt.getSize(); k++) { final ValueMember vm = vt.getValueMemberAt(k); if (vm.isSet()) { if (vm.getExpr().isVariable()) { final VarMember var = avt.getVarMemberAt(vm.getExprAsText()); if (var != null) var.setMark(mark); } else if (vm.getExpr().isComplex()) { Vector<String> vec = new Vector<String>(3); vm.getExpr().getAllVariables(vec); for (String s: vec) { VarMember var = avt.getVarMemberAt(s); if (var != null) var.setMark(mark); } } } } } } while (arcs.hasNext()) { final GraphObject o = arcs.next(); if (o.getAttribute() != null) { final ValueTuple vt = (ValueTuple) o.getAttribute(); for (int k = 0; k < vt.getSize(); k++) { final ValueMember vm = vt.getValueMemberAt(k); if (vm.isSet()) { if (vm.getExpr().isVariable()) { final VarMember var = avt.getVarMemberAt(vm.getExprAsText()); if (var != null) var.setMark(mark); } else if (vm.getExpr().isComplex()) { Vector<String> vec = new Vector<String>(3); vm.getExpr().getAllVariables(vec); for (String s: vec) { VarMember var = avt.getVarMemberAt(s); if (var != null) var.setMark(mark); } } } } } } } /** * Prepares info about this rule: * node, edges to preserve, change, delete, create; * types which should be checked due to node resp. edge type multiplicity. * These infos can be called by methods: * getElementsToPreserve(), getElementsToChange(), getElementsToDelete(), * getElementsToCreate(), getTypesWhichNeedMultiplicityCheck. */ public void prepareRuleInfo() { this.preserved = this.findElementsToPreserve(); this.created = this.findElementsToCreate(); this.deleted = this.findElementsToDelete(); this.changedPreserved = this.findElementsToChange(); this.typesWhichNeedMultiplicityCheck = this.findTypesWhichNeedMultiplicityCheck(); this.hasEnabledGACs = this.hasEnabledACs(true); if ("true".equals(this.formStr)) this.setDefaultFormulaTrue(); else if ("false".equals(this.formStr)) this.setDefaultFormulaFalse(); } /* * Update infos about this rule (creating, deleting, changing) after * the specified graph object of the LHS or RHS is removed. * @param obj removed object * @deprecated the update of rule infos is always done in the method * this.isReadyToTransform() */ /* private void updateInfosAfterRemove(final GraphObject obj) { if (preserved != null && preserved.contains(obj)) { preserved.remove(obj); } else if (created != null && created.contains(obj)) { created.remove(obj); } else if (deleted != null && deleted.contains(obj)) { deleted.remove(obj); } if (changedPreserved != null && changedPreserved.contains(obj)) { changedPreserved.remove(obj); } } */ /* private Class<?> getStaticClass(String name) { Class<?> klass = null; try { // check static class klass = Class.forName(name); System.out.println("Rule.getStaticClass:: for "+name+" => Class "+klass); return klass; } catch (ClassNotFoundException cnfe) { System.out.println("Rule.getStaticClass:: ClassNotFoundException: "+cnfe.getMessage()); return null; } } */ /** * Return true if its left and right graphs are empty * and there aren't any application conditions, * otherwise - false. */ public boolean isEmptyRule() { return (this.itsOrig.isEmpty() && this.itsImag.isEmpty() && this.itsNACs.isEmpty() && this.itsPACs.isEmpty() && this.itsACs.isEmpty()); } public List<Type> getTypesOfLeftGraph() { final List<Type> list = new Vector<Type>(); for (final Iterator<Node> en = getLeft().getNodesSet().iterator(); en.hasNext();) { final Node o = en.next(); if (!list.contains(o.getType())) list.add(o.getType()); } for (final Iterator<Arc> en = getLeft().getArcsSet().iterator(); en.hasNext();) { final Arc o = en.next(); if (!list.contains(o.getType())) list.add(o.getType()); } return list; } public List<Type> getTypeOfObjectToDelete() { final List<Type> list = new Vector<Type>(); for (final Iterator<Node> en = getLeft().getNodesSet().iterator(); en.hasNext();) { final Node o = en.next(); if (getImage(o) == null && !list.contains(o.getType())) list.add(o.getType()); } for (final Iterator<Arc> en = getLeft().getArcsSet().iterator(); en.hasNext();) { final Arc o = en.next(); if (getImage(o) == null && !list.contains(o.getType())) list.add(o.getType()); } return list; } public List<Type> getTypeOfObjectToCreate() { final List<Type> list = new Vector<Type>(); for (Iterator<Node> en = getRight().getNodesSet().iterator(); en.hasNext();) { GraphObject o = en.next(); if (!getInverseImage(o).hasMoreElements() && !list.contains(o.getType())) list.add(o.getType()); } for (Iterator<Arc> en = getRight().getArcsSet().iterator(); en.hasNext();) { GraphObject o = en.next(); if (!getInverseImage(o).hasMoreElements() && !list.contains(o.getType())) list.add(o.getType()); } return list; } /* * * @return */ public List<String> getTypesWhichNeedMultiplicityCheck() { if (this.typesWhichNeedMultiplicityCheck == null) this.typesWhichNeedMultiplicityCheck = findTypesWhichNeedMultiplicityCheck(); this.itsOrig.changed = false; this.itsImag.changed = false; return this.typesWhichNeedMultiplicityCheck; } private List<String> findTypesWhichNeedMultiplicityCheck() { final List<String> list = new Vector<String>(); final List<GraphObject> list1 = new Vector<GraphObject>(); list1.addAll(this.getElementsToCreate()); list1.addAll(this.getElementsToDelete()); for (int i=0; i<list1.size(); i++) { final GraphObject go = list1.get(i); final String typekey = go.convertToKey(); if (!list.contains(typekey)) { if (go.isNode()) { int min = go.getType().getSourceMin(); int max = go.getType().getSourceMax(); if (min > 0 || max > 0) { list.add(typekey); final List<Type> children = go.getType().getChildren(); for (int ch=0; ch<children.size(); ch++) { list.add(children.get(ch).convertToKey()); } } } else { int srcMin = go.getType().getSourceMin(((Arc)go).getSource().getType(), ((Arc)go).getTarget().getType()); int srcMax = go.getType().getSourceMax(((Arc)go).getSource().getType(), ((Arc)go).getTarget().getType()); int tarMin = go.getType().getTargetMin(((Arc)go).getSource().getType(), ((Arc)go).getTarget().getType()); int tarMax = go.getType().getTargetMax(((Arc)go).getSource().getType(), ((Arc)go).getTarget().getType()); if (srcMin > 0 || tarMin > 0 || srcMax > 0 || tarMax > 0) { list.add(typekey); } } } } return list; } /** * Returns true if this rule will create new graph elements, * otherwise - false. */ public boolean isCreating() { // LHS graph size > rule mapping size this.isCreating = this.itsImag.getSize() > this.getCodomainSize(); if (this.isCreating) { this.created = findElementsToCreate(); } return this.isCreating; } /** * @deprecated replaced by <code>Vector<GraphObject> getElementsToCreate()</code> */ public List<GraphObject> getObjectsToCreate() { return getElementsToCreate(); } /** * @deprecated use <code>getElementsToCreate().size()</code> */ public int getNumberOfObjectsToCreate() { return getElementsToCreate().size(); } /** * Returns true if this rule will delete some graph elements, * otherwise - false. */ public boolean isDeleting() { // LHS graph size > rule mapping size this.isDeleting = this.itsOrig.getSize() > this.getDomainSize(); if (this.isDeleting) { this.deleted = findElementsToDelete(); } return this.isDeleting; } public boolean isNodeDeleting() { this.isNodeDeleting = false; if (this.isDeleting) { for (final Iterator<Node> en = this.itsOrig.getNodesSet().iterator(); en.hasNext();) { if (getImage(en.next()) == null) { this.isNodeDeleting = true; break; } } } return this.isNodeDeleting; } /** * Returns true if rule is deleting on nodes and after deleting a dangling-edge problem * may occurred. * * Otherwise returns false. */ public boolean mayCauseDanglingEdge() { final List<Node> delNodes = this.findNodesToDelete(); if (delNodes.isEmpty()) { return false; } boolean result = false; for (int i=0; i<delNodes.size() && !result; i++) { final Node n = delNodes.get(i); final Vector<Arc> inheritedArcs = this.getTypeSet().getInheritedArcs(n.getType()); if (inheritedArcs.size() > 0) { // TypeGraph exists and arcs at Node of type n.getType() for (int j=0; j<inheritedArcs.size() && !result; j++) { final Arc a = inheritedArcs.get(j); if (a.getSourceType().isParentOf(n.getType())) { int number = n.getNumberOfOutgoingArcsOfTypeToTargetType(a.getType(), a.getTarget().getType()); if (number > 0) { int tarMax = a.getType().getTargetMax(a.getSource().getType(), a.getTarget().getType()); if (tarMax != TypeSet.UNDEFINED && number != tarMax) { result = true; } } else if (!this.hasNacWhichForbidsArc(a, n)) result = true; // else // result = true; } else if (a.getTargetType().isParentOf(n.getType())) { int number = n.getNumberOfIncomingArcsOfTypeFromSourceType(a.getType(), a.getSource().getType()); if (number > 0 ) { int srcMax = a.getType().getSourceMax(a.getSource().getType(), a.getTarget().getType()); if (srcMax != TypeSet.UNDEFINED && number != srcMax) { result = true; } } else if (!this.hasNacWhichForbidsArc(a, n)) result = true; // else // result = true; } } } } return result; } private boolean hasNacWhichForbidsArc(Arc typeArc, Node lhsNode) { for (int i=0; i<this.itsNACs.size(); i++) { OrdinaryMorphism nac = this.itsNACs.get(i); if (!nac.isEnabled()) continue; Iterator<Arc> arcs = nac.getTarget().getArcsCollection().iterator(); while (arcs.hasNext()) { Arc a = arcs.next(); if (!nac.getInverseImage(a).hasMoreElements() && a.getType() == typeArc.getType()) { Node n = (Node)nac.getImage(lhsNode); if (n == a.getSource()) { return true; } else if (n == a.getTarget()) { return true; } } } } return false; } public boolean isArcDeleting() { if (this.isDeleting) { for (final Iterator<Arc> en = getLeft().getArcsSet().iterator(); en.hasNext();) { if (getImage(en.next()) == null) { return true; } } } return false; } /* * Checks whether this rule deletes an edge of the given type * and the specified source and target nodes. * The nodes must be contained in the LHS of this rule. */ public boolean isArcDeleting(final Node src, final Type arct, final Node tar) { if (this.itsOrig.getNodesSet().contains(src) && this.itsOrig.getNodesSet().contains(tar)) { for (final Iterator<Arc> en = src.getOutgoingArcs(arct, tar.getType()).iterator(); en.hasNext();) { if (getImage(en.next()) == null) { return true; } } } return false; } /* * Checks whether this rule deletes the specified edge. * The edge must be contained in the LHS of this rule. */ public boolean isArcDeleting(final Arc a) { if (this.itsOrig.getArcsSet().contains(a) && this.getImage(a) == null) { return true; } return false; } /* * Checks whether this rule creates an edge of the given type * and the specified source and target nodes. * The nodes must be contained in the LHS of this rule. */ public boolean isArcCreating(final Node src, final Type arct, final Node tar) { if (this.isCreating && this.itsOrig.getNodesSet().contains(src) && this.itsOrig.getNodesSet().contains(tar)) { for (final Iterator<Arc> en = this.itsImag.getArcsSet().iterator(); en.hasNext();) { Arc a = en.next(); if (a.getType().compareTo(arct) && !this.getInverseImage(a).hasMoreElements()) { List<GraphObject> inv1 = this.getInverseImageList(a.getSource()); if (inv1.contains(src)) { List<GraphObject> inv2 = this.getInverseImageList(a.getTarget()); if (inv2.contains(tar)) { return true; } } } } } return false; } /* * Checks whether this rule creates the specified edge. * The edge must be contained in the RHS of this rule. * The source and target nodes must be preserved by this rule. */ public boolean isArcCreating(final Arc a) { if (//this.itsImag.getArcsSet().contains(a) && !this.getInverseImage(a).hasMoreElements() && this.getInverseImage(a.getSource()).hasMoreElements() && this.getInverseImage(a.getTarget()).hasMoreElements()) { return true; } return false; } /** * @deprecated replaced by <code>Vector<GraphObject> getElementsToDelete()</code> */ public List<GraphObject> getObjectsToDelete() { return getElementsToDelete(); } /** * @deprecated use <code>getElementsToDelete().size()</code> */ public int getNumberOfObjectsToDelete() { return getElementsToDelete().size(); } /** * Returns elements of the LHS which should be preserved. */ public List<GraphObject> getElementsToPreserve() { if (this.preserved == null || this.itsImag.changed) { this.preserved = findElementsToPreserve(); } return this.preserved; } /** * Returns elements of the RHS to create. */ public List<GraphObject> getElementsToCreate() { if (this.created == null || this.itsImag.changed) { this.created = findElementsToCreate(); } return this.created; } /** * Returns elements of the LHS to delete. */ public List<GraphObject> getElementsToDelete() { if (this.deleted == null || this.itsOrig.changed) { this.deleted = findElementsToDelete(); } return this.deleted; } /** * Returns preserved elements which attributes should be changed. * The key is an object of the LHS, the value - its image of the RHS. */ public Hashtable<GraphObject, GraphObject> getElementsToChange() { if (this.changedPreserved == null || this.itsOrig.changed) this.changedPreserved = findElementsToChange(); return this.changedPreserved; } private List<GraphObject> findElementsToPreserve() { List<GraphObject> vec = new Vector<GraphObject>(); vec.addAll(this.itsDomObjects); return vec; } private List<GraphObject> findElementsToCreate() { List<GraphObject> vec = new Vector<GraphObject>(); vec.addAll(this.findNodesToCreate()); vec.addAll(this.findArcsToCreate()); this.isCreating = !vec.isEmpty(); return vec; } private List<Node> findNodesToCreate() { List<Node> vec = new Vector<Node>(); for (Iterator<Node> en = getRight().getNodesSet().iterator(); en.hasNext();) { Node o = en.next(); if (!getInverseImage(o).hasMoreElements()) vec.add(o); } return vec; } private List<Arc> findArcsToCreate() { List<Arc> vec = new Vector<Arc>(); for (Iterator<Arc> en = getRight().getArcsSet().iterator(); en.hasNext();) { Arc o = en.next(); if (!getInverseImage(o).hasMoreElements()) vec.add(o); } return vec; } private List<GraphObject> findElementsToDelete() { final List<GraphObject> vec = new Vector<GraphObject>(); vec.addAll(findNodesToDelete()); vec.addAll(findArcsToDelete()); return vec; } private List<Node> findNodesToDelete() { final List<Node> vec = new Vector<Node>(); for (final Iterator<Node> en = getLeft().getNodesSet().iterator(); en.hasNext();) { final Node o = en.next(); if (getImage(o) == null) vec.add(o); } this.isDeleting = !vec.isEmpty(); this.isNodeDeleting = this.isDeleting; return vec; } private Vector<Arc> findArcsToDelete() { final Vector<Arc> vec = new Vector<Arc>(); for (final Iterator<Arc> en = getLeft().getArcsSet().iterator(); en.hasNext();) { final Arc o = en.next(); if (getImage(o) == null) vec.addElement(o); } this.isDeleting = this.isDeleting || !vec.isEmpty(); return vec; } /** * Returns true if this rule will change some attributes of the graph elements, * otherwise - false. */ public boolean isChanging() { for (int i=0; i<this.itsDomObjects.size(); i++) { GraphObject go = this.itsDomObjects.get(i); if (isChangingAttribute(go, getImage(go))) { this.isChanging = true; break; } } return this.isChanging; } /* * Returns preserved graph objects to be changed. The key is a graph object * of the LHS, the value is its image object of the RHS */ private Hashtable<GraphObject, GraphObject> findElementsToChange() { Hashtable<GraphObject, GraphObject> set = new Hashtable<GraphObject, GraphObject>(); for (int i=0; i<this.itsDomObjects.size(); i++) { GraphObject go = this.itsDomObjects.get(i); if (isChangingAttribute(go, getImage(go))) { set.put(go, getImage(go)); } } this.isChanging = !set.isEmpty(); return set; } private boolean isChangingAttribute(GraphObject obj, GraphObject img) { if (img.getAttribute() == null || img.getAttribute().getNumberOfEntries() == 0) return false; ValueTuple vtObj = (ValueTuple) obj.getAttribute(); ValueTuple vtImg = (ValueTuple) img.getAttribute(); for (int i = 0; i < vtObj.getNumberOfEntries(); i++) { ValueMember vmObj = vtObj.getValueMemberAt(i); ValueMember vmImg = vtImg.getValueMemberAt(vmObj.getName()); if (vmImg != null && vmImg.isSet()) { if (!vmObj.isSet()) return true; else if (!vmImg.getExprAsText().equals(vmObj.getExprAsText())) return true; } } return false; } /* * protected boolean differentVariablesUsed(Graph g, Enumeration nacs) { * AttrContext ac = getAttrContext(); VarTuple avt = (VarTuple) * ac.getVariables(); Hashtable<VarMember,Boolean> used = new Hashtable<VarMember,Boolean>(avt.getSize()); * for (int i = 0; i < avt.getSize(); i++) { VarMember var = * avt.getVarMemberAt(i); used.put(var, Boolean.valueOf(false)); } Enumeration e = * g.getElements(); while (nacs.hasMoreElements()) { used = new Hashtable<VarMember,Boolean>(avt.getSize()); * for (int i = 0; i < avt.getSize(); i++) { VarMember var = * avt.getVarMemberAt(i); used.put(var, Boolean.valueOf(false)); } * OrdinaryMorphism m = (OrdinaryMorphism) nacs.nextElement(); e = * m.getTarget().getElements(); while (e.hasMoreElements()) { GraphObject o = * (GraphObject) e.nextElement(); if(o.getAttribute() == null) continue; * AttrInstance attr = o.getAttribute(); ValueTuple vt = (ValueTuple) attr; * if (m.getInverseImage(o).hasMoreElements()) { GraphObject orig = * (GraphObject) m.getInverseImage(o).nextElement(); ValueTuple vtOrig = * (ValueTuple) orig.getAttribute(); for (int k = 0; k < vt.getSize(); k++) { * ValueMember vm = vt.getValueMemberAt(k); ValueMember vmOrig = * vtOrig.getValueMemberAt(k); if (vmOrig.isSet() && vm.isSet()) { if * (vmOrig.getExpr().isVariable() && vm.getExpr().isVariable()) { // * System.out.println(vm.getExpr()); if * (!vmOrig.getExprAsText().equals(vm.getExprAsText())) return false; } } } } } } * return true; } * * * protected boolean areSameVariablesUsed() { AttrContext ac = * getAttrContext(); VarTuple avt = (VarTuple) ac.getVariables(); Hashtable<VarMember,Boolean> * used = new Hashtable<VarMember,Boolean>(avt.getSize()); for (int i = 0; * i < avt.getSize(); i++) { VarMember var = avt.getVarMemberAt(i); * used.put(var, Boolean.valueOf(false)); } Vector<VarMember> result = new * Vector<VarMember>(); Enumeration e = getLeft().getElements(); while * (e.hasMoreElements()) { GraphObject o = (GraphObject) e.nextElement(); * if(o.getAttribute() == null) continue; AttrInstance attr = * o.getAttribute(); ValueTuple vt = (ValueTuple) attr; for (int k = 0; k < * vt.getSize(); k++) { ValueMember vm = vt.getValueMemberAt(k); if * (vm.isSet()) { if (vm.getExpr().isVariable()) { // * System.out.println(vm.getExpr()); VarMember var = * avt.getVarMemberAt(vm.getExprAsText()); if (((Boolean) * used.get(var)).booleanValue() == false) used.put(var, Boolean.valueOf(true)); * else { if (!result.contains(var)) result.add(var); } } } } } if * (result.size() != 0) return true; else return false; } */ /** * Restores variable declarations of the RHS, NACs and PACs. * The reason is: the variables declarations can be lost after a step. * Before the next application of this rule can be done * the lost variable declarations have to be restored. * This method is called during Critical Pair Analysis. */ protected void restoreVariableDeclaration() { VarTuple vart = (VarTuple) getAttrContext().getVariables(); if (this.itsImag.isAttributed()) { // check vars of RHS this.restoreVarDecl(this.itsImag, vart); } // check vars of NACs for (int l=0; l<this.itsNACs.size(); l++) { OrdinaryMorphism nac = this.itsNACs.get(l); if (nac.getImage().isAttributed()) { this.restoreVarDecl(nac.getImage(), vart); } } // check vars of PACs for (int l=0; l<this.itsPACs.size(); l++) { OrdinaryMorphism pac = this.itsPACs.get(l); if (pac.getImage().isAttributed()) { this.restoreVarDecl(pac.getImage(), vart); } } // check vars of nested ACs for (int l=0; l<this.itsACs.size(); l++) { OrdinaryMorphism ac = this.itsACs.get(l); if (ac.getImage().isAttributed()) { this.restoreVarDecl(ac.getImage(), vart); } } } private void restoreVarDecl(final Graph g, final VarTuple vart) { Enumeration<GraphObject> en1 = g.getElements(); while (en1.hasMoreElements()) { GraphObject o = en1.nextElement(); if (o.getAttribute() == null) continue; AttrInstance attr = o.getAttribute(); ValueTuple vt = (ValueTuple) attr; for (int k = 0; k < vt.getSize(); k++) { ValueMember vm = vt.getValueMemberAt(k); if (vm.isSet() && vm.getExpr().isVariable()) { String n = vm.getExprAsText(); String t = vm.getDeclaration().getTypeName(); VarMember varm = vart.getVarMemberAt(n); String t_varm = ""; if (varm != null) t_varm = varm.getDeclaration().getTypeName(); if (varm == null || !t.equals(t_varm)) { vart.declare(vm.getDeclaration().getHandler(), t, n); ((VarMember) vart.getMemberAt(n)) .setTransient(true); } } } } } public Vector<Type> getUsedTypes() { // get types of LHS and RHS final Vector<Type> vec = super.getUsedTypes(); // add types of NACs for (int i = 0; i < this.itsNACs.size(); i++) { OrdinaryMorphism om = this.itsNACs.get(i); addUsedTypes(om.getTarget(), vec); } // add types of PACs for (int i = 0; i < this.itsPACs.size(); i++) { OrdinaryMorphism om = this.itsPACs.get(i); addUsedTypes(om.getTarget(), vec); } // add types of nested ACs for (int i = 0; i < this.itsACs.size(); i++) { OrdinaryMorphism om = this.itsACs.get(i); addUsedTypes(om.getTarget(), vec); } return vec; } private void addUsedTypes(final Graph g, final List<Type> vec) { Iterator<Node> nodes= g.getNodesSet().iterator(); while (nodes.hasNext()) { GraphObject o = nodes.next(); if (!vec.contains(o.getType())) vec.add(o.getType()); } Iterator<Arc> arcs= g.getArcsSet().iterator(); while (arcs.hasNext()) { GraphObject o = arcs.next(); if (!vec.contains(o.getType())) vec.add(o.getType()); } } /** * Returns error message if this rule is not ready to transform. * * @see agg.xt_basis.Rule#isReadyToTransform(). */ public String getErrorMsg() { return this.errorMsg; } /** * Returns true if this rule can make a match basically. * It works for INJECTIVE matching, only. */ public boolean canMatch(Graph g, MorphCompletionStrategy strategy) { // check graph size if injective morphism if (strategy.getProperties().get(CompletionPropertyBits.INJECTIVE)) { if ((getLeft().getNodesCount() > g.getNodesCount()) || (getLeft().getArcsCount() > g.getArcsCount())) return false; } // check types: all types of the orig. graph should be in image, too Vector<Type> origTypes = getLeft().getUsedTypes(); // TODO::mit PACs origTypes erweitern Vector<Type> otherTypes = g.getUsedAndInheritedTypes(); for (int i = 0; i < origTypes.size(); i++) { if (!otherTypes.contains(origTypes.get(i))) return false; } return true; } /** * Set its match to the specified parameter. */ public void setMatch(Match m) { this.itsMatch = m; } /** * Reset target graph of its match, if it exists. */ public void resetTargetOfMatch(Graph g) { if (this.itsMatch != null) { this.itsMatch.setTarget(g); } } public void setParallelMatchingEnabled(boolean b) { this.parallelMatching = b; } public boolean isParallelApplyEnabled() { return this.parallelMatching; } public void setRandomizedCSPDomain(boolean b) { this.randomCSPDomain = b; } public boolean isRandomizedCSPDomain() { return this.randomCSPDomain; } /** * Allows to define the CSP solver has to do * next match completion starting always by first CSP variable.<br> * This works for parallel match only. * The method <code>setParallelMatchingEnabled(true)</code> should be called before. */ public void setStartParallelMatchingByFirst(boolean b) { this.startParallelMatchByFirstCSPVar = b; } /** * Set value of the input parameter of its attribute context. * The specified parameters contain: * String - is a name of an input parameter, * first Object of a Vector - is the value, * second Object of a Vector - is the type of this input parameter. */ public void setInputParameters(HashMap<String, Vector<Object>> parameters) { VarTuple var = (VarTuple) getAttrContext().getVariables(); int j = 0; for (int i = 0; i < var.getNumberOfEntries(); i++) { VarMember varm = var.getVarMemberAt(i); if (varm.isInputParameter()) { Vector<Object> valuePair = parameters.get(varm.getName()); Object value = valuePair.get(0); String type = (String) valuePair.get(1); if (type.equals("int") || type.equals("boolean") || type.equals("float") || type.equals("double") || type.equals("short") || type.equals("long")) { varm.setExprAsEvaluatedText(value.toString()); } else { varm.setExprAsObject(value); } j++; } if (j > parameters.size()) { break; } } } protected boolean evalDefaultFormula() { if (this.itsMatch == null) return false; if (this.itsACs.size() == 0) { return true; } int n = this.itsACs.size(); final List<Evaluable> vars = new Vector<Evaluable>(n); String tmp = ""; int indx = -1; for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); if (ac.isEnabled()) { indx++; ac.setRelatedMorphism(this.itsMatch); vars.add(ac); if (indx == 0) { if (this.formStr.equals("false")) tmp = tmp.concat("!".concat(String.valueOf(vars.size()))); else tmp = tmp.concat(String.valueOf(vars.size())); } else { if (this.formStr.equals("false")) tmp = tmp.concat("&!").concat(String.valueOf(vars.size())); else tmp = tmp.concat("&").concat(String.valueOf(vars.size())); } } } System.out.println("Test formula of (nested) appl conds: " + tmp); boolean res = this.itsFormula.setFormula(vars, tmp) && this.itsFormula.eval(this.itsMatch.getImage()); if (!res) { this.itsMatch.setErrorMsg("Formula: " + tmp + " is violated!"); } return res; } public boolean setDefaultFormulaTrue() { if (this.itsACs.size() == 0) { this.formStr = "true"; this.formReadStr = "true"; return true; } final List<Evaluable> vars = new Vector<Evaluable>(this.itsACs.size()); for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); if (ac.isEnabled()) { vars.add(ac); } } String tmp = ""; for (int i=0; i<vars.size(); i++) { String tmp1 = (i == 0)? tmp.concat(String.valueOf(i+1)): tmp.concat("&").concat(String.valueOf(i+1)); tmp = tmp1; } if ("".equals(tmp)) { this.formStr = "true"; this.formReadStr = "true"; return true; } if (this.itsFormula.setFormula(vars, tmp)) { this.formStr = this.itsFormula.getAsString(vars); this.formReadStr = this.itsFormula.getAsString(vars, this.getNameOfEnabledACs()); // System.out.println(this.formReadStr); // this.setTextualComment("Formula: ".concat(this.formReadStr)); return true; } return false; } public boolean setDefaultFormulaFalse() { if (this.itsACs.size() == 0) { this.formStr = "true"; this.formReadStr = "true"; return true; } final List<Evaluable> vars = new Vector<Evaluable>(this.itsACs.size()); for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); if (ac.isEnabled()) { vars.add(ac); } } String tmp = ""; for (int i=0; i<vars.size(); i++) { String tmp1 = (i == 0)? tmp.concat(String.valueOf(i+1)): tmp.concat("&").concat(String.valueOf(i+1)); tmp = tmp1; } if ("".equals(tmp)) { this.formStr = "true"; this.formReadStr = "true"; return true; } else { tmp ="!(".concat(tmp).concat(")"); } if (this.itsFormula.setFormula(vars, tmp)) { this.formStr = this.itsFormula.getAsString(vars); this.formReadStr = this.itsFormula.getAsString(vars, this.getNameOfEnabledACs()); // System.out.println(this.formReadStr); // this.setTextualComment("Formula: ".concat(this.formReadStr)); return true; } return false; } public boolean evalFormula() { boolean result = true; if (this.itsMatch != null && this.itsACs.size() != 0) { for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); if (ac.isEnabled()) { ac.setRelatedMorphism(this.itsMatch); } } if (this.formStr.equals("true")) this.setDefaultFormulaTrue(); else if (this.formStr.equals("false")) this.setDefaultFormulaFalse(); result = this.itsFormula.eval(this.itsMatch.getImage()); if (!result) { this.itsMatch.setErrorMsg("Formula: " + this.formReadStr + " is violated!"); } this.disposeResultsOfNestedACs(); return result; } else return true; } public void setFormula(Formula f) { // this.itsFormula = f; // this.formulaStr = this.itsFormula.getAsString(this.getEnabledGeneralACsAsEvaluable()); // this.setTextualComment("Formula: ".concat(this.formulaStr)); this.setFormula(f.getAsString(this.getEnabledGeneralACsAsEvaluable()), this.getEnabledACs()); } /** * Set a boolean formula represented by the specified bnf string * above nested application conditions. * @param bnf */ public boolean setFormula(String bnf) { // final List<NestedApplCond> vars = new Vector<NestedApplCond>(this.itsACs.size()); // for (int i=0; i<this.itsACs.size(); i++) { // vars.add((NestedApplCond) this.itsACs.get(i)); // } return this.setFormula(bnf, this.getEnabledACs()); } /** * Set a boolean formula represented by the specified bnf string * above nested application conditions. * @param bnf */ public boolean setFormula(String bnf, final List<NestedApplCond> list) { if (bnf.equals("true")) { // this.formStr = bnf; // this.formReadStr = bnf; // return true; return this.setDefaultFormulaTrue(); } else if (bnf.equals("false")) { return this.setDefaultFormulaFalse(); } final List<Evaluable> vars = new Vector<Evaluable>(); for (int i=0; i<list.size(); i++) { NestedApplCond ac = list.get(i); if (ac.isEnabled()) { vars.add(ac); } } if (vars.isEmpty()) { this.formStr = "true"; this.formReadStr = "true"; return true; } if (this.itsFormula.setFormula(vars, bnf)) { this.formStr = this.itsFormula.getAsString(vars); this.formReadStr = this.itsFormula.getAsString(vars, this.getNameOfEnabledACs()); // System.out.println(this.formReadStr); this.setTextualComment("Formula: ".concat(this.formReadStr)); return true; } else return false; } public boolean refreshFormula(final List<Evaluable> vars) { String bnf = this.formStr; if (this.itsFormula.setFormula(vars, bnf)) { this.formStr = this.itsFormula.getAsString(vars); this.formReadStr = this.itsFormula.getAsString(vars, this.getNameOfEnabledACs()); this.setTextualComment("Formula: ".concat(this.formReadStr)); return true; } else { this.formStr = "true"; this.formReadStr = "true"; } return false; } /** * Returns the formula string as internal represantation * like this: (1&2).>br> * This method shoud be used for all actions relationg to Formula objects. */ public String getFormulaStr() { return this.formStr; } /** * Returns the formula string as readable represantation * like this: (nameOf1 & nameOf2).<br> * This method shoud be used for messages. */ public String getFormulaText() { return this.formReadStr; } public Formula getFormula() { return this.itsFormula; } /** * Returns true, if it contains enabled nested application conditions. */ public boolean hasEnabledACs(boolean checkBefore) { if (checkBefore) { this.hasEnabledGACs = false; for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); if (ac.isEnabled()) { this.hasEnabledGACs = true; break; } } } return this.hasEnabledGACs; } /** * Returns a list with names of enabled general application conditions. */ public List<String> getNameOfEnabledACs() { final List<String> vars = new Vector<String>(); for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); if (ac.isEnabled()) vars.add(ac.getName()); } return vars; } /** * Returns a list with names of enabled general application conditions * and its nested ACs inclusively. */ public List<String> getNameOfEnabledNestedACs() { final List<String> vars = new Vector<String>(); for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); if (ac.isEnabled()) vars.add(ac.getName()); vars.addAll(ac.getNameOfEnabledNestedACs()); } return vars; } /** * Returns a list with names of all general application conditions * and its nested ACs inclusively. */ public List<String> getNameOfNestedACs() { final List<String> vars = new Vector<String>(); for (int i=0; i<this.itsACs.size(); i++) { NestedApplCond ac = (NestedApplCond) this.itsACs.get(i); vars.add(ac.getName()); vars.addAll(ac.getNameOfEnabledNestedACs()); } return vars; } /** * Makes the minimal rule from the given rule. * A minimal rule comprises the effects of a given rule in a minimal context. */ public Rule getMinimalRule() { return BaseFactory.theBaseFactory.makeMinimalOfRule(this); } /** * Returns an inverse construction of this rule.<br> * This rule has to be injective, otherwise returns null.<br> * <br> * Note: This method is mainly used during critical pair analysis. */ public InverseRuleConstructData getInverseConstructData() { if (this.isInjective()) { if (this.invConstruct == null) { this.invConstruct = new InverseRuleConstructData(this); } return this.invConstruct; } return null; } /** * This method does not destroy the Rule and OrdinaryMorphism instances of the inverse construction. * They must be disposed by the user object explicitly. * The local pair references set to null, only. */ public void disposeInverseConstruct() { if (this.invConstruct != null) { this.invConstruct.dispose(); this.invConstruct = null; } } /** * Destroys the Rule and OrdinaryMorphism instances of the inverse construction. * The local pair references set to null. */ public void destroyInverseConstruct() { if (this.invConstruct != null) { this.invConstruct.destroy(); this.invConstruct = null; } } public void initSignatur() { ((VarTuple)this.getAttrContext().getVariables()).initSignaturOrder(); } public void disposeSignatur() { ((VarTuple)this.getAttrContext().getVariables()).disposeSignaturOrder(); } public List<Integer> getSignaturOrder() { return ((VarTuple)this.getAttrContext().getVariables()).getSignaturOrder(); } public String getSignatur() { VarTuple vars = (VarTuple)this.getAttrContext().getVariables(); String s = this.getName().concat("("); String s1 = ""; List<Integer> order = vars.getSignaturOrder(); for (int i = 0; i < order.size(); i++) { VarMember m = (VarMember) vars.getMemberAt(order.get(i).intValue()); String nt = m.getName().concat(":").concat(m.getDeclaration().getTypeName()); s1 = s1.concat(nt); if (i < (order.size()-1)) s1 = s1.concat(", "); } String s2 = ""; for (int i = 0; i < vars.getSize(); i++) { VarMember m = (VarMember) vars.getMemberAt(i); if (m.isOutputParameter()) { if (!s1.isEmpty()) s2 = s2.concat(", "); s2 = s2.concat("out "); String nt = m.getName().concat(":").concat(m.getDeclaration().getTypeName()); s2 = s2.concat(nt); break; } } s = s.concat(s1).concat(s2); s = s.concat(")"); return s; } public void addInToSignatur(int indxOfVar) { ((VarTuple)this.getAttrContext().getVariables()).addToSignaturOrder(indxOfVar); } public void removeInFromSignatur(int indxOfVar) { ((VarTuple)this.getAttrContext().getVariables()).removeFromSignaturOrder(indxOfVar); } public void addOutToSignatur(int indxOfVar) { VarTuple vars = (VarTuple)this.getAttrContext().getVariables(); for (int i = 0; i < vars.getSize(); i++) { VarMember m = (VarMember) vars.getMemberAt(i); if (i == indxOfVar) m.setOutputParameter(true); else m.setOutputParameter(false); } } public void removeOutFromSignatur(int indxOfVar) { VarTuple vars = (VarTuple)this.getAttrContext().getVariables(); VarMember m = (VarMember) vars.getMemberAt(indxOfVar); if (m != null) m.setOutputParameter(false); } }