001    package org.vmdb.hl7;
002    
003    import java.util.*;
004    
005    /**
006     * <p><Title:> Message Header (MSH) Segment. </p>
007     * <p>Description: HL7 Network Connectivity For VMDB. </p>
008     * <p>Copyright: Copyright (c) 2002-2003. </p>
009     * <p>Company: Veterinary Medical Database (VMDB). </p>
010     * <p>The MSH segment defines the intent, source, destination, and some
011     * specifics of the syntax of a message.  Because this information is needed by
012     * the program in order to properly construct the segments that follow, the MSH
013     * should be populated before any additional segments are added.</p>
014     * <p>See HL7 Standard Chapter 2 for details.</p>
015     * @author Michael K. Martin
016     * @version 1.0
017     */
018    
019    public class MSHSegment extends HL7Segment {
020       private String sNm = "MSH";
021       private String sRl = "DT ST ST[HD]HD[HD][HD][TS][ST]MSG ST PT VID" +
022                            "[NM][ST][ID][ID][ID][ID][CE]";
023       private String sVersionId = "2.4";
024    
025       /**
026        * Construct an empty header segment.
027        */
028       public MSHSegment() {
029          setName( sNm );
030          setRule( sRl );
031       }
032    
033       /**
034        * Construct an empty header segment, setting its containing message
035        * object.
036        * @param msgParent HL7Message object that contains this header.  While
037        * declared as an HL7SegmentContainer for consistency with other segments,
038        * The parent of MSH is always a Message object rather than a loop.
039        */
040       public MSHSegment( HL7SegmentContainer msgParent ) {
041          super( msgParent );
042          setName( sNm );
043          setRule( sRl );
044       }
045    
046       void initialize() {
047          super.initialize();
048          setVersionId( sVersionId );
049          setSeparators( super.getSeparators() );
050       }
051    
052       /**
053        * The message name is a concatenation of the message type and version.<br><br>
054        * In the segment structure, these are held in two components of the message name field,
055        * but for display and importantly in the XML tag labels it is displayed with
056        * an underscore between the type and version.  "ORU_R01"
057        * @return String representation of message type and version.
058        */
059       public String getMessageName() {
060          if( getField( 9 ) == null ) return "";
061          MSGElement eField = (MSGElement)getField( 9 );
062          String sMsgType = eField.getMsgType();
063          String sMsgVer = eField.getEventType();
064          StringBuffer sb = new StringBuffer();
065          sb.append( sMsgType );
066          if( sMsgVer != null && sMsgVer.length() > 0 ) {
067             sb.append( '_' );
068             sb.append( sMsgVer );
069          }
070          return sb.toString();
071       }
072    
073    
074       /**
075        * Set the message type and version.<br><br>
076        * This should be called automatically
077        * with no valid reason for the calling system to change it.<br>
078        * Message structure is often but not always name_event.  Where messages
079        * for various events share structure, they use the first event.
080        * @param sMsgType String with message type abbreviation such as "ORU"
081        * @param sEventType String with message event such as "R01"
082        * @param sMsgStructure String with message event such as "ORU_R01"
083        */
084       public void setMessageName( String sMsgType, String sEventType, String sMsgStructure ) {
085          MSGElement eField = null;
086          if( getField( 9 ) == null )
087             eField = new MSGElement();
088          else
089             eField = (MSGElement)getField( 9 );
090          eField.setMsgType( sMsgType );
091          eField.setEventType( sEventType );
092          eField.setMsgStructure( sMsgStructure );
093          try {
094             setField( eField, 9 );
095          }
096          catch( ArrayIndexOutOfBoundsException ae ) {
097             ae.printStackTrace();
098          }
099          catch( MalformedSegmentException mfe ) {
100             mfe.printStackTrace();
101          }
102      }
103    
104    
105       /**
106        * Output segment as HL7.
107        * We have to override HL7Segment because the first two fields are so weird
108        * @return String HL7 properly delimited.
109        */
110       public String toString() {
111          Iterator i = vFields.iterator();
112          StringBuffer sb = new StringBuffer();
113          String sLastName = null;
114          while( i.hasNext() ) {
115             HL7Element eNext = (HL7Element)i.next();
116             String sThisName = eNext.getName();
117             if( sThisName.equals( "MSH.1" ) ) {
118                sb.append( "" );
119             }
120             else if( sThisName.equals( sLastName ) ) {
121                sb.append( getSeparator( REP_SEP ) );
122             }
123             else if( sLastName != null ) {
124                sb.append( getSeparator( FIELD_SEP ) );
125             }
126             sLastName = sThisName;
127             if( sThisName.equals( "MSH.2" ) )
128                sb.append( getSeparators().substring(1,5) );
129             else if( !sThisName.equals( "MSH.1" ) )
130                sb.append( eNext.toString() );
131          }
132          sb.append( getSeparator( FIELD_SEP ) );
133          sb.append( "\n" );
134          return sb.toString();
135       }
136    
137       boolean processField( String sField, String sType, boolean bRepeatable )
138              throws MalformedFieldException,
139                     MalformedSegmentException {
140          boolean bRetVal = false;
141          if( sField == null || sField.length() == 0 || sNextField == null )
142             bRetVal = false;
143          else {
144             // Check field against definition of sField
145             HL7Element e = null;
146             e = HL7Element.makeElement( HL7Element.FIELD, getSeparators(), sType, sField );
147             // Don't try to parse the list of separators or we'll get really |^/&'ed up!
148             if( sField.equalsIgnoreCase("MSH.1") ) {
149                e.setValue("|");
150             }
151             else if( sField.equalsIgnoreCase("MSH.2") ) {
152                e.setValue( sNextField );
153             }
154             else {
155                e.readString( sNextField );
156             }
157             setField( e, sField );
158             bRetVal = true;
159             if( !sField.equalsIgnoreCase( "MSH.0" ) ) {
160                if( slFields.hasMoreStrings() )
161                   sNextField = slFields.nextString();
162                else
163                   sNextField = null;
164             }
165          }
166          return bRetVal;
167       }
168    
169       /*
170        * The following are accessors and mutators for the named values transmitted
171        * in an MSH segment.
172        */
173    
174        /**
175         * Set separators for the message and all its segments.<br><br>
176         * It is strongly suggested that you leave the default separator set as is.
177         * That said, HL7 does allow different separators so this is how they can
178         * be set.  This method is also used within the package to set the default
179         * separators.
180         * @param sSeparators string with separators.
181         */
182       public void setSeparators( String sSeparators ) {
183          super.setSeparators( sSeparators );
184          // hack to set field value in addition to the variable only if
185          // this is an already initialized segment.
186          if( vFields != null && vFields.size() > 2
187              && sSeparators != null && sSeparators.length() > 1 ) {
188             SimpleElement sE1 = new SimpleElement();
189             SimpleElement sE2 = new SimpleElement();
190             sE1.setName( "MSH.2" );
191             sE1.setType( "ST" );
192             sE1.setValue( sSeparators.substring(0,1) );
193             sE2.setName( "MSH.2" );
194             sE2.setType( "ST" );
195             sE2.setValue( sSeparators.substring(1) );
196             try {
197                setField( sE1, 1 );
198                setField( sE2, 2 );
199             }
200             catch( ArrayIndexOutOfBoundsException ae ) {
201                ae.printStackTrace();
202             }
203             catch( MalformedSegmentException mfe ) {
204                mfe.printStackTrace();
205             }
206          }
207       }
208    
209       /**
210        * Set the sending facility.<br><br>
211        * This version takes only the facility ID
212        * @param sName Facility name as listed by VMDB
213        */
214       public void setSendingFacility( String sName ) {
215          setSendingFacility( sName, "", "VMDB" );
216       }
217    
218       /**
219        * Set the sending facility.<br><br>
220        * This version takes a full HD element (mainly for copying)
221        * @param sName Facility name as listed by VMDB
222        */
223       public void setSendingFacility( HDElement hdFacility ) {
224          try {
225             setField( hdFacility, 4 );
226          }
227          catch( ArrayIndexOutOfBoundsException ae ) {
228             ae.printStackTrace();
229          }
230          catch( MalformedSegmentException mfe ) {
231             mfe.printStackTrace();
232          }
233       }
234    
235       /**
236        * Set the sending facility.<br><br>
237        * This version takes only the facility ID
238        * @param sName Facility name as listed by VMDB
239        * @param sID VMDB assigned id number
240        */
241       public void setSendingFacility( String sName, String sId ) {
242          setSendingFacility( sName, sId, "VMDB" );
243       }
244    
245       /**
246        * Set the sending facility.<br><br>
247        * This version takes the fully qualified HD elements
248        * @param sName Facility name as listed by VMDB
249        * @param sID VMDB assigned id number
250        * @param sIDType should always be "VMDB"
251        */
252       public void setSendingFacility( String sNamespaceId, String sId, String sIdType ) {
253          HDElement hdE = new HDElement();
254          hdE.setNamespaceId( sNamespaceId );
255          hdE.setUniversalId( sId );
256          hdE.setUniversalIdType( sIdType );
257          hdE.setName( "MSH.4" );
258          try {
259             setField( hdE, 4 );
260          }
261          catch( ArrayIndexOutOfBoundsException ae ) {
262             ae.printStackTrace();
263          }
264          catch( MalformedSegmentException mfe ) {
265             mfe.printStackTrace();
266          }
267       }
268    
269       /**
270        * Get the sending facility as the complete HDElement.
271        * @return HDElement with sending facility
272        */
273       public HDElement getSendingFacility() {
274          return (HDElement)getField( 4 );
275       }
276    
277       /**
278        * Get just the namespace id of the sending facility, the text string
279        * for the facility name in this case.
280        * @return String with id
281        */
282       public String getSendingFacilityName() {
283          HDElement hdE = (HDElement)getField( 4 );
284          if( hdE != null )
285             return hdE.getNamespaceId();
286          else
287             return "";
288       }
289    
290       /**
291        * Get just the universal id of the sending facility, the VMDB
292        * identifier in this case.
293        * @return String with id
294        */
295       public String getSendingFacilityId() {
296          HDElement hdE = (HDElement)getField( 4 );
297          if( hdE != null )
298             return hdE.getUniversalId();
299          else
300             return "";
301       }
302    
303       /**
304        * Set the Receiving facility.<br><br>
305        * This version takes only the facility ID
306        * @param sName Facility name as listed by VMDB
307        */
308       public void setReceivingFacility( String sName ) {
309          setReceivingFacility( sName, "", "VMDB" );
310       }
311    
312       /**
313        * Set the Receiving facility.<br><br>
314        * This version takes only the facility ID
315        * @param sName Facility name as listed by VMDB
316        * @param sID VMDB assigned id number
317        */
318       public void setReceivingFacility( String sName, String sId ) {
319          setReceivingFacility( sName, sId, "VMDB" );
320       }
321    
322       /**
323        * Set the sending facility.<br><br>
324        * This version takes a full HD element (mainly for copying)
325        * @param sName Facility name as listed by VMDB
326        */
327       public void setReceivingFacility( HDElement hdFacility ) {
328          try {
329             setField( hdFacility, 6 );
330          }
331          catch( ArrayIndexOutOfBoundsException ae ) {
332             ae.printStackTrace();
333          }
334          catch( MalformedSegmentException mfe ) {
335             mfe.printStackTrace();
336          }
337       }
338    
339       /**
340        * Set the Receiving facility.<br><br>
341        * This version takes the fully qualified HD elements
342        * @param sName Facility name as listed by VMDB
343        * @param sID VMDB assigned id number
344        * @param sIDType should always be "VMDB"
345        */
346       public void setReceivingFacility( String sNamespaceId, String sId, String sIdType ) {
347          HDElement hdE = new HDElement();
348          hdE.setNamespaceId( sNamespaceId );
349          hdE.setUniversalId( sId );
350          hdE.setUniversalIdType( sIdType );
351          hdE.setName( "MSH.6" );
352          try {
353             setField( hdE, 6 );
354          }
355          catch( ArrayIndexOutOfBoundsException ae ) {
356             ae.printStackTrace();
357          }
358          catch( MalformedSegmentException mfe ) {
359             mfe.printStackTrace();
360          }
361       }
362    
363       /**
364        * Get the Receiving facility as the complete HDElement.
365        * @return HDElement with Receiving facility
366        */
367       public HDElement getReceivingFacility() {
368          return (HDElement)getField( 6 );
369       }
370    
371       /**
372        * Get just the namespace id of the Receiving facility, the text string
373        * for the facility name in this case.
374        * @return String with id
375        */
376       public String getReceivingFacilityName() {
377          HDElement hdE = (HDElement)getField( 6 );
378          if( hdE != null )
379             return hdE.getNamespaceId();
380          else
381             return "";
382       }
383    
384       /**
385        * Get just the universal id of the Receiving facility, the VMDB
386        * identifier in this case.
387        * @return String with id
388        */
389       public String getReceivingFacilityId() {
390          HDElement hdE = (HDElement)getField( 6 );
391          if( hdE != null )
392             return hdE.getUniversalId();
393          else
394             return "";
395       }
396    
397       /**
398        * Set the date/time of the message to the time now.
399        *
400        */
401       public void setMessageDateTime() {
402          java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat( "yyyyMMddHHmmss" );
403          String sDate = sdf.format( new Date() );
404          TSElement tse = new TSElement();
405          tse.setName( "MSH.7" );
406          tse.setDateTime( sDate );
407          try {
408             setField( tse, 7 );
409          }
410          catch( ArrayIndexOutOfBoundsException ae ) {
411             ae.printStackTrace();
412          }
413          catch( MalformedSegmentException mfe ) {
414             mfe.printStackTrace();
415          }
416       }
417    
418       /**
419        * Set the date/time of the message to string formatted date/time.
420        * @param sDateTime String with date/time in yyyyMMddHHmmss format
421        *
422        */
423       public void setMessageDateTime( String sDateTime ) {
424          TSElement tse = new TSElement();
425          tse.setName( "MSH.7" );
426          tse.setDateTime( sDateTime );
427          try {
428             setField( tse, 7 );
429          }
430          catch( ArrayIndexOutOfBoundsException ae ) {
431             ae.printStackTrace();
432          }
433          catch( MalformedSegmentException mfe ) {
434             mfe.printStackTrace();
435          }
436       }
437    
438       /**
439        * Get the date/time as a string.
440        * @return String date/time
441        */
442       public String getMessageDateTime() {
443          TSElement tse = (TSElement)getField( 7 );
444          if( tse != null )
445             return tse.getDateTime();
446          else
447             return "";
448       }
449    
450       /**
451        * Set the message control ID.<br><br>
452        * This identifier is used to uniquely
453        * identify this message in returned acknowlegements, etc.
454        * @param sMessageControlId a String up to 20 characters usually
455        * a random unique sequence.
456        *
457        */
458       public void setMessageControlId( String sMessageControlId ) {
459          try {
460             setField( sMessageControlId, 10 );
461          }
462          catch( ArrayIndexOutOfBoundsException ae ) {
463             ae.printStackTrace();
464          }
465       }
466    
467       /**
468        * Get the message control ID as a string.
469        * @return String
470        */
471       public String getMessageControlId() {
472          try {
473             return getFieldValue( 10 );
474          }
475          catch( ArrayIndexOutOfBoundsException ae ) {
476             ae.printStackTrace();
477          }
478          return "";
479       }
480    
481       /**
482        * Set the processing ID.<br><br>
483        * This version just the id string
484        * @param sProcessingID D-debug, P-production, or T-training
485        */
486       public void setProcessingId( String sProcessingId ) {
487          HL7Element hE = (HL7Element)getField( 11 );
488          PTElement ptE = null;
489          if( hE == null || !(hE instanceof PTElement) ) {
490             ptE = new PTElement();
491             ptE.setName( "MSH.11" );
492          }
493          else
494             ptE = (PTElement)hE;
495          ptE.setProcessingId( sProcessingId );
496          try {
497             setField( ptE, 11 );
498          }
499          catch( ArrayIndexOutOfBoundsException ae ) {
500             ae.printStackTrace();
501          }
502          catch( MalformedSegmentException mfe ) {
503             mfe.printStackTrace();
504          }
505       }
506    
507       /**
508        * Set the processing mode.<br><br>
509        * This version takes just the mode string
510        * @param sProcessingMode A-archive, R-restore from archive, I-initial load (default)
511        *                        T-current processing.
512        */
513       public void setProcessingMode( String sProcessingMode ) {
514          HL7Element hE = (HL7Element)getField( 11 );
515          PTElement ptE = null;
516          if( hE == null || !(hE instanceof PTElement) ) {
517             ptE = new PTElement();
518             ptE.setName( "MSH.11" );
519          }
520          else
521             ptE = (PTElement)hE;
522          ptE.setProcessingMode( sProcessingMode );
523          ptE.setName( "MSH.11" );
524          try {
525             setField( ptE, 11 );
526          }
527          catch( ArrayIndexOutOfBoundsException ae ) {
528             ae.printStackTrace();
529          }
530          catch( MalformedSegmentException mfe ) {
531             mfe.printStackTrace();
532          }
533       }
534    
535       /**
536        * Set the processing ID from the individual components of a PT Element
537        * @param sProcessingID D-debug, P-production, or T-training
538        * @param sProcessingMode A-archive, R-restore from archive, I-initial load (default)
539        *                        T-current processing.
540        */
541       public void setProcessingId( String sProcessingId, String sProcessingMode ) {
542          PTElement ptE = new PTElement();
543          ptE.setProcessingId( sProcessingId );
544          ptE.setProcessingMode( sProcessingMode );
545          ptE.setName( "MSH.11" );
546          try {
547             setField( ptE, 11 );
548          }
549          catch( ArrayIndexOutOfBoundsException ae ) {
550             ae.printStackTrace();
551          }
552          catch( MalformedSegmentException mfe ) {
553             mfe.printStackTrace();
554          }
555    
556       }
557    
558       /**
559        * Get the processing Id as PT Element.
560        * @return PTElement with sending facility
561        */
562       public PTElement getProcessingIdElement() {
563          return (PTElement)getField( 11 );
564       }
565    
566       /**
567        * Get just the processing Id
568        * @return String with id
569        */
570       public String getProcessingId() {
571          PTElement ptE = (PTElement)getField( 11 );
572          if( ptE != null )
573             return ptE.getProcessingId();
574          else
575             return "";
576       }
577    
578       /**
579        * Get just the processing mode.
580        * @return String with mode
581        */
582       public String getProcessingMode() {
583          PTElement ptE = (PTElement)getField( 11 );
584          if( ptE != null )
585             return ptE.getProcessingMode();
586          else
587             return "";
588       }
589    
590       /**
591        * Set the HL7 Version number.<br><br>
592        * You don't want to do this because it will be wrong if not the constant
593        * included here.  But there may be future exceptions.
594        * @param sVersionId String with version number
595        */
596       public void setVersionId( String sVersionId ) {
597          try {
598             VIDElement vid = (VIDElement)getField( 12 );
599             if( vid != null )
600                vid.setVersionID( sVersionId );
601             else {
602                vid = new VIDElement();
603                vid.setVersionID( sVersionId );
604                setField( sVersionId, 12 );
605             }
606          }
607          catch( ArrayIndexOutOfBoundsException ae ) {
608             ae.printStackTrace();
609          }
610       }
611    
612       /**
613        * Get the HL7 Version number.
614        * @return sVersionId String with version number
615        *
616        */
617       public String getVersionId() {
618          try {
619             VIDElement vid = (VIDElement)getField( 12 );
620             if( vid != null )
621                return vid.getVersionID();
622             else
623                return "";
624          }
625          catch( ArrayIndexOutOfBoundsException ae ) {
626             ae.printStackTrace();
627          }
628          return "";
629       }
630    
631    } // End Class MSHSegment