
001/* 002 * #%L 003 * HAPI FHIR - Core Library 004 * %% 005 * Copyright (C) 2014 - 2025 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.i18n.Msg; 025import ca.uhn.fhir.model.api.ICompositeElement; 026import ca.uhn.fhir.model.api.IElement; 027import jakarta.annotation.Nullable; 028import org.hl7.fhir.instance.model.api.IBase; 029import org.hl7.fhir.instance.model.api.IBaseResource; 030import org.hl7.fhir.instance.model.api.IPrimitiveType; 031 032import java.util.ArrayList; 033import java.util.Date; 034import java.util.List; 035import java.util.function.Function; 036 037public class ElementUtil { 038 039 public static final Function<IBase, String> CONVERT_PRIMITIVE_TO_STRING = 040 e -> ((IPrimitiveType<?>) e).getValueAsString(); 041 public static final Function<IBase, IBaseResource> CAST_BASE_TO_RESOURCE = e -> (IBaseResource) e; 042 043 @SuppressWarnings("unchecked") 044 public static final Function<IBase, IPrimitiveType<Date>> CAST_TO_PRIMITIVE_DATE = e -> ((IPrimitiveType<Date>) e); 045 046 @SuppressWarnings("unchecked") 047 public static boolean isEmpty(Object... theElements) { 048 if (theElements == null) { 049 return true; 050 } 051 for (int i = 0; i < theElements.length; i++) { 052 Object next = theElements[i]; 053 if (next instanceof List) { 054 if (!isEmpty((List<? extends IBase>) next)) { 055 return false; 056 } 057 } else if (next instanceof String && (!((String) next).isEmpty())) { 058 return false; 059 } else if (next != null && !((IBase) next).isEmpty()) { 060 return false; 061 } 062 } 063 return true; 064 } 065 066 public static boolean isEmpty(IBase... theElements) { 067 if (theElements == null) { 068 return true; 069 } 070 for (int i = 0; i < theElements.length; i++) { 071 IBase next = theElements[i]; 072 if (next != null && !next.isEmpty()) { 073 return false; 074 } 075 } 076 return true; 077 } 078 079 public static boolean isEmpty(IElement... theElements) { 080 if (theElements == null) { 081 return true; 082 } 083 for (int i = 0; i < theElements.length; i++) { 084 IBase next = theElements[i]; 085 if (next != null && !next.isEmpty()) { 086 return false; 087 } 088 } 089 return true; 090 } 091 092 public static boolean isEmpty(List<? extends IBase> theElements) { 093 if (theElements == null) { 094 return true; 095 } 096 for (int i = 0; i < theElements.size(); i++) { 097 IBase next; 098 try { 099 next = theElements.get(i); 100 } catch (ClassCastException e) { 101 List<?> elements = theElements; 102 String s = "Found instance of " + elements.get(i).getClass() 103 + " - Did you set a field value to the incorrect type? Expected " + IBase.class.getName(); 104 throw new ClassCastException(Msg.code(1748) + s); 105 } 106 if (next != null && !next.isEmpty()) { 107 return false; 108 } 109 } 110 return true; 111 } 112 113 /** 114 * Note that this method does not work on HL7.org structures 115 */ 116 public static <T extends IElement> List<T> allPopulatedChildElements(Class<T> theType, Object... theElements) { 117 ArrayList<T> retVal = new ArrayList<>(); 118 for (Object next : theElements) { 119 if (next == null) { 120 continue; 121 } else if (next instanceof IElement) { 122 addElement(retVal, (IElement) next, theType); 123 } else if (next instanceof List) { 124 for (Object nextElement : ((List<?>) next)) { 125 if (!(nextElement instanceof IBase)) { 126 throw new IllegalArgumentException( 127 Msg.code(1749) + "Found element of " + nextElement.getClass()); 128 } 129 addElement(retVal, (IElement) nextElement, theType); 130 } 131 } else { 132 throw new IllegalArgumentException(Msg.code(1750) + "Found element of " + next.getClass()); 133 } 134 } 135 return retVal; 136 } 137 138 // @SuppressWarnings("unchecked") 139 private static <T extends IElement> void addElement(ArrayList<T> retVal, IElement next, Class<T> theType) { 140 if (theType != null && theType.isAssignableFrom(next.getClass())) { 141 retVal.add(theType.cast(next)); 142 } 143 if (next instanceof ICompositeElement) { 144 ICompositeElement iCompositeElement = (ICompositeElement) next; 145 // TODO: Use of a deprecated method should be resolved. 146 retVal.addAll(iCompositeElement.getAllPopulatedChildElementsOfType(theType)); 147 } 148 } 149 150 public static IBase setValue(IBase theTarget, BaseRuntimeChildDefinition theChildDef, Object theValue) { 151 BaseRuntimeElementDefinition<?> elementDefinition = theChildDef.getChildByName(theChildDef.getElementName()); 152 IBase value; 153 if (theValue == null || elementDefinition.getImplementingClass().isInstance(theValue)) { 154 value = (IBase) theValue; 155 } else { 156 value = elementDefinition.newInstance(theValue); 157 } 158 theChildDef.getMutator().setValue(theTarget, value); 159 return value; 160 } 161 162 @Nullable 163 public static <T> T getSingleValueOrNull( 164 IBase theParentElement, BaseRuntimeChildDefinition theChildDefinition, Function<IBase, T> theConverter) { 165 if (theParentElement == null) { 166 return null; 167 } 168 return theChildDefinition 169 .getAccessor() 170 .getFirstValueOrNull(theParentElement) 171 .map(theConverter) 172 .orElse(null); 173 } 174}