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.FhirContext;
023import ca.uhn.fhir.context.RuntimeResourceDefinition;
024import org.hl7.fhir.instance.model.api.IBase;
025import org.hl7.fhir.instance.model.api.IBaseResource;
026
027import java.util.List;
028
029/**
030 * Wrapper class holding context-related instances, and the resource being operated on. Sample use case is
031 *
032 * <pre>{@code
033 * TerserUtilHelper helper = TerserUtilHelper.newHelper(ourFhirContext, "Patient");
034 * helper.setField("identifier.system", "http://org.com/sys");
035 * helper.setField("identifier.value", "123");
036 * ...
037 * Patient patient = helper.getResource();
038 * }</pre>
039 */
040public class TerserUtilHelper {
041
042        /**
043         * Factory method for creating a new instance of the wrapper
044         *
045         * @param theFhirContext  FHIR Context to be used for all further operations
046         * @param theResourceName Name of the resource type
047         * @return Returns a new helper instance
048         */
049        public static TerserUtilHelper newHelper(FhirContext theFhirContext, String theResourceName) {
050                return newHelper(theFhirContext, (IBaseResource) TerserUtil.newResource(theFhirContext, theResourceName));
051        }
052
053        /**
054         * Factory method for creating a new instance of the wrapper
055         *
056         * @param theFhirContext FHIR Context to be used for all further operations
057         * @param theResource    The resource to operate on
058         * @return Returns a new helper instance
059         */
060        public static TerserUtilHelper newHelper(FhirContext theFhirContext, IBaseResource theResource) {
061                TerserUtilHelper retVal = new TerserUtilHelper(theFhirContext, theResource);
062                return retVal;
063        }
064
065        private FhirContext myContext;
066        private FhirTerser myTerser;
067        private IBaseResource myResource;
068
069        protected TerserUtilHelper(FhirContext theFhirContext, IBaseResource theResource) {
070                myContext = theFhirContext;
071                myResource = theResource;
072        }
073
074        /**
075         * Sets string field at the specified FHIR path
076         *
077         * @param theField The FHIR Path to set the values at
078         * @param theValue The string value to be set
079         * @return Returns current instance
080         */
081        public TerserUtilHelper setField(String theField, String theValue) {
082                IBase value = newStringElement(theValue);
083                TerserUtil.setFieldByFhirPath(getTerser(), theField, myResource, value);
084                return this;
085        }
086
087        /**
088         * Sets field at the specified FHIR path
089         *
090         * @param theField The FHIR Path to set the values at
091         * @param theValue The value to be set
092         * @return Returns current instance
093         */
094        public TerserUtilHelper setField(String theField, String theFieldType, Object theValue) {
095                IBase value = newElement(theFieldType, theValue);
096                TerserUtil.setFieldByFhirPath(getTerser(), theField, myResource, value);
097                return this;
098        }
099
100        protected IBase newStringElement(String theValue) {
101                return newElement("string", theValue);
102        }
103
104        protected IBase newElement(String theElementType, Object theValue) {
105                IBase value = TerserUtil.newElement(myContext, theElementType, theValue);
106                return value;
107        }
108
109        /**
110         * Gets values for the specified child field.
111         *
112         * @param theField The field to get values from
113         * @return Returns a list of retrieved values or null if the specified field doesn't exist
114         */
115        public List<IBase> getFieldValues(String theField) {
116                return TerserUtil.getValues(myContext, myResource, theField);
117        }
118
119        /**
120         * Gets values for the specified field values by FHIRPath.
121         *
122         * @param theFhirPath The FHIR path expression to get the values from
123         * @return Returns a collection of values or null if the specified field doesn't exist
124         */
125        public List<IBase> getFieldValuesByFhirPath(String theFhirPath) {
126                return TerserUtil.getFieldByFhirPath(myContext, theFhirPath, myResource);
127        }
128
129        /**
130         * Gets first available value for the specified field values by FHIRPath.
131         *
132         * @param theFhirPath The FHIR path expression to get the values from
133         * @return Returns the value or null if the specified field doesn't exist or is empty
134         */
135        public IBase getFieldValueByFhirPath(String theFhirPath) {
136                return TerserUtil.getFirstFieldByFhirPath(myContext, theFhirPath, myResource);
137        }
138
139        /**
140         * Gets first available values of the specified field.
141         *
142         * @param theField The field to get values from
143         * @return Returns the first available value for the field name or null if the
144         * specified field doesn't exist or has no values
145         */
146        public IBase getFieldValue(String theField) {
147                List<IBase> values = getFieldValues(theField);
148                if (values == null || values.isEmpty()) {
149                        return null;
150                }
151                return values.get(0);
152        }
153
154        /**
155         * Gets the terser instance, creating one if necessary.
156         *
157         * @return Returns the terser
158         */
159        public FhirTerser getTerser() {
160                if (myTerser == null) {
161                        myTerser = myContext.newTerser();
162                }
163                return myTerser;
164        }
165
166        /**
167         * Gets resource that this helper operates on
168         *
169         * @param <T> Instance type of the resource
170         * @return Returns the resources
171         */
172        public <T extends IBaseResource> T getResource() {
173                return (T) myResource;
174        }
175
176        /**
177         * Gets runtime definition for the resource
178         *
179         * @return Returns resource definition.
180         */
181        public RuntimeResourceDefinition getResourceDefinition() {
182                return myContext.getResourceDefinition(myResource);
183        }
184
185        /**
186         * Creates a new element
187         *
188         * @param theElementName Name of the element to create
189         * @return Returns a new element
190         */
191        public IBase newElement(String theElementName) {
192                return TerserUtil.newElement(myContext, theElementName);
193        }
194
195        /**
196         * Gets context holding resource definition.
197         *
198         * @return Returns the current FHIR context.
199         */
200        public FhirContext getContext() {
201                return myContext;
202        }
203}