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.util; 021 022import ca.uhn.fhir.context.BaseRuntimeChildDefinition; 023import ca.uhn.fhir.context.BaseRuntimeElementDefinition; 024import ca.uhn.fhir.context.FhirContext; 025import ca.uhn.fhir.context.FhirVersionEnum; 026import ca.uhn.fhir.context.RuntimeResourceDefinition; 027import org.hl7.fhir.instance.model.api.IBase; 028import org.hl7.fhir.instance.model.api.IBaseBinary; 029import org.hl7.fhir.instance.model.api.IBaseReference; 030import org.hl7.fhir.instance.model.api.IPrimitiveType; 031 032import java.util.List; 033 034public class BinaryUtil { 035 036 private BinaryUtil() { 037 // non instantiable 038 } 039 040 /** 041 * Fetches the base64Binary value of Binary.data (or Binary.content on versions of 042 * FHIR before R4), creating it if it does not already exist. 043 */ 044 @SuppressWarnings("unchecked") 045 public static IPrimitiveType<byte[]> getOrCreateData(FhirContext theContext, IBaseBinary theBinary) { 046 String elementName = "content"; 047 if (theContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R4)) { 048 elementName = "data"; 049 } 050 051 BaseRuntimeChildDefinition entryChild = AttachmentUtil.getChild(theContext, theBinary, elementName); 052 List<IBase> entries = entryChild.getAccessor().getValues(theBinary); 053 return entries.stream().map(t -> (IPrimitiveType<byte[]>) t).findFirst().orElseGet(() -> { 054 IPrimitiveType<byte[]> binary = AttachmentUtil.newPrimitive(theContext, "base64Binary", null); 055 entryChild.getMutator().setValue(theBinary, binary); 056 return binary; 057 }); 058 } 059 060 public static IBaseReference getSecurityContext(FhirContext theCtx, IBaseBinary theBinary) { 061 RuntimeResourceDefinition def = theCtx.getResourceDefinition("Binary"); 062 BaseRuntimeChildDefinition child = def.getChildByName("securityContext"); 063 IBaseReference retVal = null; 064 if (child != null) { 065 List<IBase> values = child.getAccessor().getValues(theBinary); 066 if (values.size() > 0) { 067 retVal = (IBaseReference) values.get(0); 068 } 069 } 070 return retVal; 071 } 072 073 public static IBaseBinary newBinary(FhirContext theCtx) { 074 return (IBaseBinary) theCtx.getResourceDefinition("Binary").newInstance(); 075 } 076 077 public static void setSecurityContext(FhirContext theCtx, IBaseBinary theBinary, String theSecurityContext) { 078 RuntimeResourceDefinition def = theCtx.getResourceDefinition("Binary"); 079 BaseRuntimeChildDefinition child = def.getChildByName("securityContext"); 080 081 BaseRuntimeElementDefinition<?> referenceDef = theCtx.getElementDefinition("reference"); 082 IBaseReference reference = (IBaseReference) referenceDef.newInstance(); 083 child.getMutator().addValue(theBinary, reference); 084 085 reference.setReference(theSecurityContext); 086 } 087 088 public static void setData(FhirContext theCtx, IBaseBinary theBinary, byte[] theBytes, String theContentType) { 089 getOrCreateData(theCtx, theBinary).setValue(theBytes); 090 091 String elementName = "contentType"; 092 BaseRuntimeChildDefinition entryChild = AttachmentUtil.getChild(theCtx, theBinary, elementName); 093 List<IBase> entries = entryChild.getAccessor().getValues(theBinary); 094 IPrimitiveType<String> contentTypeElement = entries.stream() 095 .map(t -> (IPrimitiveType<String>) t) 096 .findFirst() 097 .orElseGet(() -> { 098 IPrimitiveType<String> stringType = AttachmentUtil.newPrimitive(theCtx, "code", null); 099 entryChild.getMutator().setValue(theBinary, stringType); 100 return stringType; 101 }); 102 contentTypeElement.setValue(theContentType); 103 } 104}