View Javadoc
1   /**
2    * The contents of this file are subject to the Mozilla Public License Version 1.1
3    * (the "License"); you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
5    * Software distributed under the License is distributed on an "AS IS" basis,
6    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
7    * specific language governing rights and limitations under the License.
8    *
9    * The Original Code is "ReadOnlyMessageIterator.java".  Description:
10   * "Iterator though existing Stuctures in a message.   "
11   *
12   * The Initial Developer of the Original Code is University Health Network. Copyright (C)
13   * 2005.  All Rights Reserved.
14   *
15   * Contributor(s): ______________________________________.
16   *
17   * Alternatively, the contents of this file may be used under the terms of the
18   * GNU General Public License (the "GPL"), in which case the provisions of the GPL are
19   * applicable instead of those above.  If you wish to allow use of your version of this
20   * file only under the terms of the GPL and not to allow others to use your version
21   * of this file under the MPL, indicate your decision by deleting  the provisions above
22   * and replace  them with the notice and other provisions required by the GPL License.
23   * If you do not delete the provisions above, a recipient may use your version of
24   * this file under either the MPL or the GPL.
25   *
26   */
27  package ca.uhn.hl7v2.util;
28  
29  import java.util.ArrayList;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.NoSuchElementException;
33  
34  import ca.uhn.hl7v2.HL7Exception;
35  import ca.uhn.hl7v2.model.Group;
36  import ca.uhn.hl7v2.model.Segment;
37  import ca.uhn.hl7v2.model.Structure;
38  
39  /**
40   * Iterator though existing Stuctures in a message.  No new repetitions or optional 
41   * structures are created during iteration (in contrast to MessageIterator).  
42   * 
43   * Note that some structures are created during parsing, so the iteration may include 
44   * structures which were not present in the original encoded message.  If these are 
45   * not desired they can be skipped using a FilterIterator.  In fact to obtain an  
46   * iterator only over populated segments (not groups or empty segments) use the factory 
47   * method in this class.  
48   *  
49   * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
50   * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:27 $ by $Author: jamesagnew $
51   */
52  public class ReadOnlyMessageIterator implements Iterator<Structure> {
53  
54      private final List<Structure> myRemaining; //remaining nodes in reverse order (i.e. last is next)
55      
56      /**
57       * @param theRoot root of depth first iteration, which starts with the first child  
58       */
59      public ReadOnlyMessageIterator(Group theRoot) {
60          myRemaining = new ArrayList<>(40);
61          addChildren(theRoot);
62      }
63      
64      /**
65       * @param theRoot root of depth first iteration, which starts with the first child
66       * @return an iterator that skips groups and empty segments, returning only populated 
67       *      segments  
68       */
69      public static Iterator<Structure> createPopulatedSegmentIterator(Group theRoot) {
70          return createPopulatedStructureIterator(theRoot, Segment.class);       
71      }
72      
73      /**
74       * @param theRoot root of depth first iteration, which starts with the first child
75       * @param c structure class to look for
76       * @return an iterator that skips all structures that do not match the parameter
77       */
78      public static Iterator<Structure> createPopulatedStructureIterator(Group theRoot, Class<? extends Structure> c) {
79          return createPopulatedStructureIterator(theRoot, new StructurePredicate(c));       
80      }    
81  
82      /**
83       * @param theRoot root of depth first iteration, which starts with the first child
84       * @param structureName structure name to look for
85       * @return an iterator that skips all structures that do not match the parameter
86       */
87      public static Iterator<Structure> createPopulatedStructureIterator(Group theRoot, String structureName) {
88          return createPopulatedStructureIterator(theRoot, new StructureNamePredicate(structureName));
89      }
90      
91      /**
92       * @param theRoot root of depth first iteration, which starts with the first child
93       * @param structureFilter filter class
94       * @return iterator that skips all structures that the filter does not accept
95       */
96      public static Iterator<Structure> createPopulatedStructureIterator(Group theRoot, FilterIterator.Predicate<Structure> structureFilter) {
97          Iterator<Structure> allIterator = new ReadOnlyMessageIterator(theRoot);
98          Iterator<Structure> structureIterator = new FilterIterator<>(allIterator, structureFilter);
99          
100         FilterIterator.Predicate<Structure> populatedOnly = obj -> {
101             try {
102                 return !obj.isEmpty();
103             } catch (HL7Exception e) {
104                 return false; // no exception expected
105             }
106         };
107         return new FilterIterator<>(structureIterator, populatedOnly);
108     }
109     
110     private void addChildren(Group theParent) {
111         String[] names = theParent.getNames();
112         for (int i = names.length - 1; i >= 0; i--) {
113             try {
114                 Structure[] reps = theParent.getAll(names[i]);
115                 for (int j = reps.length - 1; j >= 0; j--) {
116                     myRemaining.add(reps[j]);
117                 }
118             } catch (HL7Exception e) {
119                 throw new Error("Internal error: an invalid child name was obtained from its parent.");
120             }
121         }
122     }
123 
124     /** 
125      * @see java.util.Iterator#hasNext()
126      */
127     public boolean hasNext() {
128         return !myRemaining.isEmpty();
129     }
130 
131     /** 
132      * @see java.util.Iterator#next()
133      */
134     public Structure next() {
135         if (!hasNext()) {
136             throw new NoSuchElementException("No more nodes in message");
137         }
138         
139         Structure next = myRemaining.remove(myRemaining.size() - 1);
140         
141         if (next instanceof Group) {
142             addChildren((Group) next);
143         }
144         
145         return next;
146     }
147 
148     /** 
149      * Not supported.  
150      */
151     public void remove() {
152         throw new UnsupportedOperationException("Can't remove a node from a message");
153     }
154 
155 }