001/*- 002 * #%L 003 * HAPI FHIR - Core Library 004 * %% 005 * Copyright (C) 2014 - 2023 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 054 .stream() 055 .map(t -> (IPrimitiveType<byte[]>) t) 056 .findFirst() 057 .orElseGet(() -> { 058 IPrimitiveType<byte[]> binary = AttachmentUtil.newPrimitive(theContext, "base64Binary", null); 059 entryChild.getMutator().setValue(theBinary, binary); 060 return binary; 061 }); 062 } 063 064 065 public static IBaseReference getSecurityContext(FhirContext theCtx, IBaseBinary theBinary) { 066 RuntimeResourceDefinition def = theCtx.getResourceDefinition("Binary"); 067 BaseRuntimeChildDefinition child = def.getChildByName("securityContext"); 068 IBaseReference retVal = null; 069 if (child != null) { 070 List<IBase> values = child.getAccessor().getValues(theBinary); 071 if (values.size() > 0) { 072 retVal = (IBaseReference) values.get(0); 073 } 074 } 075 return retVal; 076 } 077 078 public static IBaseBinary newBinary(FhirContext theCtx) { 079 return (IBaseBinary) theCtx.getResourceDefinition("Binary").newInstance(); 080 } 081 082 public static void setSecurityContext(FhirContext theCtx, IBaseBinary theBinary, String theSecurityContext) { 083 RuntimeResourceDefinition def = theCtx.getResourceDefinition("Binary"); 084 BaseRuntimeChildDefinition child = def.getChildByName("securityContext"); 085 086 BaseRuntimeElementDefinition<?> referenceDef = theCtx.getElementDefinition("reference"); 087 IBaseReference reference = (IBaseReference) referenceDef.newInstance(); 088 child.getMutator().addValue(theBinary, reference); 089 090 reference.setReference(theSecurityContext); 091 } 092 093 public static void setData(FhirContext theCtx, IBaseBinary theBinary, byte[] theBytes, String theContentType) { 094 getOrCreateData(theCtx, theBinary).setValue(theBytes); 095 096 String elementName = "contentType"; 097 BaseRuntimeChildDefinition entryChild = AttachmentUtil.getChild(theCtx, theBinary, elementName); 098 List<IBase> entries = entryChild.getAccessor().getValues(theBinary); 099 IPrimitiveType<String> contentTypeElement = entries 100 .stream() 101 .map(t -> (IPrimitiveType<String>) t) 102 .findFirst() 103 .orElseGet(() -> { 104 IPrimitiveType<String> stringType = AttachmentUtil.newPrimitive(theCtx, "code", null); 105 entryChild.getMutator().setValue(theBinary, stringType); 106 return stringType; 107 }); 108 contentTypeElement.setValue(theContentType); 109 110 } 111}