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