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 "GroupPointer.java".  Description: 
010    "A GroupPointer is used when parsing traditionally encoded HL7 messages" 
011    
012    The Initial Developer of the Original Code is University Health Network. Copyright (C) 
013    2001.  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    
028    package ca.uhn.hl7v2.parser;
029    
030    import ca.uhn.hl7v2.HL7Exception;
031    import ca.uhn.hl7v2.model.Group;
032    
033    /**
034     * A GroupPointer is used when parsing traditionally encoded HL7 messages. 
035     * It acts as a placeholder for a unique group "slot" in a message structure. 
036     * There is one GroupPointer per unique Group path (even if the group 
037     * repeats, and regardless of whether any instances exist).  
038     *
039     * @deprecated MessageIterator is now used 
040     * @author Bryan Tripp (bryan_tripp@sourceforge.net)
041     */
042    public class GroupPointer extends Pointer {
043    
044        private PipeParser parser;
045        private Group parent;
046        private String name;
047        private boolean repeating;
048        private EncodingCharacters encodingChars;
049        private Pointer[] children;
050        private Group currentGroup = null;
051        private int childAtWhichToStart;
052    
053        /** 
054         * Creates new GroupPointer 
055         */
056        public GroupPointer(PipeParser parser, Group parent, int position, EncodingCharacters encodingChars)
057            throws HL7Exception {
058            this.parser = parser;
059            this.parent = parent;
060            this.name = parent.getNames()[position];
061            this.repeating = parent.isRepeating(this.name);
062            this.encodingChars = encodingChars;
063            //this.createNewInstance();  
064        }
065    
066        /**
067         * Parses the given String, which must contain a single traditionally encoded 
068         * message segment, into the current repetition of the message Group  
069         * underlying this Pointer by forwarding it to each of it's children until 
070         * one of them succeeds.    
071         */
072        public int setSegment(String segment, boolean orderedCorrectly) throws HL7Exception {
073            if (this.currentGroup == null)
074                createNewInstance(); //make first instance of the group
075            int status = tryToFillChildren(segment, orderedCorrectly);
076            if ((status == Pointer.FILL_FAILED_FULL || status == Pointer.FILL_FAILED_OUT_OF_ORDER)
077                && this.repeating
078                && orderedCorrectly) {
079                createNewInstance();
080                status = tryToFillChildren(segment, orderedCorrectly);
081            }
082            return status;
083        }
084    
085        private int tryToFillChildren(String segment, boolean orderedCorrectlyInParent) throws HL7Exception {
086            int status = Pointer.FILL_FAILED_WRONG_SEGMENT;
087            int c = 0;
088            boolean fullOneExists = false;
089            boolean rightSegmentWrongOrder = false;
090    
091            //loop through children ... 
092            //note: can't just stop if FILL_FAILED_FULL b/c have to check all nesting levels 
093            while (status != Pointer.FILL_OK && c < this.children.length) {
094                boolean orderedCorrectly = orderedCorrectlyInParent;
095                if (c < childAtWhichToStart)
096                    orderedCorrectly = false;
097    
098                status = children[c++].setSegment(segment, orderedCorrectly);
099                if (status == Pointer.FILL_FAILED_FULL)
100                    fullOneExists = true;
101                if (status == Pointer.FILL_FAILED_OUT_OF_ORDER)
102                    rightSegmentWrongOrder = true;
103            }
104    
105            //note: but if there was a FILL_FAILED_FULL at any point, can't return FILL_FAILED_WRONG_SEGMENT
106            if (fullOneExists && status == Pointer.FILL_FAILED_WRONG_SEGMENT)
107                status = Pointer.FILL_FAILED_FULL;
108            if (rightSegmentWrongOrder && status == Pointer.FILL_FAILED_WRONG_SEGMENT)
109                status = Pointer.FILL_FAILED_OUT_OF_ORDER;
110    
111            //if filled, update start location so that subsequent segments can't be 
112            //parsed into locations prior to this one 
113            if (status == Pointer.FILL_OK)
114                childAtWhichToStart = c - 1;
115    
116            return status;
117        }
118    
119        /** 
120         * Creates a new, empty repetition of the underlying Group and sets up 
121         * Pointers to it's components.  
122         * @thows HL7Exception if there is already 1 rep and group is non-repeating
123         */
124        private void createNewInstance() throws HL7Exception {
125            //find next rep # ... 
126            int nextRepNum = parent.getAll(this.name).length;
127    
128            this.currentGroup = (Group) parent.get(this.name, nextRepNum);
129            this.childAtWhichToStart = 0;
130    
131            //set up pointers for children ... 
132            String[] childNames = currentGroup.getNames();
133            this.children = new Pointer[childNames.length];
134            for (int i = 0; i < childNames.length; i++) {
135                Pointer p;
136                //make new SegmentPointer or GroupPointer depending on whether child is a Group ... 
137                Class childClass = currentGroup.getClass(childNames[i]);
138                if (Group.class.isAssignableFrom(childClass)) {
139                    p = new GroupPointer(this.parser, currentGroup, i, this.encodingChars);
140                }
141                else {
142                    p = new SegmentPointer(this.parser, currentGroup, i, encodingChars);
143                }
144    
145                this.children[i] = p;
146            }
147    
148        }
149    
150    }