package agg.xt_basis; import java.util.Collection; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Observable; import java.util.Observer; import java.util.Vector; import java.util.Hashtable; import java.util.List; import agg.attribute.AttrContext; import agg.attribute.AttrInstance; import agg.attribute.AttrManager; import agg.attribute.AttrMapping; import agg.attribute.impl.AttrTupleManager; import agg.attribute.impl.ValueTuple; import agg.attribute.impl.ValueMember; import agg.attribute.impl.VarTuple; import agg.attribute.impl.VarMember; import agg.attribute.impl.ContextView; import agg.util.Change; import agg.util.CopyMemory; import agg.util.ExtObservable; import agg.util.LinkedGOHashSet; import agg.util.Pair; import agg.util.XMLHelper; import agg.util.XMLObject; import agg.xt_basis.csp.CompletionPropertyBits; /** * This class extends simple graphs with the possibility * to have arcs between nodes. * * @version $Id: Graph.java,v 1.145 2010/11/16 23:34:19 olga Exp $ * @author $Author: olga $ */ // * Class Graph is capable of passing the following change informations // * as an argument to its observers' <code>update()</code> methods: // * Graph_Change_ObjectCreated, Graph_Change_ObjectDestroyed, // * Graph_Change_ObjectModified. // * Additionally, <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 graph. // * @see agg.xt_basis.Graph_Change_ObjectCreated // * @see agg.xt_basis.Graph_Change_ObjectDestroyed // * @see agg.xt_basis.Graph_Change_ObjectModified // * @see agg.util.Change_ObservableGone public class Graph extends ExtObservable implements Observer, XMLObject { // test: node XY-position as attribute public boolean xyAttr = false; protected Vector<Observer> observer; protected LinkedGOHashSet<Node> itsNodes; protected LinkedGOHashSet<Arc> itsArcs; protected Hashtable<String, HashSet<GraphObject>> itsTypeObjectsMap; protected Vector<OrdinaryMorphism> itsUsingMorphs; protected String kind; protected String itsName; protected String comment; protected String info; protected AttrContext itsAttrContext; boolean notificationRequired; protected boolean attributed; protected boolean changed; /* object for creating and checking types and holding the type graph */ protected TypeSet itsTypes; /* true for a host graph, false - otherwise */ protected boolean completeGraph; /** * Creates an empty graph with an empty TypeSet. * * Use {@link #Graph(boolean)}, to create a complete graph * (a host graph). */ public Graph() { this.itsTypes = new TypeSet(); init(); } /** * Creates an empty graph with the specified TypeSet. * * Use {@link #Graph(TypeSet,boolean)}, to create a complete * graph (a host graph). */ public Graph(TypeSet aTypeSet) { this.itsTypes = aTypeSet; init(); } /** * Creates an empty graph with an empty TypeSet. * * @param completeGraph * true, to create a host graph */ public Graph(boolean completeGraph) { this.itsTypes = new TypeSet(); this.completeGraph = completeGraph; init(); } /** * Creates an empty graph with the specified TypeSet. * * @param aTypeSet * the TypeSet to use * @param completeGraph * true, to create a host graph */ public Graph(TypeSet aTypeSet, boolean completeGraph) { this.itsTypes = aTypeSet; this.completeGraph = completeGraph; init(); } private void init() { observer = new Vector<Observer>(); itsNodes = new LinkedGOHashSet<Node>(); itsArcs = new LinkedGOHashSet<Arc>(); itsTypeObjectsMap = new Hashtable<String, HashSet<GraphObject>>(); itsUsingMorphs = new Vector<OrdinaryMorphism>(); kind = GraphKind.GRAPH; comment = ""; itsName = "Graph"; info = ""; } /** * @see java.util.Observable#addObserver(java.util.Observer) */ public synchronized void addObserver(Observer o) { if (!this.observer.contains(o)) { this.observer.add(o); this.notificationRequired = true; super.addObserver(o); } } /** * @see java.util.Observable#deleteObserver(java.util.Observer) */ public synchronized void deleteObserver(Observer o) { if (this.observer.contains(o)) { this.observer.remove(o); super.deleteObserver(o); if(this.observer.isEmpty()) this.notificationRequired = false; } } public List<Observer> getObservers() { return this.observer; } public void setObservers(List<?> o) { if (o == null) return; for (int i = 0; i < o.size(); i++) { this.addObserver((Observer) o.get(i)); } } /** * A kind is a role of a graph in a grammar, * for exmpl.: a type graph - TG, a host graph - HOST, * the left graph of a rule - LHS, the right graph of a rule - RHS, * a NAC graph - NAC, a PAC graph - PAC and so on. * * @see agg.xt_basis.GraphKind * * @return the kind of this graph */ public String getKind() { return this.kind; } /** * A kind is a role of a graph in a grammar, * for exmpl.: a type graph - TG, a host graph - HOST, * the left graph of a rule - LHS, the right graph of a rule - RHS, * a NAC graph - NAC, a PAC graph - PAC and so on. * * @see agg.xt_basis.GraphKind */ public void setKind(final String aKind) { this.kind = aKind; } public void setNotificationRequired(boolean b) { this.notificationRequired = b; } public boolean isNotificationRequired() { return this.notificationRequired; } public boolean hasChanged() { return this.changed; } /** * Set the given type set to its type set. * @param types * a type set which contains all types already used in this * graph. This won't be checked. */ public void setTypeSet(TypeSet types) { this.itsTypes = types; } /** * Returns its type set. */ public TypeSet getTypeSet() { return this.itsTypes; } /** * Tries to add a copy of the specified graph to my elements. * The existing type graph should be disabled. * * @param g * @return true if a copy was added, otherwise - false. */ public boolean addCopyOfGraph(Graph g, boolean disabledTypeGraph) { synchronized (this) { if (!disabledTypeGraph || this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.DISABLED) { boolean failed = false; final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(g .getSize()); Iterator<Node> vtxList = g.getNodesSet().iterator(); while (vtxList.hasNext()) { Node vtxOrig = vtxList.next(); Node vtxCopy = null; Type type = this.itsTypes.getSimilarType(vtxOrig.getType()); if (type == null) { type = this.itsTypes.getTypeByName(vtxOrig.getType() .getName()); if (type != null && !type.isNodeType()) type = null; } try { if (type != null) { vtxCopy = this.createNode(type); vtxCopy.setObjectName(vtxOrig.getObjectName()); vtxCopy.copyAttributes(vtxOrig); vtxCopy.setContextUsage(vtxOrig .getContextUsage()); memo1.put(vtxOrig, vtxCopy); propagateChange(new Change( Change.OBJECT_CREATED, vtxCopy)); } } catch (TypeException e) { } } Iterator<Arc> arcList = g.getArcsSet().iterator(); while (arcList.hasNext()) { Arc arcOrig = arcList.next(); Arc arcCopy = null; Type type = this.itsTypes.getSimilarType(arcOrig.getType()); if (type == null) { type = this.itsTypes.getTypeByName(arcOrig.getType() .getName()); if (type != null && !type.isArcType()) type = null; } try { if (type != null) { Node source = (Node) arcOrig.getSource(); Node target = (Node) arcOrig.getTarget(); Node srcImg = memo1.get(source); Node tgtImg = memo1.get(target); arcCopy = this.createArc(type, srcImg, tgtImg); arcCopy.setObjectName(arcOrig.getObjectName()); arcCopy.copyAttributes(arcOrig); arcCopy.setContextUsage(arcOrig .getContextUsage()); propagateChange(new Change( Change.OBJECT_CREATED, arcCopy)); } } catch (TypeException e) {} } memo1.clear(); if (!failed) return true; } } return false; } @SuppressWarnings("unused") private boolean integrateCopyOfGraph(Graph g) { synchronized (this) { if (this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.DISABLED) { boolean failed = false; final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(g .getSize()); Iterator<Node> vtxList = g.getNodesSet().iterator(); while (vtxList.hasNext()) { Node vtxOrig = vtxList.next(); Node vtxCopy = null; Type type = this.itsTypes.getSimilarType(vtxOrig.getType()); if (type == null) { type = this.itsTypes.getTypeByName(vtxOrig.getType() .getName()); if (type != null && !type.isNodeType()) type = null; } try { if (type != null) { boolean found = false; String keystr = type.convertToKey(); HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr); if (objSet != null) { Iterator<GraphObject> iter = objSet.iterator(); while (iter.hasNext()) { GraphObject o = iter.next(); if (vtxOrig.compareTo(o)) { found = true; memo1.put(vtxOrig, (Node)o); } } } if (!found) { vtxCopy = this.createNode(type); vtxCopy.setObjectName(vtxOrig.getObjectName()); vtxCopy.copyAttributes(vtxOrig); vtxCopy.setContextUsage(vtxOrig .getContextUsage()); memo1.put(vtxOrig, vtxCopy); propagateChange(new Change( Change.OBJECT_CREATED, vtxCopy)); } } } catch (TypeException e) { } } Iterator<Arc> arcList = g.getArcsSet().iterator(); while (arcList.hasNext()) { Arc arcOrig = arcList.next(); Type type = this.itsTypes.getSimilarType(arcOrig.getType()); if (type == null) { type = this.itsTypes.getTypeByName(arcOrig.getType() .getName()); if (type != null && !type.isArcType()) type = null; } try { if (type != null) { Node source = (Node) arcOrig.getSource(); Node target = (Node) arcOrig.getTarget(); Node src = memo1.get(source); Node tar = memo1.get(target); boolean found = false; String keystr = src.convertToKey() + arcOrig.getType().convertToKey() + tar.convertToKey(); HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr); if (objSet != null) { Iterator<GraphObject> iter = objSet.iterator(); while (iter.hasNext()) { GraphObject o = iter.next(); if (arcOrig.compareTo(o)) { found = true; } } } if (!found) { Arc arcCopy = this.createArc(type, src, tar); arcCopy.setObjectName(arcOrig.getObjectName()); arcCopy.copyAttributes(arcOrig); arcCopy.setContextUsage(arcOrig .getContextUsage()); propagateChange(new Change( Change.OBJECT_CREATED, arcCopy)); } } } catch (TypeException e) {} } memo1.clear(); if (!failed) return true; } } return false; } public Graph copyLight(TypeSet typeSet) { synchronized (this) { TypeError typeError = null; int tglevel = typeSet.getLevelOfTypeGraphCheck(); if (tglevel == TypeSet.ENABLED_MAX_MIN) typeSet.setLevelOfTypeGraphCheck(TypeSet.ENABLED_MAX); boolean failed = false; final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this .getSize()); Graph theCopy = BaseFactory.theFactory().createGraph(typeSet); theCopy.setCompleteGraph(this.isCompleteGraph()); if ((this.getAttrContext() != null) && ((ContextView) this.getAttrContext()) .getAllowedMapping() == AttrMapping.GRAPH_MAP) { agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager .getDefaultManager().newContext( agg.attribute.AttrMapping.GRAPH_MAP); theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager .getDefaultManager().newRightContext(aGraphContext)); } Iterator<?> iter = this.itsNodes.iterator(); while (iter.hasNext()) { Node vtxOrig = (Node)iter.next(); Node vtxCopy = null; Type type = typeSet.getSimilarType(vtxOrig.getType()); if (type == null) { type = typeSet.getTypeByName(vtxOrig.getType().getName()); if (type != null && !type.isNodeType()) type = null; } if (type != null) { try { vtxCopy = theCopy.createNode(type); /** side effect! */ if (vtxCopy != null) { // check this graph against the type graph typeError = typeSet.checkType(vtxCopy, this .isCompleteGraph()); if (typeError != null) { theCopy.dispose(); throw new TypeException(typeError); } vtxCopy.setObjectName(vtxOrig.getObjectName()); if (vtxOrig.getAttribute() != null) { if (vtxCopy.getAttribute() == null) { vtxCopy.createAttributeInstance(); } ((ValueTuple) vtxCopy.getAttribute()) .copyEntriesToSimilarMembers(vtxOrig .getAttribute()); } vtxCopy.setContextUsage(vtxOrig .getContextUsage()); memo1.put(vtxOrig, vtxCopy); } } catch (TypeException e) { // e.printStackTrace(); failed = true; theCopy.dispose(); } } } iter = this.itsArcs.iterator(); while (!failed && iter.hasNext()){ Arc arcOrig = (Arc)iter.next(); Arc arcCopy = null; Type type = typeSet.getSimilarType(arcOrig.getType()); if (type == null) { type = typeSet.getTypeByName(arcOrig.getType() .getName()); if (type != null && !type.isArcType()) type = null; } if (type != null) { try { Node source = (Node) arcOrig.getSource(); Node target = (Node) arcOrig.getTarget(); Node srcImg = memo1.get(source); Node tgtImg = memo1.get(target); arcCopy = theCopy.createArc(type, srcImg, tgtImg); if (arcCopy != null) { arcCopy.setObjectName(arcOrig.getObjectName()); if (arcOrig.getAttribute() != null) { if (arcCopy.getAttribute() == null) { arcCopy.createAttributeInstance(); } ((ValueTuple) arcCopy.getAttribute()) .copyEntriesToSimilarMembers(arcOrig .getAttribute()); } arcCopy.setContextUsage(arcOrig .getContextUsage()); } } catch (TypeException e) { // e.printStackTrace(); failed = true; theCopy.dispose(); } } } if (!failed) { if (tglevel == TypeSet.ENABLED_MAX_MIN) typeSet.setLevelOfTypeGraphCheck(TypeSet.ENABLED_MAX_MIN); } memo1.clear(); if (failed) return null; return (theCopy); } } /** * Returns a copy of this graph using specified type set. * The specified type set should be compatible to its type set. */ public Graph copy(TypeSet types) { return graphcopy(types); } private Graph graphcopy(final TypeSet typeSet) { synchronized (this) { TypeError typeError = null; int tglevel = typeSet.getLevelOfTypeGraphCheck(); if (tglevel == TypeSet.ENABLED_MAX_MIN) typeSet.setLevelOfTypeGraphCheck(TypeSet.ENABLED_MAX); boolean failed = false; final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this.getSize()); Graph theCopy = BaseFactory.theFactory().createGraph(typeSet); theCopy.setCompleteGraph(this.isCompleteGraph()); if ((this.getAttrContext() != null) && ((ContextView) this.getAttrContext()) .getAllowedMapping() == AttrMapping.GRAPH_MAP) { agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager .getDefaultManager().newContext( agg.attribute.AttrMapping.GRAPH_MAP); theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager .getDefaultManager().newRightContext(aGraphContext)); } Iterator<?> iter = this.itsNodes.iterator(); while (!failed && iter.hasNext()) { Node vtxOrig = (Node)iter.next(); Node vtxCopy = null; try { Type type = typeSet.getSimilarType(vtxOrig.getType()); if (type != null) { vtxCopy = theCopy.createNode(type); /** side effect! */ if (vtxCopy != null) { // not a type graph, so check this graph // against the type graph typeError = typeSet.checkType(vtxCopy, this .isCompleteGraph()); if (typeError != null) { theCopy.dispose(); throw new TypeException(typeError); } vtxCopy.setObjectName(vtxOrig.getObjectName()); vtxCopy.copyAttributes(vtxOrig); vtxCopy.setContextUsage(vtxOrig.getContextUsage()); memo1.put(vtxOrig, vtxCopy); propagateChange(new Change(Change.OBJECT_CREATED, vtxCopy)); } } } catch (TypeException e) { // If this graph is checked, the copy should also be ok // so no Exception should happen. // e.printStackTrace(); failed = true; theCopy.dispose(); } /*************************************************************** * At loop termination, the memory hashtable contains * * information about the node twins that are induced * by the * copyprocess. At this point, the copied graph contains its * nodes but yet no arcs.* **************************************************************/ } iter = this.itsArcs.iterator(); while (!failed && iter.hasNext()) { Arc arcOrig = (Arc)iter.next(); Arc arcCopy = null; try { Type type = typeSet.getSimilarType(arcOrig.getType()); if (type != null) { Node source = (Node) arcOrig.getSource(); Node target = (Node) arcOrig.getTarget(); Node srcImg = memo1.get(source); Node tgtImg = memo1.get(target); arcCopy = theCopy.createArc(type, srcImg, tgtImg); if (arcCopy != null) { // not a type graph, so check this graph // against the type graph // typeError = typeSet.checkType(arcCopy, this // .isCompleteGraph()); // if (typeError != null) { // theCopy.dispose(); // throw new TypeException(typeError); // } arcCopy.setObjectName(arcOrig.getObjectName()); arcCopy.copyAttributes(arcOrig); arcCopy.setContextUsage(arcOrig.getContextUsage()); // propagateChange(new // Change(Change.OBJECT_CREATED,arcCopy)); } } } catch (TypeException e) { // If the given graph is well typed, // the resulting graph should be also well typed // e.printStackTrace(); failed = true; theCopy.dispose(); } } if (!failed) { if (tglevel == TypeSet.ENABLED_MAX_MIN) typeSet.setLevelOfTypeGraphCheck(TypeSet.ENABLED_MAX_MIN); // set Observers ??? // for(Iterator it = getObservers().iterator(); // it.hasNext();) // theCopy.addObserver((Observer)it.next()); } memo1.clear(); if (failed) return null; return (theCopy); } } /** * Returns a copy of this graph * * @param orig2copy * the specified table is used to store pairs (original, copy), * where an original is a node/edge of this graph and a copy * is the appropriate node/edge of the graph copy. * @return a copy of this graph or null if an error occurred */ public Graph copy(final Hashtable<GraphObject, GraphObject> orig2copy) { return graphcopy(orig2copy); } /** * Makes a copy of this graph and stores elements into the specified Hashtable. * * @param orig2copy * the table is used to store the relation of this graph to the copy. * Keys are nodes resp. edges of this graph and values are the corresponding * nodes resp. edges of the copy. * @return a copy of this graph or null if an error occurred */ private Graph graphcopy(final Hashtable<GraphObject, GraphObject> orig2copy) { synchronized (this) { int currentLevelOfTGcheck = this.getTypeSet().getLevelOfTypeGraphCheck(); if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN) this.getTypeSet().setLevelOfTypeGraph(TypeSet.ENABLED_MAX); boolean failed = false; Graph theCopy = BaseFactory.theFactory().createGraph(getTypeSet()); if ((this.getAttrContext() != null) && ((ContextView) this.getAttrContext()) .getAllowedMapping() == AttrMapping.GRAPH_MAP) { agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager .getDefaultManager().newContext( agg.attribute.AttrMapping.GRAPH_MAP); theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager .getDefaultManager().newRightContext(aGraphContext)); } Iterator<?> iter = this.itsNodes.iterator(); while (!failed && iter.hasNext()) { Node vtxOrig = (Node)iter.next(); Node vtxCopy = null; try { vtxCopy = theCopy.copyNode(vtxOrig); /** side effect! */ vtxCopy.setContextUsage(vtxOrig.getContextUsage()); orig2copy.put(vtxOrig, vtxCopy); } catch (TypeException e) { // e.printStackTrace(); failed = true; theCopy.dispose(); } } iter = this.itsArcs.iterator(); while (!failed && iter.hasNext()) { Arc arcOrig = (Arc)iter.next(); Node source = (Node) arcOrig.getSource(); Node target = (Node) arcOrig.getTarget(); Node srcImg = (Node) orig2copy.get(source); Node tgtImg = (Node) orig2copy.get(target); try { Arc arcCopy = theCopy.copyArc(arcOrig, srcImg, tgtImg); arcCopy.setContextUsage(arcOrig.getContextUsage()); orig2copy.put(arcOrig, arcCopy); } catch (TypeException e) { // e.printStackTrace(); failed = true; theCopy.dispose(); } } if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN) this.getTypeSet().setLevelOfTypeGraph(currentLevelOfTGcheck); if (!failed) { // set Observers ??? // for(Iterator it = getObservers().iterator(); // it.hasNext();) // theCopy.addObserver((Observer)it.next()); return theCopy; } return null; } } /** * Returns a copy of the graph itself. The mappings of * original nodes / arcs and copied nodes / arcs are stored in a Hashtable * of the class <code>CopyMemory</code>. The method * <code>CopyMemory.REQUEST(n)</code> returns an appropriate Hashtable. * * @param n * can be 1 or 2. */ public Graph graphcopy(int n) { synchronized (this) { int currentLevelOfTGcheck = this.getTypeSet().getLevelOfTypeGraphCheck(); if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN) this.getTypeSet().setLevelOfTypeGraph(TypeSet.ENABLED_MAX); boolean failed = false; CopyMemory.INSTALL(n); Graph theCopy = BaseFactory.theFactory().createGraph(getTypeSet()); if ((this.getAttrContext() != null) && ((ContextView) this.getAttrContext()) .getAllowedMapping() == AttrMapping.GRAPH_MAP) { agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager .getDefaultManager().newContext( agg.attribute.AttrMapping.GRAPH_MAP); theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager .getDefaultManager().newRightContext(aGraphContext)); } theCopy.setCompleteGraph(this.isCompleteGraph()); theCopy.setName(this.getName() + "_copy"); Iterator<?> iter = this.itsNodes.iterator(); while (!failed && iter.hasNext()) { Node vtxOrig = (Node)iter.next(); Node vtxCopy = null; try { vtxCopy = theCopy.newNode(vtxOrig.getType()); vtxCopy.setObjectName(vtxOrig.getObjectName()); vtxCopy.copyAttributes(vtxOrig); vtxCopy.setContextUsage(vtxOrig.getContextUsage()); CopyMemory.STORE(vtxOrig, vtxCopy, n); } catch (TypeException e) { failed = true; theCopy.dispose(); } } iter = this.itsArcs.iterator(); while (!failed && iter.hasNext()) { Arc arcOrig = (Arc)iter.next(); try { Node source = (Node) arcOrig.getSource(); Node target = (Node) arcOrig.getTarget(); Node srcImg = (Node) CopyMemory.SELECT(source, n); Node tgtImg = (Node) CopyMemory.SELECT(target, n); Arc arcCopy = theCopy.newArc(arcOrig.getType(), srcImg, tgtImg); if (arcCopy != null) { arcCopy.setObjectName(arcOrig.getObjectName()); arcCopy.copyAttributes(arcOrig); arcCopy.setContextUsage(arcOrig.getContextUsage()); CopyMemory.STORE(arcOrig, arcCopy, n); } } catch (TypeException e) { failed = true; theCopy.dispose(); } } if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN) this.getTypeSet().setLevelOfTypeGraph(currentLevelOfTGcheck); if (failed) return null; return theCopy; } } /** * The method returns a copy of the graph itself. */ public Graph graphcopy() { synchronized (this) { int currentLevelOfTGcheck = this.getTypeSet().getLevelOfTypeGraphCheck(); if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN) this.getTypeSet().setLevelOfTypeGraph(TypeSet.ENABLED_MAX); boolean failed = false; Graph theCopy = BaseFactory.theFactory().createGraph(this.itsTypes); if ((this.getAttrContext() != null) && ((ContextView) this.getAttrContext()) .getAllowedMapping() == AttrMapping.GRAPH_MAP) { agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager .getDefaultManager().newContext( agg.attribute.AttrMapping.GRAPH_MAP); theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager .getDefaultManager().newRightContext(aGraphContext)); } theCopy.setCompleteGraph(this.isCompleteGraph()); theCopy.setName(this.getName() + "_copy"); final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this.getSize()); Iterator<?> iter = this.itsNodes.iterator(); while (!failed && iter.hasNext()) { Node vtxOrig = (Node)iter.next(); Node vtxCopy = null; try { vtxCopy = theCopy.newNode(vtxOrig.getType()); vtxCopy.setObjectName(vtxOrig.getObjectName()); vtxCopy.copyAttributes(vtxOrig); vtxCopy.setContextUsage(vtxOrig.getContextUsage()); memo1.put(vtxOrig, vtxCopy); } catch (TypeException e) { failed = true; theCopy.dispose(); } } iter = this.itsArcs.iterator(); while (!failed && iter.hasNext()) { Arc arcOrig = (Arc)iter.next(); try { Node source = (Node) arcOrig.getSource(); Node target = (Node) arcOrig.getTarget(); Node srcImg = memo1.get(source); Node tgtImg = memo1.get(target); Arc arcCopy = theCopy.newArc(arcOrig.getType(), srcImg, tgtImg); if (arcCopy != null) { arcCopy.setObjectName(arcOrig.getObjectName()); arcCopy.copyAttributes(arcOrig); arcCopy.setContextUsage(arcOrig.getContextUsage()); } } catch (TypeException e) { failed = true; theCopy.dispose(); } } memo1.clear(); if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN) this.getTypeSet().setLevelOfTypeGraph(currentLevelOfTGcheck); return failed ? null : theCopy; } } /** * Returns a flat copy (without references) of this graph. */ public Graph copy() { return graphcopy(); } /** * Copy the specified Graph g into this graph.<br> * Pre-condition: this graph has to be empty and has to use the same type * set as the Graph g . */ public Graph graphcopy(Graph g) { synchronized (g) { int currentLevelOfTGcheck = this.getTypeSet().getLevelOfTypeGraphCheck(); if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN) this.getTypeSet().setLevelOfTypeGraph(TypeSet.ENABLED_MAX); boolean failed = false; final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(g.getSize()); Graph theCopy = this; if ((g.getAttrContext() != null) && ((ContextView) g.getAttrContext()).getAllowedMapping() == AttrMapping.GRAPH_MAP) { agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager .getDefaultManager().newContext( agg.attribute.AttrMapping.GRAPH_MAP); theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager .getDefaultManager().newRightContext(aGraphContext)); } Iterator<Node> vtxList = g.getNodesSet().iterator(); while (!failed && vtxList.hasNext()) { Node vtxOrig = vtxList.next(); Node vtxCopy = null; try { vtxCopy = theCopy.copyNode(vtxOrig); vtxCopy.setContextUsage(vtxOrig.getContextUsage()); memo1.put(vtxOrig, vtxCopy); } catch (TypeException e) { failed = true; } } Iterator<Arc> arcList = g.getArcsSet().iterator(); while (!failed && arcList.hasNext()) { try { Arc arcOrig = arcList.next(); Node source = (Node) arcOrig.getSource(); Node target = (Node) arcOrig.getTarget(); Node srcImg = memo1.get(source); Node tgtImg = memo1.get(target); Arc arcCopy = theCopy.copyArc(arcOrig, srcImg, tgtImg); if (arcCopy != null) arcCopy.setContextUsage(arcOrig.getContextUsage()); } catch (TypeException e) { failed = true; } } memo1.clear(); if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN) this.getTypeSet().setLevelOfTypeGraph(currentLevelOfTGcheck); if (failed) theCopy.clear(); return theCopy; } } // public OrdinaryMorphism extendByGraph(final Graph g) { // final OrdinaryMorphism map = BaseFactory.theFactory().createMorphism(g, this); // Enumeration<Node> nodes = g.getNodes(); // while (nodes.hasMoreElements()) { // Node elem= nodes.nextElement(); // try { // Node copy = this.copyNode(elem); //// System.out.println("Graph.extendByGraph:: Node copy: "+copy+" orig: "+elem); //// if (copy != null) { // map.addMapping(elem, copy); //// } //// else { //// System.out.println("Graph.extendByGraph:: Node copy: "+copy+" orig: "+elem); //// } // } // catch (TypeException ex) {} // catch (BadMappingException e) {} // } // Enumeration<Arc> arcs = g.getArcs(); // while (arcs.hasMoreElements()) { // Arc elem = arcs.nextElement(); // try { // Node s = (Node) map.getImage(elem.getSource()); // Node t = (Node) map.getImage(elem.getTarget()); // Arc copy = this.copyArc(elem, s, t); //// if (copy != null) { // map.addMapping(elem, copy); //// } //// else { //// System.out.println("Graph.extendByGraph:: Arc copy : "+copy+" src: "+s+" tar: "+t); //// System.out.println("Graph.extendByGraph:: Arc original: "+elem+" src: "+elem.getSource()+" tar: "+elem.getTarget()); //// } // } // catch (TypeException ex) {} // catch (BadMappingException e) {} // } // return map; // } /** * Prepares this graph for garbage collection, so cut all connections to * other objects and dispose all graph object contained. * @throws ClassNotFoundException */ public void dispose() { if (this.observer != null) { this.observer.clear(); this.observer.trimToSize(); super.dispose(); // dispose observer } this.itsName = "Graph"; if (this.itsUsingMorphs != null) { this.itsUsingMorphs.clear(); this.itsUsingMorphs.trimToSize(); } destroyArcs(); destroyNodes(); this.itsNodes = null; this.itsArcs = null; this.itsAttrContext = null; this.itsTypes = null; this.changed = false; // System.out.println("Graph.dispose() DONE "+this.hashCode()); } public void finalize() { } private void destroyNodes() { if (this.itsNodes != null) { Iterator<Node> iter = this.itsNodes.iterator(); while (iter.hasNext()) { this.destroyNodeFast(iter.next()); iter = this.itsNodes.iterator(); } } } private void destroyArcs() { if (this.itsArcs != null) { Iterator<Arc> iter = this.itsArcs.iterator(); while (iter.hasNext()) { this.destroyArcFast(iter.next()); iter = this.itsArcs.iterator(); } } } public final void update(Observable obs, Object change) { } public final void setName(String n) { this.itsName = n; } public final String getName() { return this.itsName; } /** * The user of AGG APIs can set help info for his own purposes. * He takes care of usage and unset this help info, too. * * @param str help info */ public void setHelpInfo(String str) { this.info = str; } public String getHelpInfo() { return this.info; } public String getHelpInfoAboutVariableEquality() { if (this.info.indexOf(":VariableEquality:") != -1) { final String[] array = this.info.split(":VariableEquality:"); if (array.length == 1) return array[0]; else if (array.length == 2) return array[1]; } return ""; } public String getHelpInfoAboutPAC() { if (this.info.indexOf(":VariableEquality:") != -1) { final String[] array = this.info.split(":VariableEquality:"); if (array.length == 2) { if (array[0].indexOf("PAC") != -1) return array[0].replaceFirst("PAC:", ""); } } else if (this.info.indexOf("PAC") != -1) { return this.info.replaceFirst("PAC:", ""); } return ""; } public String getHelpInfoAboutNAC() { if (this.info.indexOf(":VariableEquality:") != -1) { final String[] array = this.info.split(":VariableEquality:"); if (array.length == 2) { if (array[0].indexOf("NAC:") != -1) return array[0].replaceFirst("NAC:", ""); } } else if (this.info.indexOf("NAC:") != -1) { return this.info.replaceFirst("NAC:", ""); } return ""; } /** Set textual comments (description) of this graph. * This description can be used in AGG GUI. */ public void setTextualComment(String text) { this.comment = text; } /** Return textual comments of this graph. */ public String getTextualComment() { return this.comment; } /** * @deprecated moved to {@link TypeSet} * @see agg.xt_basis.Type */ public final Enumeration<Type> getTypes() { return this.itsTypes.getTypes(); } public Vector<Type> getUsedTypes() { final Vector<Type> vec = new Vector<Type>(); getTypesOfGOs(this.itsNodes.iterator(), vec); getTypesOfGOs(this.itsArcs.iterator(), vec); vec.trimToSize(); return vec; } private void getTypesOfGOs(final Iterator<?> iter, final Vector<Type> result) { while (iter.hasNext()) { GraphObject o = (GraphObject)iter.next(); if (!result.contains(o.getType())) result.add(o.getType()); } } public Vector<Type> getUsedAndInheritedTypes() { final Vector<Type> vec = new Vector<Type>(); Iterator<?> iter = this.itsNodes.iterator(); while (iter.hasNext()) { GraphObject o = (GraphObject)iter.next(); Type t = o.getType(); if (!vec.contains(t)) vec.add(t); Vector<Type> pars = t.getAllParents(); for (int i = 0; i < pars.size(); i++) { Type pt = pars.get(i); if (!vec.contains(pt)) vec.add(pt); } } iter = this.itsArcs.iterator(); while (iter.hasNext()) { GraphObject o = (GraphObject)iter.next(); Type t = o.getType(); if (!vec.contains(t)) vec.add(t); } vec.trimToSize(); return vec; } /** * Adds the specified node to my nodes. The type of the specified node has * to be in my type set. */ public void addNode(Node n) { if (!this.itsNodes.contains(n)) { this.itsNodes.add(n); addToTypeObjectsMap(n); // if (n.getAttribute() != null) { // ((ValueTuple) n.getAttribute()).addObserver(n); // } this.attributed = this.attributed || n.getAttribute() != null; this.changed = true; } } protected void removeNode(final Node n) { if (n.getContext() == this) { for (int i = 0; i < this.itsUsingMorphs.size(); i++) { this.itsUsingMorphs.get(i).removeMapping(n); } Iterator<Arc> anIter = n.getIncomingArcsSet().iterator(); while (anIter.hasNext()) { Arc aNeighbor = anIter.next(); removeArc(aNeighbor); anIter = n.getIncomingArcsSet().iterator(); } anIter = n.getOutgoingArcsSet().iterator(); while (anIter.hasNext()) { Arc aNeighbor = anIter.next(); removeArc(aNeighbor); anIter = n.getOutgoingArcsSet().iterator(); } this.itsNodes.remove(n); removeNodeFromTypeObjectsMap(n); this.changed = true; } } /** * Adds the specified edge to my edges. The type of the specified edge has * to be in my type set. */ public void addArc(Arc anArc) { if (!this.itsArcs.contains(anArc)) { this.itsArcs.add(anArc); addToTypeObjectsMap(anArc); this.attributed = this.attributed || anArc.getAttribute() != null; this.changed = true; } } protected void removeArc(final Arc a) { if (a.getContext() == this) { // remove arc from its source / target ((Node)a.getSource()).removeOut(a); ((Node)a.getTarget()).removeIn(a); for (int i = 0; i < this.itsUsingMorphs.size(); i++) { this.itsUsingMorphs.get(i).removeMapping(a); } this.itsArcs.remove(a); removeArcFromTypeObjectsMap(a); this.changed = true; } } /** * Creates and adds a new node. */ protected Node newNode(Type t) throws TypeException { Node aNode = new Node(t, this); // check for type mismatches, also multiplicity max TypeError typeError = this.itsTypes.checkType(aNode, this.isCompleteGraph()); if (typeError != null) { throw new TypeException(typeError); } this.attributed = this.attributed || aNode.getAttribute() != null; this.itsNodes.add(aNode); addToTypeObjectsMap(aNode); this.changed = true; propagateChange(new Change(Change.OBJECT_CREATED, aNode)); return aNode; } protected Node newNodeFast(Type t) { Node aNode = new Node(t, this); this.attributed = this.attributed || aNode.getAttribute() != null; this.itsNodes.add(aNode); addToTypeObjectsMap(aNode); this.changed = true; propagateChange(new Change(Change.OBJECT_CREATED, aNode)); return aNode; } /** Creates and adds a new Node of the specified type. * */ public Node createNode(Type type) throws TypeException { Type t = this.itsTypes.adoptClan(type); Node aNode = new Node(t, this); // check for type mismatches TypeError typeError = this.itsTypes.checkType(aNode, this.isCompleteGraph()); if (typeError != null) { throw new TypeException(typeError); } this.attributed = this.attributed || aNode.getAttribute() != null; this.itsNodes.add(aNode); addToTypeObjectsMap(aNode); this.changed = true; propagateChange(new Change(Change.OBJECT_CREATED, aNode)); return aNode; } /** * @deprecated use the method <code>copyNode(Node orig)</code> */ public Node createNode(Node orig) throws TypeException { Node aNode = createNode(orig.getType()); if (aNode != null) { if (orig.getAttribute() != null) { ((ValueTuple) aNode.getAttribute()).copyEntries(orig .getAttribute()); } } return aNode; } /** * Creates a new node as a copy of the specified <code>orig</code>. * Only type and attributes are copied, * the structural context (incoming/outgoing arcs) - is not. */ public Node copyNode(Node orig) throws TypeException { try { Node node = createNode(orig.getType()); if (node != null) { node.setObjectName(orig.getObjectName()); if (orig.getAttribute() != null) { node.createAttributeInstance(); ((ValueTuple) node.getAttribute()). copyEntries(orig.getAttribute()); } } else { throw new TypeException("Graph.copyNode:: Cannot create a Node of type : " +orig.getType().getStringRepr()); } return node; } catch (TypeException ex) { throw new TypeException("Graph.copyNode:: "+ex.getLocalizedMessage()); } } /** * Deletes a Node. Dangling arcs are deleted implicitly. The node is * removed from this graph and from all morphism mappings using this * node. * * @throws TypeException * If this graph is a type graph, and there are nodes of this * type node in one of other graphs, an exception is thrown. */ public void destroyNode(Node node) throws TypeException { destroyNode(node, true); } /** * Deletes a Node. Dangling arcs are deleted implicitly. The node is * removed from this graph and from all morphism mappings using this * node. * * If the specified parameter checkFirst is false, * the arc is destroyed without any checks. * * @throws TypeException * If this graph is a type graph, and there are nodes of this * type node in one of other graphs, an exception is thrown. */ public synchronized void destroyNode(Node node, boolean checkFirst) throws TypeException { destroyNode(node, checkFirst, false); } /** * Deletes a Node. Dangling arcs are deleted implicitly. The node is * removed from this graph and from all morphism mappings using this * node. * * If the specified parameter checkFirst is false, * the arc is destroyed without any checks. * * @throws TypeException * If this graph is a type graph, and there are nodes of this * type node in one of other graphs, an exception is thrown when * forceDestroy is false, otherwise - does thrown any exception. */ public synchronized void destroyNode(final Node node, boolean checkFirst, boolean forceDestroy) throws TypeException { // can we remove this node? // check for multiplicity if (checkFirst && this.isCompleteGraph() && !forceDestroy) { TypeError typeError = this.itsTypes.checkIfRemovable(node); if (typeError != null) { typeError.setContainingGraph(this); throw new TypeException(typeError); } } // remove mapping of node for (int i = 0; i < this.itsUsingMorphs.size(); i++) { OrdinaryMorphism morph = this.itsUsingMorphs.get(i); morph.removeMapping(node); } // destroy incoming/outgoing arcs Arc a; Iterator<Arc> iter = node.getIncomingArcsSet().iterator(); while (iter.hasNext()) { a = iter.next(); destroyArc(a, false, false); iter = node.getIncomingArcsSet().iterator(); } iter = node.getOutgoingArcsSet().iterator(); while (iter.hasNext()) { a = iter.next(); destroyArc(a, false, false); iter = node.getOutgoingArcsSet().iterator(); } propagateChange(new Change(Change.WANT_DESTROY_OBJECT, node)); removeNodeFromTypeObjectsMap(node); this.itsNodes.remove(node); node.dispose(); this.changed = true; propagateChange(new Change(Change.OBJECT_DESTROYED, node)); } public synchronized void destroyNodeFast(final Node node) { // remove mapping of node for (int i = 0; i < this.itsUsingMorphs.size(); i++) { this.itsUsingMorphs.get(i).removeMapping(node); } // destroy incoming arcs while (node.getIncomingArcsSet().iterator().hasNext()) { destroyArcFast(node.getIncomingArcsSet().iterator().next()); } // destroy outgoing arcs while (node.getOutgoingArcsSet().iterator().hasNext()) { destroyArcFast(node.getOutgoingArcsSet().iterator().next()); } propagateChange(new Change(Change.WANT_DESTROY_OBJECT, node)); removeNodeFromTypeObjectsMap(node); this.itsNodes.remove(node); node.dispose(); this.changed = true; propagateChange(new Change(Change.OBJECT_DESTROYED, node)); } /** * Creates and adds a new arc. */ protected Arc newArc(Type t, Node src, Node tar) throws TypeException { TypeError typeError = this.checkConnectValid(t, src, tar); if (typeError != null) { throw new TypeException(typeError); } Arc anArc = new Arc(t, src, tar, this); anArc.setDirected(!(this instanceof UndirectedGraph)); // check for type mismatches, also multiplicity max of source and target typeError = this.itsTypes.checkType(anArc, this.isCompleteGraph()); if (typeError != null) { ((Node)anArc.getSource()).removeOut(anArc); ((Node)anArc.getTarget()).removeIn(anArc); throw new TypeException(typeError); } this.attributed = this.attributed || anArc.getAttribute() != null; this.itsArcs.add(anArc); addToTypeObjectsMap(anArc); this.changed = true; propagateChange(new Change(Change.OBJECT_CREATED, anArc)); return anArc; } protected Arc newArcFast(Type t, Node src, Node tar) { // long time = System.nanoTime(); Arc anArc = new Arc(t, src, tar, this); anArc.setDirected(!(this instanceof UndirectedGraph)); this.attributed = this.attributed || anArc.getAttribute() != null; this.itsArcs.add(anArc); addToTypeObjectsMap(anArc); this.changed = true; propagateChange(new Change(Change.OBJECT_CREATED, anArc)); // System.out.println("Arc created in: "+(System.nanoTime()-time)+"nano"); return anArc; } /** * Creates and add a new Arc of the specified type, source and target nodes, * which must be part of this graph. */ public Arc createArc(Type type, Node src, Node tar) throws TypeException { if (src == null || tar == null) { throw new TypeException("Graph.createArc:: Cannot create an Arc of type : "+type.getStringRepr()+" Source or target node is null!"); } else if (!this.isNode(src) || !this.isNode(tar)) { throw new TypeException("Graph.createArc:: Cannot create an Arc of type : "+type.getStringRepr()+" Source or target is not a Node!"); } Type t = null; if (this.itsTypes.containsType(type)) t = type; if (t == null) { t = this.itsTypes.getSimilarType(type); if (t == null) t = this.itsTypes.addType(type); if (t.getAdditionalRepr().indexOf("[EDGE]") == -1) t.setAdditionalRepr("[EDGE]"); } TypeError typeError = this.checkConnectValid(t, src, tar); if (typeError != null) { throw new TypeException(typeError); } Arc anArc = new Arc(t, src, tar, this); anArc.setDirected(!(this instanceof UndirectedGraph)); // if this is not a type graph, so check this graph // against its type graph typeError = this.itsTypes.checkType(anArc, this.isCompleteGraph()); if (typeError != null) { ((Node)anArc.getSource()).removeOut(anArc); ((Node)anArc.getTarget()).removeIn(anArc); throw new TypeException(typeError); } this.attributed = this.attributed || anArc.getAttribute() != null; this.itsArcs.add(anArc); addToTypeObjectsMap(anArc); this.changed = true; propagateChange(new Change(Change.OBJECT_CREATED, anArc)); return anArc; } /** * Creates a new Arc as a copy of the <code>orig</code>. * Only its type and attributes are copied, * the structural context (source, target) - is not. * The specified source <code>src</code> and target <code>tar</code> objects * must be a part of this graph, but this is not checked here. */ public Arc copyArc(final Arc orig, final Node src, final Node tar) throws TypeException { Arc arc = null; try { arc = createArc(orig.getType(), src, tar); if (arc != null) { arc.setDirected(!(this instanceof UndirectedGraph)); arc.setObjectName(orig.getObjectName()); if (orig.getAttribute() != null) { arc.createAttributeInstance(); ((ValueTuple) arc.getAttribute()).copyEntries(orig .getAttribute()); } } else { throw new TypeException("Graph.copyArc:: Cannot create an Arc of type : " +orig.getType().getName()); } } catch (TypeException ex) { if (src != null && tar != null) { throw new TypeException(" " +orig.getType().getName() +" from "+src.getType().getName() +" to "+tar.getType().getName() +" "+ex.getLocalizedMessage()); } throw new TypeException(ex.getLocalizedMessage()); } return arc; } /** * Deletes the specified arc. The arc will be removed from this graph and * from all morphism mappings with this arc. * * @throws TypeException * If this graph is a type graph, and there are arcs of this * type arc in one of other graphs, an exception is thrown. */ public void destroyArc(Arc arc) throws TypeException { destroyArc(arc, true, false); } /** * Deletes the specified arc. The arc will be removed from this graph and * from all morphism mappings with this arc. * * If the specified parameter checkFirst is false, * the arc is destroyed without any checks. * * @throws TypeException * If this graph is a type graph, and there are arcs of this * type arc in one of other graphs, an exception is thrown. */ public synchronized void destroyArc(Arc arc, boolean checkFirst) throws TypeException { destroyArc(arc, checkFirst, false); } /** * Deletes the specified arc. The arc will be removed from this graph and * from all morphism mappings with this arc. * * If the specified parameter checkFirst is false, * the arc is destroyed without any checks. * * @throws TypeException * If this graph is a type graph, and there are arcs of this * type arc in one of other graphs, an exception is thrown when * forceDestroy is false, otherwise - does thrown any exception. */ public synchronized void destroyArc( final Arc arc, final boolean checkFirst, final boolean forceDestroy) throws TypeException { if (arc != null) { // can we remove this arc? // check for multiplicity if (checkFirst && this.isCompleteGraph() && !forceDestroy) { TypeError typeError = this.itsTypes.checkIfRemovable(arc); if (typeError != null) { typeError.setContainingGraph(this); throw new TypeException(typeError); } } propagateChange(new Change(Change.WANT_DESTROY_OBJECT, arc)); // remove mapping of arc for (int i = 0; i < this.itsUsingMorphs.size(); i++) { OrdinaryMorphism morph = this.itsUsingMorphs.get(i); morph.removeMapping(arc); } removeArcFromTypeObjectsMap(arc); this.itsArcs.remove(arc); arc.dispose(); this.changed = true; propagateChange(new Change(Change.OBJECT_DESTROYED, arc)); } } public synchronized void destroyArcFast(final Arc arc) { propagateChange(new Change(Change.WANT_DESTROY_OBJECT, arc)); // remove mapping of arc for (int i = 0; i < this.itsUsingMorphs.size(); i++) { this.itsUsingMorphs.get(i).removeMapping(arc); } removeArcFromTypeObjectsMap(arc); // long t0 = System.nanoTime(); this.itsArcs.remove(arc); // System.out.println(this.itsArcs.size()+") "+(System.nanoTime()-t0)+" nano"); arc.dispose(); this.changed = true; propagateChange(new Change(Change.OBJECT_DESTROYED, arc)); } public void destroyObject(GraphObject obj) throws TypeException { if (obj.isNode()) { destroyNode((Node) obj, true, false); } else if (obj.isArc()) { destroyArc((Arc) obj, true, false); } } public void forceDestroyObject(GraphObject obj) throws TypeException { if (obj.isNode()) { destroyNode((Node) obj, true, true); } else if (obj.isArc()) { destroyArc((Arc) obj, true, true); } } public boolean destroyObjectsOfType(Type t) { boolean done = false; Iterator<?> iter = this.itsArcs.iterator(); while (iter.hasNext()) { Arc o = (Arc)iter.next(); if (o.getType().compareTo(t)) { try { destroyArc(o, false, true); done = true; } catch (TypeException e) { System.out.println("Graph.destroyObjectsOfType FAILED! " + e.getMessage()); } } } if (done) return true; iter = this.itsNodes.iterator(); while (iter.hasNext()) { Node o = (Node)iter.next(); if (t.isParentOf(o.getType())) { try { destroyNode(o, false, true); done = true; } catch (TypeException e) { System.out.println("Graph.destroyObjectsOfType FAILED! " + e.getMessage()); } } } return done; } /** * * @param types * @return null if destroy was successful, otherwise a list with failed types */ public Vector<String> destroyObjectsOfTypes(Vector<Type> types) { Vector<String> failed = null; for (int i = 0; i < types.size(); i++) { Type t = types.get(i); if (!destroyObjectsOfType(t)) { if (failed == null) failed = new Vector<String>(5); failed.add("Graph: ".concat(this.itsName).concat(" Type: ").concat(t.getName())); } } return failed; } public HashSet<Node> getNodesSet() { return this.itsNodes; } public Collection<Node> getNodesCollection() { return this.itsNodes; } /** * @deprecated replaced by <code>HashSet<Node> getNodesSet()</code> */ public Enumeration<Node> getNodes() { return this.itsNodes.elements(); } /** * @deprecated replaced by <code>HashSet<Node> getNodesSet()</code> */ public List<Node> getNodesList() { return this.itsNodes.list(); } public int getNodesCount() { return this.itsNodes.size(); } public HashSet<Arc> getArcsSet() { return this.itsArcs; } public Collection<Arc> getArcsCollection() { return this.itsArcs; } /** * @deprecated replaced by <code>HashSet<Arc> getArcsSet()</code> */ public Enumeration<Arc> getArcs() { return this.itsArcs.elements(); } /** * @deprecated replaced by <code>HashSet<Arc> getArcsSet()</code> */ public List<Arc> getArcsList() { return this.itsArcs.list(); } public int getArcsCount() { return this.itsArcs.size(); } /** * Returns edges between specified source and target objects, otherwise null. */ public Vector<Arc> getArcs(final GraphObject src, final GraphObject tar) { Vector<Arc> res = null; Iterator<Arc> outs = ((Node)src).getOutgoingArcsSet().iterator(); while (outs.hasNext()) { Arc go = outs.next(); if (go.getTarget() == tar) { if (res == null) res = new Vector<Arc>(); res.add(go); } } return res; } /** * Returns nodes of the specified type, otherwise null. */ public List<Node> getNodes(final Type t) { Vector<Node> res = null; Iterator<Node> iter = this.itsNodes.iterator(); while (iter.hasNext()) { Node go = iter.next(); if (t.isParentOf(go.getType())) { if (res == null) res = new Vector<Node>(); res.add(go); } } return res; } /** * Iterate through my nodes to find related nodes of the specified type. */ public Vector<Node> getNodesByParentType(final Type t) { Vector<Node> res = null; Iterator<Node> iter = this.itsNodes.iterator(); while (iter.hasNext()) { Node go = iter.next(); if (t.isParentOf(go.getType())) { if (res == null) res = new Vector<Node>(); res.add(go); } } return res; } /** * Iterate through my nodes to find nodes with type equal to the specified type. * Otherwise returns null. */ public Vector<Node> getNodesByCompareType(final Type t) { Vector<Node> res = null; Iterator<Node> iter = this.itsNodes.iterator(); while (iter.hasNext()) { Node go = iter.next(); if (go.getType().compareTo(t)) { if (res == null) res = new Vector<Node>(); res.add(go); } } return res; } /** * Iterate through my edges to find edges of the specified type between the * specified source and target. Otherwise returns null. */ public Vector<Arc> getArcs(final Type t, final GraphObject src, final GraphObject tar) { Vector<Arc> res = null; Iterator<Arc> outs = ((Node)src).getOutgoingArcsSet().iterator(); while (outs.hasNext()) { Arc go = outs.next(); if ( (go.getTarget() == tar) && go.getType().compareTo(t) //&& go.getType().isRelatedTo(t) ) { if (res == null) res = new Vector<Arc>(); res.add(go); } } return res; } /** * Iterate through my edges to find edges of the specified type. * Otherwise returns null. */ public Vector<Arc> getArcs(final Type type) { Vector<Arc> res = null; Iterator<Arc> iter = this.itsArcs.iterator(); while (iter.hasNext()){ Arc obj = iter.next(); if(obj.getType().compareTo(type)) { if (res == null) res = new Vector<Arc>(); res.add(obj); } } return res; } /** * Returns type names of nodes and edges of this graph. * If a type is unnamed, returns "[UNNAMED_NODE]" or "[UNNAMED_EDGE]". * The order of the type names is the order of the node * and edges of this graph. */ public Vector<String> getTypeNamesOfGraphObjects() { final Vector<String> v = new Vector<String>(getSize()); getTypeNamesOfGOs(this.itsNodes.iterator(), v); getTypeNamesOfGOs(this.itsArcs.iterator(), v); return v; } private void getTypeNamesOfGOs(final Iterator<?> iter, final Vector<String> result) { while (iter.hasNext()) { GraphObject o = (GraphObject)iter.next(); String goname = o.getType().getName(); if (goname.equals("")) goname = "[UNNAMED_NODE]"; result.add(goname); } } /** * Iterate through my nodes and arcs. * * @see agg.xt_basis.GraphObject */ public Enumeration<GraphObject> getElements() { Vector<GraphObject> elems = new Vector<GraphObject>(this.itsNodes); elems.addAll(this.itsArcs); return elems.elements(); } /** * Iterate through my nodes and arcs to find all elements of type with * specified typeName. * * @see agg.xt_basis.GraphObject */ public Enumeration<GraphObject> getElementsOfType(final String typeName) { return getElementsOfTypeAsVector(typeName).elements(); } /** * Iterate through my Nodes and Arcs to find all elements of type with * specified typeName. * * @see agg.xt_basis.GraphObject */ public Vector<GraphObject> getElementsOfTypeAsVector(final String typeName) { final Vector<GraphObject> elems = new Vector<GraphObject>(); if (!this.getElemsOfTypeName(typeName, this.itsNodes.iterator(), elems)) this.getElemsOfTypeName(typeName, this.itsArcs.iterator(), elems); return elems; } private boolean getElemsOfTypeName( final String typeName, final Iterator<?> iter, final Vector<GraphObject> result) { while (iter.hasNext()){ GraphObject obj = (GraphObject)iter.next(); if(obj.getType().getName().equals(typeName)) result.addElement(obj); } return !result.isEmpty(); } /** * Iterate through my nodes and arcs to find all elements of type with * specified type. * * @see agg.xt_basis.GraphObject */ public Enumeration<GraphObject> getElementsOfType(final Type type) { return getElementsOfTypeAsVector(type).elements(); } /** * Iterate through my Nodes and Arcs to find all elements of type with * specified type. * @see agg.xt_basis.GraphObject */ public Vector<GraphObject> getElementsOfTypeAsVector(final Type type) { final Vector<GraphObject> elems = new Vector<GraphObject>(); if (!this.getElemsOfType(type, this.itsNodes.iterator(), elems)) this.getElemsOfType(type, this.itsArcs.iterator(), elems); return elems; } private boolean getElemsOfType( final Type type, final Iterator<?> iter, final Vector<GraphObject> result) { while (iter.hasNext()){ GraphObject obj = (GraphObject)iter.next(); if(obj.getType().compareTo(type)) result.addElement(obj); } return !result.isEmpty(); } public Vector<GraphObject> getElementsOfTypeAsVector(final Type type, final boolean withChildren) { final Vector<GraphObject> elems = new Vector<GraphObject>(); Iterator<?> iter = this.itsNodes.iterator(); while (iter.hasNext()) { Node obj = (Node)iter.next(); if (obj.getType().compareTo(type) || (withChildren && obj.getType().isChildOf(type))) { elems.addElement(obj); } } if(!elems.isEmpty()) { return elems; } iter = this.itsArcs.iterator(); while (iter.hasNext()) { Arc obj = (Arc)iter.next(); if(obj.getType().compareTo(type)) { elems.addElement(obj); } } return elems; } /** * Iterate through my arcs to find all elements of type with specified * type, source and target. * * @see agg.xt_basis.GraphObject */ public Enumeration<GraphObject> getElementsOfType(Type type, Type src, Type tar) { return getElementsOfTypeAsVector(type, src, tar).elements(); } /** * Iterate through my edges to find all edges of the specified type. For * all these edges holds: the source is of the specified src type and the * target is of the specified tar type. * * @see agg.xt_basis.GraphObject */ public Vector<GraphObject> getElementsOfTypeAsVector(final Type type, final Type src, final Type tar) { final Vector<GraphObject> elems = new Vector<GraphObject>(); Iterator<Arc> iter = this.itsArcs.iterator(); while (iter.hasNext()) { Arc obj = iter.next(); if (obj.getType().compareTo(type) && (obj.getSource().getType().compareTo(src) || obj.getSource().getType().isChildOf(src)) && (obj.getTarget().getType().compareTo(tar) || obj.getTarget().getType().isChildOf(tar))) { elems.addElement(obj); } } return elems; } /** * Iterate through my Nodes and Arcs * to find all elements of type with * specified type. * * @see agg.xt_basis.GraphObject */ public Enumeration<GraphObject> getElementsOfType(final GraphObject type) { return getElementsOfTypeAsVector(type).elements(); } /** * Iterate through my Nodes and Arcs to find all elements of type with * specified type. * * @see agg.xt_basis.GraphObject */ public Vector<GraphObject> getElementsOfTypeAsVector(final GraphObject type) { Vector<GraphObject> elems = new Vector<GraphObject>(); if (type.isNode()) { elems = getElementsOfTypeAsVector(type.getType()); if (!elems.isEmpty()) return elems; } else { elems = getElementsOfTypeAsVector(type.getType(), ((Arc) type) .getSource().getType(), ((Arc) type).getTarget().getType()); if (!elems.isEmpty()) return elems; } return elems; } public void setAttrContext(AttrContext context) { this.itsAttrContext = context; } public AttrContext getAttrContext() { return this.itsAttrContext; } public AttrManager getAttrManager() { return AttrTupleManager.getDefaultManager(); } public void createAttrInstanceWhereNeeded() { Iterator<Node> iterNodes = this.itsNodes.iterator(); while (iterNodes.hasNext()) { Node go = iterNodes.next(); if ((!go.getType().isAttrTypeEmpty() || !go.getType().isParentAttrTypeEmpty()) && go.getAttribute() == null) { go.createAttributeInstance(); } } Iterator<Arc> iterArcs = this.itsArcs.iterator(); while (iterArcs.hasNext()) { Arc go = iterArcs.next(); if (!go.getType().isAttrTypeEmpty() && go.getAttribute() == null) { go.createAttributeInstance(); } } } public void createAttrInstanceOfTypeWhereNeeded(final Type t) { Iterator<Node> iterNodes = this.itsNodes.iterator(); while (iterNodes.hasNext()) { Node go = iterNodes.next(); if ((go.getType() == t || t.isParentOf(go.getType())) && (!t.isAttrTypeEmpty() || !t.isParentAttrTypeEmpty()) && go.getAttribute() == null) { go.createAttributeInstance(); } } Iterator<Arc> iterArcs = this.itsArcs.iterator(); while (iterArcs.hasNext()) { Arc go = iterArcs.next(); if (go.getType() == t && !t.isAttrTypeEmpty() && go.getAttribute() == null) { go.createAttributeInstance(); } } } protected void propagateChange(agg.util.Change ch) { if (this.notificationRequired) { setChanged(); notifyObservers(ch); } } /** * Stores the specified morphism if it is its source or target graph. * @param m */ public void addUsingMorph(OrdinaryMorphism m) { this.itsUsingMorphs.add(m); } /** * Removes the specified morphism from stored morphisms. */ public boolean removeUsingMorph(final OrdinaryMorphism m) { return this.itsUsingMorphs.remove(m); } public boolean isEmpty() { return this.itsNodes.isEmpty(); } /** Returns <code>true</code> if it contains the specified graph object. */ public boolean isElement(GraphObject obj) { if (this.itsNodes == null) { System.out.println(this.itsName); } if (obj.getContext() == this) return true; else return false; } /** Returns <code>true</code> if its nodes contain the specified node. */ public boolean isNode(Node obj) { return this.itsNodes.contains(obj); } /** Returns <code>true</code> if its arcs contain the specified arc. */ public boolean isArc(Arc obj) { return this.itsArcs.contains(obj); } /** Returns <code>true</code> if this graph uses the specified type. */ public boolean isUsingType(GraphObject t) { if (t.isArc()) { boolean hasTypeGraphArc = this.getTypeSet().getTypeGraphArc( t.getType(), ((Arc) t).getSource().getType(), ((Arc) t).getTarget().getType()) != null ? true : false; Iterator<Arc> iter = this.itsArcs.iterator(); while (iter.hasNext()) { Arc o = iter.next(); if (hasTypeGraphArc) { if (o.getType().compareTo(t.getType()) && ((o.getSource().getType().compareTo(((Arc) t) .getSource().getType())) || (o.getSource() .getType().isChildOf(((Arc) t).getSource() .getType()))) && ((o.getTarget().getType().compareTo(((Arc) t) .getTarget().getType())) || (o.getTarget() .getType().isChildOf(((Arc) t).getTarget() .getType())))) { return true; } } else if (o.getType().compareTo(t.getType())) { return true; } } } else { while (this.itsNodes.iterator().hasNext()) { Node o = this.itsNodes.iterator().next(); if (o.getType().compareTo(t.getType())) return true; else if (o.getType().isChildOf(t.getType())) return true; } } return false; } public boolean isUsingType(Type t) { return doesUseType(t, this.itsNodes.iterator()) || doesUseType(t, this.itsArcs.iterator()); } private boolean doesUseType(final Type t, final Iterator<?> iter) { while (iter.hasNext()) { GraphObject go = (GraphObject)iter.next(); if (go.getType().compareTo(t)) return true; else if (go.getType().isChildOf(t)) return true; } return false; } public boolean isUsingVariable(VarMember v) { return this.doUseVar(v, this.itsNodes.iterator()) || this.doUseVar(v, this.itsArcs.iterator()); } private boolean doUseVar(final VarMember v, final Iterator<?> iter) { while (iter.hasNext()){ GraphObject go = (GraphObject)iter.next(); if (go.getAttribute() == null) continue; ValueTuple val = (ValueTuple) go.getAttribute(); for (int j = 0; j < val.getSize(); j++) { ValueMember mem = val.getValueMemberAt(j); if (mem.getExpr() != null) { if (mem.getExpr().isVariable()) { if (mem.getDeclaration().getTypeName().equals( v.getDeclaration().getTypeName()) && mem.getExprAsText().equals(v.getName())) return true; } else if (mem.getExpr().isComplex()) { if (mem.getAllVariableNamesOfExpression().contains( v.getName())) return true; } } } } return false; } /** * Delete all of my graph objects. * <p> * <b>Post:</b> <code>isEmpty()</code>* */ public void clear() { this.changed = false; this.itsUsingMorphs.clear(); this.destroyArcs(); this.destroyNodes(); propagateChange(new Change(Change.OBJECT_DESTROYED, null)); } /** * Tries to glue two graph objects. * The context of the graph object to keep will be extended * by out- and in-edges of the glue object. * The unset attributes of the keep object will get the attribute value * of the glue object if it is a constant. * At the end the glue object will be destroyed. */ public synchronized boolean glue( final GraphObject keep, final GraphObject glue) throws TypeException { return glue(keep, glue, null); } public synchronized boolean glue( final GraphObject keep, final GraphObject glue, final GraphObject targetObj) throws TypeException { if (keep.equals(glue)) { return true; } if ((glue == null) || !glue.getType().isParentOf(keep.getType())) { // if (!keep.getType().compareTo(glue.getType())) { return false; } // System.out.println("Graph.glue: keep: "+keep.getType().getName()+" glue: "+glue.getType().getName()); if (keep.isArc() && (!glue(((Arc) keep).getSource(), ((Arc) glue).getSource()) || !glue(((Arc) keep).getTarget(), ((Arc) glue).getTarget()))) { return false; } // check attr. value if (keep.getAttribute() != null && glue.getAttribute() != null) { for (int i = 0; i < ((ValueTuple) keep.getAttribute()) .getNumberOfEntries(); i++) { ValueMember amKeep = ((ValueTuple) keep.getAttribute()) .getValueMemberAt(i); ValueMember amGlue = ((ValueTuple) glue.getAttribute()) .getValueMemberAt(amKeep.getName()); if (amKeep.isSet() && amGlue != null && amGlue.isSet()) { if (amKeep.getExpr().isConstant()) { if (amGlue.getExpr().isConstant()) { if (targetObj != null) { ValueMember tarVal = ((ValueTuple) targetObj.getAttribute()) .getValueMemberAt(amKeep.getName()); if (tarVal != null && !tarVal.isSet() && !amKeep.getExprAsText().equals(amGlue.getExprAsText())) { throw new TypeException("Graph.glue: Checking attribute constant values of objects to glue failed!"); // return false; } } else if (!amKeep.getExprAsText().equals(amGlue.getExprAsText())) { throw new TypeException("Graph.glue: Checking attribute constant values of objects to glue failed!"); // return false; } } } else if (amKeep.getExpr().isVariable()) { // if ((amGlue.getExpr().isConstant() // || amGlue.getExpr().isVariable())) // ; } else { throw new TypeException("Graph.glue: Checking attribute (expresion) values of objects to glue failed!"); // return false; } } } } if (glue.isNode()) { // Move Incoming Arcs context from "glue" to "keep" // Inverse relations are implicitly updated final List<Arc> incoms = new Vector<Arc> (((Node)glue).getIncomingArcsSet()); for (int i=0; i<incoms.size(); i++) { Arc arc = incoms.get(i); if ((this.itsTypes.checkIfRemovableFromTarget(arc) == null) && (this.itsTypes.checkIfEdgeCreatable(arc.getType(), (Node) arc .getSource(), (Node) keep) == null)) { propagateChange(new Change(Change.TARGET_UNSET, arc)); arc.setTarget((Node) keep); propagateChange(new Change(Change.TARGET_SET, arc)); } else { throw new TypeException("Graph.glue: Checking arcs (type multiplicity) to glue failed!"); // return false; } } incoms.clear(); // Move Outgoing Arcs context from "glue" to "keep" final List<Arc> outcoms = new Vector<Arc> (((Node)glue).getOutgoingArcsSet()); for (int i=0; i<outcoms.size(); i++) { Arc arc = outcoms.get(i); if ((this.itsTypes.checkIfRemovableFromSource(arc) == null) && (this.itsTypes.checkIfEdgeCreatable(arc.getType(), (Node) keep, (Node) arc.getTarget()) == null)) { propagateChange(new Change(Change.SOURCE_UNSET, arc)); arc.setSource((Node) keep); propagateChange(new Change(Change.SOURCE_SET, arc)); } else { throw new TypeException("Graph.glue: Checking arcs (type multiplicity) to glue failed!"); // return false; } } outcoms.clear(); } // set attr. value if (keep.getAttribute() != null && glue.getAttribute() != null) { for (int i = 0; i < ((ValueTuple) keep.getAttribute()) .getNumberOfEntries(); i++) { ValueMember amKeep = ((ValueTuple) keep.getAttribute()) .getValueMemberAt(i); ValueMember amGlue = ((ValueTuple) glue.getAttribute()) .getValueMemberAt(i); if ((!amKeep.isSet() || amKeep.getExpr().isVariable()) && (amGlue != null && amGlue.isSet() && amGlue.getExpr().isConstant())) { amKeep.setExprAsText(amGlue.getExprAsText()); } } } // propagateChange(new Change(Change.OBJECT_GLUED, // new Pair<GraphObject, GraphObject>(keep, glue))); try { if (glue.isNode()) this.destroyNode((Node) glue, true, false); else this.destroyArc((Arc) glue, true, false); propagateChange(new Change(Change.OBJECT_DESTROYED, glue)); } catch (TypeException e) { // must not happened, because we removed all relations, // so the glue object should be removable throw e; //return false; } return true; } /** * Returns false if not all attributes of its graph objects are set, * otherwise - true. */ public boolean isReadyForTransform() { return (isAttributeSet(this.itsNodes.iterator(), null) && isAttributeSet(this.itsArcs.iterator(), null)); } protected boolean isAttributeSet( final Iterator<?> iter, final Vector<GraphObject> storeOfFailedObjs) { boolean failed = false; while (iter.hasNext() && !failed) { GraphObject o = (GraphObject)iter.next(); if (o.getAttribute() == null) { if ((o.getType().getAttrType() != null) && (o.getType().getAttrType().getNumberOfEntries() != 0)) { o.createAttributeInstance(); this.attributed = true; } else continue; } if (o.isNode()) failed = !applyDefaultAttrValuesOfTypeGraph((Node)o, storeOfFailedObjs); else failed = !applyDefaultAttrValuesOfTypeGraph((Arc)o, storeOfFailedObjs); } return !failed; } public GraphObject getObjectWithVariableOfAttrs(VarMember v) { Iterator<Node> niter = this.itsNodes.iterator(); while (niter.hasNext()) { Node n = niter.next(); if (n.getAttribute() != null) { AttrInstance attrs = n.getAttribute(); for (int i=0; i<attrs.getNumberOfEntries(); i++) { ValueMember val = (ValueMember)attrs.getMemberAt(i); if (val.getExpr() != null && val.getExprAsText().equals(v.getName())) { return n; } } } } Iterator<Arc> aiter = this.itsArcs.iterator(); while (aiter.hasNext()) { Arc a = aiter.next(); if (a.getAttribute() != null) { AttrInstance attrs = a.getAttribute(); for (int i=0; i<attrs.getNumberOfEntries(); i++) { ValueMember val = (ValueMember)attrs.getMemberAt(i); if (val.getExpr() != null && val.getExprAsText().equals(v.getName())) { return a; } } } } return null; } protected boolean applyDefaultAttrValuesOfTypeGraph(final Node go, final Vector<GraphObject> storeOfFailedObjs) { final Node typeNode = go.getType().getTypeGraphNodeObject(); if (typeNode != null && typeNode.getAttribute() != null) { final ValueTuple value = (ValueTuple) go.getAttribute(); // search all parents for default attribute value final Vector<Type> itsParents = go.getType().getAllParents(); for (int p=0; p<itsParents.size(); p++) { final Node pNode = itsParents.get(p).getTypeGraphNodeObject(); if (pNode != null) { final ValueTuple pNodeAttr = (ValueTuple) pNode.getAttribute(); if (pNodeAttr == null) { continue; } for (int i = 0; i < value.getSize(); i++) { ValueMember vm = value.getValueMemberAt(i); if (!vm.isSet()) { ValueMember pnvm = pNodeAttr.getValueMemberAt(vm.getName()); if (pnvm != null && pnvm.isSet()) { vm.setExpr(pnvm.getExpr()); } } } } } if (!this.getTypeSet().isEmptyAttrAllowed()) { // check for not set attribute for (int i = 0; i < value.getSize(); i++) { ValueMember vm = value.getValueMemberAt(i); if (!vm.isSet()) { if (storeOfFailedObjs != null) storeOfFailedObjs.add(go); else return false; } } } } return true; } protected boolean applyDefaultAttrValuesOfTypeGraph(final Arc go, final Vector<GraphObject> storeOfFailedObjs) { final Arc typeArc = go.getType().getTypeGraphArcObject(go.getSourceType(), go.getTargetType()); if (typeArc != null && typeArc.getAttribute() != null) { final ValueTuple typeValue = (ValueTuple) typeArc.getAttribute(); final ValueTuple value = (ValueTuple) go.getAttribute(); for (int i = 0; i < value.getSize(); i++) { ValueMember vm = value.getValueMemberAt(i); if (!vm.isSet()) { ValueMember typevm = typeValue.getValueMemberAt(vm.getName()); if (typevm != null && typevm.isSet()) { vm.setExprAsText(typevm.getExprAsText()); } } } // search for not set attribute value and return false if found for (int i = 0; i < value.getSize(); i++) { ValueMember vm = value.getValueMemberAt(i); if (!vm.isSet()) { if (storeOfFailedObjs != null) storeOfFailedObjs.add(go); else return false; } } } return true; } /** * Returns false if not all attributes of its graph objects are set, * otherwise - true. The specified Vector * <code>storeOfFailedObjs</code> will contain nodes and edges which are * not initialized completely. */ public boolean isReadyForTransform(final Vector<GraphObject> storeOfFailedObjs) { return isAttributeSet(this.itsNodes.iterator(), storeOfFailedObjs) && isAttributeSet(this.itsArcs.iterator(), storeOfFailedObjs); } public boolean isIsomorphicTo(Graph g) { final OrdinaryMorphism h = this.getIsomorphicWith(g); if (h == null) return false; return true; } /** * Tries to compute an isomorphic morphism * of this graph into the specified graph g. * * @param g * is target graph of the result morphism * @return an isomorphic morphism or null. */ public OrdinaryMorphism getIsomorphicWith(final Graph g) { if (this.getNodesCount() != g.getNodesCount() || this.getArcsCount() != g.getArcsCount()) { return null; } boolean result = false; OrdinaryMorphism h = BaseFactory.theFactory().createMorphism(this, g); h.setCompletionStrategy(new Completion_InjCSP()); if (h.nextCompletion()) { result = true; // additionally, check type of source - target nodes in case of // Typegraph with Node Type Inheritance if (this.getTypeSet().getTypeGraph() != null // && this.getTypeSet().getLevelOfTypeGraphCheck() >= TypeSet.ENABLED && this.getTypeSet().hasInheritance()) { Iterator<Node> origs = this.itsNodes.iterator(); while (origs.hasNext() && result) { final Node orig = origs.next(); if (!orig.getType().compareTo(h.getImage(orig).getType())) { result = false; } } } } if (!result) { h.dispose(); h = null; } return h; } /** * Tries to compute isomorphic morphisms of this graph into the * specified graph. * * @param g * the target graph of a morphism * @param map * contains morphism mappings : keys are elements of * this graph, values are elements of the graph g. * * @return computed isomorphic morphisms or null */ public Vector<OrdinaryMorphism> getIsomorphicWith(final Graph g, final Hashtable<GraphObject, GraphObject> map) { // fast test if (this.getNodesCount() != g.getNodesCount() || this.getArcsCount() != g.getArcsCount()) { return null; } final Vector<OrdinaryMorphism> isos = new Vector<OrdinaryMorphism>(5); // try to get an isomorphism OrdinaryMorphism h = BaseFactory.theFactory().createMorphism(this, g); h.setCompletionStrategy(new Completion_InjCSP()); // set mappings Enumeration<GraphObject> keys = map.keys(); while (keys.hasMoreElements()) { GraphObject o = keys.nextElement(); GraphObject i = map.get(o); if (o != null && i != null) { try { h.addMapping(o, i); } catch (BadMappingException exc) {} } } // make possible completions while (h.nextCompletion()) { boolean result = true; // additionally, check type of source - target nodes in case of // Typegraph with Node Type Inheritance if (this.getTypeSet().getTypeGraph() != null && this.getTypeSet().getLevelOfTypeGraphCheck() >= TypeSet.ENABLED && this.getTypeSet().hasInheritance()) { Iterator<Node> origs = this.itsNodes.iterator(); while (origs.hasNext() && result) { final Node orig = origs.next(); if (!orig.getType().compareTo(h.getImage(orig).getType())) { result = false; } } } if (result) { // store this completion OrdinaryMorphism m = BaseFactory.theFactory().createMorphism(this, g); Enumeration<GraphObject> e = h.getDomain(); while (e.hasMoreElements()) { GraphObject o = e.nextElement(); m.addMapping(o, h.getImage(o)); } isos.add(m); } } return isos.isEmpty() ? null : isos; } /** * Tries to compute all isomorphic morphisms * of this graph into the specified graph g. * * @param g * is target graph of morphisms * @param all * is true - compute all possible isomorphic morphisms, * otherwise - only first one. * @return computed isomorphic morphisms or null */ public Vector<OrdinaryMorphism> getIsomorphicWith(final Graph g, final boolean all) { Vector<OrdinaryMorphism> allIsos = new Vector<OrdinaryMorphism>(5); if (!all) { OrdinaryMorphism h = getIsomorphicWith(g); if (h != null) { allIsos.add(h); } return allIsos; } if ((this.getNodesCount() != g.getNodesCount()) || (this.getArcsCount() != g.getArcsCount())) { return null; } OrdinaryMorphism h = BaseFactory.theFactory().createMorphism(this, g); h.setCompletionStrategy(new Completion_InjCSP()); // make possible completions while (h.nextCompletion()) { boolean result = true; // additionally, check type of source - target nodes in case of // Typegraph with Node Type Inheritance if (this.getTypeSet().getTypeGraph() != null && this.getTypeSet().getLevelOfTypeGraphCheck() >= TypeSet.ENABLED && this.getTypeSet().hasInheritance()) { Iterator<Node> origs = this.itsNodes.iterator(); while (origs.hasNext() && result) { final Node orig = origs.next(); if (!orig.getType().compareTo(h.getImage(orig).getType())) { result = false; } } } if (result) { // store this completion OrdinaryMorphism m = BaseFactory.theFactory().createMorphism(this, g); Enumeration<GraphObject> e = h.getDomain(); while (e.hasMoreElements()) { GraphObject o = e.nextElement(); try { m.addMapping(o, h.getImage(o)); } catch (Exception ex) {} } allIsos.add(m); } } return allIsos; } /** * Returns an isomorphism between this graph and its ad-hoc-created copy. * * @deprecated replaced by <code>isomorphicCopy()</code> */ public OrdinaryMorphism isoToCopy(int n) { return isomorphicCopy(); } /** * Returns an isomorphism between this graph and its ad-hoc-created copy. * The attributes values are copied, too. * * @return morphism this --> copy */ public OrdinaryMorphism isomorphicCopy() { return this.isomorphicCopy(false); } /** * @see OrdinaryMorphism isomorphicCopy() * @return morphism this --> copy */ public OrdinaryMorphism isoCopy() { return this.isomorphicCopy(false); } /** * Returns an isomorphism between this graph and its ad-hoc-created copy. * The attributes values are copied, too. * * @return morphism copy --> this */ public OrdinaryMorphism inverseIsoCopy() { return this.isomorphicCopy(true); } public OrdinaryMorphism plainCopy() { synchronized (this) { Graph copy = BaseFactory.theFactory().createGraph(getTypeSet(), this.isCompleteGraph()); OrdinaryMorphism iso = new OrdinaryMorphism(this, copy, agg.attribute.impl.AttrTupleManager .getDefaultManager().newContext(AttrMapping.PLAIN_MAP)); copy.setName(this.getName().concat("_copy")); iso.setName("IsoMorph"); if (makeIsocopy(false, iso, copy)) return iso; else { iso.dispose(); copy.dispose(); copy = null; iso = null; return null; } } } /** * Returns an isomorphism between this graph and its ad-hoc-created copy. * The attributes values are copied, too. * * @return morphism this --> copy if inverse is FALSE, otherwise copy --> this */ private OrdinaryMorphism isomorphicCopy(boolean inverse) { synchronized (this) { Graph copy = BaseFactory.theFactory().createGraph(getTypeSet(), this.isCompleteGraph()); OrdinaryMorphism iso = null; if (inverse) iso = BaseFactory.theFactory().createMorphism(copy, this); else iso = BaseFactory.theFactory().createMorphism(this, copy); copy.setName(this.getName().concat("_copy")); iso.setName("IsoMorph"); if (makeIsocopy(inverse, iso, copy)) return iso; else { iso.dispose(); copy.dispose(); copy = null; iso = null; return null; } } } /** * Makes the given empty graph <code>theCopy</code> to a copy of myself. * The attributes values are copied, too. * If inverse is TRUE, the <code>iso</code> morphism is given by <code>theCopy -> this</code>, * otherwise by <code>this -> theCopy</code> */ public boolean makeIsocopy(boolean inverse, OrdinaryMorphism iso, Graph theCopy) { boolean failed = false; final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this .getSize()); Iterator<?> iter = this.itsNodes.iterator(); while (!failed && iter.hasNext()) { Node vtxOrig = (Node)iter.next(); try { Node vtxCopy = theCopy.copyNode(vtxOrig); vtxCopy.setContextUsage(vtxOrig.getContextUsage()); memo1.put(vtxOrig, vtxCopy); try { if (inverse) iso.addPlainMapping(vtxCopy, vtxOrig); else iso.addPlainMapping(vtxOrig, vtxCopy); } catch (BadMappingException bme) { failed = true; } } catch (TypeException ex) { failed = true; } } iter = this.itsArcs.iterator(); while (!failed && iter.hasNext()) { Arc arcOrig = (Arc)iter.next(); Node source = (Node) arcOrig.getSource(); Node target = (Node) arcOrig.getTarget(); Node srcImg = memo1.get(source); Node tgtImg = memo1.get(target); if ((srcImg != null) && (tgtImg != null)) { try { Arc arcCopy = theCopy.copyArc(arcOrig, srcImg, tgtImg); arcCopy.setContextUsage(arcOrig.getContextUsage()); try { if (inverse) iso.addPlainMapping(arcCopy, arcOrig); else iso.addPlainMapping(arcOrig, arcCopy); } catch (BadMappingException bme) { failed = true; } } catch (TypeException ex) { failed = true; } } } memo1.clear(); return !failed; } /** * Returns an isomorphism between this graph and its graph-structure copy. * The attributes values are not copied. * * @return morphism this --> copy */ public OrdinaryMorphism isoGraph() { return isomorphicGraph(false); } /** * Returns an isomorphism between a graph-structure copy and this graph. * The attributes values are not copied. * * @return morphism copy --> this */ public OrdinaryMorphism inverseIsoGraph() { return isomorphicGraph(true); } /** * Returns an isomorphism between this graph and its graph-structure copy. * The attributes values are not copied. */ public OrdinaryMorphism isomorphicGraph(boolean inverse) { synchronized (this) { boolean failed = false; Graph theCopy = BaseFactory.theFactory().createGraph(getTypeSet(), this.isCompleteGraph()); OrdinaryMorphism iso = null; if (inverse) iso = BaseFactory.theFactory().createMorphism(theCopy, this); else iso = BaseFactory.theFactory().createMorphism(this, theCopy); theCopy.setName(this.getName().concat("_copy")); iso.setName("IsoMorph"); final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this .getSize()); Iterator<?> iter = this.itsNodes.iterator(); while (!failed && iter.hasNext()) { Node vtxOrig = (Node)iter.next(); try { Node vtxCopy = theCopy.createNode(vtxOrig.getType()); vtxCopy.setObjectName(vtxOrig.getObjectName()); vtxCopy.setContextUsage(vtxOrig.getContextUsage()); memo1.put(vtxOrig, vtxCopy); try { if (inverse) iso.addPlainMapping(vtxCopy, vtxOrig); else iso.addPlainMapping(vtxOrig, vtxCopy); } catch (BadMappingException bme) { failed = true; iso.dispose(); theCopy.dispose(); } } catch (TypeException ex) {} } iter = this.itsArcs.iterator(); while (!failed && iter.hasNext()) { Arc arcOrig = (Arc)iter.next(); Node srcImg = memo1.get(arcOrig.getSource()); Node tgtImg = memo1.get(arcOrig.getTarget()); if ((srcImg != null) && (tgtImg != null)) { try { Arc arcCopy = theCopy.createArc(arcOrig.getType(), srcImg, tgtImg); arcCopy.setObjectName(arcOrig.getObjectName()); arcCopy.setContextUsage(arcOrig.getContextUsage()); try { if (inverse) iso.addPlainMapping(arcCopy, arcOrig); else iso.addPlainMapping(arcOrig, arcCopy); } catch (BadMappingException bme) { failed = true; iso.dispose(); theCopy.dispose(); } } catch (TypeException ex) {} } } memo1.clear(); return (iso); } } /** * Returns an isomorphism between ad-hoc-created copy and this graph. */ public OrdinaryMorphism reverseIsomorphicCopy() { synchronized (this) { boolean failed = false; Iterator<Arc> arcList = this.itsArcs.iterator(); Iterator<Node> vtxList = this.itsNodes.iterator(); Graph theCopy = BaseFactory.theFactory().createGraph(getTypeSet()); theCopy.setName(this.getName().concat("_copy")); OrdinaryMorphism iso = BaseFactory.theFactory().createMorphism( theCopy, this); iso.setName("IsoMorph"); final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this .getSize()); while (vtxList.hasNext()) { Node vtxOrig = vtxList.next(); Node vtxCopy = null; try { vtxCopy = theCopy.copyNode(vtxOrig); /** side effect! */ vtxCopy.setContextUsage(vtxOrig.getContextUsage()); iso.addMapping(vtxCopy, vtxOrig); /** output construction */ memo1.put(vtxOrig, vtxCopy); } catch (TypeException e) { // e.printStackTrace(); failed = true; } } while (!failed && arcList.hasNext()) { Arc arcOrig = arcList.next(); Node source = (Node) arcOrig.getSource(); Node target = (Node) arcOrig.getTarget(); Node srcImg = memo1.get(source); Node tgtImg = memo1.get(target); Arc arcCopy = null; if ((srcImg != null) && (tgtImg != null)) { try { arcCopy = theCopy.copyArc(arcOrig, srcImg, tgtImg); arcCopy.setContextUsage(arcOrig.getContextUsage()); iso.addMapping(arcCopy, arcOrig); } catch (TypeException e) { // e.printStackTrace(); failed = true; } } } memo1.clear(); return (iso); } } /** * see appropriate method <code>BaseFactory.getOverlappings</code> */ public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, boolean withIsomorphic) { return BaseFactory.theBaseFactory.getOverlappings(this, g, withIsomorphic); } /** * see appropriate method <code>BaseFactory.getOverlappings</code> */ public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, boolean disjunion, boolean withIsomorphic) { return BaseFactory.theBaseFactory.getOverlappings(this, g, disjunion, withIsomorphic); } /** * see appropriate method <code>BaseFactory.getOverlappings</code> */ public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, int sizeOfInclusions, boolean withIsomorphic) { return BaseFactory.theBaseFactory.getOverlappings(this, g, sizeOfInclusions, withIsomorphic); } /** * see appropriate method <code>BaseFactory.getOverlappings</code> */ public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, int sizeOfInclusions, boolean disjunion, boolean withIsomorphic) { return BaseFactory.theBaseFactory.getOverlappings(this, g, sizeOfInclusions, disjunion, withIsomorphic); } /** * Implements the interface of XMLObject */ public void XwriteObject(XMLHelper h) { this.refreshAttributed(); this.changed = false; h.openNewElem("Graph", this); if (!this.kind.equals("")) h.addAttr("kind", this.kind); h.addAttr("name", getName()); if (!this.comment.equals("")) h.addAttr("comment", this.comment); if (!this.info.equals("")) h.addAttr("info", this.info); h.addIteration("", this.itsNodes.iterator(), true); h.addIteration("", this.itsArcs.iterator(), true); h.close(); // updateTypeObjectsMap(); } /** * Implements the interface of XMLObject */ public void XreadObject(XMLHelper h) { if (h.isTag("Graph", this)) { String str = h.readAttr("name"); setName(str.replaceAll(" ", "")); str = h.readAttr("comment"); if (!str.equals("")) this.comment = str.toString(); str = h.readAttr("info"); if (!str.equals("")) this.info = str.toString(); Enumeration<?> en = h.getEnumeration("", null, true, "Node"); while (en.hasMoreElements()) { h.peekElement(en.nextElement()); Type t = (Type) h.getObject("type", null, false); if (t != null) { Node n = null; try { n = newNode(t); n = (Node) h.loadObject(n); } catch (TypeException e) { // while loading the type check should be disabled, // so this Exception should never be thrown System.out.println("Graph.XreadObject: cannot load a Node : <" +t.getName()+"> into graph <"+this.getName()+"> " +e.getMessage()); } } h.close(); } en = h.getEnumeration("", null, true, "Edge"); while (en.hasMoreElements()) { h.peekElement(en.nextElement()); Type t = (Type) h.getObject("type", null, false); Node n1 = (Node) h.getObject("source", null, false); Node n2 = (Node) h.getObject("target", null, false); if (t != null && n1 != null && n2 != null) { try { Arc a = newArc(t, n1, n2); a = (Arc) h.loadObject(a); } catch (TypeException e) { // while loading the type check should be disabled, // so this Exception should never be thrown System.out.println("Graph.XreadObject: cannot load an Arc : <" +t.getName()+"> into graph <"+this.getName()+"> " +e.getMessage()); } } h.close(); } h.close(); } // this.showTypeMap(this.getTypeObjectsMap()); } public String toString() { return showGraph(); } public String showGraph() { String result = this.getName(); result = "\nGraph: " + this.getName() + " {\n"; Iterator<Arc> e = this.itsArcs.iterator(); while (e.hasNext()) { Arc arc = e.next(); result += ((Node) arc.getSource()).toString() + arc.toString() + ((Node) arc.getTarget()).toString(); } if (this.isTypeGraph()) { Vector<Arc> inheritArcs = this.getTypeSet().getInheritanceArcs(); e = inheritArcs.iterator(); while (e.hasNext()) { Arc arc = e.next(); result += ((Node) arc.getSource()).toString() + "--inherits-->" + ((Node) arc.getTarget()).toString(); } } Iterator<Node> e1 = this.itsNodes.iterator(); while (e1.hasNext()) { Node node = e1.next(); if (!node.getIncomingArcsSet().iterator().hasNext() && !node.getOutgoingArcsSet().iterator().hasNext()) result += node.toString(); } result += " }\n"; return result; } /* protected String showNodes() { String result = this.getName(); result = "\nGraph: " + this.getName() + " Nodes:: " + getNodesCount() + "{\n"; Iterator<Node> e = this.itsNodes.iterator(); while (e.hasNext()) { Node node = e.next(); result += node.toString(); } result += " }\n"; return result; } protected String showArcs() { String result = this.getName(); result = "\nGraph: " + this.getName() + " Edges:: " + getArcsCount() + "{\n"; Iterator<Arc> e = this.itsArcs.iterator(); while (e.hasNext()) { Arc arc = e.next(); result += ((Node) arc.getSource()).toString() + arc.toString() + ((Node) arc.getTarget()).toString(); } if (this.isTypeGraph()) { Vector<Arc> inheritArcs = this.getTypeSet().getInheritanceArcs(); e = inheritArcs.iterator(); while (e.hasNext()) { Arc arc = e.next(); result += ((Node) arc.getSource()).toString() // +arc.toString() + "--inherits-->" + ((Node) arc.getTarget()).toString(); } } result += " }\n"; return result; } private String attributesToString() { String result = "\nGraph: " + this.getName() + " {\n"; Iterator<Node> e = this.itsNodes.iterator(); while (e.hasNext()) { Node node = e.next(); // if(!node.getIncomingArcs().hasMoreElements() // && !node.getOutgoingArcs().hasMoreElements()) { result += node.toString(); result += attributeToString(node); } } // // e = getArcs(); while(e.hasMoreElements()) { Arc arc = (Arc) // e.nextElement(); result += arc.toString(); result += // attributeToString(arc); } // result += "\n}"; return result; } */ // private String attributeToString(GraphObject o) { // return o.attributeToString(); // } /** * Returns true if the given set of graph objects represents a valid graph. * * @param goSet * a Vector of GraphObjects * * @see GraphObject * @see TypeSet#checkType(Graph) */ public boolean isGraph(final List<GraphObject> goSet) { for (int i=0; i<goSet.size(); i++) { GraphObject go = goSet.get(i); if (go.isArc()) { if (!goSet.contains(((Arc)go).getSource()) || !goSet.contains(((Arc)go).getTarget())) return false; } } return true; } /** * Returns true if this graph is used as a type graph. This works only if * this graph is registered as type graph in its own {@link TypeSet}. */ public boolean isTypeGraph() { if (this.itsTypes == null) { return false; } return this == this.itsTypes.getTypeGraph(); } public boolean isAttributed() { return this.attributed; } public boolean areAnyAttributesSet(final Iterator<?> iter) { boolean anyAttrsSet = false; while (iter.hasNext()) { GraphObject a = (GraphObject) iter.next(); if (a.getAttribute() == null) continue; ValueTuple value = (ValueTuple) a.getAttribute(); for (int j = 0; j < value.getSize(); j++) { if (value.getValueMemberAt(j).isSet()) { anyAttrsSet = true; break; } } } return anyAttrsSet; } public boolean areAnyAttributesOfNodesSet() { return this.areAnyAttributesSet(this.itsNodes.iterator()); } public boolean areAnyAttributesOfArcsSet() { return this.areAnyAttributesSet(this.itsArcs.iterator()); } /** * Returns true, if this graph is a complete graph. * A complete graph is not allowed to use variables in attributes * of its node and edges. * The host graph of a gragra is always a complete graph. * */ public boolean isCompleteGraph() { return this.completeGraph; } /** * A complete graph is not allowed to use variables in attributes * of its node and edges. */ public void setCompleteGraph(boolean complete) { this.completeGraph = complete; } public boolean isDirected() { return this.getTypeSet().isArcDirected(); } /** * return TRUE if this graph is a NAC graph */ public boolean isNacGraph() { return (this.kind == GraphKind.NAC) ? true : false; } /** * return TRUE if this graph is a PAC graph */ public boolean isPacGraph() { return (this.kind == GraphKind.PAC) ? true : false; } /** * return TRUE if this graph is a nested Appl Cond graph */ public boolean isApplCondGraph() { return (this.kind == GraphKind.AC) ? true : false; } public boolean compareTo(Graph g) { if (this.getNodesCount() != g.getNodesCount()) { return (false); } if (this.getArcsCount() != g.getArcsCount()) { return (false); } boolean result = false; OrdinaryMorphism m = (BaseFactory.theFactory()).createMorphism(this, g); m.setCompletionStrategy(new Completion_InjCSP(), true); // m.getCompletionStrategy().showProperties(); while (!result && m.nextCompletionWithConstantsChecking()) { result = true; // 1. check free objects in g Iterator<?> e = g.getNodesSet().iterator(); while (result && e.hasNext()) { GraphObject o = (GraphObject) e.next(); if (!m.getInverseImage(o).hasMoreElements()) { result = false; } } e = g.getArcsSet().iterator(); while (result && e.hasNext()) { GraphObject o = (GraphObject) e.next(); if (!m.getInverseImage(o).hasMoreElements()) { result = false; } } // 2. check objects using compareTo e = this.getNodesSet().iterator(); while (result && e.hasNext()) { GraphObject o = (GraphObject) e.next(); GraphObject i = m.getImage(o); if (!o.compareTo(i)) { result = false; } } e = this.getArcsSet().iterator(); while (result && e.hasNext()) { GraphObject o = (GraphObject) e.next(); GraphObject i = m.getImage(o); if (!o.compareTo(i)) { result = false; } } } m.dispose(); m = null; return result; } public boolean contains(Graph g) { return contains(g, null); } public boolean contains(Graph g, MorphCompletionStrategy mcs) { boolean result = false; if (g.isEmpty()) { result = true; } else if (this.getSize() >= g.getSize()) { if (!this.isEmpty() && mcs != null) { if (mcs.getProperties().get(CompletionPropertyBits.INJECTIVE) && this.getSize() < g.getSize()) { return false; } OrdinaryMorphism m = (BaseFactory.theFactory()).createMorphism(g, this); m.setCompletionStrategy(mcs, true); while (!result && m.nextCompletionWithConstantsChecking()) { result = true; // check objects using compareTo Iterator<?> e = g.getNodesSet().iterator(); while (result && e.hasNext()) { GraphObject o = (GraphObject) e.next(); GraphObject i = m.getImage(o); if (!o.compareTo(i)) { result = false; } } e = g.getArcsSet().iterator(); while (result && e.hasNext()) { GraphObject o = (GraphObject) e.next(); GraphObject i = m.getImage(o); if (!o.compareTo(i)) { result = false; } } } m.dispose(); m = null; } } else { result = true; } return result; } public int getSize() { return this.itsNodes.size() +this.itsArcs.size(); } public int getSizeOfNodes() { return this.itsNodes.size(); } public int getSizeOfArcs() { return this.itsArcs.size(); } /** * Checks if the specified edge to create is allowed. */ public TypeError checkConnectValid(Type edgeType, Node src, Node tar) { if (this.itsTypes.getTypeGraph() == null || this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.DISABLED || this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.ENABLED_INHERITANCE) { if (isParallelArcAllowed(edgeType, src, tar)) { return null; } return new TypeError(TypeError.NO_PARALLEL_ARC, "No parallel edges allowed"); } Arc typearc = this.itsTypes.getTypeGraphArc( edgeType, src.getType(), tar.getType()); if (typearc != null) { if (isParallelArcAllowed(edgeType, src, tar)) { return null; } return new TypeError(TypeError.NO_PARALLEL_ARC, "No parallel edges allowed"); } return new TypeError(TypeError.NO_SUCH_TYPE, "The edge of the type \"" + edgeType.getName() + "\" is not allowed between node types \"" + src.getType().getName() + "\" and \"" + tar.getType().getName() + "\"."); } public boolean isParallelArcAllowed(Type edgeType, Node src, Node tar) { if (this.itsTypes.isArcParallel() || (src.getOutgoingArc(edgeType, tar) == null)) return true; else return false; } public TypeError checkNodeRequiresArc(final int actTypeGraphLevel) { if (this.itsTypes.getTypeGraph() == null || actTypeGraphLevel != TypeSet.ENABLED_MAX_MIN) return null; Iterator<Node> iter = this.itsNodes.iterator(); while (iter.hasNext()) { Node n = iter.next(); List<String> list = this.itsTypes.nodeRequiresArc(n); if (list != null && !list.isEmpty()) { return new TypeError(TypeError.TO_LESS_ARCS, "Node type " + "\""+n.getType().getName()+ "\" \n" + "requires edge(s) of type: \n" + list.toString(), n.getType()); } } return null; } /** * Returns en error if the type multiplicity check failed after a node of * the specified type would be created, otherwise - null. */ public TypeError canCreateNode( final Type nodeType, int currentTypeGraphLevel) { return this.itsTypes.canCreateNode(this, nodeType, currentTypeGraphLevel); } /** * Returns an error if the type multiplicity check failed after an edge of * the specified type would be created, otherwise - null. */ public TypeError canCreateArc( final Type edgeType, final Node source, final Node target, int currentTypeGraphLevel) { return this.itsTypes.canCreateArc(this, edgeType, source, target, currentTypeGraphLevel); } public Vector<String> getVariableNamesOfAttributes() { final Vector<String> result = new Vector<String>(); getVarNamesOfAttrs(this.itsNodes.iterator(), result); getVarNamesOfAttrs(this.itsArcs.iterator(), result); return result; } private void getVarNamesOfAttrs(final Iterator<?> iter, final Vector<String> result) { while (iter.hasNext()) { GraphObject o = (GraphObject)iter.next(); if (o.getAttribute() == null) { continue; } Vector<String> vars = o.getVariableNamesOfAttribute(); for (int i = 0; i < vars.size(); i++) { String name = vars.elementAt(i); if (!result.contains(name)) result.addElement(name); } } } public Vector<VarMember> getSameVariablesOfAttributes() { final Vector<VarMember> result = new Vector<VarMember>(); final AttrContext ac = getAttrContext(); final VarTuple avt = (VarTuple) ac.getVariables(); final Hashtable<VarMember, Boolean> used = new Hashtable<VarMember, Boolean>( avt.getSize()); for (int i = 0; i < avt.getSize(); i++) { VarMember var = avt.getVarMemberAt(i); used.put(var, Boolean.valueOf(false)); } if (used.isEmpty()) return result; this.getSameVarsOfAttrs(avt, this.itsNodes.iterator(), used, result); this.getSameVarsOfAttrs(avt, this.itsArcs.iterator(), used, result); return result; } public void getSameVarsOfAttrs( final VarTuple avt, final Iterator<?> iter, final Hashtable<VarMember, Boolean> used, final Vector<VarMember> result) { while (iter.hasNext()) { GraphObject o = (GraphObject)iter.next(); if (o.getAttribute() == null) continue; ValueTuple vt = (ValueTuple) o.getAttribute(); for (int k = 0; k < vt.getSize(); k++) { ValueMember vm = vt.getValueMemberAt(k); if (vm.isSet()) { if (vm.getExpr().isVariable()) { VarMember var = avt.getVarMemberAt(vm.getExprAsText()); if (!var.isInputParameter()) { if (used.get(var).booleanValue() == false) used.put(var, Boolean.valueOf(true)); else { if (!result.contains(var)) result.add(var); } } } } } } } /* * * @deprecated use {@link #copyNode} or {@link #copyArc}, this method * cannot work properly in case a type graph is defined and in * use. * public final Object execute(Object obj) { try { if (((GraphObject) obj).isNode()) { return copyNode((Node) obj); } else { return copyArc((Arc) obj, (Node) ((Arc) obj).getSource(), (Node) ((Arc) obj).getTarget()); } } catch (TypeException e) { // Whoever use this function, could not // recieve the Exception in case of type mismatch. // so this method is deprecated. System.out.println(e); e.printStackTrace(); return null; } } */ public void graphDidChange() { propagateChange(new Change(Change.MODIFIED)); } public void unsetCriticalObjects() { Iterator<?> e = this.itsArcs.iterator(); while (e.hasNext()) { GraphObject o = (GraphObject) e.next(); o.setCritical(false); } e = this.itsNodes.iterator(); while (e.hasNext()) { GraphObject o = (GraphObject) e.next(); o.setCritical(false); } } public void unsetTransientAttrValues() { this.unsetTransAttrValues(this.itsNodes.iterator()); this.unsetTransAttrValues(this.itsArcs.iterator()); } private void unsetTransAttrValues(final Iterator<?> iter) { while (iter.hasNext()) { GraphObject go = (GraphObject)iter.next(); if (go.getAttribute() == null) continue; ValueTuple val = (ValueTuple) go.getAttribute(); for (int i = 0; i < val.getNumberOfEntries(); i++) { ValueMember vm = val.getValueMemberAt(i); if (vm.isTransient()) { vm.setExpr(null); } } } } public void unsetAttributeValueWhereVariable() { this.unsetAttrValueWhichIsVar(this.itsNodes.iterator()); this.unsetAttrValueWhichIsVar(this.itsArcs.iterator()); } private void unsetAttrValueWhichIsVar(final Iterator<?> iter) { while (iter.hasNext()) { GraphObject go = (GraphObject)iter.next(); if (go.getAttribute() == null) continue; ValueTuple vt = (ValueTuple) go.getAttribute(); for (int j = 0; j < vt.getNumberOfEntries(); j++) { ValueMember vm = vt.getValueMemberAt(j); if (vm.isSet() && vm.getExpr().isVariable()) vm.setExpr(null); } } } /** * Tries to compute partial morphisms of this graph * into the specified set of graph objects. * * @param set is target of morphisms * * @return set of computed partial morphisms, * where keys are objects of this graph, * values - objects of the specified target set */ public Vector<Hashtable<GraphObject, GraphObject>> getPartialMorphismIntoSet( final Vector<GraphObject> set) { if (set.isEmpty() || set.size() > this.getSize()) { return null; } final Vector<Hashtable<GraphObject, GraphObject>> result = new Vector<Hashtable<GraphObject, GraphObject>>(); final Hashtable<GraphObject, GraphObject> store = new Hashtable<GraphObject, GraphObject>(); // create graph g from set and store new/original objects Graph g = BaseFactory.theFactory().createGraph(this.getTypeSet()); for (int i = 0; i < set.size(); i++) { GraphObject go = set.get(i); if (go.isNode()) { try { Node n = g.copyNode((Node) go); store.put(n, go); } catch (TypeException e) { } } else { try { Arc a = g.copyArc((Arc) go, (Node) ((Arc) go).getSource(), (Node) ((Arc) go).getTarget()); store.put(a, go); } catch (TypeException e) { } } } // create morphism m: g -> this OrdinaryMorphism m = BaseFactory.theFactory().createMorphism(g, this); // because this can be LHS of a rule set variable attr context ((AttrTupleManager) m.getAttrManager()).setVariableContext(true); while (m.nextCompletion()) { final Hashtable<GraphObject, GraphObject> table = new Hashtable<GraphObject, GraphObject>(); Enumeration<GraphObject> en = m.getDomain(); while (en.hasMoreElements()) { GraphObject obj = en.nextElement(); GraphObject img = m.getImage(obj); table.put(img, store.get(obj)); } result.add(table); } return result; } /** * Returns object domains for used types. * The key of a node type is built by <code>type.convertToKey()</code>, * the key of an arc type by * <code>srcNodeType.convertToKey()+type.convertToKey()+tarNodeType.convertToKey()</code>. */ public Hashtable<String, HashSet<GraphObject>> getTypeObjectsMap() { if (this.itsTypeObjectsMap.isEmpty()) { fillTypeObjectsMap(); } return this.itsTypeObjectsMap; } /** * Refreshs object domains for used types. */ public void updateTypeObjectsMap() { this.itsTypeObjectsMap.clear(); // fill domain vector of each type with new objects fillTypeObjectsMap(); } protected void addToTypeObjectsMap(GraphObject anObj) { if (anObj.isNode()) { extendTypeObjectsMapByNode((Node)anObj); } else { extendTypeObjectsMapByArc((Arc)anObj); } } protected void removeNodeFromTypeObjectsMap(final Node anObj) { if (anObj.getType().hasParent()) { Vector<Type> myParents = anObj.getType().getAllParents(); for (int i = 0; i < myParents.size(); ++i) { final String keystr = myParents.get(i).convertToKey(); final HashSet<GraphObject> anObjVec = this.itsTypeObjectsMap.get(keystr); if (anObjVec != null) { anObjVec.remove(anObj); } } } else { final String keystr = anObj.getType().convertToKey(); final HashSet<GraphObject> anObjVec = this.itsTypeObjectsMap.get(keystr); if (anObjVec != null) { anObjVec.remove(anObj); } } } protected void removeArcFromTypeObjectsMap(final Arc anObj) { if (anObj.getSource() != null && anObj.getTarget() != null) { if (anObj.getSource().getType().hasParent() || anObj.getTarget().getType().hasParent()) { Vector<Type> mySrcParents = anObj.getSource().getType().getAllParents(); Vector<Type> myTarParents = anObj.getTarget().getType().getAllParents(); for (int i = 0; i < mySrcParents.size(); ++i) { for (int j = 0; j < myTarParents.size(); ++j) { String keystr = mySrcParents.get(i).convertToKey() + anObj.getType().convertToKey() + myTarParents.get(j).convertToKey(); final HashSet<GraphObject> anObjVec = this.itsTypeObjectsMap.get(keystr); if (anObjVec != null) { anObjVec.remove(anObj); } } } } else { String keystr = anObj.convertToKey(); final HashSet<GraphObject> anObjVec = this.itsTypeObjectsMap.get(keystr); if (anObjVec != null) { anObjVec.remove(anObj); } } } } protected void removeFromTypeObjectsMap(final GraphObject anObj) { if (anObj instanceof Node) removeNodeFromTypeObjectsMap((Node) anObj); else removeArcFromTypeObjectsMap((Arc) anObj); } public void fillTypeObjectsMap() { Iterator<?> iter = this.itsNodes.iterator(); while (iter.hasNext()) { final Node obj = (Node)iter.next(); extendTypeObjectsMapByNode(obj); } iter = this.itsArcs.iterator(); while (iter.hasNext()) { extendTypeObjectsMapByArc((Arc)iter.next()); } } protected void extendTypeObjectsMap(final Type childType, final Type parentType) { final Iterator<Node> iter = this.itsNodes.iterator(); while (iter.hasNext()) { Node obj = iter.next(); if (childType.isParentOf(obj.getType())) { extendTypeObjectsMapByNode(obj, parentType); Iterator<Arc> iter2 = obj.getOutgoingArcsSet().iterator(); while (iter2.hasNext()) { extendTypeObjectsMapByArc(iter2.next()); } iter2 = obj.getIncomingArcsSet().iterator(); while (iter2.hasNext()) { extendTypeObjectsMapByArc(iter2.next()); } } } } private void extendTypeObjectsMapByNode(final Node node, final Type parent) { Vector<Type> newParents = parent.getAllParents(); for (int i = 0; i < newParents.size(); ++i) { String keystr = newParents.get(i).convertToKey(); HashSet<GraphObject> anObjVec = this.itsTypeObjectsMap.get(keystr); if (anObjVec == null) { anObjVec = new LinkedHashSet<GraphObject>(); this.itsTypeObjectsMap.put(keystr, anObjVec); } anObjVec.add(node); } } protected void extendTypeObjectsMapByNode(final Node node) { if (node.getType().hasParent()) { Vector<Type> myParents = node.getType().getAllParents(); for (int i = 0; i < myParents.size(); ++i) { String keystr = myParents.get(i).convertToKey(); HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr); if (objSet == null) { objSet = new LinkedHashSet<GraphObject>(); this.itsTypeObjectsMap.put(keystr, objSet); } objSet.add(node); } } else { String keystr = node.convertToKey(); HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr); if (objSet == null) { objSet = new LinkedHashSet<GraphObject>(); this.itsTypeObjectsMap.put(keystr, objSet); } objSet.add(node); } } protected void extendTypeObjectsMapByArc(final Arc arc) { if (this.itsTypes.hasInheritance() && arc.getSource().getType().hasParent() || arc.getTarget().getType().hasParent()) { Vector<Type> srcParents = arc.getSource().getType().getAllParents(); Vector<Type> tarParents = arc.getTarget().getType().getAllParents(); for (int i = 0; i < srcParents.size(); ++i) { for (int j = 0; j < tarParents.size(); ++j) { String keystr = srcParents.get(i).convertToKey() + arc.getType().convertToKey() + tarParents.get(j).convertToKey(); HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr); if (objSet == null) { objSet = new LinkedHashSet<GraphObject>(); this.itsTypeObjectsMap.put(keystr, objSet); } objSet.add(arc); } } } else { String keystr = arc.convertToKey(); HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr); if (objSet == null) { objSet = new LinkedHashSet<GraphObject>(); this.itsTypeObjectsMap.put(keystr, objSet); } objSet.add(arc); } } public void refreshAttributed() { this.attributed = false; Iterator<?> iter = this.itsNodes.iterator(); while (iter.hasNext()) { GraphObject o = (GraphObject)iter.next(); if ((o.getType().getAttrType() != null) && (o.getType().getAttrType().getNumberOfEntries() != 0)) { this.attributed = true; } } iter = this.itsArcs.iterator(); while (iter.hasNext()) { GraphObject o = (GraphObject)iter.next(); if ((o.getType().getAttrType() != null) && (o.getType().getAttrType().getNumberOfEntries() != 0)) { this.attributed = true; } } } /** * Trims the capacity of used vectors to be the vector's current * size. */ public void trimToSize() { this.observer.trimToSize(); this.itsUsingMorphs.trimToSize(); } /* private void showTypeMap(Hashtable<String, List<GraphObject>> d) { System.out.println("****** TYPE DOMAINS ******"); Enumeration<String> keys = d.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); System.out.println(key); List<GraphObject> v = d.get(key); for (int i = 0; i < v.size(); i++) { GraphObject go = v.get(i); System.out.print(go + " "); } System.out.println(); } System.out.println("***********"); } */ java.lang.String s; }