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.i18n.Msg;
023import ca.uhn.fhir.model.api.annotation.DatatypeDef;
024import ca.uhn.fhir.model.api.annotation.ResourceDef;
025import org.hl7.fhir.instance.model.api.IBase;
026import org.hl7.fhir.instance.model.api.IBaseDatatype;
027import org.hl7.fhir.instance.model.api.ICompositeType;
028
029import java.util.Map;
030
031import static org.apache.commons.lang3.StringUtils.isBlank;
032
033public class RuntimeCompositeDatatypeDefinition extends BaseRuntimeElementCompositeDefinition<ICompositeType>
034                implements IRuntimeDatatypeDefinition {
035
036        private boolean mySpecialization;
037        private Class<? extends IBaseDatatype> myProfileOfType;
038        private BaseRuntimeElementDefinition<?> myProfileOf;
039
040        public RuntimeCompositeDatatypeDefinition(
041                        DatatypeDef theDef,
042                        Class<? extends ICompositeType> theImplementingClass,
043                        boolean theStandardType,
044                        FhirContext theContext,
045                        Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
046                super(theDef.name(), theImplementingClass, theStandardType, theContext, theClassToElementDefinitions);
047
048                String resourceName = theDef.name();
049                if (isBlank(resourceName)) {
050                        throw new ConfigurationException(Msg.code(1712) + "Resource type @" + ResourceDef.class.getSimpleName()
051                                        + " annotation contains no resource name: " + theImplementingClass.getCanonicalName());
052                }
053
054                mySpecialization = theDef.isSpecialization();
055                myProfileOfType = theDef.profileOf();
056                if (myProfileOfType.equals(IBaseDatatype.class)) {
057                        myProfileOfType = null;
058                }
059        }
060
061        @Override
062        public void sealAndInitialize(
063                        FhirContext theContext,
064                        Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
065                super.sealAndInitialize(theContext, theClassToElementDefinitions);
066
067                if (myProfileOfType != null) {
068                        myProfileOf = theClassToElementDefinitions.get(myProfileOfType);
069                        if (myProfileOf == null) {
070                                throw new ConfigurationException(Msg.code(1713) + "Unknown profileOf value: " + myProfileOfType);
071                        }
072                }
073        }
074
075        @Override
076        public Class<? extends IBaseDatatype> getProfileOf() {
077                return myProfileOfType;
078        }
079
080        @Override
081        public boolean isSpecialization() {
082                return mySpecialization;
083        }
084
085        @Override
086        public ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum getChildType() {
087                return ChildTypeEnum.COMPOSITE_DATATYPE;
088        }
089
090        @Override
091        public boolean isProfileOf(Class<? extends IBaseDatatype> theType) {
092                validateSealed();
093                if (myProfileOfType != null) {
094                        if (myProfileOfType.equals(theType)) {
095                                return true;
096                        } else if (myProfileOf instanceof IRuntimeDatatypeDefinition) {
097                                return ((IRuntimeDatatypeDefinition) myProfileOf).isProfileOf(theType);
098                        }
099                }
100                return false;
101        }
102}