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