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 */ 027package ca.uhn.hl7v2.util; 028 029import java.util.ArrayList; 030import java.util.Iterator; 031import java.util.List; 032import java.util.NoSuchElementException; 033 034import ca.uhn.hl7v2.HL7Exception; 035import ca.uhn.hl7v2.model.Group; 036import ca.uhn.hl7v2.model.Segment; 037import ca.uhn.hl7v2.model.Structure; 038 039/** 040 * Iterator though existing Stuctures in a message. No new repetitions or optional 041 * structures are created during iteration (in contrast to MessageIterator). 042 * 043 * Note that some structures are created during parsing, so the iteration may include 044 * structures which were not present in the original encoded message. If these are 045 * not desired they can be skipped using a FilterIterator. In fact to obtain an 046 * iterator only over populated segments (not groups or empty segments) use the factory 047 * method in this class. 048 * 049 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a> 050 * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:27 $ by $Author: jamesagnew $ 051 */ 052public class ReadOnlyMessageIterator implements Iterator<Structure> { 053 054 private List<Structure> myRemaining; //remaining nodes in reverse order (i.e. last is next) 055 056 /** 057 * @param theRoot root of depth first iteration, which starts with the first child 058 */ 059 public ReadOnlyMessageIterator(Group theRoot) { 060 myRemaining = new ArrayList<Structure>(40); 061 addChildren(theRoot); 062 } 063 064 /** 065 * @param theRoot root of depth first iteration, which starts with the first child 066 * @return an iterator that skips groups and empty segments, returning only populated 067 * segments 068 */ 069 public static Iterator<Structure> createPopulatedSegmentIterator(Group theRoot) { 070 return createPopulatedStructureIterator(theRoot, Segment.class); 071 } 072 073 /** 074 * @param theRoot root of depth first iteration, which starts with the first child 075 * @param c structure class to look for 076 * @return an iterator that skips all structures that do not match the parameter 077 */ 078 public static Iterator<Structure> createPopulatedStructureIterator(Group theRoot, Class<? extends Structure> c) { 079 return createPopulatedStructureIterator(theRoot, new StructurePredicate(c)); 080 } 081 082 /** 083 * @param theRoot root of depth first iteration, which starts with the first child 084 * @param structureName structure name to look for 085 * @return an iterator that skips all structures that do not match the parameter 086 */ 087 public static Iterator<Structure> createPopulatedStructureIterator(Group theRoot, String structureName) { 088 return createPopulatedStructureIterator(theRoot, new StructureNamePredicate(structureName)); 089 } 090 091 /** 092 * @param theRoot root of depth first iteration, which starts with the first child 093 * @param structureFilter filter class 094 * @return iterator that skips all structures that the filter does not accept 095 */ 096 public static Iterator<Structure> createPopulatedStructureIterator(Group theRoot, FilterIterator.Predicate<Structure> structureFilter) { 097 Iterator<Structure> allIterator = new ReadOnlyMessageIterator(theRoot); 098 Iterator<Structure> structureIterator = new FilterIterator<Structure>(allIterator, structureFilter); 099 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}