001    package org.vmdb.hl7;
002    
003    /**
004     * <p><Title:> Observation/Result (OBX) Segment. </p>
005     * <p>Description: HL7 Network Connectivity For VMDB. </p>
006     * <p>Copyright: Copyright (c) 2002-2003. </p>
007     * <p>Company: Veterinary Medical Database (VMDB). </p>
008     * <p>The OBX segment is used to transmit a single observation or observation
009     * fragment.  It represents the smallest indivisible unit of a visit summary
010     * report.  The OBX segment identifies the specific type of observation result
011     * being reported (OBX-3) and the specific value of the observation (OBX-5).</p>
012     * <p>Reporting to the VMDB focuses on OBX-3 and OBX-5 as the most informative
013     * elements of the message and thus, full effort should be made to make OBX-3
014     * and OBX-5 as valid and unambiguous as possible.  Because of its flexible
015     * nature, observations of nearly all types can be transmitted through a series
016     * of OBX segments.  Because each segment identifies a separate unique value
017     * for an observation type-observation value pair, there is no limit to the
018     * number of observations that may be transmitted in a single ORU message.
019     * For VMDB reporting a minimum of one diagnosis OBX segment is required.</p>
020     * <p>See HL7 Standard Chapter 7 for details.</p>
021     * @author Michael K. Martin
022     * @version 1.0
023     */
024    
025    public class OBXSegment extends HL7Segment {
026       private String sNm = "OBX";
027       private String sRl =
028                   "DT[SI]ID CE[ST]*[CE][ST][IS][NM][ID]ID[TS]" +
029                   "[ST][TS][CE][XCN][CE][EI][TS]";
030    
031       /**
032       * Construct an empty observation result segment.
033       */
034      public OBXSegment() {
035          setName( sNm );
036          setRule( sRl );
037       }
038    
039       /**
040        * Construct an empty observation result segment, setting its containing message
041        * object.
042        * @param msgParent HL7SegmentContainer (normally a loop) object that
043        * contains this segment.
044        */
045       public OBXSegment( HL7SegmentContainer msgParent ) {
046          super( msgParent );
047          setName( sNm );
048          setRule( sRl );
049       }
050    
051       void initialize() {
052          super.initialize();
053          // Default required by HL7 and almost never changed by us.
054          setResultStatus( "F" );
055       }
056    
057       /**
058        * Override HL7Segment processField to deal with the exceptional case of
059        * OBX 6 Which has type conditional on the value of OBX 2
060        * Let the super class do the heavy lifting by calling it first
061        * @param sField String field name to process
062        * @param sType String with data type of field
063        * @param bRepeatable boolean true if this field <i>may</i> repeat.
064        */
065       boolean processField( String sField, String sType, boolean bRepeatable )
066              throws MalformedFieldException,
067                     MalformedSegmentException {
068            // OBX.5 Type is specified in OBX.2 instead of in the rule
069          if( sField.equalsIgnoreCase( "OBX.5") ) {
070             sType = ((HL7Element)vFields.elementAt(2)).getValue();
071          }
072          return super.processField( sField, sType, bRepeatable );
073       }// End processFields
074    
075       // The following implement direct type-specific get/set pairs based upon position
076    
077       /**
078        * Set the observation set id used to distinguish individual OBX's.
079        * @param sSubId String with 1, 2, 3, etc.
080        */
081       public void setSetId( String sSetId )
082       {
083          try {
084             setField( sSetId, 1 );
085          }
086          catch( ArrayIndexOutOfBoundsException ae ) {
087             ae.printStackTrace();
088          }
089       }
090    
091       /**
092        * Get the observation set id
093        * @return String with set id
094        */
095       public String getSetId() {
096          HL7Element e = getField(1);
097          if( e != null )
098             return e.getValue();
099          else
100             return "";
101       }
102    
103       /**
104        * Set the type of OBX.5 as one of the HL7 data types.  For now, we only
105        * allow those types that we have implemented.
106        * @param sType String with CE, SN, NM, or ST value
107        */
108       public void setObservationValueType( String sType )
109          throws org.vmdb.hl7.MalformedFieldException
110       {
111          if( sType == null ||
112              // TODO: Expand this list to every type allowed keep in order of
113              //       most frequent to least so it will short-circuit the string compares
114              ( !sType.equalsIgnoreCase( "CE" ) &&
115                !sType.equalsIgnoreCase( "SN" ) &&
116                !sType.equalsIgnoreCase( "NM" ) &&
117                !sType.equalsIgnoreCase( "ST" ) ) )
118          {
119             throw new MalformedFieldException( "Type " + sType +
120                                                " not implemented in ObsType" );
121          }
122          getField   (2).setValue( sType.toUpperCase() );
123       }
124    
125       /**
126        * Get the HL7 data type of OBX.5.
127        * @return String with type code
128        */
129       public String getObservationValueType() {
130          HL7Element e = getField(2);
131          if( e != null )
132             return e.getValue();
133          else
134             return "";
135       }
136    
137       /**
138        * Set the type of observation as a LOINC coded CE element.
139        * @param ceObsId a constructed CEElement coding for the observation identifier.
140        *        Normally this will be a preconstructed constant for one of the VMDB
141        *        pre-LOINC-coded identifiers.
142        */
143       public void setObservationIdentifier( CEElement ceObsId ) {
144          try {
145             setField( ceObsId, 3 );
146          }
147          catch( ArrayIndexOutOfBoundsException ae ) {
148             ae.printStackTrace();
149          }
150          catch( MalformedSegmentException mfe ) {
151             mfe.printStackTrace();
152          }
153       }
154    
155       /**
156        * Get the observation identifier as a CEElement.
157        * @return CEElement with identifier.  Use getText() to retrieve human-readable form.
158        */
159       public CEElement getObservationIdentifier() { return (CEElement)getField(3); }
160    
161       /**
162        * Set the observation sub id used to relate two or more OBX's as part of the
163        * same observation such as a modifier added to a term.<br><br>
164        * Normally, it is best to leave this to the logic coded into the
165        * {@link org.vmdb.hl7.ORUMessage#modifyObservation(OBXSegment,CEElement,CEElement) modifyObservation}
166        * method of the ORU message class.
167        * @param sSubId String with 1.1, 1.2, 2.1, etc.
168        */
169       public void setSubId( String sSubId )
170       {
171          try {
172             setField( sSubId, 4 );
173          }
174          catch( ArrayIndexOutOfBoundsException ae ) {
175             ae.printStackTrace();
176          }
177       }
178    
179       /**
180        * Get the observation sub id.
181        * @return String with sub id value.
182        */
183       public String getSubId() {
184          HL7Element e = getField(4);
185          if( e != null )
186             return e.getValue();
187          else
188             return "";
189       }
190    
191       /**
192        * Set the observation value.<br><br>
193        * Since OBX.5 is polymorphic, we use the base
194        * class HL7Element as the input.  The actual value supplied should be the
195        * appropriate subtype as specified in setValueType above.
196        * @param eNewValue HL7Element (or subclass) with value.
197        */
198       public void setObservationValue( HL7Element eNewValue ) {
199          try {
200             setField( eNewValue, 5 );
201          }
202          catch( ArrayIndexOutOfBoundsException ae ) {
203             ae.printStackTrace();
204          }
205          catch( MalformedSegmentException mfe ) {
206             mfe.printStackTrace();
207          }
208       }
209    
210       /**
211        * Set the observation value.<br><br>
212        * This version takes a string representing any of the simple HL7 types.
213        * @param sNewValue String with value of simple data type.
214        */
215       public void setObservationValue( String sNewValue ) {
216          try {
217             setField( sNewValue, 5 );
218          }
219          catch( ArrayIndexOutOfBoundsException ae ) {
220             ae.printStackTrace();
221          }
222       }
223    
224       /**
225        * Get the observation value as base class HL7Element
226        * @return HL7Element containing value.  Cast to appropriate subclass to
227        * extract human-readable form.
228        */
229       public HL7Element getObservationValue() {
230          return getField( 5 );
231       }
232    
233       /**
234        * Set the Units as preformed CEElement.<br><br>
235        * Normally will use a precoded ISO or ANSI coded units.
236        * @param eUnits CEElement with units coded as ISO+ or ANS+
237        */
238       public void setUnits( CEElement eUnits ) {
239          try {
240             setField( eUnits, 6 );
241          }
242          catch( ArrayIndexOutOfBoundsException ae ) {
243             ae.printStackTrace();
244          }
245          catch( MalformedSegmentException mfe ) {
246             mfe.printStackTrace();
247          }
248       }
249    
250       /**
251        * Set the Units as String.<br><br>
252        * Should normally will use a precoded ISO or ANSI coded units but this method
253        * allows use of arbitrary strings for units.
254        * @param sUnits String with units
255        */
256       public void setUnits( String sUnits ) {
257          try {
258             setField( sUnits, 6 );
259          }
260          catch( ArrayIndexOutOfBoundsException ae ) {
261             ae.printStackTrace();
262          }
263       }
264    
265       /**
266        * Get the units as a CEElement
267        * @return CEElement with coded units
268        */
269       public CEElement getUnits() {
270          return (CEElement)getField(6);
271       }
272    
273       /**
274        * Set the result status.<br><br>
275        * This will almost always retain the default of
276        * "F" for final results.  See HL7 2.4 chapter 7 for usage of other codes.
277        * @param sCode String with result status (normally "F")
278        */
279       public void setResultStatus( String sCode ) {
280          try {
281             setField( sCode, 11 );
282          }
283          catch( ArrayIndexOutOfBoundsException ae ) {
284             ae.printStackTrace();
285          }
286       }
287    
288    }// End class OBXSegment
289