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;
27
28 import java.util.ArrayList;
29 import java.util.Iterator;
30 import java.util.List;
31
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import ca.uhn.hl7v2.HL7Exception;
36 import ca.uhn.hl7v2.Location;
37 import ca.uhn.hl7v2.model.Composite;
38 import ca.uhn.hl7v2.model.Message;
39 import ca.uhn.hl7v2.model.Primitive;
40 import ca.uhn.hl7v2.model.Segment;
41 import ca.uhn.hl7v2.model.Structure;
42 import ca.uhn.hl7v2.model.Type;
43 import ca.uhn.hl7v2.model.Varies;
44 import ca.uhn.hl7v2.util.ReadOnlyMessageIterator;
45 import ca.uhn.hl7v2.util.Terser;
46
47
48
49
50
51
52
53
54
55 public abstract class AbstractValidator<R> implements Validator<R> {
56
57 private static final Logger LOG = LoggerFactory.getLogger(AbstractValidator.class);
58
59 private boolean validatePrimitives;
60
61
62
63
64
65
66
67 public void setValidatePrimitives(boolean validatePrimitives) {
68 this.validatePrimitives = validatePrimitives;
69 }
70
71
72
73
74 public boolean isValidatePrimitives() {
75 return validatePrimitives;
76 }
77
78
79
80
81
82
83
84 public R validate(Message message) throws HL7Exception {
85 return validate(message, initializeHandler());
86 }
87
88
89
90
91
92 public R validate(Message message, ValidationExceptionHandler<R> handler) throws HL7Exception {
93 if (message == null) {
94 throw new NullPointerException("Message may not be null");
95 }
96 if (handler == null) {
97 throw new NullPointerException("ValidationExceptionHandler may not be null");
98 }
99 handler.setValidationSubject(message);
100 if (isValidatePrimitives()) testPrimitiveRules(message, handler);
101 testMessageRules(message, handler);
102 return handler.result();
103 }
104
105 private void testMessageRules(Message message, ValidationExceptionHandler<R> handler)
106 throws HL7Exception {
107 Terser t = new Terser(message);
108 String messageType = t.get("MSH-9-1");
109 String triggerEvent = t.get("MSH-9-2");
110 List<MessageRule> rules = new ArrayList<>();
111 if (getValidationContext() != null) {
112 rules.addAll(getValidationContext().getMessageRules(message.getVersion(), messageType,
113 triggerEvent));
114 }
115 LOG.debug("Validating message against {} message rules", rules.size());
116 for (MessageRule rule : rules) {
117 ValidationException[] ex = rule.apply(message);
118 if (ex != null && ex.length > 0) {
119 handler.onExceptions(ex);
120 }
121 }
122 }
123
124 private void testPrimitiveRules(Message message, ValidationExceptionHandler<R> handler)
125 throws HL7Exception {
126 LOG.debug("Validating message against primitive type rules");
127 for (Iterator<Structure> iter = ReadOnlyMessageIterator
128 .createPopulatedSegmentIterator(message); iter.hasNext();) {
129 Segment s = (Segment) iter.next();
130 for (int field = 1; field <= s.numFields(); field++) {
131 Type[] t = s.getField(field);
132 for (int rep = 0; rep < t.length; rep++) {
133 Location location = new Location();
134 location
135 .withSegmentName(s.getName())
136 .withField(field)
137 .withFieldRepetition(rep);
138 testType(t[rep], handler, location);
139 }
140 }
141 }
142 }
143
144 private void testType(Type type, ValidationExceptionHandler<R> handler, Location l) {
145 if (type instanceof Composite) {
146 Type[] components = ((Composite) type).getComponents();
147 for (int comp = 0; comp < components.length; comp++) {
148 Location location = new Location(l).withComponent(comp + 1);
149 testComponent(components[comp], handler, location);
150 }
151 } else if (type instanceof Varies) {
152 testType(((Varies) type).getData(), handler, l);
153 } else {
154 testPrimitive((Primitive) type, handler, l);
155 }
156 }
157
158 private void testComponent(Type type, ValidationExceptionHandler<R> handler, Location l) {
159 if (type instanceof Composite) {
160 Type[] component = ((Composite) type).getComponents();
161 for (int sub = 0; sub < component.length; sub++) {
162 Location location = new Location(l).withSubcomponent(sub + 1);
163 testSubComponent(component[sub], handler, location);
164 }
165 } else if (type instanceof Varies) {
166 testComponent(((Varies) type).getData(), handler, l);
167 } else {
168 testPrimitive((Primitive) type, handler, l);
169 }
170 }
171
172 private void testSubComponent(Type type, ValidationExceptionHandler<R> handler, Location l) {
173 if (type instanceof Primitive) {
174 testPrimitive((Primitive) type, handler, l);
175 } else if (type instanceof Varies) {
176 testSubComponent(((Varies) type).getData(), handler, l);
177 }
178 }
179
180 private void testPrimitive(Primitive p, ValidationExceptionHandler<R> handler, Location l) {
181 List<PrimitiveTypeRule> rules = new ArrayList<>();
182 Message m = p.getMessage();
183 if (getValidationContext() != null) {
184 rules.addAll(getValidationContext().getPrimitiveRules(m.getVersion(), p.getName(), p));
185 }
186 for (PrimitiveTypeRule rule : rules) {
187 ValidationException[] exceptions = rule.apply(p.getValue());
188 for (ValidationException ve : exceptions) {
189 ve.setLocation(l);
190 }
191 if (exceptions.length > 0) {
192 handler.onExceptions(exceptions);
193 }
194 }
195 }
196
197
198
199
200
201
202
203
204 public R validate(String message, boolean isXML, String version) throws HL7Exception {
205 return validate(message, isXML, version, initializeHandler());
206 }
207
208
209
210
211
212
213 public R validate(String message, boolean isXML, String version,
214 ValidationExceptionHandler<R> handler) throws HL7Exception {
215 if (message == null) {
216 throw new NullPointerException("Message may not be null");
217 }
218 if (handler == null) {
219 throw new NullPointerException("ValidationExceptionHandler may not be null");
220 }
221 handler.setValidationSubject(message);
222 List<EncodingRule> rules = new ArrayList<>();
223 if (getValidationContext() != null) {
224 rules.addAll(getValidationContext().getEncodingRules(version, isXML ? "XML" : "ER7"));
225 }
226 LOG.debug("Validating message against {} encoding rules", rules.size());
227 for (EncodingRule rule : rules) {
228 ValidationException[] ex = rule.apply(message);
229 if (ex != null && ex.length > 0) {
230 handler.onExceptions(ex);
231 }
232 }
233 return handler.result();
234 }
235
236 protected abstract ValidationContext getValidationContext();
237
238 protected abstract ValidationExceptionHandler<R> initializeHandler();
239
240 }