1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package ca.uhn.hl7v2.testpanel.model.msg;
27
28 import static org.apache.commons.lang.StringUtils.*;
29
30 import java.awt.EventQueue;
31 import java.beans.PropertyVetoException;
32 import java.io.IOException;
33 import java.io.StringReader;
34 import java.io.StringWriter;
35 import java.io.Writer;
36 import java.nio.charset.Charset;
37 import java.nio.charset.IllegalCharsetNameException;
38 import java.util.ArrayList;
39 import java.util.Collections;
40 import java.util.List;
41 import java.util.UUID;
42 import java.util.regex.Matcher;
43 import java.util.regex.Pattern;
44
45 import jakarta.xml.bind.JAXB;
46 import jakarta.xml.bind.annotation.XmlAccessType;
47 import jakarta.xml.bind.annotation.XmlAccessorType;
48 import jakarta.xml.bind.annotation.XmlAttribute;
49 import jakarta.xml.bind.annotation.XmlElement;
50 import jakarta.xml.bind.annotation.XmlRootElement;
51
52 import org.apache.commons.lang.StringUtils;
53 import org.apache.commons.lang.Validate;
54 import org.apache.commons.lang.builder.HashCodeBuilder;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 import ca.uhn.hl7v2.HL7Exception;
59 import ca.uhn.hl7v2.conf.ProfileException;
60 import ca.uhn.hl7v2.model.Message;
61 import ca.uhn.hl7v2.model.Segment;
62 import ca.uhn.hl7v2.parser.GenericParser;
63 import ca.uhn.hl7v2.testpanel.model.AbstractModelClass;
64 import ca.uhn.hl7v2.testpanel.model.UnknownMessage;
65 import ca.uhn.hl7v2.testpanel.model.conf.ProfileFileList;
66 import ca.uhn.hl7v2.testpanel.model.conf.ProfileGroup;
67 import ca.uhn.hl7v2.testpanel.ui.ShowEnum;
68 import ca.uhn.hl7v2.testpanel.util.ClassUtils;
69 import ca.uhn.hl7v2.testpanel.util.LineEndingsEnum;
70 import ca.uhn.hl7v2.testpanel.util.Range;
71 import ca.uhn.hl7v2.testpanel.util.SegmentAndComponentPath;
72 import ca.uhn.hl7v2.testpanel.xsd.Hl7V2EncodingTypeEnum;
73 import ca.uhn.hl7v2.validation.ValidationContext;
74 import ca.uhn.hl7v2.validation.impl.DefaultValidation;
75 import ca.uhn.hl7v2.validation.impl.ValidationContextImpl;
76
77 public class Hl7V2MessageCollection extends AbstractModelClass {
78 private static final Pattern FIRSTLINE_COMMENT_PATTERN = Pattern.compile("^\\#\\s*(\\S.*)");
79 private static final Logger ourLog = LoggerFactory.getLogger(Hl7V2MessageCollection.class);
80 public static final String PARSED_MESSAGES_PROPERTY = Hl7V2MessageCollection.class.getName() + "PARSED_MESSAGES_PROPERTY";
81 public static final String PROP_DESCRIPTION = Hl7V2MessageCollection.class.getName() + "DESCRIPTION";
82 public static final String PROP_ENCODING = Hl7V2MessageCollection.class.getName() + "ENCODING";
83 public static final String PROP_HIGHLITED_PATH = Hl7V2MessageCollection.class.getName() + "HIGHLITED_PATH";
84 public static final String PROP_HIGHLITED_RANGE = Hl7V2MessageCollection.class.getName() + "HIGHLITED_RANGE";
85 public static final String PROP_SAVE_FILENAME = Hl7V2MessageCollection.class.getName() + "SAVE_FILENAME";
86 public static final String PROP_VALIDATIONCONTEXT_OR_PROFILE = Hl7V2MessageCollection.class.getName() + "VALIDATIONCONTEXT";
87 public static final String SAVED_PROPERTY = AbstractMessage.class.getName() + "SAVED_PROPERTY";
88 public static final String SOURCE_MESSAGE_PROPERTY = Hl7V2MessageCollection.class.getName() + "SOURCE_MESSAGE_PROPERTY";
89
90 private Hl7V2EncodingTypeEnum myEncoding = Hl7V2EncodingTypeEnum.ER_7;
91 private String myHighlitedPath;
92 private Range myHighlitedRange;
93 private String myId;
94 private String myLastSendToInterfaceId;
95 private String myMessageDescription;
96 private List<Range> myMessageRanges = new ArrayList<Range>();
97 private List<AbstractMessage<?>> myMessages = new ArrayList<AbstractMessage<?>>();
98 private GenericParser myParser;
99 private String myProfileId;
100 private ProfileGroup myRuntimeProfile;
101 private Charset mySaveCharset;
102 private boolean mySaved;
103 private String mySaveFileName;
104 private long mySaveFileTimestamp;
105 private LineEndingsEnum mySaveLineEndings;
106 private int mySendNumberOfTimes = 1;
107 private ShowEnum myShow;
108 private String mySourceMessage;
109 private boolean myStripSaveComments;
110 private ValidationContext myValidationContext = new DefaultValidation();
111
112
113
114
115 public Hl7V2MessageCollection() {
116 myParser = new GenericParser();
117 myParser.setValidationContext(new ValidationContextImpl());
118
119 myId = UUID.randomUUID().toString();
120 }
121
122 public synchronized void addComment(String theComment) {
123 String oldValue = mySourceMessage;
124
125 ensureSourceMessage();
126
127 StringBuilder b = new StringBuilder();
128 if (myEncoding == Hl7V2EncodingTypeEnum.ER_7) {
129 for (String next : theComment.split("\\n")) {
130 if (StringUtils.isNotBlank(next)) {
131 b.append("#");
132 b.append(next);
133 b.append("\n");
134 } else {
135 b.append("\n");
136 }
137 }
138
139 } else {
140 b.append("<!--");
141 b.append(theComment);
142 b.append("-->\n");
143 }
144
145 int originalLength = mySourceMessage.length();
146 mySourceMessage += b.toString();
147
148 Comment comment = new Comment();
149 comment.setSourceMessage(theComment);
150 myMessages.add(comment);
151
152 ensureSourceMessage();
153
154 myMessageRanges.add(new Range(originalLength, originalLength + b.length()));
155
156 firePropertyChange(SOURCE_MESSAGE_PROPERTY, oldValue, mySourceMessage);
157 firePropertyChange(PARSED_MESSAGES_PROPERTY, oldValue, mySourceMessage);
158 }
159
160 public synchronized void addMessage(AbstractMessage<?> theMessage) {
161 Validate.notNull(theMessage);
162
163 int newIndex = myMessages.size();
164 myMessages.add(theMessage);
165
166 ensureSourceMessage();
167
168 myMessageRanges.add(new Range(mySourceMessage.length()));
169
170 if (theMessage instanceof Hl7V2MessageBase) {
171 updateSourceMessageBasedOnParsedMessage(newIndex, (Message) theMessage.getParsedMessage());
172 }
173 }
174
175 public void clearHighlight() {
176 Range oldValue = myHighlitedRange;
177 myHighlitedRange = null;
178 firePropertyChange(PROP_HIGHLITED_RANGE, oldValue, myHighlitedRange);
179
180 }
181
182 public int countMessagesOfType(Class<Hl7V2MessageBase> theClass) {
183 int retVal = 0;
184 for (AbstractMessage<?> next : getMessages()) {
185 if (theClass.isAssignableFrom(next.getClass())) {
186 retVal++;
187 }
188 }
189 return retVal;
190 }
191
192 private synchronized void doSetSourceMessageEr7(String message) {
193 String[] lines = message.split("\\r");
194
195 StringBuilder buf = new StringBuilder();
196 ParserState curState = ParserState.NONE;
197 int curStart = 0;
198 for (String nextLine : lines) {
199 ParserState newState;
200 if (nextLine.startsWith("#")) {
201 newState = ParserState.COMMENT;
202 } else if (nextLine.startsWith("MSH")) {
203 newState = ParserState.AT_MSG_START;
204 } else {
205 if (nextLine.trim().length() > 0) {
206 if (curState == ParserState.IN_MSG && nextLine.matches("^[A-Z][A-Z0-9][A-Z0-9].*")) {
207 newState = ParserState.IN_MSG;
208 } else {
209 newState = ParserState.UNKNOWN;
210 }
211 } else {
212 newState = ParserState.NONE;
213 }
214 }
215
216 if (curState != newState) {
217 AbstractMessage<?> msg = null;
218 String bufToString = buf.toString();
219 if (bufToString.length() > 0) {
220 switch (curState) {
221 case AT_MSG_START:
222 case IN_MSG:
223 try {
224
225
226
227
228
229
230 ourLog.info("Found ER7 message");
231 Hl7V2MessageBase hl7msg = new Hl7V2MessageEr7();
232 hl7msg.setIndexWithinCollection(myMessages.size());
233 hl7msg.setRuntimeProfile(myRuntimeProfile);
234 hl7msg.setSourceMessage(bufToString);
235 msg = hl7msg;
236
237 } catch (PropertyVetoException e) {
238 msg = new UnknownMessage(bufToString);
239 }
240 break;
241 case COMMENT:
242 msg = new Comment(bufToString);
243 break;
244 case UNKNOWN:
245 msg = new UnknownMessage(bufToString);
246 break;
247 }
248
249 if (msg != null) {
250 myMessages.add(msg);
251 myMessageRanges.add(new Range(curStart, curStart + bufToString.length()));
252 }
253 }
254
255 curStart = curStart + bufToString.length();
256 buf.setLength(0);
257
258 if (newState == ParserState.AT_MSG_START) {
259 curState = ParserState.IN_MSG;
260 } else {
261 curState = newState;
262 }
263 }
264
265 buf.append(nextLine).append('\r');
266
267 }
268
269 String bufToString = buf.toString();
270 if (bufToString.trim().length() > 0) {
271 AbstractMessage<?> msg = null;
272 switch (curState) {
273 case IN_MSG:
274 case AT_MSG_START:
275 try {
276
277 ourLog.info("Found ER7 message");
278 Hl7V2MessageBase hl7msg = new Hl7V2MessageEr7();
279 hl7msg.setIndexWithinCollection(myMessages.size());
280 hl7msg.setRuntimeProfile(myRuntimeProfile);
281 hl7msg.setSourceMessage(bufToString);
282 msg = hl7msg;
283
284 } catch (PropertyVetoException e) {
285 msg = new UnknownMessage(bufToString);
286 }
287 break;
288 case COMMENT:
289 msg = new Comment(bufToString);
290 break;
291 case UNKNOWN:
292 msg = new UnknownMessage(bufToString);
293 break;
294 }
295
296 if (msg != null) {
297 myMessages.add(msg);
298 myMessageRanges.add(new Range(curStart, curStart + bufToString.length()));
299 }
300
301 }
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341 }
342
343 private synchronized void doSetSourceMessageXml(String theMessage) {
344 int rangeStart = 0;
345 int rangeEnd = 0;
346
347 Pattern p = Pattern.compile("<([A-Za-z0-9_]+).*?>");
348 Matcher m = p.matcher(theMessage);
349
350 while (rangeStart < theMessage.length() && m.find(rangeStart)) {
351
352 int startIndex = m.start();
353 String tagName = m.group(1);
354
355 Pattern endP = Pattern.compile("</" + tagName + "(\\s.*?)?>");
356 Matcher endM = endP.matcher(theMessage);
357 boolean foundEnd = endM.find(startIndex);
358
359 if (foundEnd) {
360
361 String fullMsg = theMessage.substring(startIndex, endM.end());
362 Hl7V2MessageXml nextMsg = new Hl7V2MessageXml();
363 nextMsg.setIndexWithinCollection(myMessages.size());
364 nextMsg.setRuntimeProfile(myRuntimeProfile);
365 nextMsg.setEncoding(Hl7V2EncodingTypeEnum.XML);
366 try {
367 nextMsg.setSourceMessage(fullMsg);
368 myMessages.add(nextMsg);
369 } catch (PropertyVetoException e) {
370 UnknownMessage nextUnk = new UnknownMessage(fullMsg);
371 myMessages.add(nextUnk);
372 }
373
374 rangeEnd = endM.end();
375
376 } else {
377
378 String fullMsg = theMessage.substring(startIndex);
379 UnknownMessage nextUnk = new UnknownMessage(fullMsg);
380 myMessages.add(nextUnk);
381 rangeEnd = theMessage.length();
382
383 }
384
385 myMessageRanges.add(new Range(rangeStart, rangeEnd));
386 rangeStart = rangeEnd;
387
388 }
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409 }
410
411 private void ensureSourceMessage() {
412 if (mySourceMessage == null) {
413 mySourceMessage = "";
414 }
415 }
416
417
418
419
420 @Override
421 public boolean equals(Object theObj) {
422 if (!(theObj instanceof Hl7V2MessageCollection)) {
423 return false;
424 }
425 Hl7V2MessageCollection o = (Hl7V2MessageCollection) theObj;
426 return StringUtils.equals(myId, o.myId);
427 }
428
429 @Override
430 public String exportConfigToXml() {
431 XmlFormat xml = exportCreate();
432 return exportWrite(xml);
433 }
434
435 public XmlFormat exportConfigToXmlWithoutContents() {
436 XmlFormat xml = exportCreate();
437 xml.mySourceMessage = null;
438 return xml;
439 }
440
441 private XmlFormat exportCreate() {
442 XmlFormat xml = new XmlFormat();
443
444 xml.myId = this.myId;
445
446 if (getSaveFileName() == null) {
447 xml.mySourceMessage = this.mySourceMessage.replaceAll("((\r\n)|\r)|(\n)", "\n");
448 }
449
450 xml.mySaveCharsetName = mySaveCharset != null ? mySaveCharset.name() : "";
451 xml.mySaved = this.mySaved;
452 xml.mySaveFileName = StringUtils.isNotBlank(mySaveFileName) ? mySaveFileName : "";
453 xml.myEncodingType = myEncoding.name();
454 xml.myValidationContextClass = myValidationContext != null ? myValidationContext.getClass().getName() : "";
455 xml.myProfileId = myProfileId != null ? myProfileId : "";
456 xml.mySaveStripComments = Boolean.toString(myStripSaveComments);
457 xml.mySaveLineEndings = mySaveLineEndings != null ? mySaveLineEndings.name() : "";
458 xml.mySaveTimestamp = mySaveFileTimestamp;
459 xml.myLastSendToInterfaceId = myLastSendToInterfaceId;
460 xml.myEditorShowMode = getEditorShowMode();
461 xml.mySendNumberOfTimes = mySendNumberOfTimes;
462 return xml;
463 }
464
465 private String exportWrite(XmlFormat xml) {
466 StringWriter stringWriter = new StringWriter();
467 JAXB.marshal(xml, stringWriter);
468 String string = stringWriter.toString();
469 return string;
470 }
471
472 private synchronized int findSegmentMsgIndex(Message message) {
473 int msgIndex = -1;
474 for (int i = 0; i < myMessages.size(); i++) {
475 Object nextParsed = myMessages.get(i).getParsedMessage();
476 if (nextParsed == message) {
477 msgIndex = i;
478 break;
479 }
480 }
481 return msgIndex;
482 }
483
484 private String fixLineEndings(String theSourceMessage, LineEndingsEnum theEndings) {
485 StringBuilder b = new StringBuilder(theSourceMessage.length());
486
487 for (int i = 0; i < theSourceMessage.length(); i++) {
488
489 char next = theSourceMessage.charAt(i);
490 boolean isEnd = false;
491 if (next == '\r') {
492 isEnd = true;
493 } else if (next == '\n') {
494 if (i > 0 && theSourceMessage.charAt(i - 1) == '\r') {
495 continue;
496 } else {
497 isEnd = true;
498 }
499 }
500
501 if (isEnd) {
502 if (theEndings == LineEndingsEnum.UNIX) {
503 b.append('\n');
504 } else if (theEndings == LineEndingsEnum.HL7) {
505 b.append('\r');
506 } else if (theEndings == LineEndingsEnum.WINDOWS) {
507 b.append('\r');
508 b.append('\n');
509 }
510 } else {
511 b.append(next);
512 }
513
514 }
515
516 return b.toString();
517 }
518
519
520
521
522
523 public String getBestDescription() {
524 if (mySaveFileName != null) {
525 return mySaveFileName;
526 }
527 return getMessageDescription();
528 }
529
530
531
532
533 public ShowEnum getEditorShowMode() {
534 if (myShow == null) {
535 myShow = ShowEnum.POPULATED;
536 }
537 return myShow;
538 }
539
540 public Hl7V2EncodingTypeEnum getEncoding() {
541 return myEncoding;
542 }
543
544 public String getHighlitedPath() {
545 return myHighlitedPath;
546 }
547
548 public String getId() {
549 return myId;
550 }
551
552
553
554
555 public String getLastSendToInterfaceId() {
556 return myLastSendToInterfaceId;
557 }
558
559 public String getMessageDescription() {
560 if (myMessageDescription == null) {
561 updateMessageDescription();
562 }
563 return myMessageDescription;
564 }
565
566
567
568
569 public List<Range> getMessageRanges() {
570 return Collections.unmodifiableList(myMessageRanges);
571 }
572
573
574
575
576 public List<AbstractMessage<?>> getMessages() {
577 return myMessages;
578 }
579
580
581
582
583 public ProfileGroup getRuntimeProfile() {
584 return myRuntimeProfile;
585 }
586
587
588
589
590 public Charset getSaveCharset() {
591 return mySaveCharset;
592 }
593
594
595
596
597 public String getSaveFileName() {
598 return mySaveFileName;
599 }
600
601
602
603
604 public long getSaveFileTimestamp() {
605 return mySaveFileTimestamp;
606 }
607
608
609
610
611 public LineEndingsEnum getSaveLineEndings() {
612 return mySaveLineEndings;
613 }
614
615
616
617
618 public int getSendNumberOfTimes() {
619 if (mySendNumberOfTimes <= 0) {
620 return 1;
621 }
622 return mySendNumberOfTimes;
623 }
624
625 public String getSourceMessage() {
626 return mySourceMessage;
627 }
628
629
630
631
632 public ValidationContext getValidationContext() {
633 return myValidationContext;
634 }
635
636
637
638
639 @Override
640 public int hashCode() {
641 return new HashCodeBuilder().append(myId).toHashCode();
642 }
643
644
645
646
647 public boolean isSaved() {
648 return mySaved;
649 }
650
651
652
653
654 public boolean isSaveStripComments() {
655 return myStripSaveComments;
656 }
657
658 public boolean isValidating() {
659 return myValidationContext != null || myRuntimeProfile != null;
660 }
661
662
663
664
665
666 public void setEditorShowMode(ShowEnum theShow) {
667 myShow = theShow;
668 }
669
670 public void setEncoding(Hl7V2EncodingTypeEnum theEncoding) {
671 Validate.notNull(theEncoding);
672
673 Hl7V2EncodingTypeEnum oldEncodingValue = myEncoding;
674 if (myEncoding != theEncoding) {
675 myEncoding = theEncoding;
676
677 switch (myEncoding) {
678 case ER_7:
679 myParser.setPipeParserAsPrimary();
680 break;
681 case XML:
682 myParser.setXMLParserAsPrimary();
683 break;
684 }
685
686 StringBuilder b = new StringBuilder();
687 myMessageRanges.clear();
688
689 for (int i = 0; i < myMessages.size(); i++) {
690 int start = b.length();
691
692 AbstractMessage<?> nextObj = myMessages.get(i);
693 if (nextObj instanceof Hl7V2MessageBase) {
694
695 Hl7V2MessageBase messageImpl = (Hl7V2MessageBase) nextObj;
696 messageImpl = messageImpl.asEncoding(myEncoding);
697
698 b.append(messageImpl.getSourceMessage());
699 myMessages.set(i, messageImpl);
700
701 } else if (nextObj instanceof UnknownMessage) {
702
703 UnknownMessage messageImpl = (UnknownMessage) nextObj;
704 b.append(messageImpl.getSourceMessage());
705
706 }
707
708 b.append("\r\r");
709 int end = b.length();
710 myMessageRanges.add(new Range(start, end));
711 }
712
713 String oldValue = mySourceMessage;
714 mySourceMessage = b.toString();
715 firePropertyChange(SOURCE_MESSAGE_PROPERTY, oldValue, mySourceMessage);
716
717 if (StringUtils.equals(oldValue, mySourceMessage) == false) {
718 setSaved(false);
719 }
720
721 firePropertyChange(PROP_ENCODING, oldEncodingValue, myEncoding);
722 }
723 }
724
725 public void setHighlitedPathBasedOnRange(Range theRange) {
726
727 final String oldValue = myHighlitedPath;
728
729 if (theRange == null) {
730 myHighlitedPath = null;
731 } else {
732 for (int i = 0; i < myMessageRanges.size(); i++) {
733 Range range = myMessageRanges.get(i);
734 if (range.contains(theRange.getStart())) {
735 AbstractMessage<?> am = myMessages.get(i);
736 if (am instanceof Hl7V2MessageBase) {
737 Hl7V2MessageBase messageImpl = (Hl7V2MessageBase) am;
738 messageImpl.setHighlitedPathBasedOnRange(theRange.add(-range.getStart()));
739 myHighlitedPath = i + messageImpl.getHighlitedPath();
740 }
741 break;
742 }
743 }
744 }
745
746 EventQueue.invokeLater(new Runnable() {
747 public void run() {
748 firePropertyChange(PROP_HIGHLITED_PATH, oldValue, myHighlitedPath);
749 updateMessageDescription();
750 }
751 });
752
753 }
754
755 public void setHighlitedRangeBasedOnField(SegmentAndComponentPath thePath) {
756 Segment segment = thePath.getSegment();
757 Message message = segment.getMessage();
758 int msgIndex = findSegmentMsgIndex(message);
759
760 Range oldValue = myHighlitedRange;
761 if (msgIndex != -1) {
762 Hl7V2MessageBase msg = (Hl7V2MessageBase) myMessages.get(msgIndex);
763 msg.setHighlitedField(thePath);
764 myHighlitedRange = msg.getHighlitedRange();
765 if (myHighlitedRange != null) {
766 myHighlitedRange = myHighlitedRange.add(myMessageRanges.get(msgIndex).getStart());
767 } else {
768 ourLog.info("No highlited range");
769 }
770 } else {
771 ourLog.info("Couldn't find message");
772 }
773
774 firePropertyChange(PROP_HIGHLITED_RANGE, oldValue, myHighlitedRange);
775 }
776
777 public void setHighlitedRangeBasedOnSegment(Segment... theSegment) {
778 Range oldValue = myHighlitedRange;
779
780 if (theSegment == null || theSegment.length == 0) {
781 myHighlitedRange = null;
782 firePropertyChange(PROP_HIGHLITED_RANGE, oldValue, myHighlitedRange);
783 return;
784 }
785
786 Message message = theSegment[0].getMessage();
787 int msgIndex = findSegmentMsgIndex(message);
788
789 if (msgIndex != -1) {
790 Hl7V2MessageBase msg = (Hl7V2MessageBase) myMessages.get(msgIndex);
791 msg.setHighlitedRangeBasedOnSegment(theSegment);
792 myHighlitedRange = msg.getHighlitedRange();
793 if (myHighlitedRange != null) {
794 myHighlitedRange = myHighlitedRange.add(myMessageRanges.get(msgIndex).getStart());
795 } else {
796 ourLog.info("No highlited range");
797 }
798 } else {
799 ourLog.info("Couldn't find message");
800 }
801
802 firePropertyChange(PROP_HIGHLITED_RANGE, oldValue, myHighlitedRange);
803
804 }
805
806 private void setId(String theId) {
807 myId = theId;
808 }
809
810
811
812
813
814 public void setLastSendToInterfaceId(String theLastSendToInterfaceId) {
815 myLastSendToInterfaceId = theLastSendToInterfaceId;
816 }
817
818 public void setRuntimeProfile(ProfileGroup theProfileGroup) throws ProfileException {
819 if (theProfileGroup == null && myRuntimeProfile == null && myValidationContext == null) {
820 return;
821 }
822
823 if (theProfileGroup == null && myRuntimeProfile == null && myValidationContext != null) {
824 myValidationContext = null;
825 myRuntimeProfile = null;
826 myProfileId = null;
827 firePropertyChange(PROP_VALIDATIONCONTEXT_OR_PROFILE, null, null);
828 return;
829 }
830
831 myRuntimeProfile = theProfileGroup;
832 myValidationContext = null;
833 myProfileId = theProfileGroup.getId();
834
835 for (AbstractMessage<?> next : myMessages) {
836 if (next instanceof Hl7V2MessageBase) {
837 ((Hl7V2MessageBase) next).setRuntimeProfile(myRuntimeProfile);
838 }
839 }
840
841 firePropertyChange(PROP_VALIDATIONCONTEXT_OR_PROFILE, null, null);
842 }
843
844
845
846
847
848 public void setSaveCharset(Charset theSaveCharset) {
849 mySaveCharset = theSaveCharset;
850 }
851
852
853
854
855
856 public void setSaved(boolean theSaved) {
857 boolean oldValue = mySaved;
858 mySaved = theSaved;
859 firePropertyChange(SAVED_PROPERTY, oldValue, mySaved);
860 }
861
862
863
864
865
866 public void setSaveFileName(String theFileName) {
867 String oldValue = null;
868 mySaveFileName = theFileName;
869 firePropertyChange(PROP_SAVE_FILENAME, oldValue, theFileName);
870
871 updateMessageDescription();
872 }
873
874
875
876
877
878 public void setSaveFileTimestamp(long theSaveFileTimestamp) {
879 mySaveFileTimestamp = theSaveFileTimestamp;
880 }
881
882 public void setSaveLineEndings(LineEndingsEnum theLineEndings) {
883 mySaveLineEndings = theLineEndings;
884 }
885
886 public void setSaveStripComments(boolean theSaveComments) {
887 myStripSaveComments = theSaveComments;
888 }
889
890
891
892
893
894 public void setSendNumberOfTimes(int theSendNumberOfTimes) {
895 mySendNumberOfTimes = theSendNumberOfTimes;
896 }
897
898 public void setSourceMessage(String theSourceMessage) {
899 ourLog.info("About to set source message for collection");
900
901 ArrayList<AbstractMessage<?>> oldMessages = new ArrayList<AbstractMessage<?>>(myMessages);
902 myMessages.clear();
903 myMessageRanges.clear();
904
905 String message = fixLineEndings(theSourceMessage, LineEndingsEnum.HL7);
906
907 if (myEncoding == Hl7V2EncodingTypeEnum.ER_7) {
908 doSetSourceMessageEr7(message);
909 } else {
910 doSetSourceMessageXml(message);
911 }
912
913 String oldValue = mySourceMessage;
914 mySourceMessage = theSourceMessage;
915
916 ourLog.info("Firing message change event");
917
918 firePropertyChange(PARSED_MESSAGES_PROPERTY, oldMessages, myMessages);
919 firePropertyChange(SOURCE_MESSAGE_PROPERTY, oldValue, mySourceMessage);
920
921 if (StringUtils.equals(oldValue, mySourceMessage) == false) {
922 setSaved(false);
923 }
924
925 updateMessageDescription();
926
927 ourLog.info("Done setting source message for collection");
928 }
929
930
931
932
933
934 public void setValidationContext(ValidationContext theValidationContext) {
935 if (myValidationContext instanceof DefaultValidationpl/DefaultValidation.html#DefaultValidation">DefaultValidation && theValidationContext instanceof DefaultValidation) {
936 return;
937 }
938
939 if (theValidationContext != null) {
940 myRuntimeProfile = null;
941 myRuntimeProfile = null;
942 }
943
944 ourLog.info("Setting validation context to: " + theValidationContext);
945
946 for (AbstractMessage<?> next : myMessages) {
947 if (next instanceof Hl7V2MessageBase) {
948 ((Hl7V2MessageBase) next).setRuntimeProfile(null);
949 }
950 }
951
952 ValidationContext oldValue = myValidationContext;
953 myValidationContext = theValidationContext;
954 firePropertyChange(PROP_VALIDATIONCONTEXT_OR_PROFILE, oldValue, theValidationContext);
955 }
956
957
958
959
960 @Override
961 public String toString() {
962 return Hl7V2MessageCollection.class.getSimpleName() + "[" + getSaveFileName() + "]";
963 }
964
965 private void updateMessageDescription() {
966 String oldValue = myMessageDescription;
967
968 Matcher matcher = FIRSTLINE_COMMENT_PATTERN.matcher(StringUtils.defaultString(mySourceMessage));
969 if (matcher.find()) {
970
971 myMessageDescription = matcher.group(1).trim();
972
973 } else if (mySaveFileName == null) {
974
975 int msgs = 0;
976 AbstractMessage<?> firstNonComment = null;
977 for (AbstractMessage<?> next : myMessages) {
978 if (!(next instanceof Comment)) {
979 if (msgs == 0) {
980 firstNonComment = next;
981 }
982 msgs++;
983 }
984 }
985
986 if (msgs == 0) {
987 myMessageDescription = "None";
988 } else if (msgs == 1) {
989 if (firstNonComment instanceof UnknownMessage) {
990 myMessageDescription = "Unknown";
991 } else if (firstNonComment instanceof Hl7V2MessageBase) {
992 myMessageDescription = ((Hl7V2MessageBase) firstNonComment).getMessageDescription();
993 } else {
994 myMessageDescription = "None";
995 }
996 } else {
997 myMessageDescription = msgs + " messages";
998 }
999
1000 } else {
1001
1002 myMessageDescription = mySaveFileName.replaceAll(".*(\\\\|\\/)", "");
1003
1004 }
1005
1006 firePropertyChange(PROP_DESCRIPTION, oldValue, myMessageDescription);
1007 }
1008
1009 public void updateSourceMessage(String theNewSource, int theChangeStart, int theChangeEnd) {
1010
1011 setSourceMessage(theNewSource);
1012 }
1013
1014 private synchronized void updateSourceMessageBasedOnEncodedMessage(int theMessageIndex, String theEncodedMessage) {
1015 setHighlitedPathBasedOnRange(null);
1016
1017 Range range = myMessageRanges.get(theMessageIndex);
1018
1019 String oldValue = mySourceMessage;
1020
1021 String preMessage = mySourceMessage.substring(0, range.getStart());
1022 String postMessage = mySourceMessage.length() > range.getEnd() ? mySourceMessage.substring(range.getEnd()) : "";
1023 mySourceMessage = preMessage + theEncodedMessage + postMessage;
1024
1025 int sizeDifference = theEncodedMessage.length() - range.getDelta();
1026 for (int i = theMessageIndex; i < myMessageRanges.size(); i++) {
1027 if (i == theMessageIndex) {
1028 myMessageRanges.set(i, myMessageRanges.get(i).addToEnd(sizeDifference));
1029 } else {
1030 myMessageRanges.set(i, myMessageRanges.get(i).addToBoth(sizeDifference));
1031 }
1032 }
1033
1034 Hl7V2MessageBase msgBase = (Hl7V2MessageBase) myMessages.get(theMessageIndex);
1035 try {
1036 msgBase.setSourceMessage(theEncodedMessage);
1037 } catch (PropertyVetoException e) {
1038 ourLog.error("Failed to update message", e);
1039 }
1040
1041 firePropertyChange(SOURCE_MESSAGE_PROPERTY, oldValue, mySourceMessage);
1042
1043 if (StringUtils.equals(oldValue, mySourceMessage) == false) {
1044 setSaved(false);
1045 }
1046
1047 }
1048
1049 public void updateSourceMessageBasedOnParsedMessage(int theMessageIndex, Message theMsg) {
1050 String encodedMessage;
1051 try {
1052 encodedMessage = myParser.encode(theMsg);
1053 } catch (HL7Exception e) {
1054 ourLog.error("Failed to encode message", e);
1055 return;
1056 }
1057
1058 updateSourceMessageBasedOnEncodedMessage(theMessageIndex, encodedMessage);
1059 }
1060
1061
1062
1063
1064 public void writeToFile(Writer theWriter, boolean theSelectedSaveStripComments, LineEndingsEnum theSelectedLineEndings) throws IOException {
1065 String toWrite = mySourceMessage;
1066
1067 if (theSelectedSaveStripComments) {
1068 switch (myEncoding) {
1069 case ER_7:
1070
1071 Pattern p = Pattern.compile("(^|\\r)\\s*#[^\\r]*");
1072 Matcher m = p.matcher(toWrite);
1073 toWrite = m.replaceAll("").trim() + "\r";
1074
1075 p = Pattern.compile("\\r\\s*\\r");
1076 m = p.matcher(toWrite);
1077 toWrite = m.replaceAll("\r");
1078
1079 break;
1080 }
1081 }
1082
1083 toWrite = fixLineEndings(toWrite, theSelectedLineEndings);
1084
1085 theWriter.append(toWrite);
1086 }
1087
1088 public static Hl7V2MessageCollection fromXml(ProfileFileList theProfileFileList, String theContents) {
1089 XmlFormat xmlFormat = JAXB.unmarshal(new StringReader(theContents),XmlFormat.class);
1090 return fromXml(theProfileFileList, xmlFormat);
1091 }
1092
1093 public static Hl7V2MessageCollection fromXml(ProfileFileList theProfileFileList, XmlFormat theXmlFormat) {
1094
1095 Hl7V2MessageCollection retVal = new Hl7V2MessageCollection();
1096
1097 retVal.setSaveFileName(isNotBlank(theXmlFormat.mySaveFileName) ? theXmlFormat.mySaveFileName : null);
1098 retVal.setId(theXmlFormat.myId);
1099 retVal.setLastSendToInterfaceId(theXmlFormat.myLastSendToInterfaceId);
1100 retVal.setEditorShowMode(theXmlFormat.myEditorShowMode);
1101 retVal.setSendNumberOfTimes(theXmlFormat.mySendNumberOfTimes);
1102
1103 try {
1104 retVal.setSaveCharset(isNotEmpty(theXmlFormat.mySaveCharsetName) ? Charset.forName(theXmlFormat.mySaveCharsetName) : null);
1105 } catch (IllegalCharsetNameException e) {
1106
1107 }
1108
1109 if (isNotBlank(theXmlFormat.myValidationContextClass)) {
1110 retVal.setValidationContext(ClassUtils.instantiateOrReturnNull(theXmlFormat.myValidationContextClass, ValidationContext.class));
1111 }
1112
1113 if (isNotBlank(theXmlFormat.myProfileId)) {
1114 try {
1115 retVal.setRuntimeProfile(theProfileFileList.getProfile(theXmlFormat.myProfileId));
1116 } catch (ProfileException e) {
1117 ourLog.error("Failed to retrieve profile with id: " + theXmlFormat.myProfileId, e);
1118 }
1119 }
1120
1121 try {
1122 retVal.setSaveLineEndings(LineEndingsEnum.valueOf(theXmlFormat.mySaveLineEndings));
1123 } catch (Exception e) {
1124 retVal.setSaveLineEndings(LineEndingsEnum.HL7);
1125 }
1126
1127 retVal.setSaveStripComments(Boolean.parseBoolean(theXmlFormat.mySaveStripComments));
1128
1129 retVal.setEncoding("XML".equals(theXmlFormat.myEncodingType) ? Hl7V2EncodingTypeEnum.XML : Hl7V2EncodingTypeEnum.ER_7);
1130
1131 if (StringUtils.isNotBlank(theXmlFormat.mySourceMessage)) {
1132 retVal.setSourceMessage(theXmlFormat.mySourceMessage);
1133 } else {
1134 retVal.setSourceMessage("");
1135 }
1136
1137 retVal.setSaveFileTimestamp(theXmlFormat.mySaveTimestamp);
1138
1139
1140 retVal.setSaved(theXmlFormat.mySaved);
1141
1142 return retVal;
1143 }
1144
1145 public static void main(String[] args) {
1146
1147 System.out.println(Pattern.compile("<([A-Z0-9_]+)").matcher("<ORU_R01 xmlns=\"ffdf\">aaaaa").find());
1148
1149 }
1150
1151 private enum ParserState {
1152 AT_MSG_START, COMMENT, IN_MSG, NONE, UNKNOWN
1153 }
1154
1155 @XmlAccessorType(XmlAccessType.FIELD)
1156 @XmlRootElement(name = "Hl7V2MessageCollection", namespace = "urn:ca.uhn.hapi:testpanel")
1157 public static class XmlFormat {
1158
1159 @XmlAttribute(required = false, name = "editorShowMode")
1160 public ShowEnum myEditorShowMode;
1161
1162 @XmlAttribute(required = true, name = "encodingType")
1163 public String myEncodingType;
1164
1165 @XmlAttribute(required = true, name = "id")
1166 public String myId;
1167
1168 @XmlAttribute(required = false, name = "lastSendToInterfaceId")
1169 private String myLastSendToInterfaceId;
1170
1171 @XmlElement(required = true, name = "profileId")
1172 public String myProfileId;
1173
1174 @XmlAttribute(required = true, name = "charsetName")
1175 private String mySaveCharsetName;
1176
1177 @XmlAttribute(required = true, name = "saved")
1178 private boolean mySaved;
1179
1180 @XmlAttribute(required = true, name = "saveFileName")
1181 private String mySaveFileName;
1182
1183 @XmlAttribute(required = true, name = "saveLineEndings")
1184 private String mySaveLineEndings;
1185
1186 @XmlAttribute(required = true, name = "saveStripComments")
1187 private String mySaveStripComments;
1188
1189 @XmlAttribute(required = true, name = "saveFileTimestamp")
1190 private long mySaveTimestamp;
1191
1192 @XmlAttribute(required = false, name = "sendNumberOfTimes")
1193 public int mySendNumberOfTimes;
1194
1195 @XmlElement(required = true, name = "sourceMessage")
1196 public String mySourceMessage;
1197
1198 @XmlElement(required = true, name = "validationContextClass")
1199 public String myValidationContextClass;
1200
1201 }
1202
1203 }