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