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 }