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