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 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<Structure>(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<Structure>(allIterator, structureFilter);
99          
100         FilterIterator.Predicate<Structure> populatedOnly = new FilterIterator.Predicate<Structure>() {
101             public boolean evaluate(Structure obj) {
102                 try {
103                     return !obj.isEmpty();
104                 } catch (HL7Exception e) {
105                     return false; // no exception expected
106                 }
107             }
108         };
109         return new FilterIterator<Structure>(structureIterator, populatedOnly);         
110     }
111     
112     private void addChildren(Group theParent) {
113         String[] names = theParent.getNames();
114         for (int i = names.length - 1; i >= 0; i--) {
115             try {
116                 Structure[] reps = theParent.getAll(names[i]);
117                 for (int j = reps.length - 1; j >= 0; j--) {
118                     myRemaining.add(reps[j]);
119                 }
120             } catch (HL7Exception e) {
121                 throw new Error("Internal error: an invalid child name was obtained from its parent.");
122             }
123         }
124     }
125 
126     /** 
127      * @see java.util.Iterator#hasNext()
128      */
129     public boolean hasNext() {
130         return !myRemaining.isEmpty();
131     }
132 
133     /** 
134      * @see java.util.Iterator#next()
135      */
136     public Structure next() {
137         if (!hasNext()) {
138             throw new NoSuchElementException("No more nodes in message");
139         }
140         
141         Structure next = myRemaining.remove(myRemaining.size() - 1);
142         
143         if (next instanceof Group) {
144             addChildren((Group) next);
145         }
146         
147         return next;
148     }
149 
150     /** 
151      * Not supported.  
152      */
153     public void remove() {
154         throw new UnsupportedOperationException("Can't remove a node from a message");
155     }
156 
157 }