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 import static org.apache.commons.lang3.StringUtils.isNotBlank;
23
24 import java.lang.reflect.Field;
25 import java.lang.reflect.Modifier;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31
32 import org.hl7.fhir.instance.model.api.IBase;
33
34 import ca.uhn.fhir.model.api.IElement;
35 import ca.uhn.fhir.model.api.annotation.Child;
36 import ca.uhn.fhir.model.api.annotation.Description;
37 import ca.uhn.fhir.model.api.annotation.Extension;
38 import ca.uhn.fhir.util.ReflectionUtil;
39
40 public class RuntimeChildDeclaredExtensionDefinition extends RuntimeChildChoiceDefinition {
41
42 private boolean myDefinedLocally;
43 private String myExtensionUrl;
44 private boolean myModifier;
45 private Map<String, RuntimeChildDeclaredExtensionDefinition> myUrlToChildExtension;
46 private volatile Object myInstanceConstructorArguments;
47 private Class<?> myEnumerationType;
48 private Class<? extends IBase> myChildType;
49 private RuntimeResourceBlockDefinition myChildResourceBlock;
50 private BaseRuntimeElementDefinition<?> myChildDef;
51
52
53
54
55
56
57
58
59 RuntimeChildDeclaredExtensionDefinition(Field theField, Child theChild, Description theDescriptionAnnotation, Extension theExtension, String theElementName, String theExtensionUrl,
60 Class<? extends IBase> theChildType, Object theBoundTypeBinder)
61 throws ConfigurationException {
62 super(theField, theElementName, theChild, theDescriptionAnnotation);
63 assert isNotBlank(theExtensionUrl);
64 myExtensionUrl = theExtensionUrl;
65 myChildType = theChildType;
66 myDefinedLocally = theExtension.definedLocally();
67 myModifier = theExtension.isModifier();
68 myInstanceConstructorArguments = theBoundTypeBinder;
69
70 List<Class<? extends IBase>> choiceTypes = new ArrayList<Class<? extends IBase>>();
71 for (Class<? extends IElement> next : theChild.type()) {
72 choiceTypes.add(next);
73 }
74
75 if (Modifier.isAbstract(theChildType.getModifiers()) == false) {
76 choiceTypes.add(theChildType);
77 }
78
79 setChoiceTypes(choiceTypes);
80 }
81
82 @Override
83 public String getElementName() {
84 return "value";
85 }
86
87 @Override
88 public Object getInstanceConstructorArguments() {
89 Object retVal = myInstanceConstructorArguments;
90 if (retVal == null && myEnumerationType != null) {
91 retVal = RuntimeChildPrimitiveEnumerationDatatypeDefinition.toEnumFactory(myEnumerationType);
92 myInstanceConstructorArguments = retVal;
93 }
94 return retVal;
95 }
96
97 public void setEnumerationType(Class<?> theEnumerationType) {
98 myEnumerationType = theEnumerationType;
99 }
100
101 @Override
102 public String getChildNameByDatatype(Class<? extends IBase> theDatatype) {
103
104 String retVal = super.getChildNameByDatatype(theDatatype);
105
106 if (retVal != null) {
107 BaseRuntimeElementDefinition<?> childDef = super.getChildElementDefinitionByDatatype(theDatatype);
108 if (childDef instanceof RuntimeResourceBlockDefinition) {
109
110 retVal = null;
111 }
112 }
113
114 if (retVal == null) {
115 if (myModifier) {
116 return "modifierExtension";
117 }
118 return "extension";
119
120 }
121 return retVal;
122 }
123
124 @Override
125 public BaseRuntimeElementDefinition<?> getChildByName(String theName) {
126 String name = theName;
127 if ("extension".equals(name)||"modifierExtension".equals(name)) {
128 if (myChildResourceBlock != null) {
129 return myChildResourceBlock;
130 }
131 if (myChildDef != null) {
132 return myChildDef;
133 }
134 }
135
136 if (getValidChildNames().contains(name) == false) {
137 return null;
138 }
139
140 return super.getChildByName(name);
141 }
142
143 @Override
144 public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theDatatype) {
145 if (myChildResourceBlock != null) {
146 if (myChildResourceBlock.getImplementingClass().equals(theDatatype)) {
147 return myChildResourceBlock;
148 }
149 }
150 return super.getChildElementDefinitionByDatatype(theDatatype);
151 }
152
153 public RuntimeChildDeclaredExtensionDefinition getChildExtensionForUrl(String theUrl) {
154 return myUrlToChildExtension.get(theUrl);
155 }
156
157 @Override
158 public String getExtensionUrl() {
159 return myExtensionUrl;
160 }
161
162 public boolean isDefinedLocally() {
163 return myDefinedLocally;
164 }
165
166 @Override
167 public boolean isModifier() {
168 return myModifier;
169 }
170
171 @Override
172 void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
173 myUrlToChildExtension = new HashMap<String, RuntimeChildDeclaredExtensionDefinition>();
174
175 BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(myChildType);
176
177
178
179
180
181 if (elementDef == null) {
182 if (Modifier.isAbstract(myChildType.getModifiers()) == false) {
183 elementDef = theContext.getElementDefinition(myChildType);
184 }
185 }
186
187 if (elementDef instanceof RuntimePrimitiveDatatypeDefinition || elementDef instanceof RuntimeCompositeDatatypeDefinition) {
188
189
190
191
192
193
194
195
196 myChildDef = elementDef;
197
198 } else if (elementDef instanceof RuntimeResourceBlockDefinition) {
199 RuntimeResourceBlockDefinition extDef = ((RuntimeResourceBlockDefinition) elementDef);
200 for (RuntimeChildDeclaredExtensionDefinition next : extDef.getExtensions()) {
201 myUrlToChildExtension.put(next.getExtensionUrl(), next);
202 }
203 myChildResourceBlock = (RuntimeResourceBlockDefinition) elementDef;
204 }
205
206 myUrlToChildExtension = Collections.unmodifiableMap(myUrlToChildExtension);
207
208 super.sealAndInitialize(theContext, theClassToElementDefinitions);
209 }
210
211 public IBase newInstance() {
212 return ReflectionUtil.newInstance(myChildType);
213 }
214
215 public Class<? extends IBase> getChildType() {
216 return myChildType;
217 }
218
219 }