
001package ca.uhn.fhir.context; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2022 Smile CDR, Inc. 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import ca.uhn.fhir.model.api.annotation.Child; 024import ca.uhn.fhir.model.api.annotation.Description; 025import org.hl7.fhir.instance.model.api.IBase; 026import org.hl7.fhir.instance.model.api.IBaseReference; 027import org.hl7.fhir.instance.model.api.IBaseResource; 028 029import java.lang.reflect.Field; 030import java.util.ArrayList; 031import java.util.Collections; 032import java.util.HashSet; 033import java.util.List; 034import java.util.Map; 035import java.util.Set; 036 037public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefinition { 038 039 private BaseRuntimeElementDefinition<?> myRuntimeDef; 040 private List<Class<? extends IBaseResource>> myResourceTypes; 041 private Set<String> myValidChildNames; 042 043 /** 044 * Constructor 045 */ 046 public RuntimeChildResourceDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, List<Class<? extends IBaseResource>> theResourceTypes) { 047 super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName); 048 myResourceTypes = theResourceTypes; 049 050 if (theResourceTypes == null || theResourceTypes.isEmpty()) { 051 myResourceTypes = new ArrayList<>(); 052 myResourceTypes.add(IBaseResource.class); 053 } 054 } 055 056 @Override 057 public String getChildNameByDatatype(Class<? extends IBase> theDatatype) { 058 if (IBaseReference.class.isAssignableFrom(theDatatype)) { 059 return getElementName(); 060 } 061 return null; 062 } 063 064 @Override 065 public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theDatatype) { 066 if (IBaseReference.class.isAssignableFrom(theDatatype)) { 067 return myRuntimeDef; 068 } 069 return null; 070 } 071 072 @Override 073 public Set<String> getValidChildNames() { 074 return myValidChildNames; 075 } 076 077 @Override 078 public BaseRuntimeElementDefinition<?> getChildByName(String theName) { 079 return myRuntimeDef; 080 } 081 082 @Override 083 void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) { 084 myRuntimeDef = findResourceReferenceDefinition(theClassToElementDefinitions); 085 086 myValidChildNames = new HashSet<String>(); 087 myValidChildNames.add(getElementName()); 088 089 /* 090 * [elementName]Resource is not actually valid FHIR but we've encountered it in the wild 091 * so we'll accept it just to be nice 092 */ 093 myValidChildNames.add(getElementName() + "Resource"); 094 095 /* 096 * Below has been disabled- We used to allow field names to contain the name of the resource 097 * that they accepted. This wasn't valid but we accepted it just to be flexible because there 098 * were some bad examples containing this. This causes conflicts with actual field names in 099 * recent definitions though, so it has been disabled as of HAPI 0.9 100 */ 101// for (Class<? extends IBaseResource> next : myResourceTypes) { 102// if (next == IResource.class) { 103// for (Entry<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> nextEntry : theClassToElementDefinitions.entrySet()) { 104// if (IResource.class.isAssignableFrom(nextEntry.getKey())) { 105// RuntimeResourceDefinition nextDef = (RuntimeResourceDefinition) nextEntry.getValue(); 106// myValidChildNames.add(getElementName() + nextDef.getName()); 107// } 108// } 109// } 110// else { 111// RuntimeResourceDefinition nextDef = (RuntimeResourceDefinition) theClassToElementDefinitions.get(next); 112// if (nextDef == null) { 113// throw new ConfigurationException(Msg.code(1691) + "Can't find child of type: " + next.getCanonicalName() + " in " + getField().getDeclaringClass()); 114// } 115// myValidChildNames.add(getElementName() + nextDef.getName()); 116// } 117// } 118 119 myResourceTypes = Collections.unmodifiableList(myResourceTypes); 120 myValidChildNames = Collections.unmodifiableSet(myValidChildNames); 121 } 122 123 public List<Class<? extends IBaseResource>> getResourceTypes() { 124 return myResourceTypes; 125 } 126 127 @Override 128 public String toString() { 129 return getClass().getSimpleName() + "[" + getElementName() + "]"; 130 } 131}