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 java.lang.reflect.Field;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Set;
30  
31  import org.apache.commons.lang3.StringUtils;
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.dstu.composite.ResourceReferenceDt;
38  
39  public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefinition {
40  
41  	private List<Class<? extends IElement>> myChoiceTypes;
42  	private Map<String, BaseRuntimeElementDefinition<?>> myNameToChildDefinition;
43  	private Map<Class<? extends IElement>, String> myDatatypeToElementName;
44  	private Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> myDatatypeToElementDefinition;
45  
46  	public RuntimeChildChoiceDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, List<Class<? extends IElement>> theChoiceTypes) {
47  		super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName);
48  
49  		myChoiceTypes = Collections.unmodifiableList(theChoiceTypes);
50  	}
51  
52  	/**
53  	 * For extension, if myChoiceTypes will be set some other way
54  	 */
55  	RuntimeChildChoiceDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation) {
56  		super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName);
57  	}
58  
59  	void setChoiceTypes(List<Class<? extends IElement>> theChoiceTypes) {
60  		myChoiceTypes = Collections.unmodifiableList(theChoiceTypes);
61  	}
62  
63  	public List<Class<? extends IElement>> getChoices() {
64  		return myChoiceTypes;
65  	}
66  
67  	@Override
68  	public Set<String> getValidChildNames() {
69  		return myNameToChildDefinition.keySet();
70  	}
71  
72  	@Override
73  	public BaseRuntimeElementDefinition<?> getChildByName(String theName) {
74  		assert myNameToChildDefinition.containsKey(theName);
75  
76  		return myNameToChildDefinition.get(theName);
77  	}
78  
79  	@SuppressWarnings("unchecked")
80  	@Override
81  	void sealAndInitialize(Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
82  		myNameToChildDefinition = new HashMap<String, BaseRuntimeElementDefinition<?>>();
83  		myDatatypeToElementName = new HashMap<Class<? extends IElement>, String>();
84  		myDatatypeToElementDefinition = new HashMap<Class<? extends IElement>, BaseRuntimeElementDefinition<?>>();
85  
86  		for (Class<? extends IElement> next : myChoiceTypes) {
87  
88  			String elementName;
89  			String alternateElementName = null;
90  			BaseRuntimeElementDefinition<?> nextDef;
91  			if (IResource.class.isAssignableFrom(next)) {
92  				elementName = getElementName() + StringUtils.capitalize(next.getSimpleName());
93  				alternateElementName = getElementName() + "Resource";
94  				List<Class<? extends IResource>> types = new ArrayList<Class<? extends IResource>>();
95  				types.add((Class<? extends IResource>) next);
96  				nextDef = new RuntimeResourceReferenceDefinition(elementName, types);
97  				nextDef.sealAndInitialize(theClassToElementDefinitions);
98  			} else {
99  				nextDef = theClassToElementDefinitions.get(next);
100 				elementName = getElementName() + StringUtils.capitalize(nextDef.getName());
101 			}
102 
103 			myNameToChildDefinition.put(elementName, nextDef);
104 			if (alternateElementName != null) {
105 				myNameToChildDefinition.put(alternateElementName, nextDef);
106 			}
107 			
108 			if (IResource.class.isAssignableFrom(next)) {
109 				myDatatypeToElementDefinition.put(ResourceReferenceDt.class, nextDef);
110 				alternateElementName = getElementName() + "Resource";
111 				myDatatypeToElementName.put(ResourceReferenceDt.class, alternateElementName);
112 			}
113 			
114 			myDatatypeToElementDefinition.put(next, nextDef);
115 			myDatatypeToElementName.put(next, elementName);
116 		}
117 
118 		myNameToChildDefinition = Collections.unmodifiableMap(myNameToChildDefinition);
119 		myDatatypeToElementName = Collections.unmodifiableMap(myDatatypeToElementName);
120 		myDatatypeToElementDefinition = Collections.unmodifiableMap(myDatatypeToElementDefinition);
121 
122 	}
123 
124 	@Override
125 	public String getChildNameByDatatype(Class<? extends IElement> theDatatype) {
126 		return myDatatypeToElementName.get(theDatatype);
127 	}
128 
129 	@Override
130 	public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IElement> theDatatype) {
131 		return myDatatypeToElementDefinition.get(theDatatype);
132 	}
133 
134 	public Set<Class<? extends IElement>> getValidChildTypes() {
135 		return Collections.unmodifiableSet((myDatatypeToElementDefinition.keySet()));
136 	}
137 
138 }