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