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;
18 
19 import static com.android.healthfitness.flags.Flags.FLAG_PERSONAL_HEALTH_RECORD;
20 
21 import static java.util.Objects.hash;
22 import static java.util.Objects.requireNonNull;
23 
24 import android.annotation.FlaggedApi;
25 import android.annotation.NonNull;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 
29 /**
30  * A class to represent a unique identifier of a medical resource.
31  *
32  * <p>This class contains a set of properties that together represent a unique identifier of a
33  * medical resource.
34  */
35 @FlaggedApi(FLAG_PERSONAL_HEALTH_RECORD)
36 public final class MedicalResourceId implements Parcelable {
37     @NonNull private final String mDataSourceId;
38     // TODO(b/343451409): Maybe create IntDef for FHIR resource types. Taking a string for now.
39     @NonNull private final String mFhirResourceType;
40     @NonNull private final String mFhirResourceId;
41 
42     /**
43      * @param dataSourceId The unique identifier of where the data comes from.
44      * @param fhirResourceType The FHIR resource type. This is the "resourceType" field from a JSON
45      *     representation of FHIR resource data.
46      * @param fhirResourceId The FHIR resource ID. This is the "id" field from a JSON representation
47      *     of FHIR resource data.
48      */
MedicalResourceId( @onNull String dataSourceId, @NonNull String fhirResourceType, @NonNull String fhirResourceId)49     public MedicalResourceId(
50             @NonNull String dataSourceId,
51             @NonNull String fhirResourceType,
52             @NonNull String fhirResourceId) {
53         requireNonNull(dataSourceId);
54         requireNonNull(fhirResourceType);
55         requireNonNull(fhirResourceId);
56         mDataSourceId = dataSourceId;
57         mFhirResourceType = fhirResourceType;
58         mFhirResourceId = fhirResourceId;
59     }
60 
61     /**
62      * Constructs this object with the data present in {@code parcel}. It should be in the same
63      * order as {@link MedicalResourceId#writeToParcel}.
64      */
MedicalResourceId(@onNull Parcel in)65     private MedicalResourceId(@NonNull Parcel in) {
66         requireNonNull(in);
67         mDataSourceId = requireNonNull(in.readString());
68         mFhirResourceType = requireNonNull(in.readString());
69         mFhirResourceId = requireNonNull(in.readString());
70     }
71 
72     @NonNull
73     public static final Creator<MedicalResourceId> CREATOR =
74             new Creator<>() {
75                 /**
76                  * Reading from the {@link Parcel} should have the same order as {@link
77                  * MedicalResourceId#writeToParcel}.
78                  */
79                 @Override
80                 public MedicalResourceId createFromParcel(Parcel in) {
81                     return new MedicalResourceId(in);
82                 }
83 
84                 @Override
85                 public MedicalResourceId[] newArray(int size) {
86                     return new MedicalResourceId[size];
87                 }
88             };
89 
90     /** Returns the unique identifier of where the data comes from. */
91     @NonNull
getDataSourceId()92     public String getDataSourceId() {
93         return mDataSourceId;
94     }
95 
96     /** Returns the FHIR resource type. */
97     @NonNull
getFhirResourceType()98     public String getFhirResourceType() {
99         return mFhirResourceType;
100     }
101 
102     /** Returns the FHIR resource ID. */
103     @NonNull
getFhirResourceId()104     public String getFhirResourceId() {
105         return mFhirResourceId;
106     }
107 
108     @Override
describeContents()109     public int describeContents() {
110         return 0;
111     }
112 
113     /** Populates a {@link Parcel} with the self information. */
114     @Override
writeToParcel(@onNull Parcel dest, int flags)115     public void writeToParcel(@NonNull Parcel dest, int flags) {
116         requireNonNull(dest);
117         dest.writeString(getDataSourceId());
118         dest.writeString(getFhirResourceType());
119         dest.writeString(getFhirResourceId());
120     }
121 
122     /** Indicates whether some other object is "equal to" this one. */
123     @Override
equals(Object o)124     public boolean equals(Object o) {
125         if (this == o) return true;
126         if (!(o instanceof MedicalResourceId that)) return false;
127         return getDataSourceId().equals(that.getDataSourceId())
128                 && getFhirResourceType().equals(that.getFhirResourceType())
129                 && getFhirResourceId().equals(that.getFhirResourceId());
130     }
131 
132     /** Returns a hash code value for the object. */
133     @Override
hashCode()134     public int hashCode() {
135         return hash(getDataSourceId(), getFhirResourceType(), getFhirResourceId());
136     }
137 
138     /** Returns a string representation of this {@link MedicalResourceId}. */
139     @Override
toString()140     public String toString() {
141         StringBuilder sb = new StringBuilder();
142         sb.append(this.getClass().getSimpleName()).append("{");
143         sb.append("dataSourceId=").append(getDataSourceId());
144         sb.append(",fhirResourceType=").append(getFhirResourceType());
145         sb.append(",fhirResourceId=").append(getFhirResourceId());
146         sb.append("}");
147         return sb.toString();
148     }
149 }
150