001package ca.uhn.fhir.util;
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.context.BaseRuntimeChildDefinition;
024import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
025import ca.uhn.fhir.context.FhirContext;
026import ca.uhn.fhir.context.FhirVersionEnum;
027import ca.uhn.fhir.i18n.Msg;
028import org.hl7.fhir.instance.model.api.IBase;
029import org.hl7.fhir.instance.model.api.IBaseExtension;
030import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
031import org.hl7.fhir.instance.model.api.IBaseMetaType;
032import org.hl7.fhir.instance.model.api.IBaseResource;
033import org.hl7.fhir.instance.model.api.IPrimitiveType;
034import org.slf4j.Logger;
035import org.slf4j.LoggerFactory;
036
037import java.util.List;
038
039
040public class MetaUtil {
041        private static final Logger ourLog = LoggerFactory.getLogger(MetaUtil.class);
042
043        private MetaUtil() {
044                // non-instantiable
045        }
046
047        public static String getSource(FhirContext theContext, IBaseMetaType theMeta) {
048                if (theContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R4)) {
049                        return getSourceR4Plus(theContext, theMeta);
050                } else if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
051                        return getSourceDstu3((IBaseHasExtensions) theMeta);
052                } else {
053                        throw new UnsupportedOperationException(Msg.code(1782) + MetaUtil.class.getSimpleName() + ".getSource() not supported on FHIR Version " + theContext.getVersion().getVersion());
054                }
055        }
056
057        private static String getSourceDstu3(IBaseHasExtensions theMeta) {
058                IBaseHasExtensions metaWithExtensions = theMeta;
059                List<? extends IBaseExtension<?, ?>> extensions = metaWithExtensions.getExtension();
060                for (IBaseExtension extension : extensions) {
061                        if (HapiExtensions.EXT_META_SOURCE.equals(extension.getUrl())) {
062                                IPrimitiveType<String> value = (IPrimitiveType<String>) extension.getValue();
063                                return value.getValueAsString();
064                        }
065                }
066                return null;
067        }
068
069        private static String getSourceR4Plus(FhirContext theFhirContext, IBaseMetaType theMeta) {
070                BaseRuntimeElementCompositeDefinition<?> elementDef = (BaseRuntimeElementCompositeDefinition<?>) theFhirContext.getElementDefinition(theMeta.getClass());
071                BaseRuntimeChildDefinition sourceChild = elementDef.getChildByName("source");
072                if (sourceChild == null) {
073                        return null;
074                }
075                List<IBase> sourceValues = sourceChild.getAccessor().getValues(theMeta);
076                String retVal = null;
077                if (sourceValues.size() > 0) {
078                        retVal = ((IPrimitiveType<?>) sourceValues.get(0)).getValueAsString();
079                }
080                return retVal;
081        }
082
083        /**
084         * Sets the value for <code>Resource.meta.source</code> for R4+ resources, and places the value in
085         * an extension on <code>Resource.meta</code>
086         * with the URL <code>http://hapifhir.io/fhir/StructureDefinition/resource-meta-source</code> for DSTU3.
087         *
088         * @param theContext  The FhirContext object
089         * @param theResource The resource to modify
090         * @param theValue    The source URI
091         * @see <a href="http://hl7.org/fhir/resource-definitions.html#Resource.meta">Meta.source</a>
092         */
093        @SuppressWarnings("unchecked")
094        public static void setSource(FhirContext theContext, IBaseResource theResource, String theValue) {
095                if (theContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R4)) {
096                        MetaUtil.setSource(theContext, theResource.getMeta(), theValue);
097                } else if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
098                        IBaseExtension<?, ?> sourceExtension = ((IBaseHasExtensions) theResource.getMeta()).addExtension();
099                        sourceExtension.setUrl(HapiExtensions.EXT_META_SOURCE);
100                        IPrimitiveType<String> value = (IPrimitiveType<String>) theContext.getElementDefinition("uri").newInstance();
101                        value.setValue(theValue);
102                        sourceExtension.setValue(value);
103                } else {
104                        ourLog.debug(MetaUtil.class.getSimpleName() + ".setSource() not supported on FHIR Version " + theContext.getVersion().getVersion());
105                }
106        }
107
108        public static void setSource(FhirContext theContext, IBaseMetaType theMeta, String theValue) {
109                BaseRuntimeElementCompositeDefinition<?> elementDef = (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(theMeta.getClass());
110                BaseRuntimeChildDefinition sourceChild = elementDef.getChildByName("source");
111                List<IBase> sourceValues = sourceChild.getAccessor().getValues(theMeta);
112                IPrimitiveType<?> sourceElement;
113                if (sourceValues.size() > 0) {
114                        sourceElement = ((IPrimitiveType<?>) sourceValues.get(0));
115                } else {
116                        sourceElement = (IPrimitiveType<?>) theContext.getElementDefinition("uri").newInstance();
117                        sourceChild.getMutator().setValue(theMeta, sourceElement);
118                }
119                sourceElement.setValueAsString(theValue);
120        }
121
122}