• 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;
18 
19 import static android.health.connect.datatypes.MedicalDataSource.validateMedicalDataSourceIds;
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.NonNull;
28 import android.health.connect.datatypes.FhirVersion;
29 import android.health.connect.datatypes.MedicalDataSource;
30 import android.os.Parcel;
31 import android.os.Parcelable;
32 
33 import com.android.healthfitness.flags.Flags;
34 
35 import java.util.Set;
36 
37 /**
38  * An upsert request for {@link HealthConnectManager#upsertMedicalResources}.
39  *
40  * <p>Medical data is represented using the <a href="https://hl7.org/fhir/">Fast Healthcare
41  * Interoperability Resources (FHIR)</a> standard.
42  */
43 @FlaggedApi(FLAG_PERSONAL_HEALTH_RECORD)
44 public final class UpsertMedicalResourceRequest implements Parcelable {
45     @NonNull private final String mDataSourceId;
46     @NonNull private final FhirVersion mFhirVersion;
47     @NonNull private final String mData;
48     private int mDataSize;
49 
50     @NonNull
51     public static final Creator<UpsertMedicalResourceRequest> CREATOR =
52             new Creator<>() {
53                 @Override
54                 public UpsertMedicalResourceRequest createFromParcel(Parcel in) {
55                     return new UpsertMedicalResourceRequest(in);
56                 }
57 
58                 @Override
59                 public UpsertMedicalResourceRequest[] newArray(int size) {
60                     return new UpsertMedicalResourceRequest[size];
61                 }
62             };
63 
64     /**
65      * Creates a new instance of {@link UpsertMedicalResourceRequest}. Please see {@link
66      * UpsertMedicalResourceRequest.Builder} for more detailed parameters information.
67      */
UpsertMedicalResourceRequest( @onNull String dataSourceId, @NonNull FhirVersion fhirVersion, @NonNull String data)68     private UpsertMedicalResourceRequest(
69             @NonNull String dataSourceId, @NonNull FhirVersion fhirVersion, @NonNull String data) {
70         requireNonNull(dataSourceId);
71         requireNonNull(fhirVersion);
72         requireNonNull(data);
73         validateMedicalDataSourceIds(Set.of(dataSourceId));
74 
75         mDataSourceId = dataSourceId;
76         mFhirVersion = fhirVersion;
77         mData = data;
78     }
79 
UpsertMedicalResourceRequest(@onNull Parcel in)80     private UpsertMedicalResourceRequest(@NonNull Parcel in) {
81         requireNonNull(in);
82         int dataAvailStartPosition = in.dataAvail();
83 
84         mDataSourceId = requireNonNull(in.readString());
85         validateMedicalDataSourceIds(Set.of(mDataSourceId));
86         mFhirVersion =
87                 requireNonNull(
88                         in.readParcelable(FhirVersion.class.getClassLoader(), FhirVersion.class));
89         mData = requireNonNull(in.readString());
90 
91         if (Flags.phrUpsertFixParcelSizeCalculation()) {
92             mDataSize = dataAvailStartPosition - in.dataAvail();
93         } else {
94             mDataSize = in.dataSize();
95         }
96     }
97 
98     /**
99      * Returns the unique ID of the existing {@link MedicalDataSource}, to represent where the
100      * {@code data} is coming from.
101      */
102     @NonNull
getDataSourceId()103     public String getDataSourceId() {
104         return mDataSourceId;
105     }
106 
107     /**
108      * Returns the FHIR version being used for {@code data}. For the request to succeed this must
109      * match the {@link MedicalDataSource#getFhirVersion()} FHIR version of the {@link
110      * MedicalDataSource} with the provided {@code dataSourceId}.
111      */
112     @NonNull
getFhirVersion()113     public FhirVersion getFhirVersion() {
114         return mFhirVersion;
115     }
116 
117     /** Returns the FHIR resource data in JSON representation. */
118     @NonNull
getData()119     public String getData() {
120         return mData;
121     }
122 
123     /**
124      * Returns the size of the parcel when the class was created from Parcel.
125      *
126      * @hide
127      */
getDataSize()128     public long getDataSize() {
129         return mDataSize;
130     }
131 
132     @Override
describeContents()133     public int describeContents() {
134         return 0;
135     }
136 
137     @Override
writeToParcel(@onNull Parcel dest, int flags)138     public void writeToParcel(@NonNull Parcel dest, int flags) {
139         requireNonNull(dest);
140         dest.writeString(mDataSourceId);
141         dest.writeParcelable(mFhirVersion, 0);
142         dest.writeString(mData);
143     }
144 
145     @Override
hashCode()146     public int hashCode() {
147         return hash(getDataSourceId(), getFhirVersion(), getData());
148     }
149 
150     @Override
equals(Object o)151     public boolean equals(Object o) {
152         if (this == o) return true;
153         if (!(o instanceof UpsertMedicalResourceRequest that)) return false;
154         return getDataSourceId().equals(that.getDataSourceId())
155                 && getFhirVersion().equals(that.getFhirVersion())
156                 && getData().equals(that.getData());
157     }
158 
159     @Override
toString()160     public String toString() {
161         StringBuilder sb = new StringBuilder();
162         sb.append(this.getClass().getSimpleName()).append("{");
163         sb.append("dataSourceId=").append(mDataSourceId);
164         sb.append(",fhirVersion=").append(mFhirVersion);
165         sb.append(",data=").append(mData);
166         sb.append("}");
167         return sb.toString();
168     }
169 
170     /** Builder class for {@link UpsertMedicalResourceRequest}. */
171     public static final class Builder {
172         private String mDataSourceId;
173         private FhirVersion mFhirVersion;
174         private String mData;
175 
176         /**
177          * Constructs a new {@link UpsertMedicalResourceRequest.Builder} instance.
178          *
179          * @param dataSourceId The unique identifier of the existing {@link MedicalDataSource},
180          *     representing where the data comes from.
181          * @param fhirVersion The {@link FhirVersion} object that represents the FHIR version being
182          *     used for {@code data}. This has to match the FHIR version of the {@link
183          *     MedicalDataSource}.
184          * @param data The FHIR resource data in JSON representation.
185          * @throws IllegalArgumentException if the provided {@code dataSourceId} is not a valid ID.
186          */
Builder( @onNull String dataSourceId, @NonNull FhirVersion fhirVersion, @NonNull String data)187         public Builder(
188                 @NonNull String dataSourceId,
189                 @NonNull FhirVersion fhirVersion,
190                 @NonNull String data) {
191             requireNonNull(dataSourceId);
192             requireNonNull(fhirVersion);
193             requireNonNull(data);
194             validateMedicalDataSourceIds(Set.of(dataSourceId));
195 
196             mDataSourceId = dataSourceId;
197             mFhirVersion = fhirVersion;
198             mData = data;
199         }
200 
201         /** Constructs a clone of the other {@link UpsertMedicalResourceRequest.Builder}. */
Builder(@onNull Builder other)202         public Builder(@NonNull Builder other) {
203             requireNonNull(other);
204             mDataSourceId = other.mDataSourceId;
205             mFhirVersion = other.mFhirVersion;
206             mData = other.mData;
207         }
208 
209         /** Constructs a clone of the other {@link UpsertMedicalResourceRequest} instance. */
Builder(@onNull UpsertMedicalResourceRequest other)210         public Builder(@NonNull UpsertMedicalResourceRequest other) {
211             requireNonNull(other);
212             mDataSourceId = other.getDataSourceId();
213             mFhirVersion = other.getFhirVersion();
214             mData = other.getData();
215         }
216 
217         /**
218          * Sets the unique ID of the existing {@link MedicalDataSource}, to represent where the
219          * {@code data} is coming from.
220          *
221          * @throws IllegalArgumentException if the provided {@code dataSourceId} is not a valid ID.
222          */
223         @NonNull
setDataSourceId(@onNull String dataSourceId)224         public Builder setDataSourceId(@NonNull String dataSourceId) {
225             requireNonNull(dataSourceId);
226             validateMedicalDataSourceIds(Set.of(dataSourceId));
227             mDataSourceId = dataSourceId;
228             return this;
229         }
230 
231         /**
232          * Sets the FHIR version being used for {@code data}. For the request to succeed this must
233          * match the {@link MedicalDataSource#getFhirVersion()} FHIR version} of the {@link
234          * MedicalDataSource} with the provided {@code dataSourceId}.
235          */
236         @NonNull
setFhirVersion(@onNull FhirVersion fhirVersion)237         public Builder setFhirVersion(@NonNull FhirVersion fhirVersion) {
238             requireNonNull(fhirVersion);
239             mFhirVersion = fhirVersion;
240             return this;
241         }
242 
243         /** Sets the FHIR resource data in JSON format. */
244         @NonNull
setData(@onNull String data)245         public Builder setData(@NonNull String data) {
246             requireNonNull(data);
247             mData = data;
248             return this;
249         }
250 
251         /**
252          * Returns a new instance of {@link UpsertMedicalResourceRequest} with the specified
253          * parameters.
254          */
255         @NonNull
build()256         public UpsertMedicalResourceRequest build() {
257             return new UpsertMedicalResourceRequest(mDataSourceId, mFhirVersion, mData);
258         }
259     }
260 }
261