001 /** 002 * The contents of this file are subject to the Mozilla Public License Version 1.1 003 * (the "License"); you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at http://www.mozilla.org/MPL/ 005 * Software distributed under the License is distributed on an "AS IS" basis, 006 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 007 * specific language governing rights and limitations under the License. 008 * 009 * The Original Code is "ReadOnlyMessageIterator.java". Description: 010 * "Iterator though existing Stuctures in a message. " 011 * 012 * The Initial Developer of the Original Code is University Health Network. Copyright (C) 013 * 2005. All Rights Reserved. 014 * 015 * Contributor(s): ______________________________________. 016 * 017 * Alternatively, the contents of this file may be used under the terms of the 018 * GNU General Public License (the ?GPL?), in which case the provisions of the GPL are 019 * applicable instead of those above. If you wish to allow use of your version of this 020 * file only under the terms of the GPL and not to allow others to use your version 021 * of this file under the MPL, indicate your decision by deleting the provisions above 022 * and replace them with the notice and other provisions required by the GPL License. 023 * If you do not delete the provisions above, a recipient may use your version of 024 * this file under either the MPL or the GPL. 025 * 026 */ 027 package ca.uhn.hl7v2.util; 028 029 import java.util.ArrayList; 030 import java.util.Iterator; 031 import java.util.List; 032 import java.util.NoSuchElementException; 033 034 import ca.uhn.hl7v2.HL7Exception; 035 import ca.uhn.hl7v2.model.Group; 036 import ca.uhn.hl7v2.model.Segment; 037 import ca.uhn.hl7v2.model.Structure; 038 import ca.uhn.hl7v2.parser.EncodingCharacters; 039 import ca.uhn.hl7v2.parser.PipeParser; 040 041 /** 042 * Iterator though existing Stuctures in a message. No new repetitions or optional 043 * structures are created during iteration (in contrast to MessageIterator). 044 * 045 * Note that some structures are created during parsing, so the iteration may include 046 * structures which were not present in the original encoded message. If these are 047 * not desired they can be skipped using a FilterIterator. In fact to obtain an 048 * iterator only over populated segments (not groups or empty segments) use the factory 049 * method in this class. 050 * 051 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a> 052 * @version $Revision: 1.1 $ updated on $Date: 2007/02/19 02:24:27 $ by $Author: jamesagnew $ 053 */ 054 public class ReadOnlyMessageIterator implements Iterator { 055 056 private List myRemaining; //remaining nodes in reverse order (i.e. last is next) 057 058 /** 059 * @param theRoot root of depth first iteration, which starts with the first child 060 */ 061 public ReadOnlyMessageIterator(Group theRoot) { 062 myRemaining = new ArrayList(40); 063 addChildren(theRoot); 064 } 065 066 /** 067 * @param theRoot root of depth first iteration, which starts with the first child 068 * @return an iterator that skips groups and empty segments, returning only populated 069 * segments 070 */ 071 public static Iterator createPopulatedSegmentIterator(Group theRoot) { 072 Iterator allIterator = new ReadOnlyMessageIterator(theRoot); 073 074 FilterIterator.Predicate segmentsOnly = new FilterIterator.Predicate() { 075 public boolean evaluate(Object obj) { 076 if (Segment.class.isAssignableFrom(obj.getClass())) { 077 return true; 078 } else { 079 return false; 080 } 081 } 082 }; 083 FilterIterator segmentIterator = new FilterIterator(allIterator, segmentsOnly); 084 085 final EncodingCharacters ec = new EncodingCharacters('|', "^~\\&"); 086 FilterIterator.Predicate populatedOnly = new FilterIterator.Predicate() { 087 public boolean evaluate(Object obj) { 088 String encoded = PipeParser.encode((Segment) obj, ec); 089 if (encoded.length() > 3) { 090 return true; 091 } else { 092 return false; 093 } 094 } 095 }; 096 return new FilterIterator(segmentIterator, populatedOnly); 097 } 098 099 private void addChildren(Group theParent) { 100 String[] names = theParent.getNames(); 101 for (int i = names.length - 1; i >= 0; i--) { 102 try { 103 Structure[] reps = theParent.getAll(names[i]); 104 for (int j = reps.length - 1; j >= 0; j--) { 105 myRemaining.add(reps[j]); 106 } 107 } catch (HL7Exception e) { 108 throw new Error("Internal error: an invalid child name was obtained from its parent."); 109 } 110 } 111 } 112 113 /** 114 * @see java.util.Iterator#hasNext() 115 */ 116 public boolean hasNext() { 117 return !myRemaining.isEmpty(); 118 } 119 120 /** 121 * @see java.util.Iterator#next() 122 */ 123 public Object next() { 124 if (!hasNext()) { 125 throw new NoSuchElementException("No more nodes in message"); 126 } 127 128 Structure next = (Structure) myRemaining.remove(myRemaining.size() - 1); 129 130 if (next instanceof Group) { 131 addChildren((Group) next); 132 } 133 134 return next; 135 } 136 137 /** 138 * Not supported. 139 */ 140 public void remove() { 141 throw new UnsupportedOperationException("Can't remove a node from a message"); 142 } 143 144 }