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.validation.impl;
27
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.LinkedHashMap;
32 import java.util.List;
33 import java.util.Map;
34
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import ca.uhn.hl7v2.HL7Exception;
39 import ca.uhn.hl7v2.HapiContext;
40 import ca.uhn.hl7v2.conf.ProfileException;
41 import ca.uhn.hl7v2.conf.check.Validator;
42 import ca.uhn.hl7v2.conf.parser.ProfileParser;
43 import ca.uhn.hl7v2.conf.spec.RuntimeProfile;
44 import ca.uhn.hl7v2.conf.store.ProfileStore;
45 import ca.uhn.hl7v2.model.Message;
46 import ca.uhn.hl7v2.util.Terser;
47 import ca.uhn.hl7v2.validation.ValidationException;
48
49
50
51
52
53
54
55
56
57 @SuppressWarnings("serial")
58 public class ConformanceProfileRule extends AbstractMessageRule {
59
60 private static final Logger log = LoggerFactory.getLogger(ConformanceProfileRule.class);
61 private static final ProfileParserParser.html#ProfileParser">ProfileParser PARSER = new ProfileParser(true);
62 private String myProfileID;
63 private boolean enableCaching = true;
64
65 private static final LinkedHashMap<String, RuntimeProfile> PROFILE_CACHE = new LinkedHashMap<String, RuntimeProfile>(100, 0.75f, true) {
66 @Override
67 protected boolean removeEldestEntry(Map.Entry<String, RuntimeProfile> eldest) {
68 return size() > 100;
69 }
70 };
71
72
73
74
75
76
77 public ConformanceProfileRule() {
78 super();
79 setDescription("Unknown segments found in message");
80 setSectionReference("HL7 2.5 section 2.12");
81 }
82
83
84
85
86
87
88 public ConformanceProfileRule(String theProfileID) {
89 this();
90 myProfileID = theProfileID;
91 }
92
93
94
95
96
97 public ValidationException[] apply(Message msg) {
98 List<ValidationException> problems = new ArrayList<>();
99 String[] ids = {myProfileID};
100
101 try {
102 if (myProfileID == null) {
103 ids = getDeclaredProfileIDs(msg);
104 }
105
106 for (String id : ids) {
107 log.debug("Testing message against profile: {}", id);
108 try {
109 ValidationException[] shortList = testAgainstProfile(msg, id);
110 log.debug("{} non-conformances", shortList.length);
111 problems.addAll(Arrays.asList(shortList));
112 } catch (ProfileException e) {
113 problems.add(new ValidationException("Can't validate against profile: " + e.getMessage(), e));
114 }
115 }
116 } catch (HL7Exception e) {
117 problems.add(new ValidationException("Can't validate against profile: " + e.getMessage(), e));
118 }
119
120 return problems.toArray(new ValidationException[0]);
121 }
122
123 private String[] getDeclaredProfileIDs(Message theMessage) throws HL7Exception {
124 Terserrser.html#Terser">Terser t = new Terser(theMessage);
125 boolean noMore = false;
126 int c = 0;
127 List<String> declaredProfiles = new ArrayList<>(8);
128 while (!noMore) {
129 String path = "MSH-21(" + c++ + ")";
130 String idRep = t.get(path);
131
132 if (idRep == null || idRep.equals("")) {
133 noMore = true;
134 } else {
135 declaredProfiles.add(idRep);
136 }
137 }
138 return declaredProfiles.toArray(new String[0]);
139 }
140
141 private synchronized RuntimeProfile getProfile(String profileString) throws ProfileException {
142 RuntimeProfile profile = PROFILE_CACHE.get(profileString);
143 if (profile == null) {
144 profile = PARSER.parse(profileString);
145 if (enableCaching) PROFILE_CACHE.put(profileString, profile);
146 }
147 return profile;
148 }
149
150 private ValidationException[] testAgainstProfile(Message message, String id) throws ProfileException, HL7Exception {
151 HL7Exception[] exceptions;
152 HapiContext context = message.getParser().getHapiContext();
153 Validator validator = context.getConformanceValidator();
154 try {
155 ProfileStore profileStore = context.getProfileStore();
156 String profileString = profileStore.getProfile(id);
157 if (profileString != null) {
158 RuntimeProfile profile = getProfile(profileString);
159 exceptions = validator.validate(message, profile.getMessage());
160 } else {
161 throw new ProfileException("Unable to find the profile " + id);
162 }
163 } catch (IOException e) {
164 throw new ProfileException("Error retreiving profile " + id, e);
165 }
166
167 ValidationExceptionion.html#ValidationException">ValidationException[] result = new ValidationException[exceptions.length];
168 for (int i = 0; i < exceptions.length; i++) {
169 result[i] = ValidationException.fromHL7Exception(exceptions[i]);
170 }
171 return result;
172 }
173
174
175
176
177
178 public String getDescription() {
179 return "expected conformance to declared or predefined message profiles";
180 }
181
182
183
184
185 public String getSectionReference() {
186 return "HL7 2.5 section 2.12";
187 }
188
189 public String getProfileID() {
190 return myProfileID;
191 }
192
193 public void setEnableCaching(boolean enableCaching) {
194 this.enableCaching = enableCaching;
195 }
196 }