/* * e4vvisitor.cpp -- * * Implementation of the e4_VertexVisitor class defined in e4graph.h. * * Authors: Jacob Levy and Jean-Claude Wippler. * jyl@best.com jcw@equi4.com * * Copyright (c) 2000-2003, JYL Software Inc. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF * JYL SOFTWARE INC. IS MADE AWARE OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "e4graphimpl.h" /* * Default constructor: */ e4_VertexVisitor::e4_VertexVisitor() : done(true), detachchoice(E4_DCATTACHED), s(invalidStorage), f(invalidVertex), vm(E4_VMUNKNOWN), vf(E4_VFNONE), nameID(E4_VERTEXNOTFOUND), nodeID(E4_NODENOTFOUND), typeID(E4_VTUNKNOWN) {} /* * Copying constructor: */ e4_VertexVisitor::e4_VertexVisitor(const e4_VertexVisitor &referrer) : s(referrer.s), f(referrer.f), vm(referrer.vm), vf(referrer.vf), nameID(referrer.nameID), nodeID(referrer.nodeID), typeID(referrer.typeID), done(referrer.done), detachchoice(referrer.detachchoice) { } /* * Assignment operator: */ e4_VertexVisitor & e4_VertexVisitor::operator=(const e4_VertexVisitor &referrer) { s = referrer.s; f = referrer.f; vm = referrer.vm; vf = referrer.vf; nameID = referrer.nameID; nodeID = referrer.nodeID; typeID = referrer.typeID; done = referrer.done; detachchoice = referrer.detachchoice; return * this; } /* * Comparison operators: */ bool e4_VertexVisitor::operator==(const e4_VertexVisitor &compared) const { return ((s == compared.s) && (f == compared.f) && (vm == compared.vm) && (vf == compared.vf) && (nameID == compared.nameID) && (nodeID == compared.nodeID) && (typeID == compared.typeID) && (done == compared.done) && (detachchoice == compared.detachchoice)) ? true : false; } bool e4_VertexVisitor::operator!=(const e4_VertexVisitor &compared) const { return ((s == compared.s) && (f == compared.f) && (vm == compared.vm) && (vf == compared.vf) && (nameID == compared.nameID) && (nodeID == compared.nodeID) && (typeID == compared.typeID) && (done == compared.done) && (detachchoice == compared.detachchoice)) ? false : true; } /* * Constructors that initialize from a given node. */ e4_VertexVisitor::e4_VertexVisitor(const e4_Node &n) : done(true) { (void) SetNode(n); } e4_VertexVisitor::e4_VertexVisitor(const e4_Node &n, const char *nm, e4_VertexType vt) : done(true) { SetNode(n, nm, vt); } e4_VertexVisitor::e4_VertexVisitor(const e4_Node &child, const e4_Node &parent, e4_DetachChoice dc) { SetParentVertex(child, parent, dc, NULL); } e4_VertexVisitor::e4_VertexVisitor(const e4_Node &child, const e4_Node &parent, e4_DetachChoice dc, const char *nm) { SetParentVertex(child, parent, dc, nm); } /* * Constructors that initialize from a given vertex. */ e4_VertexVisitor::e4_VertexVisitor(const e4_Vertex &vv) : done(true) { SetVertex(vv); } e4_VertexVisitor::e4_VertexVisitor(const e4_Vertex &vv, bool useVertexName, bool useVertexType) : done(true) { SetVertex(vv, useVertexName, useVertexType); } e4_VertexVisitor::e4_VertexVisitor(const e4_Vertex &vv, bool useVertexName, bool useVertexType, e4_VisitMethod vmvm) : done(true) { SetVertex(vv, useVertexName, useVertexType, vmvm); } /* * Constructors that initialize from a storage. */ e4_VertexVisitor::e4_VertexVisitor(const e4_Storage &ss) : done(true) { SetStorage(ss, E4_DCATTACHED); } e4_VertexVisitor::e4_VertexVisitor(const e4_Storage &ss, const char *nm, e4_VertexType vt) : done(true) { SetStorage(ss, nm, vt, E4_DCATTACHED); } e4_VertexVisitor::e4_VertexVisitor(const e4_Storage &ss, e4_DetachChoice dc) : done(true) { SetStorage(ss, dc); } e4_VertexVisitor::e4_VertexVisitor(const e4_Storage &ss, e4_DetachChoice dc, const char *nm, e4_VertexType vt) { SetStorage(ss, nm, vt, dc); } /* * Destructor: */ e4_VertexVisitor::~e4_VertexVisitor() { f = invalidVertex; s = invalidStorage; } /* * Is this visitor done visiting its node? */ bool e4_VertexVisitor::IsDone() { if (done) { return true; } if (!f.IsValid() || !s.IsValid()) { done = true; } return done; } /* * Retrieve the next vertex; if none, set done to true and return false. */ bool e4_VertexVisitor::NextVertex(e4_Vertex &vv) { if (done) { return false; } done = (!s.FindNextVertex(f.GetRawUniqueID(), vm, vf, nameID, nodeID, parentID, typeID, detachchoice, vv)); if (done) { return false; } f = vv; return true; } /* * Retrieve the current vertex. */ bool e4_VertexVisitor::CurrentVertex(e4_Vertex &vv) { if (!f.IsValid() || !s.IsValid()) { done = true; return false; } vv = f; return true; } /* * Advance to the next vertex without returning it. */ bool e4_VertexVisitor::Advance() { if (done) { return false; } done = (!s.FindNextVertex(f.GetRawUniqueID(), vm, vf, nameID, nodeID, parentID, typeID, detachchoice, f)); if (done) { return false; } return true; } /* * Retrieve the current vertex and advance to the next one. */ bool e4_VertexVisitor::CurrentVertexAndAdvance(e4_Vertex &vv) { if (!CurrentVertex(vv) || IsDone()) { return false; } (void) Advance(); return true; } /* * Reset the iterator to visit all vertices in the node containing vv. */ bool e4_VertexVisitor::SetVertex(const e4_Vertex &vv) { e4_Storage ss; e4_Node n; /* * If the given vertex is invalid or we cannot get a storage from it, * bail out. */ if (!vv.IsValid() || !vv.GetStorage(ss) || !ss.IsValid() || !vv.GetNode(n) || !n.IsValid()) { done = true; return false; } f = vv; s = ss; vm = E4_VMNODE; vf = E4_VFNONE; nameID = E4_VERTEXNOTFOUND; nodeID = n.GetRawUniqueID(); typeID = E4_VTUNKNOWN; done = false; detachchoice = E4_DCATTACHED; return true; } /* * Visit all vertices in the node containing the given vertex that * match the name and type constraints imposed by the given vertex. * If no constraints are given, vertices are visited in rank order * starting with the given vertex. If constraints are given, vertices * are visited in an implementation dependent order. */ bool e4_VertexVisitor::SetVertex(const e4_Vertex &vv, bool useVertexName, bool useVertexType) { e4_Storage ss; e4_Node n; /* * If the given vertex is invalid or we cannot get a storage from it, * bail out. */ if (!vv.IsValid() || !vv.GetStorage(ss) || !ss.IsValid() || !vv.GetNode(n) || !n.IsValid()) { return false; } detachchoice = E4_DCATTACHED; s = ss; vm = E4_VMNODE; vf = E4_VFNONE; nodeID = n.GetRawUniqueID(); if (useVertexName) { vf |= E4_VFNAME; nameID = s.InternName(vv.Name()); } else { nameID = E4_VERTEXNOTFOUND; } if (useVertexType) { vf |= E4_VFTYPE; typeID = vv.Type(); } if (vf == E4_VFNONE) { f = vv; done = false; } else { done = (!s.FindNextVertex(E4_VERTEXNOTFOUND, vm, vf, nameID, nodeID, parentID, typeID, detachchoice, f)); } return true; } /* * Same as above except use the supplied visit method to find the * next vertex to visit. * * E4_VMNODE Visit vertices in the node that is the value of the * given vertex. Visit order is rank order. * E4_VMNODERANDOM Same as above except visit order is random. * E4_VMPARENT The given vertex is expected to have a node value. * Visit all attached vertices that have this node as * their value. */ bool e4_VertexVisitor::SetVertex(const e4_Vertex &vv, bool useVertexName, bool useVertexType, e4_VisitMethod vmvm) { e4_Storage ss; e4_Node n; if (!vv.IsValid() || !vv.GetStorage(ss) || !ss.IsValid() || !vv.GetNode(n) || !n.IsValid()) { return false; } detachchoice = E4_DCATTACHED; s = ss; vm = vmvm; vf = E4_VFNONE; nameID = E4_VERTEXNOTFOUND; nodeID = n.GetRawUniqueID(); typeID = E4_VTUNKNOWN; if (useVertexName) { vf |= E4_VFNAME; nameID = s.InternName(vv.Name()); } if (useVertexType) { vf |= E4_VFTYPE; typeID = vv.Type(); } if (vm == E4_VMNODE) { f = vv; done = false; } else { done = (!s.FindNextVertex(E4_VERTEXNOTFOUND, vm, vf, nameID, nodeID, parentID, typeID, detachchoice, f)); } return true; } /* * Reset the instance to the first vertex of the given node. */ bool e4_VertexVisitor::SetNode(const e4_Node &n) { e4_Storage ss; /* * Bail out if we cannot set the visitor up to visit the * provided node. */ if (!n.IsValid() || !n.GetStorage(ss) || !ss.IsValid()) { done = true; return false; } /* * If the node is empty, mark this visitor as done. */ done = (!n.GetVertexRefByRank(1, f) || !f.IsValid()); s = ss; vm = E4_VMNODE; vf = E4_VFNONE; nameID = E4_VERTEXNOTFOUND; nodeID = n.GetRawUniqueID(); parentID = E4_NODENOTFOUND; typeID = E4_VTUNKNOWN; detachchoice = E4_DCATTACHED; return true; } /* * Reset this visitor to the first vertex of the given node that * matches the given name and type constraints. */ bool e4_VertexVisitor::SetNode(const e4_Node &n, const char *nm, e4_VertexType vt) { e4_Storage ss; /* * Bail out if the visitor cannot be set up using the * supplied node. */ if (!n.IsValid() || !n.GetStorage(ss)) { done = true; return false; } s = ss; vf = E4_VFNONE; vm = E4_VMNODE; typeID = vt; nodeID = n.GetRawUniqueID(); parentID = E4_NODENOTFOUND; if (nm != NULL) { nameID = s.InternName(nm); vf |= E4_VFNAME; } if (vt != E4_VTUNKNOWN) { vf |= E4_VFTYPE; } /* * If the node is empty or contains no vertices matching the * requested constraints, mark this visitor as done. */ detachchoice = E4_DCATTACHED; done = (!s.FindNextVertex(E4_VERTEXNOTFOUND, vm, vf, nameID, nodeID, parentID, typeID, detachchoice, f)); return true; } /* * Reset the iterator to visit vertices that have the child node as their * value. If the parent is valid, the iterator only visits vertices within * that parent of the child, otherwise it visits all vertices that have the * child node as their value, as selected by the detachchoice. */ bool e4_VertexVisitor::SetParentVertex(const e4_Node &child, const e4_Node &parent, e4_DetachChoice dc, const char *nm) { e4_Storage ss; if (!child.IsValid() || !child.GetStorage(ss) || !ss.IsValid()) { done = true; return false; } nodeID = child.GetRawUniqueID(); typeID = E4_VTNODE; detachchoice = dc; s = ss; if (parent.IsValid()) { if (!parent.GetStorage(ss) || !ss.IsValid() || (s != ss)) { done = true; return false; } parentID = parent.GetRawUniqueID(); } else { parentID = E4_NODENOTFOUND; } if (nm == NULL) { vf = E4_VFNONE; nameID = E4_INVALIDUNIQUEID; } else { vf = E4_VFNAME; nameID = s.InternName(nm); } vm = E4_VMPARENT; done = (!s.FindNextVertex(E4_VERTEXNOTFOUND, vm, vf, nameID, nodeID, parentID, typeID, detachchoice, f)); return true; } /* * Reset the iterator to visit all attached vertices in a given storage. */ bool e4_VertexVisitor::SetStorage(const e4_Storage &ss) { return SetStorage(ss, E4_DCATTACHED); } /* * Reset the iterator to visit all vertices in a given storage. The * order in which vertices are visited is implementation dependent. */ bool e4_VertexVisitor::SetStorage(const e4_Storage &ss, e4_DetachChoice dc) { if (!ss.IsValid()) { return false; } s = ss; vf = E4_VFNONE; vm = E4_VMSTORAGE; nameID = E4_VERTEXNOTFOUND; nodeID = E4_NODENOTFOUND; parentID = E4_NODENOTFOUND; typeID = E4_VTUNKNOWN; /* * If the given storage is empty, mark this visitor as done. */ detachchoice = dc; done = (!s.FindNextVertex(E4_VERTEXNOTFOUND, vm, vf, nameID, nodeID, parentID, typeID, detachchoice, f)); return true; } /* * Visit all attached vertices in the given storage that match the supplied * name and type constraints. */ bool e4_VertexVisitor::SetStorage(const e4_Storage &ss, const char *nm, e4_VertexType vt) { return SetStorage(ss, nm, vt, E4_DCATTACHED); } /* * Visit all vertices in the given storage that match the supplied * name and type constraints. Vertices are visited in an implementation * dependent order. */ bool e4_VertexVisitor::SetStorage(const e4_Storage &ss, const char *nm, e4_VertexType vt, e4_DetachChoice dc) { if (!ss.IsValid()) { return false; } s = ss; vf = E4_VFNONE; vm = E4_VMSTORAGE; nodeID = E4_NODENOTFOUND; parentID = E4_NODENOTFOUND; typeID = vt; if (nm != NULL) { nameID = s.InternName(nm); vf |= E4_VFNAME; } else { nameID = E4_VERTEXNOTFOUND; } if (vt != E4_VTUNKNOWN) { vf |= E4_VFTYPE; } /* * If the storage is empty or contains no vertices matching the * supplied name and type constraints, mark this visitor * as done. */ detachchoice = dc; done = (!s.FindNextVertex(E4_VERTEXNOTFOUND, vm, vf, nameID, nodeID, parentID, typeID, detachchoice, f)); return true; } /* * Is this instance of e4_VertexVisitor valid? */ bool e4_VertexVisitor::IsValid() { if (!s.IsValid()) { done = true; return false; } return true; } /* * Return the vertex name used to select the vertices to visit. */ const char * e4_VertexVisitor::NameFilter() const { if ((!((e4_VertexVisitor *) this)->IsValid()) || (nameID == E4_VERTEXNOTFOUND)) { return NULL; } return s.GetName(nameID); } /* * Return the node currently being visited (if in visitmode E4_VMNODE or * E4_VMNODERANDOM). Return the node for which this iterator visits all * parent vertices, if visitmode is E4_VMPARENT. */ bool e4_VertexVisitor::NodeVisited(e4_Node &n) const { e4_NodeImpl *nnip; if (!s.IsValid()) { return false; } nnip = s.GetNode(nodeID); if (nnip == NULL) { return false; } e4_Node nn(nnip); n = nn; return true; }