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.IDatatype; 023import ca.uhn.fhir.model.api.IResource; 024import ca.uhn.fhir.model.api.annotation.Child; 025import ca.uhn.fhir.model.api.annotation.Description; 026import ca.uhn.fhir.model.primitive.XhtmlDt; 027import org.hl7.fhir.instance.model.api.IBase; 028import org.hl7.fhir.instance.model.api.IBaseDatatype; 029import org.hl7.fhir.instance.model.api.IBaseReference; 030 031import java.lang.reflect.Field; 032import java.util.ArrayList; 033import java.util.Collections; 034import java.util.Comparator; 035import java.util.List; 036import java.util.Map; 037 038public class RuntimeChildAny extends RuntimeChildChoiceDefinition { 039 040 public RuntimeChildAny( 041 Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation) { 042 super(theField, theElementName, theChildAnnotation, theDescriptionAnnotation); 043 } 044 045 @Override 046 void sealAndInitialize( 047 FhirContext theContext, 048 Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) { 049 List<Class<? extends IBase>> choiceTypes = new ArrayList<Class<? extends IBase>>(); 050 051 for (Class<? extends IBase> next : theClassToElementDefinitions.keySet()) { 052 if (next.equals(XhtmlDt.class)) { 053 continue; 054 } 055 056 BaseRuntimeElementDefinition<?> nextDef = theClassToElementDefinitions.get(next); 057 if (nextDef instanceof IRuntimeDatatypeDefinition) { 058 if (((IRuntimeDatatypeDefinition) nextDef).isSpecialization()) { 059 /* 060 * Things like BoundCodeDt shoudn't be considered as valid options for an "any" choice, since 061 * we'll already have CodeDt as an option 062 */ 063 continue; 064 } 065 } 066 067 if (IResource.class.isAssignableFrom(next) 068 || IDatatype.class.isAssignableFrom(next) 069 || IBaseDatatype.class.isAssignableFrom(next) 070 || IBaseReference.class.isAssignableFrom(next)) { 071 choiceTypes.add(next); 072 } 073 } 074 Collections.sort(choiceTypes, new Comparator<Class<?>>() { 075 @Override 076 public int compare(Class<?> theO1, Class<?> theO2) { 077 boolean o1res = IResource.class.isAssignableFrom(theO1); 078 boolean o2res = IResource.class.isAssignableFrom(theO2); 079 if (o1res && o2res) { 080 return theO1.getSimpleName().compareTo(theO2.getSimpleName()); 081 } else if (o1res) { 082 return -1; 083 } else if (o1res == false && o2res == false) { 084 return 0; 085 } else { 086 return 1; 087 } 088 } 089 }); 090 091 setChoiceTypes(choiceTypes); 092 093 super.sealAndInitialize(theContext, theClassToElementDefinitions); 094 } 095}