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.*; 024import ca.uhn.fhir.model.primitive.StringDt; 025import org.apache.commons.lang3.StringUtils; 026import org.apache.commons.lang3.Validate; 027import org.hl7.fhir.instance.model.api.*; 028 029import java.util.ArrayList; 030import java.util.Collection; 031import java.util.List; 032import java.util.Optional; 033 034/** 035 * Utilities for dealing with parameters resources in a version indepenedent way 036 */ 037public class ParametersUtil { 038 039 public static List<String> getNamedParameterValuesAsString(FhirContext theCtx, IBaseParameters theParameters, String theParameterName) { 040 Validate.notNull(theParameters, "theParameters must not be null"); 041 RuntimeResourceDefinition resDef = theCtx.getResourceDefinition(theParameters.getClass()); 042 BaseRuntimeChildDefinition parameterChild = resDef.getChildByName("parameter"); 043 List<IBase> parameterReps = parameterChild.getAccessor().getValues(theParameters); 044 045 List<String> retVal = new ArrayList<>(); 046 047 for (IBase nextParameter : parameterReps) { 048 BaseRuntimeElementCompositeDefinition<?> nextParameterDef = (BaseRuntimeElementCompositeDefinition<?>) theCtx.getElementDefinition(nextParameter.getClass()); 049 BaseRuntimeChildDefinition nameChild = nextParameterDef.getChildByName("name"); 050 List<IBase> nameValues = nameChild.getAccessor().getValues(nextParameter); 051 Optional<? extends IPrimitiveType<?>> nameValue = nameValues 052 .stream() 053 .filter(t -> t instanceof IPrimitiveType<?>) 054 .map(t -> ((IPrimitiveType<?>) t)) 055 .findFirst(); 056 if (!nameValue.isPresent() || !theParameterName.equals(nameValue.get().getValueAsString())) { 057 continue; 058 } 059 060 BaseRuntimeChildDefinition valueChild = nextParameterDef.getChildByName("value[x]"); 061 List<IBase> valueValues = valueChild.getAccessor().getValues(nextParameter); 062 valueValues 063 .stream() 064 .filter(t -> t instanceof IPrimitiveType<?>) 065 .map(t -> ((IPrimitiveType<?>) t).getValueAsString()) 066 .filter(StringUtils::isNotBlank) 067 .forEach(retVal::add); 068 069 } 070 071 return retVal; 072 } 073 074 private static void addClientParameter(FhirContext theContext, Object theValue, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem, String theName) { 075 Validate.notNull(theValue, "theValue must not be null"); 076 077 if (theValue instanceof IBaseResource) { 078 IBase parameter = createParameterRepetition(theContext, theTargetResource, paramChild, paramChildElem, theName); 079 paramChildElem.getChildByName("resource").getMutator().addValue(parameter, (IBaseResource) theValue); 080 } else if (theValue instanceof IBaseDatatype) { 081 IBase parameter = createParameterRepetition(theContext, theTargetResource, paramChild, paramChildElem, theName); 082 paramChildElem.getChildByName("value[x]").getMutator().addValue(parameter, (IBaseDatatype) theValue); 083 } else if (theValue instanceof Collection) { 084 Collection<?> collection = (Collection<?>) theValue; 085 for (Object next : collection) { 086 addClientParameter(theContext, next, theTargetResource, paramChild, paramChildElem, theName); 087 } 088 } else { 089 throw new IllegalArgumentException("Don't know how to handle value of type " + theValue.getClass() + " for parameter " + theName); 090 } 091 } 092 093 /** 094 * Add a paratemer value to a Parameters resource 095 * 096 * @param theContext The FhirContext 097 * @param theParameters The Parameters resource 098 * @param theName The parametr name 099 * @param theValue The parameter value (can be a {@link IBaseResource resource} or a {@link IBaseDatatype datatype}) 100 */ 101 public static void addParameterToParameters(FhirContext theContext, IBaseParameters theParameters, String theName, Object theValue) { 102 RuntimeResourceDefinition def = theContext.getResourceDefinition(theParameters); 103 BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter"); 104 BaseRuntimeElementCompositeDefinition<?> paramChildElem = (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter"); 105 106 addClientParameter(theContext, theValue, theParameters, paramChild, paramChildElem, theName); 107 } 108 109 /** 110 * Add a paratemer value to a Parameters resource 111 * 112 * @param theContext The FhirContext 113 * @param theParameters The Parameters resource 114 * @param theName The parameter name 115 * @param thePrimitiveDatatype The datatype, e.g. "string", or "uri" 116 * @param theValue The value 117 */ 118 public static void addParameterToParameters(FhirContext theContext, IBaseParameters theParameters, String theName, String thePrimitiveDatatype, String theValue) { 119 Validate.notBlank(thePrimitiveDatatype, "thePrimitiveDatatype must not be null or empty"); 120 121 BaseRuntimeElementDefinition<?> datatypeDef = theContext.getElementDefinition(thePrimitiveDatatype); 122 IPrimitiveType<?> value = (IPrimitiveType<?>) datatypeDef.newInstance(); 123 value.setValueAsString(theValue); 124 125 addParameterToParameters(theContext, theParameters, theName, value); 126 } 127 128 private static IBase createParameterRepetition(FhirContext theContext, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem, String theName) { 129 IBase parameter = paramChildElem.newInstance(); 130 paramChild.getMutator().addValue(theTargetResource, parameter); 131 IPrimitiveType<?> value; 132 value = createString(theContext, theName); 133 paramChildElem.getChildByName("name").getMutator().addValue(parameter, value); 134 return parameter; 135 } 136 137 public static IPrimitiveType<?> createString(FhirContext theContext, String theValue) { 138 IPrimitiveType<?> value; 139 if (theContext.getVersion().getVersion().isRi()) { 140 value = (IPrimitiveType<?>) theContext.getElementDefinition("string").newInstance(theValue); 141 } else { 142 value = new StringDt(theValue); 143 } 144 return value; 145 } 146 147 public static IPrimitiveType<?> createUri(FhirContext theContext, String theValue) { 148 IPrimitiveType<?> value = (IPrimitiveType<?>) theContext.getElementDefinition("uri").newInstance(theValue); 149 return value; 150 } 151 152 public static IPrimitiveType<?> createCode(FhirContext theContext, String theValue) { 153 IPrimitiveType<?> value = (IPrimitiveType<?>) theContext.getElementDefinition("code").newInstance(theValue); 154 return value; 155 } 156 157 public static IBaseParameters newInstance(FhirContext theContext) { 158 Validate.notNull(theContext, "theContext must not be null"); 159 return (IBaseParameters) theContext.getResourceDefinition("Parameters").newInstance(); 160 } 161 162 @SuppressWarnings("unchecked") 163 public static void addParameterToParametersBoolean(FhirContext theCtx, IBaseParameters theParameters, String theName, boolean theValue) { 164 IPrimitiveType<Boolean> value = (IPrimitiveType<Boolean>) theCtx.getElementDefinition("boolean").newInstance(); 165 value.setValue(theValue); 166 addParameterToParameters(theCtx, theParameters, theName, value); 167 } 168 169 @SuppressWarnings("unchecked") 170 public static void addParameterToParametersCode(FhirContext theCtx, IBaseParameters theParameters, String theName, String theValue) { 171 IPrimitiveType<String> value = (IPrimitiveType<String>) theCtx.getElementDefinition("code").newInstance(); 172 value.setValue(theValue); 173 addParameterToParameters(theCtx, theParameters, theName, value); 174 } 175 176 @SuppressWarnings("unchecked") 177 public static void addParameterToParametersInteger(FhirContext theCtx, IBaseParameters theParameters, String theName, int theValue) { 178 IPrimitiveType<Integer> count = (IPrimitiveType<Integer>) theCtx.getElementDefinition("integer").newInstance(); 179 count.setValue(theValue); 180 addParameterToParameters(theCtx, theParameters, theName, count); 181 182 } 183 184 public static void addParameterToParametersReference(FhirContext theCtx, IBaseParameters theParameters, String theName, String theReference) { 185 IBaseReference target = (IBaseReference) theCtx.getElementDefinition("reference").newInstance(); 186 target.setReference(theReference); 187 addParameterToParameters(theCtx, theParameters, theName, target); 188 } 189 190 @SuppressWarnings("unchecked") 191 public static void addParameterToParametersString(FhirContext theCtx, IBaseParameters theParameters, String theName, String theValue) { 192 IPrimitiveType<String> value = (IPrimitiveType<String>) theCtx.getElementDefinition("string").newInstance(); 193 value.setValue(theValue); 194 addParameterToParameters(theCtx, theParameters, theName, value); 195 } 196 197 @SuppressWarnings("unchecked") 198 public static void addParameterToParametersUri(FhirContext theCtx, IBaseParameters theParameters, String theName, String theValue) { 199 IPrimitiveType<String> value = (IPrimitiveType<String>) theCtx.getElementDefinition("uri").newInstance(); 200 value.setValue(theValue); 201 addParameterToParameters(theCtx, theParameters, theName, value); 202 203 } 204 205 /** 206 * Add a parameter with no value (typically because we'll be adding sub-parameters) 207 */ 208 public static IBase addParameterToParameters(FhirContext theContext, IBaseParameters theParameters, String theName) { 209 RuntimeResourceDefinition def = theContext.getResourceDefinition(theParameters); 210 BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter"); 211 BaseRuntimeElementCompositeDefinition<?> paramChildElem = (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter"); 212 213 return createParameterRepetition(theContext, theParameters, paramChild, paramChildElem, theName); 214 } 215 216 public static void addPartCode(FhirContext theContext, IBase theParameter, String theName, String theCode) { 217 IPrimitiveType<String> value = (IPrimitiveType<String>) theContext.getElementDefinition("code").newInstance(); 218 value.setValue(theCode); 219 220 addPart(theContext, theParameter, theName, value); 221 } 222 223 public static void addPartString(FhirContext theContext, IBase theParameter, String theName, String theValue) { 224 IPrimitiveType<String> value = (IPrimitiveType<String>) theContext.getElementDefinition("string").newInstance(); 225 value.setValue(theValue); 226 227 addPart(theContext, theParameter, theName, value); 228 } 229 230 public static void addPartCoding(FhirContext theContext, IBase theParameter, String theName, String theSystem, String theCode, String theDisplay) { 231 IBase coding = theContext.getElementDefinition("coding").newInstance(); 232 233 BaseRuntimeElementCompositeDefinition<?> codingDef = (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(coding.getClass()); 234 codingDef.getChildByName("system").getMutator().addValue(coding, createUri(theContext, theSystem)); 235 codingDef.getChildByName("code").getMutator().addValue(coding, createCode(theContext, theCode)); 236 codingDef.getChildByName("display").getMutator().addValue(coding, createString(theContext, theDisplay)); 237 238 addPart(theContext, theParameter, theName, coding); 239 } 240 241 private static void addPart(FhirContext theContext, IBase theParameter, String theName, IBase theValue) { 242 BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(theParameter.getClass()); 243 BaseRuntimeChildDefinition partChild = def.getChildByName("part"); 244 245 BaseRuntimeElementCompositeDefinition<?> partChildElem = (BaseRuntimeElementCompositeDefinition<?>) partChild.getChildByName("part"); 246 IBase part = partChildElem.newInstance(); 247 partChild.getMutator().addValue(theParameter, part); 248 249 IPrimitiveType<String> name = (IPrimitiveType<String>) theContext.getElementDefinition("string").newInstance(); 250 name.setValue(theName); 251 partChildElem.getChildByName("name").getMutator().addValue(part, name); 252 253 partChildElem.getChildByName("value[x]").getMutator().addValue(part, theValue); 254 } 255}