1 package ca.uhn.fhir.context;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.commons.lang3.Validate;
31 import org.apache.commons.lang3.text.WordUtils;
32
33 import ca.uhn.fhir.i18n.HapiLocalizer;
34 import ca.uhn.fhir.model.api.IElement;
35 import ca.uhn.fhir.model.api.IResource;
36 import ca.uhn.fhir.model.view.ViewGenerator;
37 import ca.uhn.fhir.narrative.INarrativeGenerator;
38 import ca.uhn.fhir.parser.DataFormatException;
39 import ca.uhn.fhir.parser.IParser;
40 import ca.uhn.fhir.parser.JsonParser;
41 import ca.uhn.fhir.parser.XmlParser;
42 import ca.uhn.fhir.rest.client.IGenericClient;
43 import ca.uhn.fhir.rest.client.IRestfulClientFactory;
44 import ca.uhn.fhir.rest.client.RestfulClientFactory;
45 import ca.uhn.fhir.rest.client.api.IBasicClient;
46 import ca.uhn.fhir.rest.client.api.IRestfulClient;
47 import ca.uhn.fhir.util.FhirTerser;
48 import ca.uhn.fhir.validation.FhirValidator;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public class FhirContext {
65
66 private static final List<Class<? extends IResource>> EMPTY_LIST = Collections.emptyList();
67 private volatile Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> myClassToElementDefinition = Collections.emptyMap();
68 private volatile Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = Collections.emptyMap();
69 private HapiLocalizer myLocalizer = new HapiLocalizer();
70 private volatile Map<String, RuntimeResourceDefinition> myNameToElementDefinition = Collections.emptyMap();
71 private Map<String, String> myNameToResourceType;
72 private volatile INarrativeGenerator myNarrativeGenerator;
73 private volatile IRestfulClientFactory myRestfulClientFactory;
74 private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
75
76
77
78
79 public FhirContext() {
80 this(EMPTY_LIST);
81 }
82
83 public FhirContext(Class<? extends IResource> theResourceType) {
84 this(toCollection(theResourceType));
85 }
86
87 public FhirContext(Class<?>... theResourceTypes) {
88 this(toCollection(theResourceTypes));
89 }
90
91 public FhirContext(Collection<Class<? extends IResource>> theResourceTypes) {
92 scanResourceTypes(theResourceTypes);
93 }
94
95
96
97
98 public BaseRuntimeElementDefinition<?> getElementDefinition(Class<? extends IElement> theElementType) {
99 return myClassToElementDefinition.get(theElementType);
100 }
101
102
103 int getElementDefinitionCount() {
104 return myClassToElementDefinition.size();
105 }
106
107
108
109
110 public HapiLocalizer getLocalizer() {
111 if (myLocalizer == null) {
112 myLocalizer = new HapiLocalizer();
113 }
114 return myLocalizer;
115 }
116
117 public INarrativeGenerator getNarrativeGenerator() {
118 return myNarrativeGenerator;
119 }
120
121
122
123
124 public RuntimeResourceDefinition getResourceDefinition(Class<? extends IResource> theResourceType) {
125 RuntimeResourceDefinition retVal = (RuntimeResourceDefinition) myClassToElementDefinition.get(theResourceType);
126 if (retVal == null) {
127 retVal = scanResourceType(theResourceType);
128 }
129 return retVal;
130 }
131
132
133
134
135 public RuntimeResourceDefinition getResourceDefinition(IResource theResource) {
136 return getResourceDefinition(theResource.getClass());
137 }
138
139
140
141
142 @SuppressWarnings("unchecked")
143 public RuntimeResourceDefinition getResourceDefinition(String theResourceName) {
144 String resourceName = theResourceName;
145
146
147
148
149 if (Character.isLowerCase(resourceName.charAt(0))) {
150 resourceName = WordUtils.capitalize(resourceName);
151 }
152
153 Validate.notBlank(resourceName, "Resource name must not be blank");
154
155 RuntimeResourceDefinition retVal = myNameToElementDefinition.get(resourceName);
156
157 if (retVal == null) {
158 try {
159 String className = myNameToResourceType.get(resourceName.toLowerCase());
160 if (className == null) {
161 throw new DataFormatException("Unknown resource name[" + resourceName + "]");
162 }
163 Class<?> clazz = Class.forName(className);
164 if (IResource.class.isAssignableFrom(clazz)) {
165 retVal = scanResourceType((Class<? extends IResource>) clazz);
166 }
167 } catch (ClassNotFoundException e) {
168 throw new DataFormatException("Unknown resource name[" + resourceName + "]");
169 }
170 }
171
172 return retVal;
173 }
174
175
176
177
178 public RuntimeResourceDefinition getResourceDefinitionById(String theId) {
179 return myIdToResourceDefinition.get(theId);
180 }
181
182
183
184
185 public Collection<RuntimeResourceDefinition> getResourceDefinitions() {
186 return myIdToResourceDefinition.values();
187 }
188
189 public IRestfulClientFactory getRestfulClientFactory() {
190 if (myRestfulClientFactory == null) {
191 myRestfulClientFactory = new RestfulClientFactory(this);
192 }
193 return myRestfulClientFactory;
194 }
195
196 public RuntimeChildUndeclaredExtensionDefinition getRuntimeChildUndeclaredExtensionDefinition() {
197 return myRuntimeChildUndeclaredExtensionDefinition;
198 }
199
200
201
202
203
204
205
206
207
208
209
210 public IParser newJsonParser() {
211 return new JsonParser(this);
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231 public <T extends IRestfulClient> T newRestfulClient(Class<T> theClientType, String theServerBase) {
232 return getRestfulClientFactory().newClient(theClientType, theServerBase);
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247 public IGenericClient newRestfulGenericClient(String theServerBase) {
248 return getRestfulClientFactory().newGenericClient(theServerBase);
249 }
250
251 public FhirTerser newTerser() {
252 return new FhirTerser(this);
253 }
254
255 public FhirValidator newValidator() {
256 return new FhirValidator(this);
257 }
258
259 public ViewGenerator newViewGenerator() {
260 return new ViewGenerator(this);
261 }
262
263
264
265
266
267
268
269
270
271
272
273 public IParser newXmlParser() {
274 return new XmlParser(this);
275 }
276
277 private RuntimeResourceDefinition scanResourceType(Class<? extends IResource> theResourceType) {
278 ArrayList<Class<? extends IResource>> resourceTypes = new ArrayList<Class<? extends IResource>>();
279 resourceTypes.add(theResourceType);
280 Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> defs = scanResourceTypes(resourceTypes);
281 return (RuntimeResourceDefinition) defs.get(theResourceType);
282 }
283
284 private Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> scanResourceTypes(Collection<Class<? extends IResource>> theResourceTypes) {
285 ModelScanner scanner = new ModelScanner(myClassToElementDefinition, theResourceTypes);
286 if (myRuntimeChildUndeclaredExtensionDefinition == null) {
287 myRuntimeChildUndeclaredExtensionDefinition = scanner.getRuntimeChildUndeclaredExtensionDefinition();
288 }
289
290 Map<String, RuntimeResourceDefinition> nameToElementDefinition = new HashMap<String, RuntimeResourceDefinition>();
291 nameToElementDefinition.putAll(myNameToElementDefinition);
292 nameToElementDefinition.putAll(scanner.getNameToResourceDefinitions());
293
294 Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> classToElementDefinition = new HashMap<Class<? extends IElement>, BaseRuntimeElementDefinition<?>>();
295 classToElementDefinition.putAll(myClassToElementDefinition);
296 classToElementDefinition.putAll(scanner.getClassToElementDefinitions());
297
298 Map<String, RuntimeResourceDefinition> idToElementDefinition = new HashMap<String, RuntimeResourceDefinition>();
299 idToElementDefinition.putAll(myIdToResourceDefinition);
300 idToElementDefinition.putAll(scanner.getIdToResourceDefinition());
301
302 myNameToElementDefinition = nameToElementDefinition;
303 myClassToElementDefinition = classToElementDefinition;
304 myIdToResourceDefinition = idToElementDefinition;
305
306 myNameToResourceType = scanner.getNameToResourceType();
307
308 return classToElementDefinition;
309 }
310
311
312
313
314 public void setLocalizer(HapiLocalizer theMessages) {
315 myLocalizer = theMessages;
316 }
317
318 public void setNarrativeGenerator(INarrativeGenerator theNarrativeGenerator) {
319 myNarrativeGenerator = theNarrativeGenerator;
320 }
321
322 private static Collection<Class<? extends IResource>> toCollection(Class<? extends IResource> theResourceType) {
323 ArrayList<Class<? extends IResource>> retVal = new ArrayList<Class<? extends IResource>>(1);
324 retVal.add(theResourceType);
325 return retVal;
326 }
327
328 @SuppressWarnings("unchecked")
329 private static List<Class<? extends IResource>> toCollection(Class<?>[] theResourceTypes) {
330 ArrayList<Class<? extends IResource>> retVal = new ArrayList<Class<? extends IResource>>(1);
331 for (Class<?> clazz : theResourceTypes) {
332 if (!IResource.class.isAssignableFrom(clazz)) {
333 throw new IllegalArgumentException(clazz.getCanonicalName() + " is not an instance of " + IResource.class.getSimpleName());
334 }
335 retVal.add((Class<? extends IResource>) clazz);
336 }
337 return retVal;
338 }
339
340 }