View Javadoc
1   package ca.uhn.fhir.context;
2   
3   /*
4    * #%L
5    * HAPI FHIR - Core Library
6    * %%
7    * Copyright (C) 2014 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 static org.apache.commons.lang3.StringUtils.*;
24  
25  import java.lang.reflect.Field;
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  import java.util.Set;
32  
33  import ca.uhn.fhir.model.api.IElement;
34  import ca.uhn.fhir.model.api.IResource;
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  
39  public class RuntimeChildDeclaredExtensionDefinition extends BaseRuntimeDeclaredChildDefinition {
40  
41  	private BaseRuntimeElementDefinition<?> myChildDef;
42  	private Class<? extends IElement> myChildType;
43  	private String myDatatypeChildName;
44  	private boolean myDefinedLocally;
45  	private String myExtensionUrl;
46  	private boolean myModifier;
47  	private Map<String, RuntimeChildDeclaredExtensionDefinition> myUrlToChildExtension;
48  
49  	/**
50  	 * @param theDefinedLocally See {@link Extension#definedLocally()}
51  	 */
52  	RuntimeChildDeclaredExtensionDefinition(Field theField, Child theChild, Description theDescriptionAnnotation, Extension theExtension, String theElementName, String theExtensionUrl, Class<? extends IElement> theChildType) throws ConfigurationException {
53  		super(theField, theChild, theDescriptionAnnotation, theElementName);
54  		assert isNotBlank(theExtensionUrl);
55  		myExtensionUrl = theExtensionUrl;
56  		myChildType = theChildType;
57  		myDefinedLocally=theExtension.definedLocally();
58  		myModifier = theExtension.isModifier();
59  	}
60  
61  	@Override
62  	public BaseRuntimeElementDefinition<?> getChildByName(String theName) {
63  		if (myDatatypeChildName != null) {
64  			if (myDatatypeChildName.equals(theName)) {
65  				return myChildDef;
66  			} else {
67  				return null;
68  			}
69  		} else {
70  			return null;
71  		}
72  	}
73  
74  	@Override
75  	public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IElement> theType) {
76  		if (myChildType.equals(theType)) {
77  			return myChildDef;
78  		}
79  		return null;
80  	}
81  
82  	public RuntimeChildDeclaredExtensionDefinition getChildExtensionForUrl(String theUrl) {
83  		return myUrlToChildExtension.get(theUrl);
84  	}
85  
86  	@Override
87  	public String getChildNameByDatatype(Class<? extends IElement> theDatatype) {
88  		if (myChildType.equals(theDatatype) && myDatatypeChildName != null) {
89  			return myDatatypeChildName;
90  		} else {
91  			return "extension";
92  		}
93  	}
94  
95  	public Class<? extends IElement> getChildType() {
96  		return myChildType;
97  	}
98  
99  	@Override
100 	public String getExtensionUrl() {
101 		return myExtensionUrl;
102 	}
103 
104 	@Override
105 	public BaseRuntimeElementDefinition<?> getSingleChildOrThrow() {
106 		return myChildDef;
107 	}
108 
109 	@Override
110 	public Set<String> getValidChildNames() {
111 		return Collections.emptySet();
112 	}
113 
114 	public boolean isDefinedLocally() {
115 		return myDefinedLocally;
116 	}
117 
118 	public boolean isModifier() {
119 		return myModifier;
120 	}
121 
122 	public IElement newInstance() {
123 		try {
124 			return myChildType.newInstance();
125 		} catch (InstantiationException e) {
126 			throw new ConfigurationException("Failed to instantiate type:" + myChildType.getName(), e);
127 		} catch (IllegalAccessException e) {
128 			throw new ConfigurationException("Failed to instantiate type:" + myChildType.getName(), e);
129 		}
130 	}
131 
132 	@Override
133 	void sealAndInitialize(Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
134 		myUrlToChildExtension = new HashMap<String, RuntimeChildDeclaredExtensionDefinition>();
135 
136 		BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(myChildType);
137 		if (elementDef instanceof RuntimePrimitiveDatatypeDefinition || elementDef instanceof RuntimeCompositeDatatypeDefinition) {
138 			myDatatypeChildName = "value" + elementDef.getName().substring(0, 1).toUpperCase() + elementDef.getName().substring(1);
139 			if ("valueResourceReference".equals(myDatatypeChildName)) {
140 				// Per one of the examples here: http://hl7.org/implement/standards/fhir/extensibility.html#extension
141 				myDatatypeChildName = "valueResource";
142 				List<Class<? extends IResource>> types = new ArrayList<Class<? extends IResource>>();
143 				types.add(IResource.class);
144 				myChildDef = new RuntimeResourceReferenceDefinition("valueResource", types);
145 			}else {
146 				myChildDef = elementDef;
147 			}
148 		} else {
149 			RuntimeResourceBlockDefinition extDef = ((RuntimeResourceBlockDefinition) elementDef);
150 			for (RuntimeChildDeclaredExtensionDefinition next : extDef.getExtensions()) {
151 				myUrlToChildExtension.put(next.getExtensionUrl(), next);
152 			}
153 			myChildDef = extDef;
154 		}
155 
156 		myUrlToChildExtension = Collections.unmodifiableMap(myUrlToChildExtension);
157 	}
158 
159 }