/// <summary> Navigates to a specific location in the message</summary> private void drillHere(Structure destination) { Structure pathElem = destination; System.Collections.ArrayList pathStack = new System.Collections.ArrayList(); System.Collections.ArrayList indexStack = new System.Collections.ArrayList(); do { NuGenMessageIterator.Index index = NuGenMessageIterator.getIndex(pathElem.Parent, pathElem); indexStack.Add(index); pathElem = pathElem.Parent; pathStack.Add(pathElem); }while (!root.Equals(pathElem) && !typeof(Message).IsAssignableFrom(pathElem.GetType())); if (!root.Equals(pathElem)) { throw new NuGenHL7Exception("The destination provided is not under the root of this navigator"); } this.reset(); while (!(pathStack.Count == 0)) { Group parent = (Group)SupportClass.StackSupport.Pop(pathStack); NuGenMessageIterator.Index index = (NuGenMessageIterator.Index)SupportClass.StackSupport.Pop(indexStack); int child = search(parent.Names, index.name); if (!(pathStack.Count == 0)) { this.drillDown(child, 0); } else { this.toChild(child); } } }
/// <summary> Determines whether the given structure matches the given name, or contains /// a child that does. /// </summary> /// <param name="s">the structure to check /// </param> /// <param name="name">the name to look for /// </param> /// <param name="firstDescendentsOnly">only checks first descendents (i.e. first /// child, first child of first child, etc.) In theory the first child /// of a group should always be present, and we don't use this method with /// subsequent children because finding the next position within a group is /// straightforward. /// </param> /// <param name="upToFirstRequired">only checks first descendents and of their siblings /// up to the first required one. This may be needed because in practice /// some first children of groups are not required. /// </param> public static bool contains(Structure s, System.String name, bool firstDescendentsOnly, bool upToFirstRequired) { bool contains = false; if (typeof(Segment).IsAssignableFrom(s.GetType())) { if (s.getName().Equals(name)) { contains = true; } } else { Group g = (Group)s; System.String[] names = g.Names; for (int i = 0; i < names.Length && !contains; i++) { try { contains = NuGenMessageIterator.contains(g.get_Renamed(names[i], 0), name, firstDescendentsOnly, upToFirstRequired); if (firstDescendentsOnly) { break; } if (upToFirstRequired && g.isRequired(names[i])) { break; } } catch (NuGenHL7Exception e) { throw new System.ApplicationException("HL7Exception due to bad index: " + e.Message); } } } return(contains); }
/// <summary> Iterates through the message tree to the next segment/group location (regardless /// of whether an instance of the segment exists). If the end of the tree is /// reached, starts over at the root. Only enters the first repetition of a /// repeating group -- explicit navigation (using the drill...() methods) is /// necessary to get to subsequent reps. /// </summary> /// <param name="segmentsOnly">if true, only stops at segments (not groups) /// </param> /// <param name="loop">if true, loops back to beginning when end of msg reached; if false, /// throws HL7Exception if end of msg reached /// </param> public virtual void iterate(bool segmentsOnly, bool loop) { Structure start = null; if (this.currentChild == -1) { start = this.currentGroup; } else { start = (this.currentGroup.get_Renamed(this.childNames[this.currentChild])); } //using a non-existent direction and not allowing segment creation means that only //the first rep of anything is traversed. System.Collections.IEnumerator it = new NuGenMessageIterator(start, "doesn't exist", false); if (segmentsOnly) { NuGenFilterIterator.Predicate predicate = new AnonymousClassPredicate(this); it = new NuGenFilterIterator(it, predicate); } if (it.MoveNext()) { Structure next = (Structure)it.Current; drillHere(next); } else if (loop) { this.reset(); } else { throw new NuGenHL7Exception("End of message reached while iterating without loop", NuGenHL7Exception.APPLICATION_INTERNAL_ERROR); } }