001/**
002The 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. 
004You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
005Software distributed under the License is distributed on an "AS IS" basis, 
006WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
007specific language governing rights and limitations under the License. 
008
009The Original Code is "SegmentPointer.java".  Description: 
010"A SegmentPointer is used when parsing traditionally encoded HL7 messages" 
011
012The Initial Developer of the Original Code is University Health Network. Copyright (C) 
0132001.  All Rights Reserved. 
014
015Contributor(s): ______________________________________. 
016
017Alternatively, the contents of this file may be used under the terms of the 
018GNU General Public License (the "GPL"), in which case the provisions of the GPL are 
019applicable instead of those above.  If you wish to allow use of your version of this 
020file only under the terms of the GPL and not to allow others to use your version 
021of this file under the MPL, indicate your decision by deleting  the provisions above 
022and replace  them with the notice and other provisions required by the GPL License.  
023If you do not delete the provisions above, a recipient may use your version of 
024this file under either the MPL or the GPL. 
025
026*/
027
028/*
029 * Created on October 15, 2001, 3:19 PM
030 */
031
032package ca.uhn.hl7v2.parser;
033
034import org.slf4j.Logger;
035import org.slf4j.LoggerFactory;
036
037import ca.uhn.hl7v2.HL7Exception;
038import ca.uhn.hl7v2.model.Group;
039import ca.uhn.hl7v2.model.Segment;
040
041/**
042 * A SegmentPointer is used when parsing traditionally encoded HL7 messages. 
043 * It acts as a placeholder for a unique segment "slot" in a message structure. 
044 * There is one SegmentPointer per unique segment path (even if the segment 
045 * repeats, and regardless of whether any instances exist).  
046 *
047 * @deprecated PipeParser now uses MessageIterator
048 * @author Bryan Tripp (bryan_tripp@sourceforge.net)
049 */
050public class SegmentPointer extends Pointer {
051
052    private static final Logger log = LoggerFactory.getLogger(SegmentPointer.class);
053    private PipeParser parser;
054    private Group parent;
055    private String name;
056    private EncodingCharacters encodingChars;
057    private boolean repeating;
058    private Segment currSegment = null;
059    private boolean currSegmentFull = true;
060
061    /** 
062     * Creates new SegmentPointer 
063     * @param parser the PipeParser used to parse segments 
064     * @param parent the Group object that would be the parent of any instances of the 
065     *      Segment underlying this SegmentPointer
066     * @param position the position (among siblings; from 0) of the underlying Segment 
067     * @param encodingChars array of encoding characters, starting w/ field delim
068     */
069    public SegmentPointer(PipeParser parser, Group parent, int position, EncodingCharacters encodingChars)
070        throws HL7Exception {
071        this.parser = parser;
072        this.parent = parent;
073        this.encodingChars = encodingChars;
074        this.name = parent.getNames()[position];
075        this.repeating = parent.isRepeating(this.name);
076
077    }
078
079    /**
080     * Parses the given String, which must contain a single traditionally encoded 
081     * message segment, into the current repetition of the message Structure 
082     * underlying this Pointer.  See Pointer static fields for return values. 
083     * @throws HL7Exception if there is an error during parsing 
084     */
085    public int setSegment(String segment, boolean correctOrder) throws HL7Exception {
086        int status = Pointer.FILL_FAILED_WRONG_SEGMENT;
087
088        //make sure segment is right kind
089        if (segment.substring(0, 3).equals(this.name)) {
090            if (correctOrder) {
091                //make sure empty rep exists
092                if (prepEmptyInstance()) {
093                    try {
094                        this.parser.parse(this.currSegment, segment, this.encodingChars);
095                    }
096                    catch (HL7Exception e) {
097                        //add segment name info and re-throw
098                        e.setSegmentName(this.name);
099                        throw e;
100                    }
101                    this.currSegmentFull = true;
102                    status = Pointer.FILL_OK;
103                }
104                else {
105                    status = Pointer.FILL_FAILED_FULL;
106                }
107            }
108            else {
109                status = Pointer.FILL_FAILED_OUT_OF_ORDER;
110            }
111        }
112        log.debug(
113            "Attempt to put segment " + segment.substring(0, 3) + " in " + this.name + ": code = " + status);
114        return status;
115    }
116
117    /** 
118     * Ensures that there is an empty repetition of the underlying message Structure.  
119     * @returns true if successful, false if structure is non-repeating and full. 
120     */
121    private boolean prepEmptyInstance() throws HL7Exception {
122        boolean success = false;
123
124        if (this.currSegment == null || (this.repeating && this.currSegmentFull)) {
125            int numExisting = parent.getAll(this.name).length;
126            this.currSegment = (Segment) parent.get(this.name, numExisting); //get next rep            
127            this.currSegmentFull = false;
128            success = true;
129        }
130        else if (!this.currSegmentFull) {
131            success = true;
132        }
133
134        return success;
135    }
136
137}