package agg.xt_basis; import java.util.Collection; import java.util.Collections; import java.util.Dictionary; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Vector; import agg.attribute.AttrContext; import agg.attribute.AttrException; import agg.attribute.AttrInstance; import agg.attribute.AttrManager; import agg.attribute.AttrMapping; import agg.attribute.handler.AttrHandlerException; import agg.attribute.handler.HandlerExpr; import agg.attribute.impl.AttrTupleManager; import agg.attribute.impl.ContextView; import agg.attribute.impl.DeclMember; import agg.attribute.impl.ValueMember; import agg.attribute.impl.ValueTuple; import agg.attribute.impl.VarMember; import agg.attribute.impl.VarTuple; import agg.attribute.impl.CondTuple; import agg.attribute.impl.CondMember; import agg.util.ExtObservable; import agg.util.XMLHelper; import agg.util.Change; import agg.util.Pair; import agg.xt_basis.csp.CompletionPropertyBits; /** * Implementation of a graph morphism. Note: This implementation is guaranteed * to keep morphism properties when objects are deleted/created/modified in the * original or image graphs. */ // Class OrdinaryMorphism is capable of passing the following change // informations as an argument to its observers' <code>update()</code> methods: // Morph_Change_MappingAdded, Morph_Change_MappingRemoved. // Additionally, the information <code>Change_ObservableGone</code> // may be generated by its base class <code>ExtObservable</code>. // If, however, the value of the change information is given as // <code>null</code>, the observer is recommended to perform a full // rescan of the morphism. public class OrdinaryMorphism extends ExtObservable implements Morphism // , Observer { protected String itsName; protected String comment = ""; protected MorphCompletionStrategy itsCompleter; protected boolean itsTouchedFlag = true; protected boolean itsInteractiveFlag = true; protected Dictionary<AttrInstance, AttrMapping> itsAttrMappings; protected AttrContext itsAttrContext; protected AttrManager itsAttrManager; protected Graph itsOrig; protected Graph itsImag; /** * Use this constant as a parameter in my constructors or in the * <code>initialize()</code> method to indicate that the attribute context * in question should not be altered. */ protected static final AttrContext cKeepContext = null; final protected Vector<GraphObject> itsDomObjects = new Vector<GraphObject>(); final protected Vector<GraphObject> itsCodomObjects = new Vector<GraphObject>(); protected OrdinaryMorphism itsCoMorph; protected boolean enabled = true; boolean mappingChanged; protected boolean changed; protected boolean typeObjectsMapChanged; protected boolean partialMorphCompletion; protected boolean shifted; protected String errorMsg; // protected Vector<String> errors; protected OrdinaryMorphism() { this(new Graph(), new Graph(), cKeepContext); } /** * @param ac * my attribute context. */ protected OrdinaryMorphism(final AttrContext ac) { this(new Graph(), new Graph(), ac); } /** * @param orig * my original graph. * @param img * my image graph. */ public OrdinaryMorphism(final Graph orig, final Graph img) { this(orig, img, cKeepContext); } /** * @param orig * my original graph. * @param img * my image graph. * @param ac * my attribute context. */ public OrdinaryMorphism(final Graph orig, final Graph img, final AttrContext ac) { this.itsName = "OrdinaryMorphism"; this.itsOrig = orig; // this.itsOrig.setKind(GraphKind.SOURCE); this.itsOrig.addUsingMorph(this); this.itsImag = img; // this.itsImag.setKind(GraphKind.TARGET); this.itsImag.addUsingMorph(this); this.itsAttrContext = ac; this.itsAttrMappings = new Hashtable<AttrInstance, AttrMapping>(20); this.itsAttrManager = AttrTupleManager.getDefaultManager(); setCompletionStrategy(CompletionStrategySelector.getDefault()); this.itsTouchedFlag = true; this.itsInteractiveFlag = true; this.errorMsg = ""; // this.errors = new Vector<String>(2, 2); } /** * Remove all graph object mappings and all relations to its source and target graphs. */ public void dispose() { if (this.itsCompleter != null) { this.itsCompleter.dispose(); } removeAllMappings(); this.itsOrig.removeUsingMorph(this); this.itsImag.removeUsingMorph(this); if (this.itsCoMorph != null) { this.itsCoMorph.dispose(); this.itsCoMorph = null; } this.clearErrorMsg(); super.dispose(); } /** * Remove all graph object mappings and all relations to its source and target graphs. * Dispose its source graph if disposableSource is TRUE, * dispose its target graph if disposableTarget is TRUE. */ public void dispose(boolean disposableSource, boolean disposableTarget) { if (this.itsCompleter != null) { this.itsCompleter.dispose(); } removeAllMappings(); this.itsOrig.removeUsingMorph(this); this.itsImag.removeUsingMorph(this); if (this.itsCoMorph != null) { this.itsCoMorph.dispose(); this.itsCoMorph = null; } this.clearErrorMsg(); super.dispose(); if (disposableSource) { this.itsOrig.dispose(); this.itsOrig = null; } if (disposableTarget) { this.itsImag.dispose(); this.itsImag = null; } } public boolean isInjectiveSet() { return this.getCompletionStrategy().getProperties().get(CompletionPropertyBits.INJECTIVE); } public boolean isDanglingSet() { return this.getCompletionStrategy().getProperties().get(CompletionPropertyBits.DANGLING); } public boolean isIdentificationSet() { return this.getCompletionStrategy().getProperties().get(CompletionPropertyBits.IDENTIFICATION); } public boolean isGluingConditionSet() { return this.getCompletionStrategy().getProperties().get(CompletionPropertyBits.DANGLING) && this.getCompletionStrategy().getProperties().get(CompletionPropertyBits.IDENTIFICATION); } public boolean isNotificationRequired() { return (this.countObservers() > 0); } public void setTarget(Graph g) { this.itsImag = g; } public void setSource(Graph g) { this.itsOrig = g; } public boolean isTypeObjectsMapChanged() { return this.typeObjectsMapChanged; } public void setTypeObjectsMapChanged(boolean b) { this.typeObjectsMapChanged = b; } public boolean hasPartialMorphismCompletion() { return this.partialMorphCompletion; } public void setPartialMorphismCompletion(boolean b) { this.partialMorphCompletion = b; } /** * Enable or disable this morphism to make it usable during transformation. */ public void setEnabled(boolean enable) { this.enabled = enable; } /** * Returns TRUE if this morphism is active otherwise * FALSE. */ public boolean isEnabled() { return this.enabled; } /* * This method is used for internal computations only. */ public boolean isShifted() { return this.shifted; } public void setErrorMsg(String msg) { this.errorMsg = msg; } /** * Return an error message if this morphism is failed, otherwise - empty * message. */ public String getErrorMsg() { return this.errorMsg; } /* public void addErrorMsg(String msg) { this.errorMsg = msg; // this.errors.add(this.errorMsg); } */ public void clearErrorMsg() { // this.errors.clear(); this.errorMsg = ""; ((agg.attribute.impl.ContextView) this.getAttrContext()).getManager() .clearErrorMsg(); ((agg.attribute.impl.ContextView) this.getAttrContext()) .clearErrorMsg(); } /** * Returns true, if the same source object refers the same target object, * otherwise false. * Precondition: this.source == m.source, this.target == m.target */ public final boolean isCommutative(Morphism m) { if (this.itsOrig.getTypeSet().isArcDirected()) return isCommutative1(m); else return isCommutative2(m); } private final boolean isCommutative1(Morphism m) { if (m == this) return true; if (m.getOriginal() == this.itsOrig) { final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator(); while (allOrigNodes.hasNext()) { GraphObject anOrig = allOrigNodes.next(); GraphObject anImage1 = this.getImage(anOrig); GraphObject anImage2 = m.getImage(anOrig); if (anImage1 == null) { if (anImage2 != null) return false; } else if (anImage1 != anImage2) return false; } final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator(); while (allOrigArcs.hasNext()) { GraphObject anOrig = allOrigArcs.next(); GraphObject anImage1 = this.getImage(anOrig); GraphObject anImage2 = m.getImage(anOrig); if (anImage1 == null){ if (anImage2 != null) return false; } else if (anImage1 != anImage2) return false; } return true; } return false; } private final boolean isCommutativeORIG(Morphism m) { if (m == this) return true; if (m.getOriginal() == this.itsOrig) { final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator(); while (allOrigNodes.hasNext()) { GraphObject anOrig = allOrigNodes.next(); GraphObject anImage1 = this.getImage(anOrig); GraphObject anImage2 = m.getImage(anOrig); if (anImage1 == null) { if (anImage2 == null) continue; return false; } else if (anImage1 == anImage2) continue; return false; } final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator(); while (allOrigArcs.hasNext()) { GraphObject anOrig = allOrigArcs.next(); GraphObject anImage1 = this.getImage(anOrig); GraphObject anImage2 = m.getImage(anOrig); if (anImage1 == null){ if (anImage2 == null) continue; return false; } else if (anImage1 == anImage2) continue; return false; } return true; } return false; } private final boolean isCommutative2(Morphism m) { if (m == this) return true; if (m.getOriginal() == this.itsOrig) { final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator(); while (allOrigArcs.hasNext()) { Arc anOrig = allOrigArcs.next(); GraphObject anImage1 = this.getImage(anOrig); GraphObject anImage2 = m.getImage(anOrig); if (anImage1 == null){ if (anImage2 != null) return false; } else if (anImage1 != anImage2) return false; } // now check isolated nodes only final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator(); while (allOrigNodes.hasNext()) { GraphObject anOrig = allOrigNodes.next(); GraphObject anImage1 = this.getImage(anOrig); GraphObject anImage2 = m.getImage(anOrig); if (anImage1 == null) { if (anImage2 != null) return false; } else if (anImage2 == null) return false; else if (anImage1.getNumberOfInOutArcs() == 0 && anImage2.getNumberOfInOutArcs() == 0) { if (anImage1 != anImage2) return false; } } return true; } return false; } /** * Returns true, if the same source object of m1 and (this o m2) * refers the same target object of this: * m2.getImage(this.getImage(obj)) == m1.getImage(obj). * Otherwise returns false. * * Precondition: * m1.source == this.source, * m2.source == this.target, * m1.target == m2.target */ public final boolean isCommutative(Morphism m1, Morphism m2) { if (this.itsOrig.getTypeSet().isArcDirected()) return isCommutative1(m1, m2); else return isCommutative2(m1, m2); } @SuppressWarnings("unused") private final boolean isCommutativeORIG(Morphism m1, Morphism m2) { if (m1 == this) return ((OrdinaryMorphism)m1).isCommutativeORIG(m2); if (m1.getOriginal() == this.itsOrig && this.itsImag == m2.getOriginal() && m1.getImage() == m2.getImage()) { final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator(); while (allOrigNodes.hasNext()) { GraphObject anOrig = allOrigNodes.next(); GraphObject anImage = this.getImage(anOrig); GraphObject anImage1 = m1.getImage(anOrig); if (anImage == null){ if (anImage1 == null) continue; return false; } else if (m2.getImage(anImage) == anImage1) continue; return false; } final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator(); while (allOrigArcs.hasNext()) { GraphObject anOrig = allOrigArcs.next(); GraphObject anImage = this.getImage(anOrig); GraphObject anImage1 = m1.getImage(anOrig); if (anImage == null){ if (anImage1 == null) continue; return false; } else if (m2.getImage(anImage) == anImage1) continue; return false; } return true; } return false; } private boolean isCommutative1(Morphism m1, Morphism m2) { if (m1 == this) return ((OrdinaryMorphism)m1).isCommutative1(m2); if (m1.getOriginal() == this.itsOrig && this.itsImag == m2.getOriginal() && m1.getImage() == m2.getImage()) { final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator(); while (allOrigNodes.hasNext()) { GraphObject anOrig = allOrigNodes.next(); GraphObject anImage = this.getImage(anOrig); GraphObject anImage1 = m1.getImage(anOrig); if (anImage == null){ if (anImage1 == null) continue; return false; } else if (m2.getImage(anImage) == anImage1) continue; return false; } final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator(); while (allOrigArcs.hasNext()) { GraphObject anOrig = allOrigArcs.next(); GraphObject anImage = this.getImage(anOrig); GraphObject anImage1 = m1.getImage(anOrig); if (anImage == null){ if (anImage1 == null) continue; return false; } else if (m2.getImage(anImage) == anImage1) continue; return false; } return true; } return false; } private boolean isCommutative2(Morphism m1, Morphism m2) { if (m1 == this) return ((OrdinaryMorphism)m1).isCommutative2(m2); if (m1.getOriginal() == this.itsOrig && this.itsImag == m2.getOriginal() && m1.getImage() == m2.getImage()) { // check arcs first final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator(); while (allOrigArcs.hasNext()) { Arc anOrig = allOrigArcs.next(); GraphObject anImage = this.getImage(anOrig); GraphObject anImage1 = m1.getImage(anOrig); GraphObject anImage2 = m2.getImage(anImage); if (anImage == null){ if (anImage1 != null) return false; } else if (anImage2 != anImage1) return false; } // now check isolated nodes only final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator(); while (allOrigNodes.hasNext()) { GraphObject anOrig = allOrigNodes.next(); GraphObject anImage = this.getImage(anOrig); GraphObject anImage1 = m1.getImage(anOrig); GraphObject anImage2 = m2.getImage(anImage); if (anImage == null){ if (anImage1 != null) return false; } else if (anImage1 == null) return false; else if (anImage.getNumberOfInOutArcs() == 0 && anImage1.getNumberOfInOutArcs() == 0) { if (anImage1 != anImage2) return false; } } return true; } return false; } /*************************************************************************** * Konstruiert aus dem Morphismus einen Match. * Der Morphismus muss * zwischen der linken Regelseite * der mitgegebenen Regel und dem aktuellen * Arbeitsgraphen definiert sein.* **************************************************************************/ /** * Construct a Match of the specified Rule from this morphism . The * source graph is the LHS of the rule. The mapping of this morphism is used * for the match mapping. Returns null when a BadMappingException occurred, * otherwise true. */ public Match makeMatch(Rule rule) { final Match m = (BaseFactory.theFactory()).createMatch(rule, this.itsImag); for (Enumeration<GraphObject> elements = this.getDomain(); elements.hasMoreElements();) { final GraphObject grob = elements.nextElement(); try { m.addMapping(grob, this.getImage(grob)); } catch (BadMappingException e) { this.errorMsg = e.getMessage(); // if (this.errorMsg.length()>0) // this.errors.add(this.errorMsg); m.dispose(); return null; } } return m; } /** * Make a copy of the source graph, copy of the target graph, and the * homomorphism on both graphs. The result shall not poses far reaching * references onto Rules, GraGras those kinds of objects. */ public OrdinaryMorphism morphcopy() { synchronized (this) { boolean failed = false; final Hashtable<GraphObject, GraphObject> orig2copySource = new Hashtable<GraphObject, GraphObject>(); final Hashtable<GraphObject, GraphObject> orig2copyTarget = new Hashtable<GraphObject, GraphObject>(); Graph sourceCopy = this.itsOrig.copy(orig2copySource); Graph targetCopy = this.itsImag.copy(orig2copyTarget); if (sourceCopy == null && targetCopy == null) return null; else if (sourceCopy == null) { targetCopy = null; return null; } else if (targetCopy == null) { sourceCopy = null; return null; } // Mapping is still empty OrdinaryMorphism theCopy = (BaseFactory.theFactory()) .createMorphism(sourceCopy, targetCopy); Enumeration<GraphObject> domainOrig = this.getDomain(); while (!failed && domainOrig.hasMoreElements()) { GraphObject x = domainOrig.nextElement(); if (x.isNode()) { Node y = (Node) this.getImage(x); if (y != null) { Node xCopy = (Node) orig2copySource.get(x); Node yCopy = (Node) orig2copyTarget.get(y); try { theCopy.addMapping(xCopy, yCopy); } catch (BadMappingException ex) { } } } } domainOrig = this.getDomain(); while (!failed && domainOrig.hasMoreElements()) { GraphObject x = domainOrig.nextElement(); if (x.isArc()) { Node vtx1 = (Node) (((Arc) x).getSource()); Node vtx2 = (Node) (((Arc) x).getTarget()); Node vtx1Copy = (Node) orig2copySource.get(vtx1); Node vtx2Copy = (Node) orig2copySource.get(vtx2); Arc y = (Arc) this.getImage(x); Node vtx3Copy = null; Node vtx4Copy = null; if (y != null) { Node vtx3 = (Node) y.getSource(); Node vtx4 = (Node) y.getTarget(); vtx3Copy = (Node) orig2copyTarget.get(vtx3); vtx4Copy = (Node) orig2copyTarget.get(vtx4); } Arc q = null; if (sourceCopy != null) { Iterator<Arc> sourceCopyArcs = sourceCopy.getArcsSet().iterator(); while (sourceCopyArcs.hasNext()) { Arc a = sourceCopyArcs.next(); if ((((Node) a.getSource()).equals(vtx1Copy)) && (((Node) a.getTarget()).equals(vtx2Copy))) { q = a; } } } Arc z = null; if (vtx3Copy != null && vtx4Copy != null && targetCopy != null) { Iterator<Arc> targetCopyArcs = targetCopy.getArcsSet().iterator(); while (targetCopyArcs.hasNext()) { Arc a = targetCopyArcs.next(); if ((((Node) a.getSource()).equals(vtx3Copy)) && (((Node) a.getTarget()).equals(vtx4Copy))) { z = a; } } } if (q != null && z != null) { try { if (theCopy != null) theCopy.addMapping(q, z); } catch (BadMappingException ex) { } } else { failed = true; if (theCopy != null) theCopy.dispose(); theCopy = null; if (sourceCopy != null) sourceCopy.dispose(); sourceCopy = null; if (targetCopy != null) targetCopy.dispose(); targetCopy = null; } } } return (theCopy); } } /** * The current (this) morphism takes two morphisms with : <br> * theFirst.source == theSecond.source, <br> * this.source == theFirst.target, <br> * this.target == theSecond.target.<br> * Completes this morphism so that: <em>theFirst o this = theSecond</em> . */ // // [Graph X]------------>[Graph Y] // | theFirst / // | / // | / // | / // | / // the|Second / this // | / // | / // | / // | / // | / // | / // \|/ |/_ // [Graph Z] // // ----------------------------------------------------------- public boolean makeDiagram(final OrdinaryMorphism theFirst, final OrdinaryMorphism theSecond) { if (!this.itsOrig.equals(theFirst.getImage())) return (false); if (!this.itsImag.equals(theSecond.getImage())) return (false); if (!theFirst.getOriginal().equals(theSecond.getOriginal())) return (false); // Untersuche Anwendungsvoraussetzungen: Graphen // (nur lesend, nicht schreibend) // Zusicherung hier: alle drei Morphismen leben auf den gleichen // Graphen. // ---------------------------------------------------------------------- // Naechster Schritt: Untersuche Anwendungsvoraussetzungen. // Gemeinsame Elemente von theFirst und theSecond, // nur lesend, nicht schreibend // [Im folgenden wird pessimistisch angenommen, dass // die verwendeten Enumerationen nichtdeterministisch // (zufaellig) gefuellt worden seien, sodass man keine // Reihenfolgenkenntnisse effizient nutzbar machen kann.] Enumeration<GraphObject> firstDom; Enumeration<GraphObject> secondDom; firstDom = theFirst.getDomain(); while (firstDom.hasMoreElements()) { boolean result = false; GraphObject elem1 = firstDom.nextElement(); // System.out.println("--> elem1: "+elem1); secondDom = theSecond.getDomain(); while (secondDom.hasMoreElements()) { GraphObject elem2 = secondDom.nextElement(); // System.out.println("--> elem2: "+elem2); if (elem1.equals(elem2)) { result = true; break; } } if (result == false) { return (result); /** EXIT * */ } } secondDom = theSecond.getDomain(); while (secondDom.hasMoreElements()) { boolean result = false; GraphObject elem1 = secondDom.nextElement(); firstDom = theFirst.getDomain(); while (firstDom.hasMoreElements()) { GraphObject elem2 = firstDom.nextElement(); if (elem1.equals(elem2)) { result = true; break; } } if (result == false) { return (result); } } // Zusicherung hier: theFirst und theSecond haben den // selben Definitionsbereich. // ---------------------------------------------------------------- // Naechster Schritt: Untersuche weitere Anwendungsvoraussetzungen. // Kompositionseigenschaften von ``this'' // (nur lesend, nicht schreibend) **/ Enumeration<GraphObject> ownDom = this.getDomain(); while (ownDom.hasMoreElements()) { GraphObject y = ownDom.nextElement(); GraphObject z = this.getImage(y); Enumeration<GraphObject> manyX = theFirst.getInverseImage(y); while (manyX.hasMoreElements()) { GraphObject x = manyX.nextElement(); // if (theSecond.getImage(x) != z) if (!(theSecond.getImage(x)).equals(z)) return (false); } } // this.getAttrContext()).getAllowedMapping()); // Zusicherung hier: Wo this definiert ist, gilt die Gleichung // this(theFirst(x))=theSecond(x)=z // -------------------------------- // Letzter Schritt: Vervollstaendigung von this (schreibend!) firstDom = theFirst.getDomain(); while (firstDom.hasMoreElements()) { GraphObject x = firstDom.nextElement(); GraphObject y = theFirst.getImage(x); GraphObject z = theSecond.getImage(x); if (z != null) { if (!z.equals(this.getImage(y))) { try { if (y.isNode()) this.addMapping(y, z); else { if (this.getImage(((Arc)y).getSource()).equals(((Arc)z).getSource()) && this.getImage(((Arc)y).getTarget()).equals(((Arc)z).getTarget())) this.addMapping(y, z); } } catch (BadMappingException ex) { System.out.println(ex.getMessage()); } } } } return (true); } /** * <b>makeWeakDiagram</b>: fuer <em>DISAGG</em><br> * Der vorliegende Homomorphismus (this) nimmt zwei weitere (theFirst, * theSecond) als Input und wird selbst so vervollstaendigt, dass<br> * <em>theFirst o this <= theSecond</em> */ // // [Graph X]-------------------->[Graph Y] // \ theFirst / // \ / // \ / // \ / // \ / // \ theSecond / this // \ / // \ / // \ / // \ / // \ / // \ / // _\| |/_ // [Graph Z] // // ----------------------------------------------------------- public boolean makeWeakDiagram(final OrdinaryMorphism theFirst, final OrdinaryMorphism theSecond) { /* * System.out.println(">>> OrdinaryMorphism.makeWeakDiagram(1, 2)"); * * System.out.println("====="); System.out.println("FIRST : "+theFirst); * System.out.println("SECOND: "+theSecond); System.out.println("THIS : * "+this); if( !this.getOriginal().equals(theFirst.getImage()) ) * {return(false);} if( !this.getImage().equals(theSecond.getImage()) ) * {return(false);} if( * !theFirst.getOriginal().equals(theSecond.getOriginal()) ) * {return(false);} // Untersuche Anwendungsvoraussetzungen: Graphen // * (nur lesend, nicht schreibend) // Zusicherung hier: alle drei * Morphismen leben auf den gleichen Graphen. // * ---------------------------------------------------------------------- // * Naechster Schritt: Untersuche Anwendungsvoraussetzungen. // * Gemeinsame Elemente von theFirst und theSecond, // nur lesend, nicht * schreibend // [Im folgenden wird pessimistisch angenommen, dass // * die verwendeten Enumerationen nichtdeterministisch // (zufaellig) * gefuellt worden seien, sodass man keine // Reihenfolgenkenntnisse * effizient nutzbar machen kann.] /* * if(!theFirst.getDomain().hasMoreElements()) System.out.println("--> * firstDom is EMPTY"); if(!theSecond.getDomain().hasMoreElements()) * System.out.println("--> secondDom is EMPTY"); * if(!this.getDomain().hasMoreElements()) System.out.println("--> * thisDom is EMPTY"); */ if (!theFirst.getDomain().hasMoreElements() && !theSecond.getDomain().hasMoreElements()) { return this.nextCompletion(); } // Zusicherung hier: theFirst und theSecond haben den // selben Definitionsbereich. // ---------------------------------------------------------------- // Naechster Schritt: Untersuche weitere Anwendungsvoraussetzungen. // Kompositionseigenschaften von ``this'' // (nur lesend, nicht schreibend) **/ Enumeration<GraphObject> ownDom = this.getDomain(); while (ownDom.hasMoreElements()) { GraphObject y = ownDom.nextElement(); // System.out.println("--> y: "+y); GraphObject z = this.getImage(y); // System.out.println("--> z: "+z); Enumeration<GraphObject> manyX = theFirst.getInverseImage(y); while (manyX.hasMoreElements()) { GraphObject x = manyX.nextElement(); // System.out.println("--> x: "+x); if (!(theSecond.getImage(x)).equals(z)) { return (false); } } } Enumeration<GraphObject> firstDom = theFirst.getDomain(); // Zusicherung hier: Wo this definiert ist, gilt die Gleichung // this(theFirst(x))=theSecond(x)=z // -------------------------------- // Letzter Schritt: Vervollstaendigung von this (schreibend!) firstDom = theFirst.getDomain(); while (firstDom.hasMoreElements()) { GraphObject x = firstDom.nextElement(); GraphObject y = theFirst.getImage(x); GraphObject z = theSecond.getImage(x); if (z != null) { if (!z.equals(this.getImage(y))) { try { this.addMapping(y, z); } catch (BadMappingException ex) {} } } } if (!theFirst.getDomain().hasMoreElements() || !theSecond.getDomain().hasMoreElements()) return this.nextCompletion(); return (true); } /** * The current Homomorphismus (this) morphism takes two morphisms with : <br> * theFirst.source == theSecond.source, <br> * this.source == theFirst.target, <br> * this.target == theSecond.target.<br> * Completes this morphism so that: <em>theFirst o this = theSecond</em> . */ // // [Graph X]------------------>[Graph Y] // \ theFirst / // \ / // \ / // \ / // \ / // \ theSecond / this // \ / // \ / // \ / // \ / // \ / // \ / // _\| |/_ // [Graph Z] // // ----------------------------------------------------------- public boolean makeFullDiagram(final OrdinaryMorphism theFirst, final OrdinaryMorphism theSecond) { if (!this.itsOrig.equals(theFirst.getImage())) return (false); if (!this.itsImag.equals(theSecond.getImage())) return (false); if (!theFirst.getOriginal().equals(theSecond.getOriginal())) return (false); Enumeration<GraphObject> firstDom; Enumeration<GraphObject> secondDom; /* suche nach gemeinsammen Elementen in theFirst und theSecond */ firstDom = theFirst.getOriginal().getElements(); while (firstDom.hasMoreElements()) { boolean result = false; GraphObject elem1 = firstDom.nextElement(); secondDom = theSecond.getOriginal().getElements(); while (secondDom.hasMoreElements()) { GraphObject elem2 = secondDom.nextElement(); if (elem1.equals(elem2)) { result = true; break; } } if (!result) { return result; } } secondDom = theSecond.getOriginal().getElements(); while (secondDom.hasMoreElements()) { boolean result = false; GraphObject elem1 = secondDom.nextElement(); firstDom = theFirst.getOriginal().getElements(); while (firstDom.hasMoreElements()) { GraphObject elem2 = firstDom.nextElement(); if (elem1.equals(elem2)) { result = true; break; } } if (!result) { return (result); } } // Zusicherung hier: theFirst und theSecond haben den // selben Definitionsbereich. // ---------------------------------------------------------------- // Naechster Schritt: Untersuche weitere Anwendungsvoraussetzungen. // Kompositionseigenschaften von ``this'' // (nur lesend, nicht schreibend) **/ Enumeration<GraphObject> ownDom = this.itsOrig.getElements(); while (ownDom.hasMoreElements()) { GraphObject y = ownDom.nextElement(); GraphObject z = this.getImage(y); if (z != null) { Enumeration<GraphObject> manyX = theFirst.getInverseImage(y); while (manyX.hasMoreElements()) { GraphObject x = manyX.nextElement(); if (!theSecond.getImage(x).equals(z)) { return false; } } } } // Zusicherung hier: Wo this definiert ist, gilt die Gleichung // this(theFirst(x))=theSecond(x)=z // -------------------------------- // Letzter Schritt: Vervollstaendigung von this (schreibend!) firstDom = theFirst.getOriginal().getElements(); while (firstDom.hasMoreElements()) { GraphObject x = firstDom.nextElement(); GraphObject y = theFirst.getImage(x); GraphObject z = theSecond.getImage(x); if ((y != null) && (z != null)) { if (!z.equals(this.getImage(y))) { try { this.addMapping(y, z); } catch (BadMappingException ex) { return false; } } } } return true; } /** * The current (this) morphism takes three morphisms, such that: this.source == * theFirst.target, theSecond.source == theFirst.source, theThird.source == * theSecond.target, this.target == theThird.target as input and this * morphism will be completed so that the diagram comutes: * theFirst o this == theSecond o theThird . */ // // [Graph X]---------------------->[Graph Y] // | \\ theFirst | // | \\ | // | \\ | // the|Second \\ |this // | \\ | // | \\ | // | \\ | // \|/ theThird _\| \|/ // [Graph J]---------------------->[Graph H] // // // ----------------------------------------------------------- public boolean makeDiagram(final OrdinaryMorphism theFirst, final OrdinaryMorphism theSecond, final OrdinaryMorphism theThird) { // System.out.println(">>> OrdinaryMorphism.makeDiagram(1, 2, 3)"); OrdinaryMorphism tmpMorph = theSecond.compose(theThird); return this.makeDiagram(theFirst, tmpMorph); } /** * <b>makeWeakDiagram</b>: fuer <em>DISAGG</em><br> * Der vorliegende Homomorphismus (this) nimmt drei weitere (theFirst, * theSecond, theThird) als Input und wird selbst so vervollstaendigt, dass * Diagramm schwach kommutiert. */ // // [Graph X]---------------------->[Graph Y] // | \ theFirst | // | \ | // | \ | // |theSecond \ |this // | \ | // | \ | // | \ | // \|/ theThird _\| \|/ // [Graph J]---------------------->[Graph H] // // // ----------------------------------------------------------- public boolean makeWeakDiagram(final OrdinaryMorphism theFirst, final OrdinaryMorphism theSecond, final OrdinaryMorphism theThird) { OrdinaryMorphism tmpMorph = theSecond.compose(theThird); if (this.makeWeakDiagram(theFirst, tmpMorph)) return true; return false; } /** * Der vorliegende Homomorphismus (this) nimmt drei weitere (theFirst, * theSecond, theThird) als Input und wird selbst so vervollstaendigt, dass * Diagramm kommutiert. */ // // [Graph X]---------------------->[Graph Y] // | \\ theFirst | // | \\ | // | \\ | // |theSecond \\ |this // | \\ | // | \\ | // | \\ | // \|/ theThird _\\| \|/ // [Graph J]---------------------->[Graph H] // // // ----------------------------------------------------------- public boolean makeFullDiagram(final OrdinaryMorphism theFirst, final OrdinaryMorphism theSecond, final OrdinaryMorphism theThird) { // OrdinaryMorphism tmpMorph = theSecond.compose(theThird); OrdinaryMorphism tmpMorph = (BaseFactory.theFactory()).createMorphism( theSecond.getOriginal(), theThird.getImage()); final Iterator<Node> theSecondDomNodes = theSecond.getOriginal().getNodesSet().iterator(); while (theSecondDomNodes.hasNext()) { GraphObject theSecondGo = theSecondDomNodes.next(); GraphObject theSecondGoImage = theSecond.getImage(theSecondGo); if (theSecondGoImage != null) { GraphObject theThirdGoImage = theThird.getImage(theSecondGoImage); if (theThirdGoImage != null) { try { tmpMorph.addMapping(theSecondGo, theThirdGoImage); } catch (BadMappingException ex) {} } } } final Iterator<Arc> theSecondDomArcs = theSecond.getOriginal().getArcsSet().iterator(); while (theSecondDomArcs.hasNext()) { GraphObject theSecondGo = theSecondDomArcs.next(); GraphObject theSecondGoImage = theSecond.getImage(theSecondGo); if (theSecondGoImage != null) { GraphObject theThirdGoImage = theThird.getImage(theSecondGoImage); if (theThirdGoImage != null) { try { tmpMorph.addMapping(theSecondGo, theThirdGoImage); } catch (BadMappingException ex) {} } } } if (this.makeFullDiagram(theFirst, tmpMorph)) return true; return false; } /** * Tries to complete this morphism to be isomorphic. */ public boolean makeIsomorphic() { // vergleiche Knotenanzahl if (this.itsOrig.getNodesCount() != this.itsImag.getNodesCount()) { return false; } // vergleiche Kantenanzahl if (this.itsOrig.getArcsCount() != this.itsOrig.getArcsCount()) { return false; } if (this.isTotal()) return true; boolean result = false; this.setCompletionStrategy(new Completion_InjCSP()); if (this.nextCompletion()) { result = true; // additionally, check type of source - target nodes in case of // Typegraph with Node Type Inheritance if (this.itsOrig.getTypeSet().getTypeGraph() != null // && this.itsOrig.getTypeSet().getLevelOfTypeGraphCheck() >= TypeSet.ENABLED && this.itsOrig.getTypeSet().hasInheritance()) { Iterator<Node> origs = this.itsOrig.itsNodes.iterator(); while (origs.hasNext() && result) { final Node orig = origs.next(); if (!orig.getType().compareTo(this.getImage(orig).getType())) { result = false; } } } } return result; } public void setName(String n) { this.itsName = n; } public String getName() { return this.itsName; } /** Set textual comments for this morphism. */ public void setTextualComment(String text) { this.comment = text; } /** Return textual comments of this morphism. */ public String getTextualComment() { return this.comment; } /** * This method tries to add morphism mapping between elements of my source * graph and elements of the specified list. The elements of this list * should be objects (nodes/edges) of my target graph. The order of the list * has to be the order of the graph objects of my source graph. It is * allowed to put null element into this list. A morphism mapping would be * set for non-null elements only. As result a partial (total) graph * morphism is done, if no errors occured. */ public void addMapping(final Vector<GraphObject> listOfGraphObjects) throws BadMappingException { // first set mapping of nodes final Iterator<Node> origs = this.itsOrig.getNodesSet().iterator(); for (int i = 0; i < listOfGraphObjects.size() && origs.hasNext(); i++) { final GraphObject go = listOfGraphObjects.get(i); final GraphObject img = origs.next(); if (go instanceof Node && img instanceof Node) { try { addMapping(go, img); } catch (BadMappingException ex) { throw ex; } } } // now set mapping of edges final Iterator<Arc> origs1 = this.itsOrig.getArcsSet().iterator(); for (int i = 0; i < listOfGraphObjects.size() && origs1.hasNext(); i++) { final GraphObject go = listOfGraphObjects.get(i); final GraphObject img = origs1.next(); if (go instanceof Arc && img instanceof Arc) { try { addMapping(go, img); } catch (BadMappingException ex) { throw ex; } } } } public void addMapping(final Hashtable<GraphObject, GraphObject> obj2img) throws BadMappingException { // first set mapping of nodes Enumeration<GraphObject> objs = obj2img.keys(); while (objs.hasMoreElements()) { final GraphObject obj = objs.nextElement(); if (obj.isNode()) { final GraphObject img = obj2img.get(obj); try { addMapping(obj, img); } catch (BadMappingException ex) { throw ex; } } } // now set mapping of edges objs = obj2img.keys(); while (objs.hasMoreElements()) { final GraphObject obj = objs.nextElement(); if (obj.isArc()) { final GraphObject img = obj2img.get(obj); try { addMapping(obj, img); } catch (BadMappingException ex) { throw ex; } } } } /** * Returns an error if the type compatibility of the specified nodes failed, * otherwise - null. */ public TypeError checkCreateMapping(final Node src, final Node tar) { if (!checkType(src.getType(), tar.getType())) { this.errorMsg = "Objects to map must be of the compatible type."; return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg); } else if (this instanceof Match) { final Enumeration<GraphObject> origEnum = getDomain(); final Match m = (Match) this; while (origEnum.hasMoreElements()) { final GraphObject currentObject = origEnum.nextElement(); if (currentObject instanceof Node && currentObject != src) { final Node currentNode = (Node) currentObject; final Node currentRuleImage = (Node) m.getRule().getImage( currentNode); final Node origRuleImage = (Node) m.getRule().getImage(src); final Node currentMatchImage = (Node) m.getImage(currentNode); if (currentRuleImage != null && currentRuleImage == origRuleImage) { if (currentMatchImage != null && !tar.getType().compareTo( currentMatchImage.getType())) { this.errorMsg = "Non-injective rules must preserve types."; return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg); } } } } } return null; } /** * Returns null if the source and target nodes of the specified edges are * already mapped and the type compatibility of these two edges is * satisfied, otherwise - an error. */ public TypeError checkCreateMapping(final Arc src, final Arc tar) { final GraphObject aSrc = src.getSource(); final GraphObject aTar = src.getTarget(); if (!src.getType().compareTo(tar.getType())) { this.errorMsg = "Objects to map must be of the same type."; return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg); } if (getImage(aSrc) != null) { if (!checkType(tar.getSource().getType(), getImage(aSrc).getType())) { this.errorMsg = "Edge mapping must be source compatible."; return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg); } } else { this.errorMsg = "The sources of the edges should be already mapped."; return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg); } if (getImage(aTar) != null) { if (!checkType(tar.getTarget().getType(), getImage(aTar).getType())) { this.errorMsg = "Edge mapping must be target compatible."; return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg); } } else { this.errorMsg = "The targets of the edges should be already mapped."; return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg); } return null; } /** * Please note: This method is only for internal use of the * critical pair analysis for grammars with node type inheritance. * Do not use it for any kind of implementations. * @param o is a child node * @param i is a parent node * @throws BadMappingException */ public void addChild2ParentMapping(final GraphObject o, final GraphObject i) throws BadMappingException { if (this.getImage(o) != i) { if (this.getSource().isElement(o) && this.getTarget().isElement(i)) { try { if (o.isNode() != i.isNode()) { this.errorMsg = "Cannot map a node to an edge."; // this.errors.add(this.errorMsg); throw new BadMappingException(this.errorMsg); } if (!o.getType().isParentOf(i.getType()) && !o.getType().isChildOf(i.getType())) { this.errorMsg = "Objects to map must to have compatible types."; // this.errors.add(this.errorMsg); throw new BadMappingException(this.errorMsg); } try { this.checkNodeTypePreserving(o, i); } catch (BadMappingException ex) { throw new BadMappingException(this.errorMsg); } try { this.checkEdgeSourceTargetCompatibility(o, i); } catch (BadMappingException ex) { throw new BadMappingException(this.errorMsg); } final GraphObject aPreviousImage = getImage(o); if (aPreviousImage != null) removeMapping(o); // try to add attribute mapping try { this.doAddChild2ParentAttrMapping(o, i); // System.out.println(">>> "+o+" --> " +i); } catch (BadMappingException exc) { this.errorMsg = exc.getMessage(); // this.errors.add(this.errorMsg); // restore previous mapping, if any: if (aPreviousImage != null) this.doAddChild2ParentAttrMapping(o, aPreviousImage); // Beware! This does not restore the mappings which may have been // removed IMPLICITLY above... throw (exc); } } catch (BadMappingException exc) { this.errorMsg = exc.getMessage(); // this.errors.add(this.errorMsg); throw exc; } // System.out.println(">>> OrdinaryMorphism.addChild2ParentMapping OK"); } } else { // System.out.println("not needed to set the same graph object mapping! only add AttrMapping!"); // attr mapping has to get update removeAttrMapping(o.getAttribute()); addAttrMapping(o.getAttribute(), i.getAttribute()); } } /** * Please note: This method is only for internal use of the * critical pair analysis for grammars with node type inheritance. * Do not use it for any kind of implementations. * @param orig is a child node * @param image is a parent node * @throws BadMappingException */ private void doAddChild2ParentAttrMapping(final GraphObject orig, final GraphObject image) throws BadMappingException { if (((ContextView) getAttrContext()).getAllowedMapping() == AttrMapping.MATCH_MAP || ((ContextView) getAttrContext()).getAllowedMapping() == AttrMapping.OBJECT_FLOW_MAP) { //System.out.println("OrdinaryMorphism.doAddChild2ParentAttrMapping AttrMapping.MATCH_MAP"); if ((orig.getAttribute() == null && image.getAttribute() == null) || orig.getType().isChildOf(image.getType()) || ((orig.getAttribute() != null) && ((ValueTuple) orig.getAttribute()).canMatchTo( ((ValueTuple) image.getAttribute()), (ContextView) getAttrContext()))) { boolean canMapAttr = true; if (orig.getType().isChildOf(image.getType()) && ((orig.getAttribute() != null) && !((ValueTuple) orig.getAttribute()).canMatchChild2Parent( ((ValueTuple) image.getAttribute()), (ContextView) getAttrContext()))) canMapAttr = false; if (canMapAttr) { try { addAttrMapping(orig.getAttribute(), image.getAttribute()); } catch (BadMappingException ex) { this.errorMsg = "Attribute mapping failed!"; // this.errors.add(this.errorMsg); throw new BadMappingException(this.errorMsg); } addDomainMapping(orig, image, true); } else { this.errorMsg = "Attribute mapping failed!"; // this.errors.add(this.errorMsg); // System.out.println("## doAddChild2ParentAttrMapping: errorMsg: "+this.errorMsg); throw new BadMappingException(this.errorMsg); } } else { this.errorMsg = "Attribute mapping failed!"; // this.errors.add(this.errorMsg); // System.out.println("### doAddChild2ParentAttrMapping: errorMsg: "+this.errorMsg); throw new BadMappingException(this.errorMsg); } } else { if (!orig.getType().isChildOf(image.getType())) { addAttrMapping(orig.getAttribute(), image.getAttribute()); addDomainMapping(orig, image, true); } } } /** * @param orig belongs to the source graph of this * @param image belongs to the target graph of this */ private void addDomainMapping(final GraphObject orig, final GraphObject image, boolean notificationRequired) { this.itsDomObjects.add(orig); this.itsCodomObjects.add(image); this.mappingChanged = true; if (notificationRequired) { if (isNotificationRequired()) { propagateChange(new Change(Change.MAPPING_ADDED, orig, this)); propagateChange(new Change(Change.MAPPING_ADDED, image, this)); } if (this.itsOrig.isNotificationRequired()) { this.itsOrig.propagateChange(new Change( Change.MAPPING_ADDED, orig, this)); } if (this.itsImag.isNotificationRequired()){ this.itsImag.propagateChange(new Change( Change.MAPPING_ADDED, image, this)); } } } /** * Map an object of source graph to an object of target graph. * The original and image objects have to belong to the same morphism. * * <p> * <b>Pre:</b> * <ol> * * <li><code>o</code> is an element of <code>getOriginal()</code>. * * <li><code>i</code> is an element of <code>getImage()</code>. * * </ol> * * * @param o * the source object of the mapping. * * @param i * the target object of the mapping. * * @exception agg.xt_basis.BadMappingException * if the given mapping violates morphism properties. * */ public void addMapping(final GraphObject o, final GraphObject i) throws BadMappingException { if (o == null || i == null) { this.errorMsg = "Mapping failed! The source or target object is null."; throw new BadMappingException(this.errorMsg); } if (this.getImage(o) != i) { if (this.getSource().isElement(o) && this.getTarget().isElement(i)) { try { doAddMapping(o, i); } catch (BadMappingException exc) { this.errorMsg = exc.getMessage(); // this.errors.add(this.errorMsg); throw exc; } } else { this.errorMsg = "Mapping failed! Graph objects to map must belong to the same morphism."; // this.errors.add(this.errorMsg); throw new BadMappingException(this.errorMsg); } } else { // attr mapping has to get update removeAttrMapping(o.getAttribute()); addAttrMapping(o.getAttribute(), i.getAttribute()); } } /** * The user of this method must take care about any checks for the mapping * of the specified graph objects. * Otherwise is null pointer exception can be thrown. * @param o * @param i * @throws BadMappingException */ public void addMappingFast(final GraphObject o, final GraphObject i) throws BadMappingException { if (o == null || i == null) { this.errorMsg = "Mapping failed! The source or target object is null."; throw new BadMappingException(this.errorMsg); } if (this.getImage(o) != i) { try { doAddMappingFast(o, i); } catch (BadMappingException exc) { this.errorMsg = exc.getMessage(); // this.errors.add(this.errorMsg); throw exc; } } else { // attr mapping has to get update removeAttrMapping(o.getAttribute()); addAttrMapping(o.getAttribute(), i.getAttribute()); } } /* * The user of this method must take care about any checks. * Otherwise null pointer exception woll be throwen. */ private void doAddMappingFast(final GraphObject orig, final GraphObject image) throws BadMappingException { // try to add attribute mapping try { this.doAddAttrMappingFast(orig, image); this.addDomainMapping(orig, image, true); this.changed = true; } catch (BadMappingException exc) { this.errorMsg = exc.getMessage(); // this.errors.add(this.errorMsg); throw (exc); } } /* * The user of this method must take care about any checks. * Otherwise null pointer exception woll be throwen. */ private void doAddAttrMappingFast(final GraphObject orig, final GraphObject image) throws BadMappingException { if (((ContextView) getAttrContext()).getAllowedMapping() == AttrMapping.MATCH_MAP) { try { addAttrMapping(orig.getAttribute(), image.getAttribute()); } catch (BadMappingException ex) { this.errorMsg = "Attribute mapping failed! "+ex.getLocalizedMessage(); // this.errors.add(this.errorMsg); throw new BadMappingException(this.errorMsg); } } else { addAttrMapping(orig.getAttribute(), image.getAttribute()); } } /** * Map an object of source graph to an object of target graph. * The image object have not to belong to the same morphism, * it will be create implicitly. * * <p> * <b>Pre:</b> * <ol> * * <li><code>o</code> is an element of <code>getOriginal()</code>. * * <li><code>i</code> is an element of <code>getImage()</code>. * * </ol> * * * @param o * the source object of the mapping. * * @param i * the target object of the mapping. * * @exception agg.xt_basis.BadMappingException * if the given mapping violates morphism properties. * * @deprecated please use <code>addMapping(final GraphObject o, final GraphObject i)</code> */ public void addMapping(final GraphObject o, final GraphObject i, final boolean mappingPropagation) throws BadMappingException { if (!mappingPropagation) { addMapping(o, i); return; } // if (!(this instanceof OrdinarySubMorphism)) { if (this.getSource().isElement(o) && this.getTarget().isElement(i)) { try { doAddMapping(o, i); } catch (BadMappingException exc) { this.errorMsg = exc.getMessage(); // this.errors.add(this.errorMsg); throw exc; } } // } else // if(this instanceof OrdinarySubMorphism) // ((OrdinarySubMorphism) this).getSuperMorphism().addMapping(o, i); } /** * Add PLAIN morphism mapping without any checks. <br> * Preconditions: <br> * - to map Node to Node and Arc to Arc only,<br> * - objects to map must be of the same type, <br> * - source and target of an edge must be already mapped. * */ protected void addPlainMapping(final GraphObject orig, final GraphObject image) throws BadMappingException { if (orig == null || image == null) { this.errorMsg = "Mapping failed! The source or target object is null."; throw new BadMappingException(this.errorMsg); } try { addAttrMapping(orig.getAttribute(), image.getAttribute()); addDomainMapping(orig, image, false); this.changed = true; } catch (BadMappingException exc) { this.errorMsg = exc.getMessage(); // this.errors.add(this.errorMsg); throw exc; } } /** * Try to add a mapping of two GraphObjects without setting the attr mapping. * * @param orig * @param image * @throws BadMappingException */ protected void addObjectPlainMapping(final GraphObject orig, final GraphObject image) throws BadMappingException { if (orig == null || image == null) { this.errorMsg = "Mapping failed! The source or target object is null."; throw new BadMappingException(this.errorMsg); } try { // addAttrMapping(orig.getAttribute(), image.getAttribute()); addDomainMapping(orig, image, false); this.changed = true; } catch (BadMappingException exc) { this.errorMsg = exc.getMessage(); // this.errors.add(this.errorMsg); throw exc; } } protected boolean checkType(Type orig, Type image) { return orig.isParentOf(image); } private void checkNodeTypePreserving(final GraphObject orig, final GraphObject image) throws BadMappingException { if (this instanceof Match && orig.isNode()) { final Enumeration<GraphObject> origEnum = getDomain(); final Match m = (Match) this; while (origEnum.hasMoreElements()) { final GraphObject currentObject = origEnum.nextElement(); if (currentObject instanceof Node && currentObject != orig) { final Node currentNode = (Node) currentObject; final Node currentRuleImage = (Node) m.getRule().getImage( currentNode); final Node origRuleImage = (Node) m.getRule().getImage(orig); final Node currentMatchImage = (Node) m.getImage(currentNode); if (currentRuleImage != null && currentRuleImage == origRuleImage) { if (currentMatchImage != null && !image.getType().compareTo( currentMatchImage.getType())) { this.errorMsg = "Non-injective rules must preserve types."; // this.errors.add(this.errorMsg); throw new BadMappingException(this.errorMsg); } } } } } } protected void checkEdgeSourceTargetCompatibility(final GraphObject orig, final GraphObject image) throws BadMappingException { try { MatchHelper.checkEdgeSourceTargetCompatibility(this, orig, image); } catch (BadMappingException ex) { throw ex; } } private void doAddAttrMapping(final GraphObject orig, final GraphObject image) throws BadMappingException { if (((ContextView) getAttrContext()).getAllowedMapping() == AttrMapping.MATCH_MAP) { if ( (orig.getAttribute() == null || orig.getAttribute().getNumberOfEntries() == 0) || ( image.getAttribute() != null && ((ValueTuple) orig.getAttribute()) .canMatchTo( ((ValueTuple) image.getAttribute()), (ContextView) getAttrContext()) ) ) { addAttrMapping(orig.getAttribute(), image.getAttribute()); } else { this.errorMsg = "Attribute mapping failed!"; // this.errors.add(this.errorMsg); throw new BadMappingException(this.errorMsg); } } else { addAttrMapping(orig.getAttribute(), image.getAttribute()); } } private void doAddMapping(final GraphObject orig, final GraphObject image) throws BadMappingException { if (orig.isNode() != image.isNode()) { this.errorMsg = "Cannot map node to edge."; // this.errors.add(this.errorMsg); throw new BadMappingException(this.errorMsg); } if (!checkType(orig.getType(), image.getType())) { this.errorMsg = "Objects to map must be of the same type."; // this.errors.add(this.errorMsg); throw new BadMappingException(this.errorMsg); } try { this.checkNodeTypePreserving(orig, image); } catch (BadMappingException ex) { throw new BadMappingException(this.errorMsg); } try { this.checkEdgeSourceTargetCompatibility(orig, image); } catch (BadMappingException ex) { this.errorMsg = ex.getLocalizedMessage(); throw new BadMappingException(this.errorMsg); } // store previous image of orig final GraphObject aPreviousImage = getImage(orig); if (aPreviousImage != null) removeMapping(orig); // try to add attribute mapping try { this.doAddAttrMapping(orig, image); this.addDomainMapping(orig, image, true); this.changed = true; } catch (BadMappingException exc) { this.errorMsg = exc.getMessage(); // this.errors.add(this.errorMsg); // restore previous mapping, if any: if (aPreviousImage != null) addMappingFast(orig, aPreviousImage); // Beware! This does not restore the mappings which may have been // removed IMPLICITLY above... throw (exc); } } protected void addAttrMapping(final AttrInstance o, final AttrInstance i) throws BadMappingException { if (getAttrContext() != null) { if (o == null && i == null) { return; } else if (o != null && i != null) { try { this.itsAttrMappings.put(o, getAttrManager().newMapping( getAttrContext(), o, i)); this.errorMsg = ""; // System.out.println("OrdinaryMorphism.addAttrMapping --> Mapping added"); } catch (AttrException exc) { this.errorMsg = exc.getMessage(); // System.out.println("OrdinaryMorphism.addAttrMapping // FAILED! \n"+this.errorMsg); throw new BadMappingException(exc.getMessage()); } } else if (o != null && o.getNumberOfEntries() != 0) { throw new BadMappingException( "Attribute mapping failed! Attribute of source or target object is null."); } } } protected boolean removeAttrMapping = true; protected void removeAttrMapping(final AttrInstance o) { if (o != null) { AttrMapping anAttrMapping = this.itsAttrMappings.get(o); if (anAttrMapping != null && this.removeAttrMapping) { anAttrMapping.remove(); this.itsAttrMappings.remove(o); } } } public void removeVariableValue(final AttrInstance o) { if (o == null) return; final ValueTuple vt = (ValueTuple) o; for (int i = 0; i < vt.getNumberOfEntries(); i++) { ValueMember vm = vt.getValueMemberAt(i); if (vm.isSet() && vm.getExpr().isVariable()) { final VarTuple vars = (VarTuple) this.itsAttrContext.getVariables(); final VarMember var = vars.getVarMemberAt(vm.getExprAsText()); if (!var.isInputParameter()) { var.setExpr(null); } } } } public void updateAttrMappings() { if (!this.itsImag.isAttributed()) return; for (int i = 0; i < this.itsDomObjects.size(); i++) { final GraphObject obj = this.itsDomObjects.get(i); final GraphObject img = this.itsCodomObjects.get(i); removeAttrMapping(obj.getAttribute()); addAttrMapping(obj.getAttribute(), img.getAttribute()); } } /** * This method should be used after the method * <code>removeMapping(GraphObject go)</code> called and befor the method * <code>nextCompletion(Enumeration varnodes, Enumeration varedges)</code> * performed. * * @param go * is an element of my source graph */ public void resetCSPVariableDomainOf(GraphObject go) { if (this.itsOrig.isElement(go)) this.itsCompleter.resetVariableDomain(go); } public void removeAllMappings() { removeAttrMappings(); this.itsDomObjects.clear(); this.itsCodomObjects.clear(); this.mappingChanged = false; } /** * Returns TRUE if removed, otherwise - FALSE */ public boolean removeMapping(final Node src, final Node tar) { if (this.getSource().isElement(src) && this.getTarget().isElement(tar)) { int i = this.itsDomObjects.indexOf(src); int j = this.itsCodomObjects.indexOf(tar); if (i >= 0 && j >= 0) { if (i != j && this.itsDomObjects.get(j) == src) i = j; if (i == j) { GraphObject aNeighbor; Iterator<Arc> anIter = src.getIncomingArcsSet().iterator(); while (anIter.hasNext()) { aNeighbor = anIter.next(); if (getImage(aNeighbor) != null) removeMapping(aNeighbor); } anIter = src.getOutgoingArcsSet().iterator(); while (anIter.hasNext()) { aNeighbor = anIter.next(); if (getImage(aNeighbor) != null) removeMapping(aNeighbor); } // update the index of Node src i = this.itsDomObjects.indexOf(src); j = this.itsCodomObjects.indexOf(tar); if (i != j && this.itsDomObjects.get(j) == src) i = j; if (i == j) { removeAttrMapping(src.getAttribute()); removeDomainMapping(i, true); return true; } } } } return false; } /** * @param i index of a graph object inside of this.itsDomObjects */ private void removeDomainMapping(int i, boolean notificationRequired) { final GraphObject dom = this.itsDomObjects.get(i); this.itsDomObjects.remove(i); final GraphObject codom = this.itsCodomObjects.get(i); this.itsCodomObjects.remove(i); this.mappingChanged = true; if (notificationRequired) { if (isNotificationRequired()) { propagateChange(new Change(Change.MAPPING_REMOVED, dom, this)); propagateChange(new Change(Change.MAPPING_REMOVED, codom, this)); } if (this.itsOrig.isNotificationRequired()) { this.itsOrig.propagateChange(new Change(Change.MAPPING_REMOVED, dom, this)); } if (this.itsImag.isNotificationRequired()) { this.itsImag.propagateChange(new Change(Change.MAPPING_REMOVED, codom, this)); } } } /** * Returns TRUE if removed, otherwise - FALSE. Note: The source and target * nodes of the specified src and tar edges still mapped. They should be * removed explicitly. */ public boolean removeMapping(final Arc src, final Arc tar) { if (this.getSource().isElement(src) && this.getTarget().isElement(tar)) { int i = this.itsDomObjects.indexOf(src); int j = this.itsCodomObjects.indexOf(tar); if (i >= 0 && j >= 0) { if (i != j && this.itsDomObjects.get(j) == src) i = j; if (i == j) { removeAttrMapping(src.getAttribute()); removeDomainMapping(i, true); return true; } } } return false; } /** * Remove the mapping of the given GraphObject. * In case of node, any mappings of incoming / outgoing arcs will be removed as well. * */ public void removeMapping(final GraphObject o) { if (this.getSource().isElement(o)) { doRemoveMapping(o); } else if (this.getTarget().isElement(o)) { final Enumeration<GraphObject> en = getInverseImage(o); while (en.hasMoreElements()) { doRemoveMapping(en.nextElement()); } } } /** * Remove the mapping of the given GraphObject. * In case of node, any mappings of incoming / outgoing arcs will be removed as well. * Precondition: <br> * - if left is true, the obj belongs to the source graph * - if left is false, the obj belongs to the target graph */ public void removeMappingFast(final GraphObject obj, boolean left) { if (left) { doRemoveMapping(obj); } else { final Enumeration<GraphObject> en = getInverseImage(obj); while (en.hasMoreElements()) { doRemoveMapping(en.nextElement()); } } } private void doRemoveMapping(final GraphObject o) { int i = this.itsDomObjects.indexOf(o); if (i >= 0) { if (o.isNode()) { GraphObject aNeighbor; Iterator<Arc> anIter = ((Node) o).getIncomingArcsSet().iterator(); while (anIter.hasNext()) { aNeighbor = anIter.next(); if (getImage(aNeighbor) != null) { doRemoveMapping(aNeighbor); } } anIter = ((Node) o).getOutgoingArcsSet().iterator(); while (anIter.hasNext()) { aNeighbor = anIter.next(); if (getImage(aNeighbor) != null) { doRemoveMapping(aNeighbor); } } // update the index of Node o i = this.itsDomObjects.indexOf(o); } removeAttrMapping(o.getAttribute()); removeDomainMapping(i, true); } } /** * Remove all mappings and reset variables of its attribute context. */ public void clear() { if (this.itsCoMorph != null) { this.itsCoMorph.dispose(); } removeAllMappings(); if (this.itsAttrContext.getVariables().getNumberOfEntries() != 0) { ((ContextView)this.itsAttrContext).resetVariableTuple(); ((ContextView)this.itsAttrContext).resetConditionTuple(); // ((VarTuple) itsAttrContext.getVariables()).getContext().removeAllMappings(); // ((CondTuple) itsAttrContext.getConditions()).getContext().removeAllMappings(); // ((VarTuple) itsAttrContext.getVariables()).updateByParent(); // ((VarTuple) itsAttrContext.getVariables()).unsetNotInputVariables(); } this.mappingChanged = false; this.partialMorphCompletion = false; clearErrorMsg(); } public void removeAttrMappings() { final Enumeration<AttrInstance> keys = this.itsAttrMappings.keys(); while (keys.hasMoreElements()) { AttrInstance key = keys.nextElement(); key.getContext().removeAllMappings(); } ((Hashtable<AttrInstance, AttrMapping>) this.itsAttrMappings).clear(); this.itsAttrContext.removeAllMappings(); } /** * Return true if its morphism mapping is empty, * otherwise - false. */ public boolean isEmpty() { return this.itsDomObjects.isEmpty(); } /** Return its source graph. */ public Graph getOriginal() { return this.itsOrig; } /** Return its source graph. */ public Graph getSource() { return this.itsOrig; } /** Return its target graph. */ public Graph getImage(){ return this.itsImag; } /** Return its target graph. */ public Graph getTarget() { return this.itsImag; } public Vector<GraphObject> getDomainObjects() { return this.itsDomObjects; } /** * Return the objects of my source graph which * are actually taking part in the current morphism mappings. */ public Enumeration<GraphObject> getDomain() { return this.itsDomObjects.elements(); } public int getDomainSize() { return this.itsDomObjects.size(); } /** * Return the objects of my target graph which * are actually taking part in the current morphism mappings. */ public Enumeration<GraphObject> getCodomain() { return this.itsCodomObjects.elements(); } public Vector<GraphObject> getCodomainObjects() { return this.itsCodomObjects; } public int getCodomainSize() { return this.itsCodomObjects.size(); } /*************************************************************************** * Return the image of the specified object. * * @return <code>null</code> if the object is not in domain.* **************************************************************************/ public GraphObject getImage(final GraphObject o) { int i = this.itsDomObjects.indexOf(o); if ((i > -1) && (i < this.itsCodomObjects.size())) { return this.itsCodomObjects.elementAt(i); } return null; } public boolean hasInverseImage(final GraphObject o) { if (this.itsCodomObjects.indexOf(o) != -1) { return true; } return false; } /** * Return an Enumeration of the inverse images of the specified object. * * Enumeration will be empty when the object is not in codomain. * * Enumeration elements are of type <code>GraphObject</code>. */ public Enumeration<GraphObject> getInverseImage(final GraphObject o) { final Vector<GraphObject> invImages = new Vector<GraphObject>(); int i = 0; int index; while ((i < this.itsCodomObjects.size()) && ((index = this.itsCodomObjects.indexOf(o, i)) != -1)) { invImages.addElement(this.itsDomObjects.elementAt(index)); i = index + 1; } return invImages.elements(); } public List<GraphObject> getInverseImageList(final GraphObject o) { final List<GraphObject> invImages = new Vector<GraphObject>(); int i = 0; int index; while ((i < this.itsCodomObjects.size()) && ((index = this.itsCodomObjects.indexOf(o, i)) != -1)) { invImages.add(this.itsDomObjects.get(index)); i = index + 1; } return invImages; } public List<GraphObject> getElementsToCreate() { final Vector<GraphObject> created = findCreatedElements(); return created; } public List<GraphObject> getElementsToDelete() { final Vector<GraphObject> deleted = findDeletedElements(); return deleted; } public Hashtable<GraphObject, GraphObject> morphToMap() { final Hashtable<GraphObject, GraphObject> map = new Hashtable<GraphObject, GraphObject>(); final Enumeration<GraphObject> dom = this.getDomain(); while (dom.hasMoreElements()) { GraphObject obj = dom.nextElement(); map.put(obj, this.getImage(obj)); } return map; } /** * Set the algorithm of morphism completion. Class * <code>CompletionStrategySelector</code> provides a way to present and * obtain available algorithms. * * @see agg.xt_basis.CompletionStrategySelector */ public void setCompletionStrategy(final MorphCompletionStrategy s, boolean rewrite) { if (rewrite) { if (this.itsCompleter == null || this.itsCompleter != s) this.itsCompleter = s; } else setCompletionStrategy(s); } /** * Set the algorithm of morphism completion. Class * <code>CompletionStrategySelector</code> provides a way to present and * obtain available algorithms. * The given strategy is internally cloned to prevent undesired side effects. * @see agg.xt_basis.CompletionStrategySelector */ public void setCompletionStrategy(final MorphCompletionStrategy s) { if (this.itsCompleter == null || !this.itsCompleter.equals(s)) { this.itsCompleter = (MorphCompletionStrategy) s.clone(); } } public final MorphCompletionStrategy getCompletionStrategy() { return this.itsCompleter; } public void unsetCompletionStrategy() { this.itsCompleter = null; } /** * Return true if my source graph can be a subgraph of the given graph g * basically. It can only work for INJECTIVE search. */ public boolean canMatch(final Graph g, final MorphCompletionStrategy strategy) { // check graph size if injective morphism if (strategy.getProperties().get(CompletionPropertyBits.INJECTIVE)) { if ((this.itsOrig.getNodesCount() > g.getNodesCount()) || (this.itsOrig.getArcsCount() > g.getArcsCount())) return false; } // check types: all types of the orig. graph should be in image, too final Vector<Type> origTypes = this.itsOrig.getUsedTypes(); final Vector<Type> otherTypes = g.getUsedAndInheritedTypes(); for (int i = 0; i < origTypes.size(); i++) { if (!otherTypes.contains(origTypes.get(i))) return false; } return true; } /** * Return true if this morphism can be completed basically. */ public boolean canComplete() { // check graph size if injective morphism if (this.itsCompleter.getProperties().get(CompletionPropertyBits.INJECTIVE)) { if ((this.itsOrig.getNodesCount() > this.itsImag.getNodesCount()) || (this.itsOrig.getArcsCount() > this.itsImag.getArcsCount())) return false; } // check types: all types of the orig. graph should be in image, too final Vector<Type> origTypes = this.itsOrig.getUsedTypes(); final Vector<Type> imagTypes = this.itsImag.getUsedAndInheritedTypes(); for (int i = 0; i < origTypes.size(); i++) { if (!imagTypes.contains(origTypes.get(i))) return false; } return true; } public boolean isMappingChanged() { return this.mappingChanged; } /*************************************************************************** * Compute next completion: * Invoke this method successively to get all * completions. * * @return <code>false</code> if there are no more completions.* **************************************************************************/ public boolean nextCompletion() { boolean ok = false; this.errorMsg = ""; ok = doNextCompletion(); if (!ok) { // get error message from attribute manager String attrMsg = ((agg.attribute.impl.ContextView) this .getAttrContext()).getManager().getErrorMsg(); if (attrMsg.length()>0) { this.errorMsg = attrMsg; // this.errors.add(this.errorMsg); } // else if (this.errorMsg.length()>0) // this.errors.add(this.errorMsg); } return ok; } /*************************************************************************** * Compute next completion: * Invoke this method successively to get all * completions for the nodes and edges specified by the Vector varnodes and * Vector varedges, only. * * @return <code>false</code> if there are no more completions.* **************************************************************************/ public boolean nextCompletion( Collection<Node> varnodes, Collection<Arc> varedges) { boolean ok = false; this.errorMsg = ""; ok = doNextCompletion(varnodes, varedges); if (!ok) { // get error message from attribute manager String attrMsg = ((agg.attribute.impl.ContextView) this .getAttrContext()).getManager().getErrorMsg(); if (attrMsg.length()>0) { this.errorMsg = attrMsg; // this.errors.add(this.errorMsg); } // else if (this.errorMsg.length()>0) // this.errors.add(this.errorMsg); } return ok; } /** * @deprecated replaced by <code> boolean nextCompletion(Collection<Node> varnodes,Collection<Arc> varedges)<\code> */ public boolean nextCompletion( Enumeration<Node> varnodes, Enumeration<Arc> varedges) { return this.nextCompletion( Collections.list(varnodes), Collections.list(varedges)); } /** * Compute next completion: * Invoke this method successively to get all completions. * * @return <code>false</code> if there are no more completions. */ public boolean nextCompletionWithConstantsChecking( Collection<Node> varnodes, Collection<Arc> varedges) { // Diese Methode ist nur bei Instanzen von OrdinaryMorphism sinvoll. // Daraus folgt: Attribute Mappingsmode ist PLAIN_MAP. boolean found = false; while (!found && this.nextCompletion(varnodes, varedges)) { found = true; if (!this.checkConstants()) { this.errorMsg = "Mismatch of constant attribute values."; // this.errors.add(this.errorMsg); found = false; } } return found; } /** * @deprecated replaced by <code>nextCompletionWithConstantsChecking(Collection<Node> varnodes,Collection<Arc> varedges)<\code> */ public boolean nextCompletionWithConstantsChecking( Enumeration<Node> varnodes, Enumeration<Arc> varedges) { return nextCompletionWithConstantsChecking( Collections.list(varnodes), Collections.list(varedges)); } /** * Compute next completion: * Invoke this method successively to get all completions. * * @return <code>false</code> if there are no more completions. */ public boolean nextCompletionWithConstantsAndVariablesChecking( Collection<Node> varnodes, Collection<Arc> varedges) { // Diese Methode ist nur bei Instanzen von OrdinaryMorphism sinvoll. // Daraus folgt: Attribute Mappingsmode ist PLAIN_MAP. boolean found = false; while (!found && this.nextCompletion(varnodes, varedges)) { found = true; if (!this.checkAll()) { this.errorMsg = "Mismatch of constant attribute values or variables."; // this.errors.add(this.errorMsg); found = false; } } return found; } private boolean doNextCompletion() { if (this.itsTouchedFlag) { this.itsCompleter.reset(); this.itsTouchedFlag = false; } this.mappingChanged = false; // temporarily turn off update processing: this.itsInteractiveFlag = false; boolean b = this.itsCompleter.next(this); // this.changed = this.changed || b; // turn update processing on again: this.itsInteractiveFlag = true; return b; } /** * Try to get completion using only nodes and edges specified by the Vector * varnodes and Vector varedges. */ private boolean doNextCompletion( Collection<Node> varnodes, Collection<Arc> varedges) { if (this.itsTouchedFlag) { this.itsCompleter.reset(); this.itsTouchedFlag = false; } // temporarily turn off update processing: this.itsInteractiveFlag = false; boolean b = this.itsCompleter.next(this, varnodes, varedges); // this.changed = this.changed || b; // turn update processing on again: this.itsInteractiveFlag = true; return b; } /** * Compute next completion: * Invoke this method successively to get all * completions. * * * @return <code>false</code> if there are no more completions. */ public boolean nextCompletionWithConstantsChecking() { // Diese Methode ist nur bei Instanzen von OrdinaryMorphism sinvoll. // Attribute Mappingsmode ist PLAIN_MAP. boolean found = false; while (!found && this.nextCompletion()) { found = true; if (!this.checkConstants()) { this.errorMsg = "Mismatch of constant attribute values."; // this.errors.add(this.errorMsg); found = false; } } return found; } /* * Diese Methode ist nur bei Instanzen von OrdinaryMorphism sinvoll. * * Daraus folgt: Attribute Mappingsmode ist PLAIN. * Bei attributierten * Graphobjekten (original --> image) * wird die Wertbelegung durch * Konstante auf deren Gleichheit getestet, * nur dann ist diese Methode * erfolgreich. * So ein Test erfolgt bei der ueblichen Methode * nextCompletion() * in PLAIN nicht. */ /* private boolean single_nextCompletionWithConstantsChecking() { // System.out.println(" // OrdinaryMorphism.nextCompletionWithConstantsChecking... "); boolean found = false; if (this.nextCompletion()) { if (this.checkConstants()) found = true; else { this.errorMsg = "Mismatch of constant attribute values."; // this.errors.add(this.errorMsg); found = false; } } return found; } */ /** * Compute next completion: * Invoke this method successively to get all * completions. * * * @return <code>false</code> if there are no more completions. */ public boolean nextCompletionWithConstantsAndVariablesChecking() { // Diese Methode ist nur bei Instanzen von OrdinaryMorphism sinvoll. // Attribute Mappingsmode ist PLAIN_MAP. boolean found = false; while (!found && this.nextCompletion()) { found = true; if (!this.checkAll()) { this.errorMsg = "Mismatch of constant attribute values or variables."; // this.errors.add(this.errorMsg); found = false; } } return found; } /** Return <code>true</code> if this is a total morphism. */ public final boolean isTotal() { return this.itsOrig.isEmpty() || (this.itsOrig.getSize() == this.itsDomObjects.size()); } /** Return <code>true</code> if this is a right total morphism. */ public boolean isRightTotal() { boolean res = false; if (this.itsCodomObjects.size() == this.itsImag.getSize() && this.itsCodomObjects.containsAll(this.itsImag.getNodesCollection()) && this.itsCodomObjects.containsAll(this.itsImag.getArcsCollection())) res = true; return res; } public boolean doesIgnoreAttrs() { boolean res = true; for (int i=0; i<this.itsDomObjects.size(); i++) { GraphObject obj = this.itsDomObjects.get(i); if (obj.getAttribute() == null) continue; GraphObject img = this.getImage(obj); ValueTuple imgVal = (ValueTuple) img.getAttribute(); for (int j=0; j<imgVal.getNumberOfEntries(); j++) { ValueMember vmImg = imgVal.getValueMemberAt(j); if (vmImg.isSet() && !vmImg.isTransient()) { ValueMember vmObj = ((ValueTuple) obj.getAttribute()).getValueMemberAt(vmImg.getName()); if (vmObj != null && vmObj.isSet() && vmObj.getExprAsText().equals(vmImg.getExprAsText())) { res = false; break; } } } } return res; } /** * Return the attribute context * that is used for attribute matching. * * @see agg.attribute.AttrContext */ public AttrContext getAttrContext() { return this.itsAttrContext; } /** * Set the attribute context that is used for attribute matching. * * @see agg.attribute.AttrContext */ public void setAttrContext(final AttrContext ac) { this.itsAttrContext = ac; } public Dictionary<AttrInstance, AttrMapping> getAttrMapping() { // return (new Hashtable<AttrInstance, AttrMapping>()) // .putAll((Hashtable<AttrInstance, AttrMapping>)this.itsAttrMappings); return this.itsAttrMappings; } public void reflectTransientOfSimilarVar(final VarTuple vars) { final VarTuple itsVars = (VarTuple) getAttrContext().getVariables(); for (int i = 0; i < vars.getSize(); i++) { final VarMember var = vars.getVarMemberAt(i); final VarMember itsvar = itsVars.getVarMemberAt(var.getName()); if (itsvar != null) { if (!itsvar.isTransient() && var.isTransient()) itsvar.setTransient(true); } } } public void adaptAttrContextValues(final AttrContext ac) { // System.out.println("OrdinaryMorphism.adaptAttrContextValues..."); final VarTuple itsVars = (VarTuple) this.getAttrContext().getVariables(); final VarTuple vars = (VarTuple) ac.getVariables(); // vars.showVariables(); for (int i = 0; i < vars.getSize(); i++) { final VarMember var = vars.getVarMemberAt(i); final VarMember itsVar = itsVars.getVarMemberAt(var.getName()); if (itsVar != null) { if (var.isSet()) { // itsVar.setExprAsText(var.getExprAsText()); itsVar.setExpr(var.getExpr()); // check if var itself uses another variable final VarMember tmp = vars.getVarMemberAt(var.getExprAsText()); if (tmp != null && tmp.isTransient()) { itsVar.setTransient(true); var.setTransient(true); } } } } } public void adaptAttrContextValuesFromExistingObjMapping() { for (int i=0; i<this.itsDomObjects.size(); i++) { GraphObject obj = this.itsDomObjects.get(i); if (obj.getAttribute() == null) continue; GraphObject img = this.getImage(obj); ValueTuple imgVal = (ValueTuple) img.getAttribute(); for (int j=0; j<imgVal.getNumberOfEntries(); j++) { ValueMember vmImg = imgVal.getValueMemberAt(j); if (vmImg.isSet()) { ValueMember vmObj = ((ValueTuple) obj.getAttribute()).getValueMemberAt(vmImg.getName()); if (vmObj != null && vmObj.isSet() && vmObj.getExpr().isVariable()) { VarMember var = ((VarTuple)this.getAttrContext().getVariables()) .getVarMemberAt(vmObj.getExprAsText()); var.setExprAsText(vmImg.getExprAsText()); } } } } } public void addToAttrContextFromList(final List<VarMember> vars, boolean setInputParameter) { final VarTuple itsVars = (VarTuple) getAttrContext().getVariables(); for (int i = 0; i < vars.size(); i++) { final VarMember var = vars.get(i); final DeclMember dm = (DeclMember) var.getDeclaration(); if (!itsVars.isDeclared(dm.getTypeName(), dm.getName())) { itsVars.declare(dm.getHandler(), dm.getTypeName(), dm.getName()); itsVars.getVarMemberAt(dm.getName()).setTransient(var.isTransient()); itsVars.getVarMemberAt(dm.getName()).setInputParameter(var.isInputParameter() || setInputParameter); } } } public void addToAttrContext(final VarTuple vars) { final VarTuple itsVars = (VarTuple) getAttrContext().getVariables(); for (int i = 0; i < vars.getSize(); i++) { final VarMember var = vars.getVarMemberAt(i); final DeclMember dm = (DeclMember) var.getDeclaration(); if (!itsVars.isDeclared(dm.getTypeName(), dm.getName())) { itsVars.declare(dm.getHandler(), dm.getTypeName(), dm.getName()); itsVars.getVarMemberAt(dm.getName()).setTransient(var.isTransient()); itsVars.getVarMemberAt(dm.getName()).setInputParameter(var.isInputParameter()); } } } public void addToAttrContextAccordingList(final VarTuple vars, final List<String> varNames) { if (varNames != null && !varNames.isEmpty()) { final VarTuple itsVars = (VarTuple) getAttrContext().getVariables(); for (int i = 0; i < vars.getSize(); i++) { final VarMember var = vars.getVarMemberAt(i); if (varNames.contains(var.getName())) { final DeclMember dm = (DeclMember) var.getDeclaration(); if (!itsVars.isDeclared(dm.getTypeName(), dm.getName())) { itsVars.declare(dm.getHandler(), dm.getTypeName(), dm.getName()); itsVars.getVarMemberAt(dm.getName()).setTransient(var.isTransient()); itsVars.getVarMemberAt(dm.getName()).setInputParameter(var.isInputParameter()); } } } } } public void addToAttrContext(final CondTuple conds) { final CondTuple itsConds = (CondTuple) getAttrContext().getConditions(); for (int i = 0; i < conds.getSize(); i++) { final CondMember cond = conds.getCondMemberAt(i); if (!itsConds.contains(cond.getExprAsText())) itsConds.addCondition(cond.getExprAsText()); } } public void addToAttrContext(final AttrContext ac) { this.addToAttrContext((VarTuple) ac.getVariables()); this.addToAttrContext((CondTuple) ac.getConditions()); } public final AttrManager getAttrManager() { return this.itsAttrManager; } // protected synchronized void setChanged() public synchronized void setChanged() { if (this.itsInteractiveFlag) this.itsTouchedFlag = true; // force initialization of morphism completion when nextCompletion() // is called. super.setChanged(); } public void writeMorphism(XMLHelper h) { h.openSubTag("Morphism"); h.addAttr("name", this.itsName); if (!this.comment.equals("")) h.addAttr("comment", this.comment); Enumeration<GraphObject> e = getDomain(); while (e.hasMoreElements()) { GraphObject s = e.nextElement(); h.openSubTag("Mapping"); h.addObject("orig", s, false); h.addObject("image", getImage(s), false); h.close(); } h.close(); } public void readMorphism(XMLHelper h) { if (h.readSubTag("Morphism")) { String str = h.readAttr("name"); setName(str.replaceAll(" ", "")); // setName(h.readAttr("name")); str = h.readAttr("comment"); if (!str.equals("")) this.comment = str.toString(); Hashtable<GraphObject, GraphObject> map = new Hashtable<GraphObject, GraphObject>(); while (h.readSubTag("Mapping")) { GraphObject o = (GraphObject) h.getObject("orig", null, false); GraphObject i = (GraphObject) h.getObject("image", null, false); if (o != null && i != null) { if (o instanceof Node) { try { addMapping(o, i); } catch (BadMappingException ex) {} } else { map.put(o, i); } } h.close(); } h.close(); Enumeration<GraphObject> en = map.keys(); while (en.hasMoreElements()) { GraphObject o = en.nextElement(); GraphObject i = map.get(o); GraphObject s = ((Arc) o).getSource(); GraphObject t = ((Arc) o).getTarget(); if (o instanceof UndirectedArc) { if (((((UndirectedArc) i).getSource() == getImage(s)) && (((UndirectedArc) i).getTarget() == getImage(t))) || ((((UndirectedArc) i).getTarget() == getImage(s)) && (((UndirectedArc) i).getSource() == getImage(t)))) { try { addMapping(o, i); } catch (BadMappingException ex) {} } } else if ((((Arc) i).getSource() == getImage(s)) && (((Arc) i).getTarget() == getImage(t))) { try { addMapping(o, i); } catch (BadMappingException ex) {} } } } } /* * Create and return a new submorphism. It is automatically added to my set * * of submorphisms. The new submorphism and its image and * original graphs * which are newly created are initially empty. * * <p> * Note that the newly created image and original subgraphs are not * * automatically removed when the submorphism itself is destroyed. */ // public final OrdinarySubMorphism createSubMorphism() // { // OrdinarySubMorphism aSubMorph = new OrdinarySubMorphism(this, this // .getOriginal().createSubGraph(), this.getImage() // .createSubGraph()); // itsSubMorphs.add(aSubMorph); // return aSubMorph; // } /* * Create and return a new submorphism. It is automatically added to my set * * of submorphisms. The new submorphism's image and original graphs are set * * to be <code>orig</code> and <code>img</code>, respectively. The * submorphism * is filled so that it maps all the objects of * <code>orig</code> in the same * way I do. * <p> * <b>Pre:</b> * <ol> * * <li> <code>orig</code> is subgraph of <code>this.getOriginal()</code>. * * <li> <code>img</code> is subgraph of <code>this.getImage()</code>. * </ol> */ // public final OrdinarySubMorphism createSubMorphism(SubGraph orig, // SubGraph img) // { // OrdinarySubMorphism aSubMorph = new OrdinarySubMorphism(this, orig, img); // //// if (itsSubMorphs == null) //// itsSubMorphs = new Vector<OrdinarySubMorphism>(5, 1); // itsSubMorphs.add(aSubMorph); // return aSubMorph; // } /* * Remove a submorphism from my set of submorphisms. * * * @return <code>false</code> iff <code>sm</code> was not an element of * my set of submorphisms.* */ // public final boolean destroySubMorphism(OrdinarySubMorphism sm) // { // if (itsSubMorphs != null && sm != null) { // if (itsSubMorphs.removeElement(sm)) { // sm.dispose(); // return true; // } // } // return false; // } // private void destroySubMorphisms() { // if (itsSubMorphs != null) { // while (itsSubMorphs.size() > 0) { // OrdinarySubMorphism sm = itsSubMorphs.get(0); // itsSubMorphs.remove(sm); // sm.dispose(); // } // } // } /* * Return an Enumeration of all of my submorphisms (not including myself). * Enumeration elements are of type <code>OrdinarySubMorphism</code>.* */ // public final Enumeration<OrdinarySubMorphism> getSubMorphisms() { // if (itsSubMorphs != null) // return itsSubMorphs.elements(); // else // return (new Vector<OrdinarySubMorphism>(0)).elements(); // } // ----------- ADDITIONAL METHODS according to Gabi's new AGG design // -------------- // -------------------- attention: yet untested! (Aug.1999) // ----------------------- /** swop domain and range <--->, if possible */ public OrdinaryMorphism invert() { if (!(this.isInjective())) { this.errorMsg = "Inverting of non-injective morphism is not possible."; return (null); } final OrdinaryMorphism inv = (BaseFactory.theFactory()).createMorphism(this.itsImag, this.itsOrig); final Enumeration<GraphObject> domain = this.itsDomObjects.elements(); while (domain.hasMoreElements()) { final GraphObject go = domain.nextElement(); try { inv.addMapping(this.getImage(go), go); } catch (BadMappingException e) { this.errorMsg = e.getMessage(); } } return (inv); } public OrdinaryMorphism simplecopy() /*************************************************************************** * Unlike "morphcopy(.)" of above, "simplecopy()" * does only return a copy * of itself without creating copies of its source and target graphs.* **************************************************************************/ { final OrdinaryMorphism output = (BaseFactory.theFactory()).createMorphism( this.itsOrig, this.itsImag); final Enumeration<GraphObject> mappedObjects = this.itsDomObjects.elements(); while (mappedObjects.hasMoreElements()) { final GraphObject go = mappedObjects.nextElement(); try { output.addMapping(go, this.getImage(go)); } catch (BadMappingException ex) { } } return (output); } public boolean isIsomorphicTo(final OrdinaryMorphism h) /* * Test if morphism h is isomorphic to this morphism. */ { final Enumeration<GraphObject> dom = this.getDomain(); final Vector<GraphObject> hDom = new Vector<GraphObject>(); final Enumeration<GraphObject> hd = h.getDomain(); while (hd.hasMoreElements()) { hDom.addElement(hd.nextElement()); } while (dom.hasMoreElements()) { final GraphObject go = dom.nextElement(); if (hDom.contains(go)) { if (!this.getImage(go).equals(h.getImage(go))) { hDom.clear(); return false; } hDom.removeElement(go); } else { hDom.clear(); return false; } } if (hDom.size() == 0) { return true; } return false; } public boolean isIsomorphicTo(final OrdinaryMorphism h, final OrdinaryMorphism targetIso) /** * Test if the specified morphism h is isomorphic to this morphism, * assuming that : * - this and h are total, * - this and h have one and the same original graph, * - the target graph of this is the source graph of targetIso, * - the target graph of h is the target graph of targetIso, * - targetIso is an isomorphism. */ { // System.out.println("OrdinaryMorphism.isIsomorphicTo(h, targetIso) // ..."); if (this.getSource() != h.getSource()) { System.out .println("OrdinaryMorphism.isIsomorphicTo:: FAILED:: this and h have different source graphs"); // Thread.dumpStack(); return false; } else if (h.getTarget() != targetIso.getTarget()) { System.out .println("OrdinaryMorphism.isIsomorphicTo:: FAILED:: targetIso and h have different target graphs"); // Thread.dumpStack(); return false; } final Iterator<Node> e = this.getSource().getNodesSet().iterator(); while (e.hasNext()) { GraphObject o = e.next(); GraphObject i1 = targetIso.getImage(this.getImage(o)); GraphObject i2 = h.getImage(o); if (i1 != i2) { return false; } } final Iterator<Arc> e1 = this.getSource().getArcsSet().iterator(); while (e1.hasNext()) { GraphObject o = e1.next(); GraphObject i1 = targetIso.getImage(this.getImage(o)); GraphObject i2 = h.getImage(o); if (i1 != i2) { return false; } } // System.out.println("OrdinaryMorphism.isIsomorphicTo .... TRUE "); return true; } /** Return <code>true</code> if this is a partial morphism. */ public boolean isPartial() { return !isTotal(); } /** * Test if this morphism is partial isomorphic to the specified morphism h, * assuming that they have one and the same original and one and the same image graph. */ public boolean isPartialIsomorphicTo(final OrdinaryMorphism h) { final Enumeration<GraphObject> dom = this.getDomain(); final Vector<GraphObject> hDomain = h.getDomainObjects(); while (dom.hasMoreElements()) { final GraphObject go = dom.nextElement(); if (hDomain.contains(go)) { if (!this.getImage(go).equals(h.getImage(go))) { return (false); } else if (go.isArc()) { if (!this.getImage(((Arc)go).getSource()).equals(h.getImage(((Arc)go).getSource())) || !this.getImage(((Arc)go).getTarget()).equals(h.getImage(((Arc)go).getTarget()))) { return (false); } } } // else // return (false); } return (true); } public boolean isSurjective() { final Enumeration<GraphObject> nonMapped = nonMappedImages(); if (nonMapped.hasMoreElements()) return (false); return (true); } public boolean isInjective() { for (int i=0; i<this.itsCodomObjects.size(); i++) { final GraphObject go = this.itsCodomObjects.get(i); if (this.getInverseImageList(go).size() > 1) return false; } return true; } public boolean isBijective() { if (isInjective() && isSurjective()) return (true); return (false); } public Enumeration<GraphObject> nonMappedOriginals() /*************************************************************************** * Returns all graph objects of the original graph * that are not mapped by * this morphism. Enumeration * elements are of type * <code>GraphObject</code>. * * @see agg.xt_basis.GraphObject.* **************************************************************************/ { final Vector<GraphObject> nonMapped = new Vector<GraphObject>(); final Iterator<Node> nodes = this.itsOrig.getNodesSet().iterator(); while (nodes.hasNext()) { GraphObject go = nodes.next(); if (!this.itsDomObjects.contains(go)) { nonMapped.addElement(go); } } final Iterator<Arc> arcs = this.itsOrig.getArcsSet().iterator(); while (arcs.hasNext()) { GraphObject go = arcs.next(); if (!this.itsDomObjects.contains(go)) { nonMapped.addElement(go); } } return (nonMapped.elements()); } public Enumeration<GraphObject> nonMappedImages() /*************************************************************************** * Returns all graph objects of the image graph * that are not used by this * morphism. Enumeration * elements are of type <code>GraphObject</code>. * * @see agg.xt_basis.GraphObject * **************************************************************************/ { final Vector<GraphObject> nonMapped = new Vector<GraphObject>(); final Iterator<Node> gos = this.itsImag.getNodesSet().iterator(); while (gos.hasNext()) { GraphObject go = gos.next(); if (!this.itsCodomObjects.contains(go)) nonMapped.addElement(go); } final Iterator<Arc> gos1 = this.itsImag.getArcsSet().iterator(); while (gos1.hasNext()) { GraphObject go = gos1.next(); if (!this.itsCodomObjects.contains(go)) nonMapped.addElement(go); } return (nonMapped.elements()); } /** * Constructs the composition of this morphism and the input morphism.<br> * this.source == output.source, <br> * this.target == input.source, <br> * input.target == output.target.<br> * . */ public OrdinaryMorphism compose(final OrdinaryMorphism input){ final OrdinaryMorphism output = (BaseFactory.theFactory()).createMorphism( this.itsOrig, input.getImage(), true); final Enumeration<GraphObject> thisDom = this.itsDomObjects.elements(); while (thisDom.hasMoreElements()) { final GraphObject thisGo = thisDom.nextElement(); final GraphObject thisGoImage = this.getImage(thisGo); final GraphObject inputGoImage = input.getImage(thisGoImage); if (inputGoImage != null) { try { output.addMapping(thisGo, inputGoImage); } catch (BadMappingException ex) { } } } return (output); } /** * Constructs composition of given morphisms morph1 and morph2 morphisms, where <br> * this.source == morph1.source <br> * this.target == morph2.target <br> * morph1.target == morph2.source. <br> * Returns true, if the source-target * condition is satisfied, otherwise - false. */ public boolean doCompose(final OrdinaryMorphism morph1, final OrdinaryMorphism morph2) { if (this.itsOrig == morph1.getSource() && this.itsImag == morph2.getTarget()) { final Enumeration<GraphObject> dom = morph1.getDomain(); while (dom.hasMoreElements()) { final GraphObject obj = dom.nextElement(); final GraphObject im = morph1.getImage(obj); final GraphObject img = morph2.getImage(im); if (img != null) { try { this.addMapping(obj, img); } catch (BadMappingException ex) { System.out.println(ex.getClass()+" "+ex.getMessage()); return false; } } } return true; } return false; } public boolean doComposeInherit(final OrdinaryMorphism morph1, final OrdinaryMorphism morph2) { if (this.itsOrig == morph1.getSource() && this.itsImag == morph2.getTarget()) { final Enumeration<GraphObject> dom = morph1.getDomain(); while (dom.hasMoreElements()) { final GraphObject obj = dom.nextElement(); final GraphObject img1 = morph1.getImage(obj); final GraphObject img2 = morph2.getImage(img1); if (img2 != null) { try { if (obj.getType().isParentOf(img2.getType())) this.addMapping(obj, img2); else if (obj.getType().isChildOf(img2.getType())) this.addChild2ParentMapping(obj, img2); } catch (BadMappingException ex) { return false; } } } return true; } return false; } /** * Given an input morphism with * input.getSource() == this.getSource() and <br> * input.getTarget() == output.getSource() and <br> * this.getTarget() == output.getTarget(). <br> * For each key try to complete * output.addMapping(input.get(key), this.getImage(key)).<br> * Returns true by success, otherwise true. */ public OrdinaryMorphism completeDiagram(final OrdinaryMorphism input) { if (!input.isInjective()) { this.errorMsg = "Completting with non-injective morphism is not possible"; return (null); } final OrdinaryMorphism compl = (BaseFactory.theFactory()).createMorphism( input.getImage(), this.itsImag); final Enumeration<GraphObject> inpDom = input.getDomain(); while (inpDom.hasMoreElements()) { final GraphObject inpGo = inpDom.nextElement(); final GraphObject inpImg = input.getImage(inpGo); final GraphObject thisImgGo = this.getImage(inpGo); try { compl.addMapping(inpImg, thisImgGo); } catch (BadMappingException ex) { (BaseFactory.theFactory()).destroyMorphism(compl); return null; } } return (compl); } /** * Given d = g o f with f: A->B, g: B->C, d: A->C. * f and d is known, g is this. * Try to complete g. * Returns true by success, otherwise false. */ public boolean completeDiagram(final Hashtable<GraphObject,GraphObject> f, final OrdinaryMorphism d) { if (f != null && d != null) { Enumeration<GraphObject> dDom = d.getDomain(); while (dDom.hasMoreElements()) { final GraphObject go3 = dDom.nextElement(); final GraphObject img3 = d.getImage(go3); final GraphObject img1 = f.get(go3); if (img1 != null && img3 != null) { try { this.addMapping(img1, img3); } catch (BadMappingException ex) { this.clear(); this.errorMsg = "Complete of diagram: d = g o f is not possible (object mapping failed)"; return false; } } } return true; } else { this.errorMsg = "Complete of diagram: d = g o f is not possible (d resp. f is null)"; return false; } } /** * We have a diagram third = first o second with first: A->B, second: B->C, third: A->C,<br> * second and third are complete.<br> * Try to complete first. * Note, first morphism is this morphism. * Returns true by success, otherwise false. */ public boolean completeDiagram1( final OrdinaryMorphism second, final OrdinaryMorphism third) { if (second != null && third != null) { // AttrContext context = agg.attribute.impl.AttrTupleManager // .getDefaultManager().newContext(AttrMapping.PLAIN_MAP); // this.setAttrContext(context); final Enumeration<GraphObject> dom = second.getDomain(); while (dom.hasMoreElements()) { GraphObject go2 = dom.nextElement(); GraphObject img2 = second.getImage(go2); Enumeration<GraphObject> en = third.getInverseImage(img2); if (en.hasMoreElements()) { GraphObject go1 = en.nextElement(); try { this.addMapping(go1, go2); } catch (BadMappingException ex) { this.clear(); this.errorMsg = "Complete of diagram1 is not possible (object mapping failed)"; return false; } } } return true; } else { this.errorMsg = "Complete of diagram1 is not possible (second or third is null)"; return false; } } /** * We have a diagram third = first o second with first: A->B, second: B->C, third: A->C,<br> * first and third are complete.<br> * Try to complete second. * Note, second morphism is this morphism. * Returns true by success, otherwise false. */ public boolean completeDiagram2( final OrdinaryMorphism first, final OrdinaryMorphism third) { if (first != null && third != null) { if (!first.isInjective()) { this.errorMsg = "Complete of diagram2 is not possible (first is non-injective)"; return false; } else { // AttrContext context = agg.attribute.impl.AttrTupleManager // .getDefaultManager().newContext(AttrMapping.PLAIN_MAP); // this.setAttrContext(context); final Enumeration<GraphObject> dom = first.getDomain(); while (dom.hasMoreElements()) { GraphObject go1 = dom.nextElement(); GraphObject img1 = first.getImage(go1); GraphObject img3 = third.getImage(go1); if (img3 != null) { try { this.addMapping(img1, img3); } catch (BadMappingException ex) { this.clear(); this.errorMsg = "Complete of diagram2 is not possible (object mapping failed)"; return false; } } } return true; } } else { this.errorMsg = "Complete of diagram2 is not possible (first resp. third is null)"; return false; } } /** * We have a diagram third = first o second with first: A->B, second: B->C, third: A->C,<br> * first and second are complete.<br> * Try to complete third. * Note, third morphism is this morphism. * Returns true by success, otherwise false. */ public boolean completeDiagram3( final OrdinaryMorphism first, final OrdinaryMorphism second) { if (first != null && second != null) { if (!first.isInjective()) { this.errorMsg = "Complete of diagram3 is not possible (first is non-injective)"; return false; } else { // AttrContext context = agg.attribute.impl.AttrTupleManager // .getDefaultManager().newContext(AttrMapping.PLAIN_MAP); // this.setAttrContext(context); final Enumeration<GraphObject> dom = first.getDomain(); while (dom.hasMoreElements()) { GraphObject go1 = dom.nextElement(); GraphObject img2 = second.getImage(first.getImage(go1)); if (img2 != null) { try { this.addMapping(go1, img2); } catch (BadMappingException ex) { this.clear(); this.errorMsg = "Complete of diagram3 is not possible (object mapping failed)"; return false; } } } return true; } } else { this.errorMsg = "Complete of diagram3 is not possible (first resp. second is null)"; return false; } } /** * Given this = d = g o f with f: A->B, g: B->C, d: A->C. * d and f are complete. * Try to complete g. * Returns true by success, otherwise false. */ public boolean completeDiagram( final OrdinaryMorphism f, final OrdinaryMorphism g) { if (f != null && g != null) { if (!f.isInjective()) { this.errorMsg = "Complete of diagram: d = g o f is not possible (f is non-injective)"; return false; } else { AttrContext context = agg.attribute.impl.AttrTupleManager .getDefaultManager().newContext(AttrMapping.PLAIN_MAP); g.setAttrContext(context); final Enumeration<GraphObject> fDom = f.getDomain(); while (fDom.hasMoreElements()) { final GraphObject fGO = fDom.nextElement(); final GraphObject img1 = f.getImage(fGO); final GraphObject img2 = this.getImage(fGO); if (img1 != null && img2 != null) { try { g.addMapping(img1, img2); } catch (BadMappingException ex) { g.clear(); this.errorMsg = "Complete of diagram: d = g o f is not possible (object mapping failed)"; return false; } } } return true; } } else { this.errorMsg = "Complete of diagram: d = g o f is not possible (g resp. f is null)"; return false; } } /** * The given morphisms h1, v2, v1 are already complete. * Try to complete this morphism : C -> D so that v2 o h1 = h2 o v1 . * * @param v1 : A -> C * @param h1 : A -> B * @param v2 : B -> D * * @return true if morphism this morphism : C -> D completed, otherwise false */ public boolean completeDiagram(final OrdinaryMorphism v1, final OrdinaryMorphism h1, final OrdinaryMorphism v2) { boolean ok = true; final Enumeration<GraphObject> dom = h1.getDomain(); while (dom.hasMoreElements() && ok) { GraphObject obj = dom.nextElement(); GraphObject obj1 = v1.getImage(obj); GraphObject obj2 = v2.getImage(h1.getImage(obj)); if (obj1 != null && obj2 != null) { try { this.addMapping(obj1, obj2); } catch (BadMappingException ex) { ok = false; } } } return ok; } public Enumeration<GraphObject> intersectCoDomains(final OrdinaryMorphism input) /*************************************************************************** * Return all graph objects of current codomain that reside * in the * codomain of the input morphism, too. Enumeration * elements are of type * <code>GraphObject</code>. * * @see agg.xt_basis.GraphObject * **************************************************************************/ { final Vector<GraphObject> intersection = new Vector<GraphObject>(); final Enumeration<GraphObject> inpCodom = input.getCodomain(); while (inpCodom.hasMoreElements()) { final GraphObject g = inpCodom.nextElement(); if (this.itsCodomObjects.contains(g)) { intersection.addElement(g); } } return (intersection.elements()); } /** * Check if the constant value of the same attribute member of the * original and image graph objects are equal. */ public boolean checkConstants() { if (this.itsDomObjects.isEmpty()) return true; for (int j=0; j<this.itsDomObjects.size(); j++) { final GraphObject orig = this.itsDomObjects.get(j); if (orig.getAttribute() == null) continue; final GraphObject image = getImage(orig); final ValueTuple valOrig = (ValueTuple) orig.getAttribute(); final ValueTuple valImage = (ValueTuple) image.getAttribute(); int n = valOrig.getNumberOfEntries(); for (int i = 0; i < n; i++) { final String name = valOrig.getNameAsString(i); ValueMember valMemberOrig = null; if (valOrig.isValueSetAt(name)) { valMemberOrig = valOrig.getValueMemberAt(name); final HandlerExpr exprOrig = valMemberOrig.getExpr(); if ((exprOrig != null) && exprOrig.isConstant()) { if (valImage.isValueSetAt(name)) { final ValueMember valMemberImage = valImage .getValueMemberAt(name); final HandlerExpr exprImage = valMemberImage.getExpr(); if ((exprImage != null) && exprImage.isConstant()) { if (!valMemberOrig.toString().equals( valMemberImage.toString())) { return false; } } } } } } } return true; } /** * Check if the variable of the same attribute member of the original and * image graph objects are equal. */ public boolean checkVariables() { if (this.itsDomObjects.isEmpty()) return true; for (int j=0; j<this.itsDomObjects.size(); j++) { final GraphObject orig = this.itsDomObjects.get(j); if (orig.getAttribute() == null) { continue; } final GraphObject image = getImage(orig); final ValueTuple valOrig = (ValueTuple) orig.getAttribute(); final ValueTuple valImage = (ValueTuple) image.getAttribute(); int n = valOrig.getNumberOfEntries(); for (int i = 0; i < n; i++) { final String name = valOrig.getNameAsString(i); ValueMember valMemberOrig = null; if (valOrig.isValueSetAt(name)) { valMemberOrig = valOrig.getValueMemberAt(name); final HandlerExpr exprOrig = valMemberOrig.getExpr(); if ((exprOrig != null) && exprOrig.isVariable()) { if (valImage.isValueSetAt(name)) { final ValueMember valMemberImage = valImage .getValueMemberAt(name); final HandlerExpr exprImage = valMemberImage.getExpr(); if ((exprImage != null) && exprImage.isVariable()) { if (!valMemberOrig.toString().equals( valMemberImage.toString())) { return false; } } } } } } } return true; } /** * Check if the setting of the same attribute member * of the original and image graph objects are equal. */ protected boolean checkAll() { if (this.itsDomObjects.isEmpty()) { return true; } for (int j=0; j<this.itsDomObjects.size(); j++) { final GraphObject orig = this.itsDomObjects.get(j); if (orig.getAttribute() == null) continue; final GraphObject image = getImage(orig); final ValueTuple valOrig = (ValueTuple) orig.getAttribute(); final ValueTuple valImage = (ValueTuple) image.getAttribute(); int n = valOrig.getNumberOfEntries(); for (int i = 0; i < n; i++) { final String name = valOrig.getNameAsString(i); ValueMember valMemberOrig = null; if (valOrig.isValueSetAt(name)) { valMemberOrig = valOrig.getValueMemberAt(name); if ((valMemberOrig.isSet())) { if (valImage.isValueSetAt(name)) { final ValueMember valMemberImage = valImage .getValueMemberAt(name); if (valMemberImage != null && valMemberImage.isSet()) { if (!valMemberOrig.getExprAsText().equals( valMemberImage.getExprAsText())) { return false; } } } } } } } return true; } public void putVarToAttrContext() { final VarTuple vars = (VarTuple) getAttrContext().getVariables(); putVarToAttrContext(this.itsOrig.getNodesSet().iterator(), vars); putVarToAttrContext(this.itsOrig.getArcsSet().iterator(), vars); putVarToAttrContext(this.itsImag.getNodesSet().iterator(), vars); putVarToAttrContext(this.itsImag.getArcsSet().iterator(), vars); } private void putVarToAttrContext( final Iterator<?> elems, final VarTuple vars) { while (elems.hasNext()) { final GraphObject o = (GraphObject) elems.next(); if (o.getAttribute() == null) continue; final ValueTuple val = (ValueTuple) o.getAttribute(); int n = val.getNumberOfEntries(); for (int i = 0; i < n; i++) { final String name = val.getNameAsString(i); final ValueMember valMem = val.getValueMemberAt(name); if (valMem != null && valMem.isSet()) { if (valMem.getExpr().isVariable()) { final String varName = valMem.getExprAsText(); if (vars.getVarMemberAt(varName) == null) { final String varType = valMem.getDeclaration() .getTypeName(); vars.declare(valMem.getDeclaration().getHandler(), varType, varName); } } } } } } /** * If the value of an attribute member of the original graphobject is unset * or is a variable, fill up such attribute value with the value (it should * be a constant value) of the same attribute member of the image * graphobject. */ public void fillUpOriginalAttrs() { final Enumeration<GraphObject> elems = this.itsDomObjects.elements(); while (elems.hasMoreElements()) { final GraphObject orig = elems.nextElement(); final GraphObject image = getImage(orig); if (orig.getAttribute() != null) { final ValueTuple valOrig = (ValueTuple) orig.getAttribute(); final ValueTuple valImage = (ValueTuple) image.getAttribute(); int n = valOrig.getNumberOfEntries(); for (int i = 0; i < n; i++) { final String name = valOrig.getNameAsString(i); ValueMember valMemberOrig = null; HandlerExpr exprOrig = null; if (valOrig.isValueSetAt(name)) { valMemberOrig = valOrig.getValueMemberAt(name); exprOrig = valMemberOrig.getExpr(); } if ((exprOrig == null) || !exprOrig.isConstant()) { if (valImage.isValueSetAt(name)) { ValueMember valMemberImage = valImage .getValueMemberAt(name); HandlerExpr exprImage = valMemberImage.getExpr(); if ((exprImage != null) && exprImage.isConstant()) { valOrig.setExprValueAt(valMemberImage .getExprAsText(), name); (valOrig.getValueMemberAt(name)) .setTransient(true); valOrig.getValueMemberAt(name).checkValidity(); } } } } } } } /** * Iff the value of an attribute member of the image graphobject is unset or * is a variable, fill up the value of such attribute member with the value * (it should be a constant value) of the same attribute member of the * original graphobject. */ public void fillUpImageAttrs() { final Enumeration<GraphObject> elems = this.itsDomObjects.elements(); while (elems.hasMoreElements()) { final GraphObject orig = elems.nextElement(); final GraphObject image = getImage(orig); if (orig.getAttribute() != null) { final ValueTuple valOrig = (ValueTuple) orig.getAttribute(); final ValueTuple valImage = (ValueTuple) image.getAttribute(); int n = valImage.getNumberOfEntries(); for (int i = 0; i < n; i++) { final String name = valImage.getNameAsString(i); ValueMember valMemberImage = null; HandlerExpr exprImage = null; if (valImage.isValueSetAt(name)) { valMemberImage = valImage.getValueMemberAt(name); exprImage = valMemberImage.getExpr(); } if ((exprImage == null) || !exprImage.isConstant()) { if (valOrig.isValueSetAt(name)) { final ValueMember valMemberOrig = valOrig .getValueMemberAt(name); final HandlerExpr exprOrig = valMemberOrig.getExpr(); if ((exprOrig != null) && exprOrig.isConstant()) { valImage.setExprValueAt(valMemberOrig .getExprAsText(), name); (valImage.getValueMemberAt(name)) .setTransient(true); valImage.getValueMemberAt(name).checkValidity(); } } } } } } } private Vector<GraphObject> findCreatedElements() { final Vector<GraphObject> vec = new Vector<GraphObject>(); for (Iterator<Node> en = this.itsImag.getNodesSet().iterator(); en.hasNext();) { final GraphObject o = en.next(); if (!getInverseImage(o).hasMoreElements()) vec.addElement(o); } for (Iterator<Arc> en = this.itsImag.getArcsSet().iterator(); en.hasNext();) { final GraphObject o = en.next(); if (!getInverseImage(o).hasMoreElements()) vec.addElement(o); } return vec; } private Vector<GraphObject> findDeletedElements() { final Vector<GraphObject> vec = new Vector<GraphObject>(); for (Iterator<Node> en = this.itsOrig.getNodesSet().iterator(); en.hasNext();) { final GraphObject o = en.next(); if (getImage(o) == null) vec.addElement(o); } for (Iterator<Arc> en = this.itsOrig.getArcsSet().iterator(); en.hasNext();) { final GraphObject o = en.next(); if (getImage(o) == null) vec.addElement(o); } return vec; } /** * Iff the value of an attribute member of the original graphobject is an * expression, unset it. */ public void unsetOriginalAttrsIfExpression() { final Iterator<Node> elems = this.itsOrig.getNodesSet().iterator(); while (elems.hasNext()) { GraphObject orig = elems.next(); if (orig.getAttribute() == null) continue; ValueTuple valOrig = (ValueTuple) orig.getAttribute(); int n = valOrig.getNumberOfEntries(); for (int i = 0; i < n; i++) { String name = valOrig.getNameAsString(i); ValueMember valMemberOrig = null; HandlerExpr exprOrig = null; if (valOrig.isValueSetAt(name)) { valMemberOrig = valOrig.getValueMemberAt(name); if(valMemberOrig != null) { exprOrig = valMemberOrig.getExpr(); if ((exprOrig != null) && exprOrig.isComplex()) valMemberOrig.setExpr(null); } } } } final Iterator<Arc> elems1 = this.itsOrig.getArcsSet().iterator(); while (elems1.hasNext()) { GraphObject orig = elems1.next(); if (orig.getAttribute() == null) continue; ValueTuple valOrig = (ValueTuple) orig.getAttribute(); int n = valOrig.getNumberOfEntries(); for (int i = 0; i < n; i++) { String name = valOrig.getNameAsString(i); ValueMember valMemberOrig = null; HandlerExpr exprOrig = null; if (valOrig.isValueSetAt(name)) { valMemberOrig = valOrig.getValueMemberAt(name); if(valMemberOrig != null) { exprOrig = valMemberOrig.getExpr(); if ((exprOrig != null) && exprOrig.isComplex()) valMemberOrig.setExpr(null); } } } } } public void fillUpAttrContext(final AttrContext other) { if ((other == null) || (this.getAttrContext() == null)) return; // System.out.println(">>> // OrdinaryMorphism.fillUpAttrContext(AttrContext other) "); final VarTuple avt = (VarTuple) this.getAttrContext().getVariables(); final VarTuple avtOther = (VarTuple) other.getVariables(); // System.out.println("--> "+avt+" "+avtOther); // gehe <other> Attrcontext durch und stelle fest // ob er schon in <this> attrcontext vorhandene Variablen // mit einem Wert als Konstante hat oder // eine neue Variable mit einem konstanten Wert, // und ersetze oder hinzufuege diese Variable. int nn = avtOther.getNumberOfEntries(); for (int i = 0; i < nn; i++) { final VarMember avmOther = avtOther.getVarMemberAt(i); final String name = avtOther.getNameAsString(i); final VarMember avm = avt.getVarMemberAt(name); // System.out.println(name+" "+avm+" "+avmOther); if (avm != null) { // if(avmOther.isInputParameter()) { // setze den Wert if (avmOther.isSet() && avmOther.getExpr().isConstant()) { avm.setExprAsText(avmOther.getExprAsText()); // System.out.println(name+" "+avm+"\nas copy of: // "+avmOther); } } } } } public void copyAttrContext(final AttrContext other) { if ((other == null) || (this.getAttrContext() == null)) return; final VarTuple avt = (VarTuple) this.itsAttrContext.getVariables(); final VarTuple avtOther = (VarTuple) other.getVariables(); int nn = avtOther.getNumberOfEntries(); for (int i = 0; i < nn; i++) { final VarMember avmOther = avtOther.getVarMemberAt(i); final String name = avtOther.getNameAsString(i); final VarMember avm = avt.getVarMemberAt(name); // System.out.println(name+" "+avm+" "+avmOther); if (avm != null) { // ersetze den Wert von der Variablen if (avmOther.isSet() && avmOther.getExpr().isConstant()) { avm.setExprAsText(avmOther.getExprAsText()); // System.out.println(name+" "+avm+"\nas copy of: // "+avmOther); } if (avmOther.isInputParameter()) avm.setInputParameter(true); } // fuege eine neue Variable mit/ohne einem Wert hinzu else { // System.out.println("add new member"); final DeclMember dm = (DeclMember) avmOther.getDeclaration(); avt.declare(dm.getHandler(), dm.getTypeName(), dm.getName()); final ValueMember newMember = avt.getVarMemberAt(dm.getName()); if ((newMember != null) && (avmOther.getExpr() != null) && avmOther.getExpr().isConstant()) { newMember.setExprAsText(avmOther.getExprAsText()); // System.out.println(name+" "+avm+"\nas copy of: // "+avmOther); } (avt.getVarMemberAt(dm.getName())).setInputParameter(avmOther .isInputParameter()); (avt.getVarMemberAt(dm.getName())).setTransient(avmOther .isTransient()); // System.out.println(name+" "+newMember+"\nas copy of: // "+avmOther); } } } /* * Returns a hashtable where the key is an input parameter and the object is * a vector of pairs. The first pair element is an attribute member and the * second pair element is appropriate graphobject type. */ public Hashtable<VarMember, Vector<Pair<ValueMember, Type>>> getUsageOfInputParameters( final AttrContext attrContext) { // AttrContext attrContext = getAttrContext(); final Hashtable<VarMember, Vector<Pair<ValueMember, Type>>> ht = new Hashtable<VarMember, Vector<Pair<ValueMember, Type>>>(); // if (this instanceof SubRule) { // System.out.println("OrdinaryMorphism.getUsageOfInputParameters : // this instance of SubRule"); // attrContext = ((SubRule) this).getSuperRule().getAttrContext(); // } if (attrContext == null || attrContext.getVariables() == null) return ht; final Vector<Type> tmp = new Vector<Type>(); final VarTuple avt = (VarTuple) attrContext.getVariables(); for (int i = 0; i < avt.getSize(); i++) { final VarMember avm = avt.getVarMemberAt(i); if (avm.getExpr() == null) return ht; // System.out.println(avm+" "+avm.getExpr()); // System.out.println(avm.getDeclaration().getName()); final Vector<Pair<ValueMember, Type>> v = new Vector<Pair<ValueMember, Type>>(); if (avm.isInputParameter()) { // System.out.println("search source graph"); final Iterator<Node> en = getSource().getNodesSet().iterator(); while (en.hasNext()) { GraphObject go = en.next(); if (go.getAttribute() == null) continue; final ValueTuple vt = (ValueTuple) go.getAttribute(); for (int j = 0; j < vt.getSize(); j++) { final ValueMember vm = vt.getValueMemberAt(j); if ((vm.getExpr() != null) && vm.getExpr().isVariable()) { // System.out.println("value member: // "+vm.getExprAsText()); // System.out.println("input param : // "+avm.getDeclaration().getName()); if (vm.getExprAsText().equals( avm.getDeclaration().getName())) { v.addElement(new Pair<ValueMember, Type>(vm, go .getType())); tmp.addElement(go.getType()); } } } } final Iterator<Arc> en1 = getSource().getArcsSet().iterator(); while (en1.hasNext()) { final GraphObject go = en1.next(); if (go.getAttribute() == null) continue; final ValueTuple vt = (ValueTuple) go.getAttribute(); for (int j = 0; j < vt.getSize(); j++) { final ValueMember vm = vt.getValueMemberAt(j); if ((vm.getExpr() != null) && vm.getExpr().isVariable()) { // System.out.println("value member: // "+vm.getExprAsText()); // System.out.println("input param : // "+avm.getDeclaration().getName()); if (vm.getExprAsText().equals( avm.getDeclaration().getName())) { v.addElement(new Pair<ValueMember, Type>(vm, go .getType())); tmp.addElement(go.getType()); } } } } // System.out.println("search target graph"); final Iterator<Node> en2 = getTarget().getNodesSet().iterator(); while (en2.hasNext()) { final GraphObject go = en2.next(); if (go.getAttribute() == null) continue; final ValueTuple vt = (ValueTuple) go.getAttribute(); for (int j = 0; j < vt.getSize(); j++) { final ValueMember vm = vt.getValueMemberAt(j); if ((vm.getExpr() != null) && vm.getExpr().isVariable()) { // System.out.println("value member: // "+vm.getExprAsText()); // System.out.println("input param : // "+avm.getDeclaration().getName()); if (vm.getExprAsText().equals( avm.getDeclaration().getName())) { // System.out.println(" will be used!"); if (tmp.isEmpty() || !tmp.contains(go.getType())) { v.addElement(new Pair<ValueMember, Type>( vm, go.getType())); tmp.addElement(go.getType()); } } } } } final Iterator<Arc> en3 = getTarget().getArcsSet().iterator(); while (en3.hasNext()) { final GraphObject go = en3.next(); if (go.getAttribute() == null) continue; final ValueTuple vt = (ValueTuple) go.getAttribute(); for (int j = 0; j < vt.getSize(); j++) { final ValueMember vm = vt.getValueMemberAt(j); if ((vm.getExpr() != null) && vm.getExpr().isVariable()) { // System.out.println("value member: // "+vm.getExprAsText()); // System.out.println("input param : // "+avm.getDeclaration().getName()); if (vm.getExprAsText().equals( avm.getDeclaration().getName())) { // System.out.println(" will be used!"); if (tmp.isEmpty() || !tmp.contains(go.getType())) { v.addElement(new Pair<ValueMember, Type>( vm, go.getType())); tmp.addElement(go.getType()); } } } } } if (v.size() != 0) ht.put(avm, v); } } // System.out.println("Count of input parameters: "+ht.size()); return ht; } /** * Computes an overlapping set of the graphs: - this.source with * other.source if other instance of OrdinaryMorphism and left is true, or - * this.target with other.target if other instance of OrdinaryMorphism and * left is false, or - this.sorce with other if other instance of Graph and * left is true, or - this.target with other if other instance of Graph and * left is false, or with respect of the rules if this and other are * instances of Rule. * * @param union * If true - the overlappings contain disjunion, too. Enumeration * elements are of type <code>Pair</code>. * @return A set of overlappings. */ public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings( final Object other, boolean left, boolean union) { return MatchHelper.getOverlappingsVector(this, other, left, union).elements(); } public Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappingsVector( final Object other, boolean left, boolean union) { return MatchHelper.getOverlappingsVector(this, other, left, union); } /** * Computes an overlapping set of the graphs: - this.source with * other.source if other instance of OrdinaryMorphism and left is true, or - * this.target with other.target if other instance of OrdinaryMorphism and * left is false, or - this.sorce with other if other instance of Graph and * left is true, or - this.target with other if other instance of Graph and * left is false, or with respect of the rules if this and other are * instances of Rule. * * @param sizeOfInclusions * The size of graph object inclusions. * @param union * If true - the overlappings contain disjunion, too. Enumeration * elements are of type <code>Pair</code>. * @return A set of overlappings. */ public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings( final Object other, boolean left, int sizeOfInclusions, boolean union) { return MatchHelper.getOverlappingsVector(this, other, left, sizeOfInclusions, union).elements(); } public Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappingsVector( final Object otherObj, boolean left, int sizeOfInclusions, boolean union) { return MatchHelper.getOverlappingsVector(this, otherObj, left, sizeOfInclusions, union); } public void setCoMorphism(final OrdinaryMorphism aCoMorph) { this.itsCoMorph = aCoMorph; } public OrdinaryMorphism getCoMorphism() { return this.itsCoMorph; } protected void deleteTransientContextVariables(Graph g) { // System.out.println("OrdinaryMorphism.deleteTransientContextVariables()"); final VarTuple vars = (VarTuple) getAttrContext().getVariables(); delTransientContextVar(g.getNodesSet().iterator(), vars); delTransientContextVar(g.getArcsSet().iterator(), vars); } private void delTransientContextVar( final Iterator<?> elems, final VarTuple vars) { while (elems.hasNext()) { GraphObject obj = (GraphObject) elems.next(); if (obj.getAttribute() == null) continue; ValueTuple value = (ValueTuple) obj.getAttribute(); for (int i = 0; i < value.getNumberOfEntries(); i++) { ValueMember valuem = value.getValueMemberAt(i); if (valuem.isTransient()) { // System.out.println(valuem+" "+valuem.getExprAsText()); if (!vars.isEmpty()) vars.getTupleType().deleteMemberAt(valuem.getExprAsText()); valuem.setExpr(null); } } } } public int getSize() { return this.itsDomObjects.size(); } public boolean compareTo(OrdinaryMorphism morph) { String errMsgHolder = null; if (!getSource().compareTo(morph.getSource())) { errMsgHolder = errMsgHolder + "LHS is different"; return false; } if (!getTarget().compareTo(morph.getTarget())) { errMsgHolder = errMsgHolder + "RHS is different"; return false; } // compare mapping Enumeration<GraphObject> e = morph.getDomain(); Vector<GraphObject> another = new Vector<GraphObject>(); while (e.hasMoreElements()) { another.add(e.nextElement()); } if (this.itsDomObjects.size() != another.size()) { return false; } for (int i = 0; i < this.itsDomObjects.size(); i++) { GraphObject obj = this.itsDomObjects.elementAt(i); GraphObject img = this.getImage(obj); for (int j = another.size() - 1; j >= 0; j--) { GraphObject obj1 = another.elementAt(j); if (obj.compareTo(obj1)) { GraphObject img1 = morph.getImage(obj1); if (img == null && img1 == null) { another.remove(obj1); break; } else if (img != null && img1 == null) { } else if (img == null && img1 != null) { } else if (img != null && img.compareTo(img1)) { another.remove(obj1); break; } } } } if (another.size() != 0) { errMsgHolder = errMsgHolder + "Morphism mapping is different"; return false; } return true; } /** * Returns a vector with variable declarations used in LHS and RHS of this * graph morphism. An Element of the vector is a Pair. * * @see agg.util.Pair * The first element is a type, the second * element is a name of a variable declaration, both elements are of * the type String. */ public Vector<Pair<String, String>> getVariableDeclarations() { final Vector<Pair<String, String>> varDecls = new Vector<Pair<String, String>>(2); // search left graph putVarDecl(this.itsOrig.getNodesSet().iterator(), varDecls); putVarDecl(this.itsOrig.getArcsSet().iterator(), varDecls); // search right graph // first search values as a variable putVarDecl(this.itsImag.getNodesSet().iterator(), varDecls); putVarDecl(this.itsImag.getArcsSet().iterator(), varDecls); // now search values as a complex expression putVarOfExpr(this.itsImag.getNodesSet().iterator(), varDecls); putVarOfExpr(this.itsImag.getArcsSet().iterator(), varDecls); return varDecls; } private void putVarDecl( final Iterator<?> elems, final Vector<Pair<String, String>> varDecls) { while (elems.hasNext()) { GraphObject o = (GraphObject) elems.next(); 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(); // 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); } // else if (vm.isSet() && !vm.getExpr().isVariable()) { // String n = vm.getExprAsText(); // String t = vm.getDeclaration().getTypeName(); // // System.out.println(o.getContext().getName()+" "+n+" ### "+t); // } } } } private void putVarOfExpr( final Iterator<?> elems, final Vector<Pair<String, String>> varDecls) { while (elems.hasNext()) { GraphObject o = (GraphObject) elems.next(); 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().isComplex()) { Vector<String> vec = vm.getAllVariableNamesOfExpression(); // System.out.println("vec: "+vec); if (vec.size() != 0) { for (int l = 0; l < vec.size(); l++) { Pair<String, String> p = null; String n = vec.elementAt(l); String t = ""; VarMember var = getAttrContext().getVariables() .getVarMemberAt(n); if ((var != null) && (var.getDeclaration() != null)) { t = var.getDeclaration().getTypeName(); p = new Pair<String, String>(t, n); // System.out.println("decl pair: "+p); } else { String className = isClassName(n); if (className != null) { t = className; p = new Pair<String, String>(t, n); // System.out.println("class pair: "+p); } else { 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; } if (!found) varDecls.addElement(p); } } } } } } public String isClassName(String name) { return AttrTupleManager.getDefaultManager().isClassName(name); } public Vector<Type> getUsedTypes() { final Vector<Type> vec = new Vector<Type>(); addUsedType(this.itsOrig.getNodesSet().iterator(), vec); addUsedType(this.itsOrig.getArcsSet().iterator(), vec); addUsedType(this.itsImag.getNodesSet().iterator(), vec); addUsedType(this.itsImag.getArcsSet().iterator(), vec); return vec; } private void addUsedType(final Iterator<?> elems, final Vector<Type> vec) { while (elems.hasNext()) { GraphObject o = (GraphObject) elems.next(); if (!vec.contains(o.getType())) vec.add(o.getType()); } } protected final void propagateChange(agg.util.Change ch) { setChanged(); notifyObservers(ch); } /** * Disables attribute conditions in which a variable inside is not declared. */ public void disableUnusedAttrCondition() { final VarTuple avt = (VarTuple) this.getAttrContext().getVariables(); final CondTuple act = (CondTuple) this.getAttrContext().getConditions(); for (int k = 0; k < act.getSize(); k++) { final CondMember cm = act.getCondMemberAt(k); final Vector<String> vars = cm.getAllVariables(); if (!vars.isEmpty()) { for (int i=0; i<vars.size(); i++) { final VarMember var = avt.getVarMemberAt(vars.get(i)); if (var == null) { cm.setEnabled(false); break; } } } } } public void enableUnusedAttrCondition() { final VarTuple avt = (VarTuple) this.getAttrContext().getVariables(); final CondTuple act = (CondTuple) this.getAttrContext().getConditions(); for (int k = 0; k < act.getSize(); k++) { final CondMember cm = act.getCondMemberAt(k); final Vector<String> vars = cm.getAllVariables(); if (!vars.isEmpty()) { for (int i=0; i<vars.size(); i++) { final VarMember var = avt.getVarMemberAt(vars.get(i)); if (var == null) { cm.setEnabled(true); break; } } } } } public void removeUnusedVariableOfAttrContext() { VarTuple vars = (VarTuple) this.getAttrContext().getVariables(); for (int i=0; i<vars.getNumberOfEntries(); i++) { VarMember vm = vars.getVarMemberAt(i); String var = vm.getName(); if (!this.getSource().getVariableNamesOfAttributes().contains(var)) { if (!this.getTarget().getVariableNamesOfAttributes().contains(var)) { vars.getTupleType().deleteMemberAt(var); // System.out.println("Rule.removeVariableOfAttrContext:: removed: "+var); } } } } protected boolean tryToApplyAttrExpr(final Hashtable<String, String> valMembeHashcode2Expr) { return tryComputeAttrExpr(this.getSource().getNodesSet().iterator(), valMembeHashcode2Expr) && tryComputeAttrExpr(this.getSource().getArcsSet().iterator(), valMembeHashcode2Expr); } private boolean tryComputeAttrExpr( final Iterator<?> elems, final Hashtable<String, String> valMemberHashcode2Expr) { // ((VarTuple)ac.getVariables()).showVariables(); // final VarTuple vars = ((VarTuple)this.getAttrContext().getVariables()); // final CondTuple conds = (CondTuple)this.getAttrContext().getConditions(); while (elems.hasNext()) { final GraphObject go = (GraphObject) elems.next(); if (go.getAttribute() != null) { final ValueTuple val = (ValueTuple) go.getAttribute(); for (int i=0; i<val.getNumberOfEntries(); i++) { ValueMember mem = val.getValueMemberAt(i); if (mem.isSet() && mem.getExpr().isComplex()) { boolean applied = false; String expr = mem.getExprAsText(); valMemberHashcode2Expr.put(String.valueOf(mem.hashCode()), expr); try { // System.out.println("tryComputeAttrExprOfNode::: "+expr); mem.getExpr().evaluate(this.getAttrContext()); applied = true; } catch (AttrHandlerException ex) {} if (!applied) { return false; } } } } } return true; } protected void resetAttrValueAsExpr(final Hashtable<String, String> valMembeHashcoder2Expr) { resetAttrValueAsExpr(this.getSource().getNodesSet().iterator(), valMembeHashcoder2Expr); resetAttrValueAsExpr(this.getSource().getArcsSet().iterator(), valMembeHashcoder2Expr); } private void resetAttrValueAsExpr(final Iterator<?> elems, final Hashtable<String, String> valMembeHashcoder2Expr) { final VarTuple vars = ((VarTuple)this.getAttrContext().getVariables()); final CondTuple conds = (CondTuple)this.getAttrContext().getConditions(); while (elems.hasNext()) { final GraphObject go = (GraphObject) elems.next(); if (go.getAttribute() != null) { final ValueTuple val = (ValueTuple) go.getAttribute(); for (int i=0; i<val.getNumberOfEntries(); i++) { ValueMember mem = val.getValueMemberAt(i); String expr = valMembeHashcoder2Expr.get(String.valueOf(mem.hashCode())); if (expr != null) { // System.out.println(mem.getExprAsText()); mem.setExprAsText(expr); // System.out.println(mem.getExprAsText()); for (int j=0; j<conds.getSize(); j++) { CondMember cond = (CondMember) conds.getMemberAt(j); if (cond.getExprAsText().endsWith("=".concat(expr)) && cond.isTransient() && (cond.getMark() == CondMember.NAC || cond.getMark() == CondMember.PAC)) { String nameStr = cond.getName(); conds.getTupleType().deleteMemberAt(j); vars.getTupleType().deleteMemberAt(nameStr); } } } } } } // vars.showVariables(); // conds.showConditions(); } /** * Trims the capacity of used vectors to be the vector's current * size. */ public void trimToSize() { this.itsOrig.trimToSize(); this.itsImag.trimToSize(); this.itsDomObjects.trimToSize(); this.itsDomObjects.trimToSize(); } }