//TODO: merge anchor() and parent() public TreeReference contextualize(TreeReference contextRef) { if (!contextRef.isAbsolute()) { return(null); } TreeReference newRef = anchor(contextRef); for (int i = 0; i < contextRef.size() && i < newRef.size(); i++) { //If the the contextRef can provide a definition for a wildcard, do so if (TreeReference.NAME_WILDCARD.Equals(newRef.getName(i)) && !TreeReference.NAME_WILDCARD.Equals(contextRef.getName(i))) { newRef.names[i] = contextRef.getName(i); } if (contextRef.getName(i).Equals(newRef.getName(i))) { newRef.setMultiplicity(i, contextRef.getMultiplicity(i)); } else { break; } } return(newRef); }
//returns true if 'this' is parent of 'child' //return true if 'this' equals 'child' only if properParent is false public Boolean isParentOf(TreeReference child, Boolean properParent) { if (refLevel != child.refLevel) { return(false); } if (child.size() < size() + (properParent ? 1 : 0)) { return(false); } for (int i = 0; i < size(); i++) { if (!this.getName(i).Equals(child.getName(i))) { return(false); } int parMult = this.getMultiplicity(i); int childMult = child.getMultiplicity(i); if (parMult != INDEX_UNBOUND && parMult != childMult && !(i == 0 && parMult == 0 && childMult == INDEX_UNBOUND)) { return(false); } } return(true); }
public TreeElement getTemplatePath(TreeReference ref_) { if (!ref_.isAbsolute()) { return(null); } TreeElement node = root; for (int i = 0; i < ref_.size(); i++) { String name = ref_.getName(i); if (ref_.getMultiplicity(i) == TreeReference.INDEX_ATTRIBUTE) { node = node.getAttribute(null, name); } else { TreeElement newNode = node.getChild(name, TreeReference.INDEX_TEMPLATE); if (newNode == null) { newNode = node.getChild(name, 0); } if (newNode == null) { return(null); } node = newNode; } } return(node); }
// same as resolveReference but return a vector containing all interstitial // nodes: top-level instance data node first, and target node last // returns null in all the same situations as resolveReference EXCEPT ref // '/' will instead return empty vector public ArrayList explodeReference(TreeReference ref_) { if (!ref_.isAbsolute()) { return(null); } ArrayList nodes = new ArrayList(); TreeElement cur = root; for (int i = 0; i < ref_.size(); i++) { String name = ref_.getName(i); int mult = ref_.getMultiplicity(i); //If the next node down the line is an attribute if (mult == TreeReference.INDEX_ATTRIBUTE) { //This is not the attribute we're testing if (cur != root) { //Add the current node nodes.Add(cur); } cur = cur.getAttribute(null, name); } //Otherwise, it's another child element else { if (mult == TreeReference.INDEX_UNBOUND) { if (cur.getChildMultiplicity(name) == 1) { mult = 0; } else { // reference is not unambiguous return(null); } } if (cur != root) { nodes.Add(cur); } cur = cur.getChild(name, mult); if (cur == null) { return(null); } } } return(nodes); }
public Boolean Equals(Object o) { if (this == o) { return(true); } else if (o is TreeReference) { TreeReference ref_ = (TreeReference)o; if (this.refLevel == ref_.refLevel && this.size() == ref_.size()) { for (int i = 0; i < this.size(); i++) { String nameA = this.getName(i); String nameB = ref_.getName(i); int multA = this.getMultiplicity(i); int multB = ref_.getMultiplicity(i); if (!nameA.Equals(nameB)) { return(false); } else if (multA != multB) { if (i == 0 && (multA == 0 || multA == INDEX_UNBOUND) && (multB == 0 || multB == INDEX_UNBOUND)) { // /data and /data[0] are functionally the same } else { return(false); } } } return(true); } else { return(false); } } else { return(false); } }
//TODO: merge anchor() and parent() public virtual TreeReference contextualize(TreeReference contextRef) { //TODO: Technically we should possibly be modifying context stuff here //instead of in the xpath stuff; if (!contextRef.Absolute) { return(null); } // I think contextualizing of absolute nodes still needs to be done. // They may contain predicates that need to be contextualized. TreeReference newRef = anchor(contextRef); // unclear... newRef.Context = contextRef.Context; //apply multiplicites and fill in wildcards as necessary based on the context ref for (int i = 0; i < contextRef.size() && i < newRef.size(); i++) { //If the the contextRef can provide a definition for a wildcard, do so if (TreeReference.NAME_WILDCARD.Equals(newRef.getName(i)) && !TreeReference.NAME_WILDCARD.Equals(contextRef.getName(i))) { newRef.data.setElementAt(newRef.data.elementAt(i).setName(contextRef.getName(i)), i); } if (contextRef.getName(i).Equals(newRef.getName(i))) { //We can't actually merge nodes if the newRef has predicates or filters //on this expression, since those reset any existing resolutions which //may have been done. if (newRef.getPredicate(i) == null) { newRef.setMultiplicity(i, contextRef.getMultiplicity(i)); } } else { break; } } return(newRef); }
// take a ref that unambiguously refers to a single node and return that node // return null if ref is ambiguous, node does not exist, ref is relative, or ref is '/' // can be used to retrieve template nodes public TreeElement resolveReference(TreeReference ref_) { if (!ref_.isAbsolute()) { return(null); } TreeElement node = root; for (int i = 0; i < ref_.size(); i++) { String name = ref_.getName(i); int mult = ref_.getMultiplicity(i); if (mult == TreeReference.INDEX_ATTRIBUTE) { //Should we possibly just return here? //I guess technically we could step back... node = node.getAttribute(null, name); continue; } if (mult == TreeReference.INDEX_UNBOUND) { if (node.getChildMultiplicity(name) == 1) { mult = 0; } else { // reference is not unambiguous node = null; break; } } node = node.getChild(name, mult); if (node == null) { break; } } return(node == root ? null : node); // never return a reference to '/' }
public override bool Equals(System.Object o) { if (this == o) { return(true); } else if (o is TreeReference) { TreeReference ref_Renamed = (TreeReference)o; if (this.refLevel == ref_Renamed.refLevel && this.size() == ref_Renamed.size()) { for (int i = 0; i < this.size(); i++) { System.String nameA = this.getName(i); System.String nameB = ref_Renamed.getName(i); int multA = this.getMultiplicity(i); int multB = ref_Renamed.getMultiplicity(i); if (!nameA.Equals(nameB)) { return(false); } else if (multA != multB) { if (i == 0 && (multA == 0 || multA == INDEX_UNBOUND) && (multB == 0 || multB == INDEX_UNBOUND)) { // /data and /data[0] are functionally the same } else { return(false); } } else if (predA != null && predB != null) { if (predA.size() != predB.size()) { return(false); } for (int j = 0; j < predA.size(); ++j) { if (!predA.elementAt(j).equals(predB.elementAt(j))) { return(false); } } } else if ((predA == null && predB != null) || (predA != null && predB == null)) { return(false); } } return(true); } else { return(false); } } else { return(false); } }
/* * create the specified node in the tree, creating all intermediary nodes at * each step, if necessary. if specified node already exists, return null * * creating a duplicate node is only allowed at the final step. it will be * done if the multiplicity of the last step is ALL or equal to the count of * nodes already there * * at intermediate steps, the specified existing node is used; if * multiplicity is ALL: if no nodes exist, a new one is created; if one node * exists, it is used; if multiple nodes exist, it's an error * * return the newly-created node; modify ref so that it's an unambiguous ref * to the node */ private TreeElement createNode(TreeReference ref_) { TreeElement node = root; for (int k = 0; k < ref_.size(); k++) { String name = ref_.getName(k); int count = node.getChildMultiplicity(name); int mult = ref_.getMultiplicity(k); TreeElement child; if (k < ref_.size() - 1) { if (mult == TreeReference.INDEX_UNBOUND) { if (count > 1) { return(null); // don't know which node to use } else { // will use existing (if one and only one) or create new mult = 0; ref_.setMultiplicity(k, 0); } } // fetch child = node.getChild(name, mult); if (child == null) { if (mult == 0) { // create child = new TreeElement(name, count); node.addChild(child); ref_.setMultiplicity(k, count); } else { return(null); // intermediate node does not exist } } } else { if (mult == TreeReference.INDEX_UNBOUND || mult == count) { if (k == 0 && root.getNumChildren() != 0) { return(null); // can only be one top-level node, and it // already exists } if (!node.isChildable()) { return(null); // current node can't have children } // create new child = new TreeElement(name, count); node.addChild(child); ref_.setMultiplicity(k, count); } else { return(null); // final node must be a newly-created node } } node = child; } return(node); }
// recursive helper function for expandReference // sourceRef: original path we're matching against // node: current node that has matched the sourceRef thus far // templateRef: explicit path that refers to the current node // refs: Vector to collect matching paths; if 'node' is a target node that // matches sourceRef, templateRef is added to refs private void expandReference(TreeReference sourceRef, TreeElement node, List <TreeReference> refs, Boolean includeTemplates) { int depth = node.getDepth(); if (depth == sourceRef.size()) { refs.Add(node.getRef()); } else { String name = sourceRef.getName(depth); int mult = sourceRef.getMultiplicity(depth); List <TreeElement> set = new List <TreeElement>(); if (node.getNumChildren() > 0) { if (mult == TreeReference.INDEX_UNBOUND) { int count = node.getChildMultiplicity(name); for (int i = 0; i < count; i++) { TreeElement child = node.getChild(name, i); if (child != null) { set.Add(child); } else { throw new InvalidOperationException(); // missing/non-sequential // nodes } } if (includeTemplates) { TreeElement template = node.getChild(name, TreeReference.INDEX_TEMPLATE); if (template != null) { set.Add(template); } } } else if (mult != TreeReference.INDEX_ATTRIBUTE) { //TODO: Make this test mult >= 0? //If the multiplicity is a simple integer, just get //the appropriate child TreeElement child = node.getChild(name, mult); if (child != null) { set.Add(child); } } } if (mult == TreeReference.INDEX_ATTRIBUTE) { TreeElement attribute = node.getAttribute(null, name); set.Add(attribute); } for (IEnumerator e = set.GetEnumerator(); e.MoveNext();) { expandReference(sourceRef, (TreeElement)e.Current, refs, includeTemplates); } } }