• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.health.connect.datatypes;
18 
19 import static android.health.connect.datatypes.validation.ValidationUtils.validateIntDefValue;
20 
21 import static com.android.healthfitness.flags.Flags.FLAG_PERSONAL_HEALTH_RECORD;
22 
23 import static java.util.Objects.hash;
24 import static java.util.Objects.requireNonNull;
25 
26 import android.annotation.FlaggedApi;
27 import android.annotation.IntDef;
28 import android.annotation.NonNull;
29 import android.os.Parcel;
30 import android.os.Parcelable;
31 
32 import java.lang.annotation.Retention;
33 import java.lang.annotation.RetentionPolicy;
34 import java.util.Set;
35 
36 /**
37  * A class to capture the FHIR resource data. This is the class used for all supported FHIR resource
38  * types, which is a subset of the resource list on <a
39  * href="https://build.fhir.org/resourcelist.html">the official FHIR website</a>. The list of
40  * supported types will likely expand in future releases.
41  *
42  * <p>FHIR stands for the <a href="https://hl7.org/fhir/">Fast Healthcare Interoperability Resources
43  * </a> standard.
44  */
45 @FlaggedApi(FLAG_PERSONAL_HEALTH_RECORD)
46 public final class FhirResource implements Parcelable {
47     // LINT.IfChange
48     /**
49      * FHIR resource type for <a href="https://www.hl7.org/fhir/immunization.html">Immunization</a>.
50      */
51     public static final int FHIR_RESOURCE_TYPE_IMMUNIZATION = 1;
52 
53     /**
54      * FHIR resource type for <a
55      * href="https://www.hl7.org/fhir/allergyintolerance.html">AllergyIntolerance</a>.
56      */
57     public static final int FHIR_RESOURCE_TYPE_ALLERGY_INTOLERANCE = 2;
58 
59     /**
60      * FHIR resource type for a <a href="https://www.hl7.org/fhir/observation.html">FHIR
61      * Observation</a>.
62      */
63     public static final int FHIR_RESOURCE_TYPE_OBSERVATION = 3;
64 
65     /**
66      * FHIR resource type for a <a href="https://www.hl7.org/fhir/condition.html">FHIR
67      * Condition</a>.
68      */
69     public static final int FHIR_RESOURCE_TYPE_CONDITION = 4;
70 
71     /**
72      * FHIR resource type for a <a href="https://www.hl7.org/fhir/procedure.html">FHIR
73      * Procedure</a>.
74      */
75     public static final int FHIR_RESOURCE_TYPE_PROCEDURE = 5;
76 
77     /**
78      * FHIR resource type for a <a href="https://www.hl7.org/fhir/medication.html">FHIR
79      * Medication</a>.
80      */
81     public static final int FHIR_RESOURCE_TYPE_MEDICATION = 6;
82 
83     /**
84      * FHIR resource type for a <a href="https://www.hl7.org/fhir/medicationrequest.html">FHIR
85      * MedicationRequest</a>.
86      */
87     public static final int FHIR_RESOURCE_TYPE_MEDICATION_REQUEST = 7;
88 
89     /**
90      * FHIR resource type for a <a href="https://www.hl7.org/fhir/medicationstatement.html">FHIR
91      * MedicationStatement</a>.
92      */
93     public static final int FHIR_RESOURCE_TYPE_MEDICATION_STATEMENT = 8;
94 
95     /**
96      * FHIR resource type for a <a href="https://www.hl7.org/fhir/patient.html">FHIR Patient</a>.
97      */
98     public static final int FHIR_RESOURCE_TYPE_PATIENT = 9;
99 
100     /**
101      * FHIR resource type for a <a href="https://www.hl7.org/fhir/practitioner.html">FHIR
102      * Practitioner</a>.
103      */
104     public static final int FHIR_RESOURCE_TYPE_PRACTITIONER = 10;
105 
106     /**
107      * FHIR resource type for a <a href="https://www.hl7.org/fhir/practitionerrole.html">FHIR
108      * PractitionerRole</a>.
109      */
110     public static final int FHIR_RESOURCE_TYPE_PRACTITIONER_ROLE = 11;
111 
112     /**
113      * FHIR resource type for a <a href="https://www.hl7.org/fhir/encounter.html">FHIR
114      * Encounter</a>.
115      */
116     public static final int FHIR_RESOURCE_TYPE_ENCOUNTER = 12;
117 
118     /**
119      * FHIR resource type for a <a href="https://www.hl7.org/fhir/location.html">FHIR Location</a>.
120      */
121     public static final int FHIR_RESOURCE_TYPE_LOCATION = 13;
122 
123     /**
124      * FHIR resource type for a <a href="https://www.hl7.org/fhir/organization.html">FHIR
125      * Organization</a>.
126      */
127     public static final int FHIR_RESOURCE_TYPE_ORGANIZATION = 14;
128 
129     // LINT.ThenChange(/service/proto/phr/fhir_spec_utils.py:fhir_resource_type_mapping)
130 
131     /** @hide */
132     @IntDef({
133         FHIR_RESOURCE_TYPE_IMMUNIZATION,
134         FHIR_RESOURCE_TYPE_ALLERGY_INTOLERANCE,
135         FHIR_RESOURCE_TYPE_OBSERVATION,
136         FHIR_RESOURCE_TYPE_CONDITION,
137         FHIR_RESOURCE_TYPE_PROCEDURE,
138         FHIR_RESOURCE_TYPE_MEDICATION,
139         FHIR_RESOURCE_TYPE_MEDICATION_REQUEST,
140         FHIR_RESOURCE_TYPE_MEDICATION_STATEMENT,
141         FHIR_RESOURCE_TYPE_PATIENT,
142         FHIR_RESOURCE_TYPE_PRACTITIONER,
143         FHIR_RESOURCE_TYPE_PRACTITIONER_ROLE,
144         FHIR_RESOURCE_TYPE_ENCOUNTER,
145         FHIR_RESOURCE_TYPE_LOCATION,
146         FHIR_RESOURCE_TYPE_ORGANIZATION,
147     })
148     @Retention(RetentionPolicy.SOURCE)
149     public @interface FhirResourceType {}
150 
151     @FhirResourceType private final int mType;
152     @NonNull private final String mId;
153     @NonNull private final String mData;
154 
155     /**
156      * Creates a new instance of {@link FhirResource}. Please see {@link FhirResource.Builder} for
157      * more detailed parameters information.
158      */
FhirResource(@hirResourceType int type, @NonNull String id, @NonNull String data)159     private FhirResource(@FhirResourceType int type, @NonNull String id, @NonNull String data) {
160         validateFhirResourceType(type);
161         requireNonNull(id);
162         requireNonNull(data);
163 
164         mType = type;
165         mId = id;
166         mData = data;
167     }
168 
169     /**
170      * Constructs this object with the data present in {@code parcel}. It should be in the same
171      * order as {@link FhirResource#writeToParcel}.
172      */
FhirResource(@onNull Parcel in)173     private FhirResource(@NonNull Parcel in) {
174         requireNonNull(in);
175         mType = in.readInt();
176         validateFhirResourceType(mType);
177         mId = requireNonNull(in.readString());
178         mData = requireNonNull(in.readString());
179     }
180 
181     @NonNull
182     public static final Creator<FhirResource> CREATOR =
183             new Creator<>() {
184                 @Override
185                 public FhirResource createFromParcel(Parcel in) {
186                     return new FhirResource(in);
187                 }
188 
189                 @Override
190                 public FhirResource[] newArray(int size) {
191                     return new FhirResource[size];
192                 }
193             };
194 
195     /**
196      * Returns the FHIR resource type. This is extracted from the "resourceType" field in {@link
197      * #getData}.
198      *
199      * <p>The list of supported types is a subset of the resource list on <a
200      * href="https://build.fhir.org/resourcelist.html">the official FHIR website</a>. For a list of
201      * supported types, see the {@link FhirResource} constants, such as {@link
202      * #FHIR_RESOURCE_TYPE_IMMUNIZATION}. Clients should be aware that this list is non exhaustive
203      * and may increase in future releases when additional types will need to be handled.
204      */
205     @FhirResourceType
getType()206     public int getType() {
207         return mType;
208     }
209 
210     /**
211      * Returns the FHIR resource ID. This is extracted from the "id" field in {@code data}. This is
212      * NOT a unique identifier among all {@link FhirResource}s.
213      */
214     @NonNull
getId()215     public String getId() {
216         return mId;
217     }
218 
219     /** Returns the FHIR resource data in JSON representation. */
220     @NonNull
getData()221     public String getData() {
222         return mData;
223     }
224 
225     @Override
describeContents()226     public int describeContents() {
227         return 0;
228     }
229 
230     @Override
writeToParcel(@onNull Parcel dest, int flags)231     public void writeToParcel(@NonNull Parcel dest, int flags) {
232         requireNonNull(dest);
233         dest.writeInt(getType());
234         dest.writeString(getId());
235         dest.writeString(getData());
236     }
237 
238     /**
239      * Valid set of values for this IntDef. Update this set when add new type or deprecate existing
240      * type.
241      */
242     private static final Set<Integer> VALID_TYPES =
243             Set.of(
244                     FHIR_RESOURCE_TYPE_IMMUNIZATION,
245                     FHIR_RESOURCE_TYPE_ALLERGY_INTOLERANCE,
246                     FHIR_RESOURCE_TYPE_OBSERVATION,
247                     FHIR_RESOURCE_TYPE_CONDITION,
248                     FHIR_RESOURCE_TYPE_PROCEDURE,
249                     FHIR_RESOURCE_TYPE_MEDICATION,
250                     FHIR_RESOURCE_TYPE_MEDICATION_REQUEST,
251                     FHIR_RESOURCE_TYPE_MEDICATION_STATEMENT,
252                     FHIR_RESOURCE_TYPE_PATIENT,
253                     FHIR_RESOURCE_TYPE_PRACTITIONER,
254                     FHIR_RESOURCE_TYPE_PRACTITIONER_ROLE,
255                     FHIR_RESOURCE_TYPE_ENCOUNTER,
256                     FHIR_RESOURCE_TYPE_LOCATION,
257                     FHIR_RESOURCE_TYPE_ORGANIZATION);
258 
259     /**
260      * Validates the provided {@code fhirResourceType} is in the {@link FhirResource#VALID_TYPES}
261      * set.
262      *
263      * <p>Throws {@link IllegalArgumentException} if not.
264      *
265      * @hide
266      */
validateFhirResourceType(@hirResourceType int fhirResourceType)267     public static void validateFhirResourceType(@FhirResourceType int fhirResourceType) {
268         validateIntDefValue(fhirResourceType, VALID_TYPES, FhirResourceType.class.getSimpleName());
269     }
270 
271     @Override
equals(Object o)272     public boolean equals(Object o) {
273         if (this == o) return true;
274         if (!(o instanceof FhirResource that)) return false;
275         return getType() == that.getType()
276                 && getId().equals(that.getId())
277                 && getData().equals(that.getData());
278     }
279 
280     @Override
hashCode()281     public int hashCode() {
282         return hash(getType(), getId(), getData());
283     }
284 
285     @Override
toString()286     public String toString() {
287         StringBuilder sb = new StringBuilder();
288         sb.append(this.getClass().getSimpleName()).append("{");
289         sb.append("type=").append(getType());
290         sb.append(",id=").append(getId());
291         sb.append(",data=").append(getData());
292         sb.append("}");
293         return sb.toString();
294     }
295 
296     /** Builder class for {@link FhirResource}. */
297     public static final class Builder {
298         @FhirResourceType private int mType;
299         @NonNull private String mId;
300         @NonNull private String mData;
301 
302         /**
303          * Constructs a new {@link FhirResource.Builder} instance.
304          *
305          * @param type The FHIR resource type extracted from the "resourceType" field in {@code
306          *     data}.
307          * @param id The FHIR resource ID extracted from the "id" field in {@code data}.
308          * @param data The FHIR resource data in JSON representation.
309          * @throws IllegalArgumentException if the provided FHIR resource {@code type} is not a
310          *     valid supported type.
311          */
Builder(@hirResourceType int type, @NonNull String id, @NonNull String data)312         public Builder(@FhirResourceType int type, @NonNull String id, @NonNull String data) {
313             validateFhirResourceType(type);
314             requireNonNull(id);
315             requireNonNull(data);
316 
317             mType = type;
318             mId = id;
319             mData = data;
320         }
321 
322         /** Constructs a clone of the other {@link FhirResource.Builder}. */
Builder(@onNull Builder other)323         public Builder(@NonNull Builder other) {
324             requireNonNull(other);
325             mType = other.mType;
326             mId = other.mId;
327             mData = other.mData;
328         }
329 
330         /** Constructs a clone of the other {@link FhirResource} instance. */
Builder(@onNull FhirResource other)331         public Builder(@NonNull FhirResource other) {
332             requireNonNull(other);
333             mType = other.getType();
334             mId = other.getId();
335             mData = other.getData();
336         }
337 
338         /**
339          * Sets the FHIR resource type. This is extracted from the "resourceType" field in {@code
340          * data}.
341          *
342          * @throws IllegalArgumentException if the provided FHIR resource {@code type} is not a
343          *     valid supported type.
344          */
345         @NonNull
setType(@hirResourceType int type)346         public Builder setType(@FhirResourceType int type) {
347             validateFhirResourceType(type);
348             mType = type;
349             return this;
350         }
351 
352         /**
353          * Sets the FHIR resource ID. This is extracted from the "id" field in {@code data}. This is
354          * NOT a unique identifier among all {@link FhirResource}s.
355          */
356         @NonNull
setId(@onNull String id)357         public Builder setId(@NonNull String id) {
358             requireNonNull(id);
359             mId = id;
360             return this;
361         }
362 
363         /** Sets the FHIR resource data in JSON representation. */
364         @NonNull
setData(@onNull String data)365         public Builder setData(@NonNull String data) {
366             requireNonNull(data);
367             mData = data;
368             return this;
369         }
370 
371         /** Returns a new instance of {@link FhirResource} with the specified parameters. */
372         @NonNull
build()373         public FhirResource build() {
374             return new FhirResource(mType, mId, mData);
375         }
376     }
377 }
378