View Javadoc
1   package ca.uhn.fhir.context;
2   
3   /*
4    * #%L
5    * HAPI FHIR - Core Library
6    * %%
7    * Copyright (C) 2014 - 2019 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<>();
53  			myResourceTypes.add(IBaseResource.class);
54  		}
55  	}
56  
57  	@Override
58  	public String getChildNameByDatatype(Class<? extends IBase> theDatatype) {
59  		if (IBaseReference.class.isAssignableFrom(theDatatype)) {
60  			return getElementName();
61  		}
62  		return null;
63  	}
64  
65  	@Override
66  	public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theDatatype) {
67  		if (IBaseReference.class.isAssignableFrom(theDatatype)) {
68  			return myRuntimeDef;
69  		}
70  		return null;
71  	}
72  
73  	@Override
74  	public Set<String> getValidChildNames() {
75  		return myValidChildNames;
76  	}
77  
78  	@Override
79  	public BaseRuntimeElementDefinition<?> getChildByName(String theName) {
80  		return myRuntimeDef;
81  	}
82  
83  	@Override
84  	void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
85  		myRuntimeDef = findResourceReferenceDefinition(theClassToElementDefinitions);
86  
87  		myValidChildNames = new HashSet<String>();
88  		myValidChildNames.add(getElementName());
89  		
90  		/*
91  		 * [elementName]Resource is not actually valid FHIR but we've encountered it in the wild
92  		 * so we'll accept it just to be nice
93  		 */
94  		myValidChildNames.add(getElementName() + "Resource");
95  
96  		/*
97  		 * Below has been disabled- We used to allow field names to contain the name of the resource
98  		 * that they accepted. This wasn't valid but we accepted it just to be flexible because there
99  		 * were some bad examples containing this. This causes conflicts with actual field names in 
100 		 * recent definitions though, so it has been disabled as of HAPI 0.9 
101 		 */
102 //		for (Class<? extends IBaseResource> next : myResourceTypes) {
103 //			if (next == IResource.class) {
104 //				for (Entry<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> nextEntry : theClassToElementDefinitions.entrySet()) {
105 //					if (IResource.class.isAssignableFrom(nextEntry.getKey())) {
106 //						RuntimeResourceDefinition nextDef = (RuntimeResourceDefinition) nextEntry.getValue();
107 //						myValidChildNames.add(getElementName() + nextDef.getName());
108 //					}
109 //				}
110 //			} 
111 //			else {
112 //				RuntimeResourceDefinition nextDef = (RuntimeResourceDefinition) theClassToElementDefinitions.get(next);
113 //				if (nextDef == null) {
114 //					throw new ConfigurationException("Can't find child of type: " + next.getCanonicalName() + " in " + getField().getDeclaringClass());
115 //				}
116 //				myValidChildNames.add(getElementName() + nextDef.getName());
117 //			}
118 //		}
119 
120 		myResourceTypes = Collections.unmodifiableList(myResourceTypes);
121 		myValidChildNames = Collections.unmodifiableSet(myValidChildNames);
122 	}
123 
124 	public List<Class<? extends IBaseResource>> getResourceTypes() {
125 		return myResourceTypes;
126 	}
127 
128 	@Override
129 	public String toString() {
130 		return getClass().getSimpleName() + "[" + getElementName() + "]";
131 	}
132 }