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