1 package ca.uhn.fhir.validation;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import ca.uhn.fhir.context.FhirContext;
24 import ca.uhn.fhir.model.api.Bundle;
25 import ca.uhn.fhir.model.api.IResource;
26 import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
27 import org.apache.commons.lang3.Validate;
28
29 import java.util.ArrayList;
30 import java.util.Iterator;
31 import java.util.List;
32
33
34
35
36
37
38
39
40 public class FhirValidator {
41
42 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirValidator.class);
43
44 private static final String I18N_KEY_NO_PHLOC_WARNING = FhirValidator.class.getName()+".noPhlocWarningOnStartup";
45 private static final String I18N_KEY_NO_PHLOC_ERROR = FhirValidator.class.getName()+".noPhlocError";
46
47 private FhirContext myContext;
48 private List<IValidator> myValidators = new ArrayList<IValidator>();
49 private static volatile Boolean ourPhlocPresentOnClasspath;
50
51
52
53
54 public FhirValidator(FhirContext theFhirContext) {
55 myContext = theFhirContext;
56 setValidateAgainstStandardSchema(true);
57
58 if (ourPhlocPresentOnClasspath == null) {
59 try {
60 Class.forName("com.phloc.schematron.ISchematronResource");
61 ourPhlocPresentOnClasspath = true;
62 } catch (ClassNotFoundException e) {
63 ourLog.info(theFhirContext.getLocalizer().getMessage(I18N_KEY_NO_PHLOC_WARNING));
64 ourPhlocPresentOnClasspath = false;
65 }
66 }
67 if (ourPhlocPresentOnClasspath) {
68 setValidateAgainstStandardSchematron(true);
69 }
70
71 }
72
73 private void addOrRemoveValidator(boolean theValidateAgainstStandardSchema, Class<? extends IValidator> type, IValidator instance) {
74 if (theValidateAgainstStandardSchema) {
75 boolean found = haveValidatorOfType(type);
76 if (!found) {
77 myValidators.add(instance);
78 }
79 } else {
80 for (Iterator<IValidator> iter = myValidators.iterator(); iter.hasNext();) {
81 IValidator next = iter.next();
82 if (next.getClass().equals(type)) {
83 iter.remove();
84 }
85 }
86 }
87 }
88
89 private boolean haveValidatorOfType(Class<? extends IValidator> type) {
90 boolean found = false;
91 for (IValidator next : myValidators) {
92 if (next.getClass().equals(type)) {
93 found = true;
94 }
95 }
96 return found;
97 }
98
99
100
101
102 public boolean isValidateAgainstStandardSchema() {
103 return haveValidatorOfType(SchemaBaseValidator.class);
104 }
105
106
107
108
109 public boolean isValidateAgainstStandardSchematron() {
110 return haveValidatorOfType(SchematronBaseValidator.class);
111 }
112
113
114
115
116 public void setValidateAgainstStandardSchema(boolean theValidateAgainstStandardSchema) {
117 addOrRemoveValidator(theValidateAgainstStandardSchema, SchemaBaseValidator.class, new SchemaBaseValidator());
118 }
119
120
121
122
123 public void setValidateAgainstStandardSchematron(boolean theValidateAgainstStandardSchematron) {
124 if (theValidateAgainstStandardSchematron && !ourPhlocPresentOnClasspath) {
125 throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_KEY_NO_PHLOC_ERROR));
126 }
127 addOrRemoveValidator(theValidateAgainstStandardSchematron, SchematronBaseValidator.class, new SchematronBaseValidator());
128 }
129
130
131
132
133
134
135
136
137
138
139 @Deprecated
140 public void validate(Bundle theBundle) {
141 ValidationResult validationResult = validateWithResult(theBundle);
142 if (!validationResult.isSuccessful()) {
143 throw new ValidationFailureException(validationResult.getOperationOutcome());
144 }
145 }
146
147
148
149
150
151
152
153
154
155
156 @Deprecated
157 public void validate(IResource theResource) throws ValidationFailureException {
158 ValidationResult validationResult = validateWithResult(theResource);
159 if (!validationResult.isSuccessful()) {
160 throw new ValidationFailureException(validationResult.getOperationOutcome());
161 }
162 }
163
164
165
166
167
168
169
170
171
172 public ValidationResult validateWithResult(Bundle theBundle) {
173 Validate.notNull(theBundle, "theBundle must not be null");
174
175 ValidationContext<Bundle> ctx = ValidationContext.forBundle(myContext, theBundle);
176
177 for (IValidator next : myValidators) {
178 next.validateBundle(ctx);
179 }
180
181 OperationOutcome oo = ctx.getOperationOutcome();
182 return ValidationResult.valueOf(oo);
183 }
184
185
186
187
188
189
190
191
192 public ValidationResult validateWithResult(IResource theResource) {
193 Validate.notNull(theResource, "theResource must not be null");
194
195 ValidationContext<IResource> ctx = ValidationContext.forResource(myContext, theResource);
196
197 for (IValidator next : myValidators) {
198 next.validateResource(ctx);
199 }
200
201 OperationOutcome oo = ctx.getOperationOutcome();
202 return ValidationResult.valueOf(oo);
203 }
204 }