View Javadoc
1   package ca.uhn.fhir.context;
2   
3   /*
4    * #%L
5    * HAPI FHIR - Core Library
6    * %%
7    * Copyright (C) 2014 - 2018 University Health Network
8    * %%
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   * 
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   * 
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * #L%
21   */
22  
23  import java.lang.reflect.Field;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.HashSet;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Set;
30  
31  import org.hl7.fhir.instance.model.api.IBase;
32  import org.hl7.fhir.instance.model.api.IBaseReference;
33  import org.hl7.fhir.instance.model.api.IBaseResource;
34  
35  import ca.uhn.fhir.model.api.annotation.Child;
36  import ca.uhn.fhir.model.api.annotation.Description;
37  
38  public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefinition {
39  
40  	private BaseRuntimeElementDefinition<?> myRuntimeDef;
41  	private List<Class<? extends IBaseResource>> myResourceTypes;
42  	private Set<String> myValidChildNames;
43  
44  	/**
45  	 * Constructor
46  	 */
47  	public RuntimeChildResourceDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, List<Class<? extends IBaseResource>> theResourceTypes) {
48  		super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName);
49  		myResourceTypes = theResourceTypes;
50  
51  		if (theResourceTypes == null || theResourceTypes.isEmpty()) {
52  			myResourceTypes = new ArrayList<Class<? extends IBaseResource>>();
53  			myResourceTypes.add(IBaseResource.class);
54  //			throw new ConfigurationException("Field '" + theField.getName() + "' on type '" + theField.getDeclaringClass().getCanonicalName() + "' has no resource types noted");
55  		}
56  	}
57  
58  	@Override
59  	public String getChildNameByDatatype(Class<? extends IBase> theDatatype) {
60  		if (IBaseReference.class.isAssignableFrom(theDatatype)) {
61  			return getElementName();
62  		}
63  		return null;
64  	}
65  
66  	@Override
67  	public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theDatatype) {
68  		if (IBaseReference.class.isAssignableFrom(theDatatype)) {
69  			return myRuntimeDef;
70  		}
71  		return null;
72  	}
73  
74  	@Override
75  	public Set<String> getValidChildNames() {
76  		return myValidChildNames;
77  	}
78  
79  	@Override
80  	public BaseRuntimeElementDefinition<?> getChildByName(String theName) {
81  		return myRuntimeDef;
82  	}
83  
84  	@Override
85  	void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
86  		myRuntimeDef = findResourceReferenceDefinition(theClassToElementDefinitions);
87  
88  		myValidChildNames = new HashSet<String>();
89  		myValidChildNames.add(getElementName());
90  		
91  		/*
92  		 * [elementName]Resource is not actually valid FHIR but we've encountered it in the wild
93  		 * so we'll accept it just to be nice
94  		 */
95  		myValidChildNames.add(getElementName() + "Resource");
96  
97  		/*
98  		 * Below has been disabled- We used to allow field names to contain the name of the resource
99  		 * that they accepted. This wasn't valid but we accepted it just to be flexible because there
100 		 * were some bad examples containing this. This causes conflicts with actual field names in 
101 		 * recent definitions though, so it has been disabled as of HAPI 0.9 
102 		 */
103 //		for (Class<? extends IBaseResource> next : myResourceTypes) {
104 //			if (next == IResource.class) {
105 //				for (Entry<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> nextEntry : theClassToElementDefinitions.entrySet()) {
106 //					if (IResource.class.isAssignableFrom(nextEntry.getKey())) {
107 //						RuntimeResourceDefinition nextDef = (RuntimeResourceDefinition) nextEntry.getValue();
108 //						myValidChildNames.add(getElementName() + nextDef.getName());
109 //					}
110 //				}
111 //			} 
112 //			else {
113 //				RuntimeResourceDefinition nextDef = (RuntimeResourceDefinition) theClassToElementDefinitions.get(next);
114 //				if (nextDef == null) {
115 //					throw new ConfigurationException("Can't find child of type: " + next.getCanonicalName() + " in " + getField().getDeclaringClass());
116 //				}
117 //				myValidChildNames.add(getElementName() + nextDef.getName());
118 //			}
119 //		}
120 
121 		myResourceTypes = Collections.unmodifiableList(myResourceTypes);
122 		myValidChildNames = Collections.unmodifiableSet(myValidChildNames);
123 	}
124 
125 	public List<Class<? extends IBaseResource>> getResourceTypes() {
126 		return myResourceTypes;
127 	}
128 
129 	@Override
130 	public String toString() {
131 		return getClass().getSimpleName() + "[" + getElementName() + "]";
132 	}
133 }