001package ca.uhn.fhir.util;
002
003/*-
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2021 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.*;
024import org.apache.commons.lang3.Validate;
025import org.hl7.fhir.instance.model.api.IBase;
026import org.hl7.fhir.instance.model.api.ICompositeType;
027import org.hl7.fhir.instance.model.api.IPrimitiveType;
028
029import java.util.List;
030
031public class AttachmentUtil {
032
033        /**
034         * Fetches the base64Binary value of Attachment.data, creating it if it does not
035         * already exist.
036         */
037        public static IPrimitiveType<byte[]> getOrCreateData(FhirContext theContext, ICompositeType theAttachment) {
038                return getOrCreateChild(theContext, theAttachment, "data", "base64Binary");
039        }
040
041        public static IPrimitiveType<String> getOrCreateContentType(FhirContext theContext, ICompositeType theAttachment) {
042                return getOrCreateChild(theContext, theAttachment, "contentType", "string");
043        }
044
045        public static IPrimitiveType<String> getOrCreateUrl(FhirContext theContext, ICompositeType theAttachment) {
046                return getOrCreateChild(theContext, theAttachment, "url", "uri");
047        }
048
049        @SuppressWarnings("unchecked")
050        private static <T> IPrimitiveType<T> getOrCreateChild(FhirContext theContext, ICompositeType theAttachment, String theChildName, String theChildDatatype) {
051                BaseRuntimeChildDefinition entryChild = getChild(theContext, theAttachment, theChildName);
052                List<IBase> entries = entryChild.getAccessor().getValues(theAttachment);
053                return entries
054                        .stream()
055                        .map(t -> (IPrimitiveType<T>) t)
056                        .findFirst()
057                        .orElseGet(() -> {
058                                IPrimitiveType<String> string = newPrimitive(theContext, theChildDatatype, null);
059                                entryChild.getMutator().setValue(theAttachment, string);
060                                return (IPrimitiveType<T>) string;
061                        });
062        }
063
064        public static void setUrl(FhirContext theContext, ICompositeType theAttachment, String theUrl) {
065                BaseRuntimeChildDefinition entryChild = getChild(theContext, theAttachment, "url");
066                assert entryChild != null : "Version " + theContext + " has no child " + "url";
067                String typeName = "uri";
068                if (theContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R4)) {
069                        typeName = "url";
070                }
071                entryChild.getMutator().setValue(theAttachment, newPrimitive(theContext, typeName, theUrl));
072        }
073
074        public static void setContentType(FhirContext theContext, ICompositeType theAttachment, String theContentType) {
075                BaseRuntimeChildDefinition entryChild = getChild(theContext, theAttachment, "contentType");
076                entryChild.getMutator().setValue(theAttachment, newPrimitive(theContext, "code", theContentType));
077        }
078
079        public static void setData(FhirContext theContext, ICompositeType theAttachment, byte[] theBytes) {
080                BaseRuntimeChildDefinition entryChild = getChild(theContext, theAttachment, "data");
081                entryChild.getMutator().setValue(theAttachment, newPrimitive(theContext, "base64Binary", theBytes));
082        }
083
084        public static void setSize(FhirContext theContext, ICompositeType theAttachment, Integer theLength) {
085                BaseRuntimeChildDefinition entryChild = getChild(theContext, theAttachment, "size");
086                if (theLength == null) {
087                        entryChild.getMutator().setValue(theAttachment, null);
088                } else if (theContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R5)){
089                        entryChild.getMutator().setValue(theAttachment, newPrimitive(theContext, "integer64", (long)theLength));
090                } else {
091                        entryChild.getMutator().setValue(theAttachment, newPrimitive(theContext, "unsignedInt", theLength));
092                }
093        }
094
095        /**
096         * This is internal API- Use with caution as it may change
097         */
098        @SuppressWarnings("unchecked")
099        static <T> IPrimitiveType<T> newPrimitive(FhirContext theContext, String theType, T theValue) {
100                BaseRuntimeElementDefinition<?> elementDefinition = theContext.getElementDefinition(theType);
101                Validate.notNull(elementDefinition, "Unknown type %s for %s", theType, theContext);
102                IPrimitiveType<T> primitive = (IPrimitiveType<T>) elementDefinition.newInstance();
103                primitive.setValue(theValue);
104                return primitive;
105        }
106
107        /**
108         * This is internal API- Use with caution as it may change
109         */
110        static BaseRuntimeChildDefinition getChild(FhirContext theContext, IBase theElement, String theName) {
111                BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(theElement.getClass());
112                return def.getChildByName(theName);
113        }
114
115        public static ICompositeType newInstance(FhirContext theFhirCtx) {
116                return (ICompositeType) theFhirCtx.getElementDefinition("Attachment").newInstance();
117        }
118}