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.healthconnect.cts.phr.utils; 18 19 import static android.health.connect.datatypes.FhirResource.FHIR_RESOURCE_TYPE_ALLERGY_INTOLERANCE; 20 import static android.health.connect.datatypes.FhirResource.FHIR_RESOURCE_TYPE_IMMUNIZATION; 21 import static android.health.connect.datatypes.FhirVersion.parseFhirVersion; 22 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES; 23 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_VACCINES; 24 25 import android.health.connect.CreateMedicalDataSourceRequest; 26 import android.health.connect.GetMedicalDataSourcesRequest; 27 import android.health.connect.MedicalResourceId; 28 import android.health.connect.UpsertMedicalResourceRequest; 29 import android.health.connect.datatypes.FhirResource; 30 import android.health.connect.datatypes.FhirVersion; 31 import android.health.connect.datatypes.MedicalDataSource; 32 import android.health.connect.datatypes.MedicalResource; 33 import android.net.Uri; 34 35 import com.google.common.truth.Correspondence; 36 37 import org.json.JSONException; 38 import org.json.JSONObject; 39 40 import java.time.Instant; 41 import java.util.ArrayList; 42 import java.util.List; 43 import java.util.Objects; 44 import java.util.Set; 45 import java.util.UUID; 46 47 public class PhrDataFactory { 48 private static final int FHIR_BASE_URI_CHARACTER_LIMIT = 2000; 49 private static final int MEDICAL_DATA_SOURCE_DISPLAY_NAME_CHARACTER_LIMIT = 90; 50 51 public static final int MAX_ALLOWED_MEDICAL_DATA_SOURCES = 20; 52 53 /** 54 * String version code for FHIR version <a href="https://hl7.org/fhir/r4/versions.html">R4</a>. 55 */ 56 public static final String R4_VERSION_STRING = "4.0.1"; 57 58 /** 59 * {@link FhirVersion} for FHIR version <a href="https://hl7.org/fhir/r4/versions.html">R4</a>. 60 */ 61 public static final FhirVersion FHIR_VERSION_R4 = parseFhirVersion(R4_VERSION_STRING); 62 63 /** String version code for FHIR version <a href="https://www.hl7.org/fhir/R4B/">R4B</a>. */ 64 public static final String R4B_VERSION_STRING = "4.3.0"; 65 66 /** {@link FhirVersion} for FHIR version <a href="https://www.hl7.org/fhir/R4B/">R4B</a>. */ 67 public static final FhirVersion FHIR_VERSION_R4B = parseFhirVersion(R4B_VERSION_STRING); 68 69 public static final String UNSUPPORTED_VERSION_STRING = "4.5.5"; 70 public static final FhirVersion FHIR_VERSION_UNSUPPORTED = 71 parseFhirVersion(UNSUPPORTED_VERSION_STRING); 72 73 public static final String RESOURCE_ID_FIELD_NAME = "id"; 74 75 public static final UUID DATA_SOURCE_UUID = UUID.randomUUID(); 76 public static final String DATA_SOURCE_ID = DATA_SOURCE_UUID.toString(); 77 public static final String DATA_SOURCE_PACKAGE_NAME = "com.example.app"; 78 public static final Uri DATA_SOURCE_FHIR_BASE_URI = 79 Uri.parse("https://fhir.com/oauth/api/FHIR/R4/"); 80 public static final Uri DATA_SOURCE_FHIR_BASE_URI_MAX_CHARS = 81 Uri.parse("d".repeat(FHIR_BASE_URI_CHARACTER_LIMIT)); 82 public static final Uri DATA_SOURCE_FHIR_BASE_URI_EXCEEDED_CHARS = 83 Uri.parse("d".repeat(FHIR_BASE_URI_CHARACTER_LIMIT + 1)); 84 public static final String DATA_SOURCE_DISPLAY_NAME = "Hospital X"; 85 public static final String DATA_SOURCE_DISPLAY_NAME_MAX_CHARS = 86 "d".repeat(MEDICAL_DATA_SOURCE_DISPLAY_NAME_CHARACTER_LIMIT); 87 public static final String DATA_SOURCE_DISPLAY_NAME_EXCEEDED_CHARS = 88 "d".repeat(MEDICAL_DATA_SOURCE_DISPLAY_NAME_CHARACTER_LIMIT + 1); 89 public static final Instant DATA_SOURCE_LAST_DATA_UPDATE_TIME = 90 Instant.parse("2024-09-10T00:02:00Z"); 91 public static final FhirVersion DATA_SOURCE_FHIR_VERSION = FHIR_VERSION_R4; 92 public static final UUID DIFFERENT_DATA_SOURCE_UUID = UUID.randomUUID(); 93 public static final String DIFFERENT_DATA_SOURCE_ID = DIFFERENT_DATA_SOURCE_UUID.toString(); 94 public static final String DIFFERENT_DATA_SOURCE_PACKAGE_NAME = "com.other.app"; 95 public static final Uri DIFFERENT_DATA_SOURCE_BASE_URI = 96 Uri.parse("https://fhir.com/oauth/api/FHIR/R5/"); 97 public static final String DIFFERENT_DATA_SOURCE_DISPLAY_NAME = "Doctor Y"; 98 public static final Instant DIFFERENT_DATA_SOURCE_LAST_DATA_UPDATE_TIME = 99 Instant.parse("2023-01-01T00:02:00Z"); 100 public static final FhirVersion DIFFERENT_DATA_SOURCE_FHIR_VERSION = FHIR_VERSION_R4B; 101 102 public static final String FHIR_RESOURCE_ID_IMMUNIZATION = "Immunization1"; 103 public static final String FHIR_DATA_IMMUNIZATION = 104 new ImmunizationBuilder().setId(FHIR_RESOURCE_ID_IMMUNIZATION).toJson(); 105 public static final String DIFFERENT_FHIR_RESOURCE_ID_IMMUNIZATION = "Immunization2"; 106 public static final String DIFFERENT_FHIR_DATA_IMMUNIZATION = 107 new ImmunizationBuilder().setId(DIFFERENT_FHIR_RESOURCE_ID_IMMUNIZATION).toJson(); 108 109 public static final String FHIR_DATA_IMMUNIZATION_ID_NOT_EXISTS = 110 new ImmunizationBuilder().removeField(RESOURCE_ID_FIELD_NAME).toJson(); 111 public static final String FHIR_DATA_IMMUNIZATION_ID_EMPTY = 112 new ImmunizationBuilder().setId("").toJson(); 113 public static final String FHIR_DATA_IMMUNIZATION_RESOURCE_TYPE_NOT_EXISTS = 114 new ImmunizationBuilder() 115 .setId(FHIR_RESOURCE_ID_IMMUNIZATION) 116 .removeField("resourceType") 117 .toJson(); 118 public static final String FHIR_DATA_IMMUNIZATION_FIELD_MISSING_INVALID = "{\"id\" : }"; 119 public static final String FHIR_RESOURCE_TYPE_UNSUPPORTED = "StructureDefinition"; 120 public static final String FHIR_DATA_IMMUNIZATION_UNSUPPORTED_RESOURCE_TYPE = 121 "{\"resourceType\" : \"StructureDefinition\", \"id\" : \"Immunization1\"}"; 122 123 public static final String FHIR_RESOURCE_ID_ALLERGY = "Allergy1"; 124 public static final String FHIR_DATA_ALLERGY = 125 new AllergyBuilder().setId(FHIR_RESOURCE_ID_ALLERGY).toJson(); 126 public static final String DIFFERENT_FHIR_RESOURCE_ID_ALLERGY = "Allergy2"; 127 public static final String DIFFERENT_FHIR_DATA_ALLERGY = 128 new AllergyBuilder().setId(DIFFERENT_FHIR_RESOURCE_ID_ALLERGY).toJson(); 129 public static final String FHIR_DATA_CONDITION = new ConditionBuilder().toJson(); 130 public static final String FHIR_DATA_MEDICATION = 131 new MedicationsBuilder.MedicationBuilder().toJson(); 132 public static final String FHIR_DATA_Patient = new PatientBuilder().toJson(); 133 public static final String FHIR_DATA_PRACTITIONER = new PractitionerBuilder().toJson(); 134 public static final String FHIR_DATA_ENCOUNTER = EncountersBuilder.encounter().toJson(); 135 public static final String FHIR_DATA_PROCEDURE = new ProcedureBuilder().toJson(); 136 public static final String FHIR_DATA_OBSERVATION_PREGNANCY = 137 new ObservationBuilder() 138 .setId("1") 139 .setPregnancyStatus(ObservationBuilder.PregnancyStatus.NOT_PREGNANT) 140 .toJson(); 141 public static final String FHIR_DATA_OBSERVATION_SOCIAL_HISTORY = 142 new ObservationBuilder() 143 .setId("2") 144 .setCategory(ObservationBuilder.ObservationCategory.SOCIAL_HISTORY) 145 .toJson(); 146 public static final String FHIR_DATA_OBSERVATION_VITAL_SIGNS = 147 new ObservationBuilder() 148 .setId("3") 149 .setCategory(ObservationBuilder.ObservationCategory.VITAL_SIGNS) 150 .toJson(); 151 public static final String FHIR_DATA_OBSERVATION_LABS = 152 new ObservationBuilder() 153 .setId("4") 154 .setCategory(ObservationBuilder.ObservationCategory.LABORATORY) 155 .toJson(); 156 157 public static final String PAGE_TOKEN = "111"; 158 159 public static final Correspondence<MedicalDataSource, MedicalDataSource> 160 MEDICAL_DATA_SOURCE_EQUIVALENCE = 161 Correspondence.from( 162 PhrDataFactory::isMedicalDataSourceEqual, "isMedicalDataSourceEqual"); 163 164 /** Creates and returns a {@link MedicalDataSource.Builder} with default arguments. */ getMedicalDataSourceBuilderRequiredFieldsOnly()165 public static MedicalDataSource.Builder getMedicalDataSourceBuilderRequiredFieldsOnly() { 166 return new MedicalDataSource.Builder( 167 DATA_SOURCE_ID, 168 DATA_SOURCE_PACKAGE_NAME, 169 DATA_SOURCE_FHIR_BASE_URI, 170 DATA_SOURCE_DISPLAY_NAME, 171 DATA_SOURCE_FHIR_VERSION); 172 } 173 174 /** Creates and returns a {@link MedicalDataSource.Builder} with default arguments. */ getMedicalDataSourceBuilderWithOptionalFields()175 public static MedicalDataSource.Builder getMedicalDataSourceBuilderWithOptionalFields() { 176 return getMedicalDataSourceBuilderRequiredFieldsOnly() 177 .setLastDataUpdateTime(DATA_SOURCE_LAST_DATA_UPDATE_TIME); 178 } 179 180 /** 181 * Creates and returns a {@link MedicalDataSource} with default arguments for required fields. 182 */ getMedicalDataSourceRequiredFieldsOnly()183 public static MedicalDataSource getMedicalDataSourceRequiredFieldsOnly() { 184 return getMedicalDataSourceBuilderRequiredFieldsOnly().build(); 185 } 186 187 /** Creates and returns a {@link MedicalDataSource} with default arguments. */ getMedicalDataSourceWithOptionalFields()188 public static MedicalDataSource getMedicalDataSourceWithOptionalFields() { 189 return getMedicalDataSourceBuilderWithOptionalFields().build(); 190 } 191 192 /** 193 * Creates and returns a {@link GetMedicalDataSourcesRequest} with given {@code packageNames}. 194 */ getGetMedicalDataSourceRequest( Set<String> packageNames)195 public static GetMedicalDataSourcesRequest getGetMedicalDataSourceRequest( 196 Set<String> packageNames) { 197 GetMedicalDataSourcesRequest.Builder builder = new GetMedicalDataSourcesRequest.Builder(); 198 for (String packageName : packageNames) { 199 builder.addPackageName(packageName); 200 } 201 return builder.build(); 202 } 203 204 /** 205 * Creates and returns a {@link CreateMedicalDataSourceRequest.Builder} with default arguments 206 * for required fields. 207 */ 208 public static CreateMedicalDataSourceRequest.Builder getCreateMedicalDataSourceRequestBuilder()209 getCreateMedicalDataSourceRequestBuilder() { 210 return new CreateMedicalDataSourceRequest.Builder( 211 DATA_SOURCE_FHIR_BASE_URI, DATA_SOURCE_DISPLAY_NAME, DATA_SOURCE_FHIR_VERSION); 212 } 213 214 /** 215 * Creates and returns a {@link CreateMedicalDataSourceRequest.Builder} with default arguments, 216 * with the given suffix appended to the base URI and name, to enable different data sources to 217 * be created. 218 */ getCreateMedicalDataSourceRequestBuilder( String suffix)219 public static CreateMedicalDataSourceRequest.Builder getCreateMedicalDataSourceRequestBuilder( 220 String suffix) { 221 Uri fhirBaseUri = Uri.withAppendedPath(DATA_SOURCE_FHIR_BASE_URI, "/" + suffix); 222 return new CreateMedicalDataSourceRequest.Builder( 223 fhirBaseUri, DATA_SOURCE_DISPLAY_NAME + " " + suffix, DATA_SOURCE_FHIR_VERSION); 224 } 225 226 /** Creates and returns a {@link CreateMedicalDataSourceRequest} with default arguments. */ getCreateMedicalDataSourceRequest()227 public static CreateMedicalDataSourceRequest getCreateMedicalDataSourceRequest() { 228 return getCreateMedicalDataSourceRequestBuilder().build(); 229 } 230 231 /** 232 * Creates and returns a {@link CreateMedicalDataSourceRequest} with the default arguments, with 233 * the given suffix appended to the base URI and name, to enable different data sources to be 234 * created. 235 */ getCreateMedicalDataSourceRequest(String suffix)236 public static CreateMedicalDataSourceRequest getCreateMedicalDataSourceRequest(String suffix) { 237 return getCreateMedicalDataSourceRequestBuilder(suffix).build(); 238 } 239 240 /** 241 * Creates and returns a {@link FhirResource.Builder} with default arguments. 242 * 243 * <p>By default, it contains the {@link PhrDataFactory#FHIR_DATA_IMMUNIZATION}. 244 */ getFhirResourceBuilder()245 public static FhirResource.Builder getFhirResourceBuilder() { 246 return new FhirResource.Builder( 247 FHIR_RESOURCE_TYPE_IMMUNIZATION, 248 FHIR_RESOURCE_ID_IMMUNIZATION, 249 FHIR_DATA_IMMUNIZATION); 250 } 251 252 /** 253 * Creates and returns a {@link FhirResource} with default arguments. 254 * 255 * <p>By default, it contains the {@link PhrDataFactory#FHIR_DATA_IMMUNIZATION}. 256 */ getFhirResource()257 public static FhirResource getFhirResource() { 258 return getFhirResourceBuilder().build(); 259 } 260 261 /** 262 * Creates and returns a {@link FhirResource} with the status field of the {@link 263 * PhrDataFactory#FHIR_DATA_IMMUNIZATION} updated. 264 */ getUpdatedImmunizationFhirResource()265 public static FhirResource getUpdatedImmunizationFhirResource() throws JSONException { 266 return new FhirResource.Builder( 267 FhirResource.FHIR_RESOURCE_TYPE_IMMUNIZATION, 268 FHIR_RESOURCE_ID_IMMUNIZATION, 269 addCompletedStatus(FHIR_DATA_IMMUNIZATION)) 270 .build(); 271 } 272 273 /** 274 * Creates and returns a {@link FhirResource} with the status field of the {@link 275 * PhrDataFactory#FHIR_DATA_ALLERGY} updated. 276 */ getUpdatedAllergyFhirResource()277 public static FhirResource getUpdatedAllergyFhirResource() throws JSONException { 278 return new FhirResource.Builder( 279 FHIR_RESOURCE_TYPE_ALLERGY_INTOLERANCE, 280 FHIR_RESOURCE_ID_ALLERGY, 281 addCompletedStatus(FHIR_DATA_ALLERGY)) 282 .build(); 283 } 284 285 /** 286 * Creates and returns a {@link FhirResource} with {@link 287 * PhrDataFactory#DIFFERENT_FHIR_DATA_IMMUNIZATION} data. 288 */ getFhirResourceDifferentImmunization()289 public static FhirResource getFhirResourceDifferentImmunization() { 290 return new FhirResource.Builder( 291 FhirResource.FHIR_RESOURCE_TYPE_IMMUNIZATION, 292 DIFFERENT_FHIR_RESOURCE_ID_IMMUNIZATION, 293 DIFFERENT_FHIR_DATA_IMMUNIZATION) 294 .build(); 295 } 296 297 /** 298 * Creates and returns a {@link FhirResource} with {@link PhrDataFactory#FHIR_DATA_ALLERGY} 299 * data. 300 */ getFhirResourceAllergy()301 public static FhirResource getFhirResourceAllergy() { 302 return new FhirResource.Builder( 303 FHIR_RESOURCE_TYPE_ALLERGY_INTOLERANCE, 304 FHIR_RESOURCE_ID_ALLERGY, 305 FHIR_DATA_ALLERGY) 306 .build(); 307 } 308 309 /** 310 * Creates and returns a {@link FhirResource} with {@link 311 * PhrDataFactory#DIFFERENT_FHIR_DATA_ALLERGY} data. 312 */ getFhirResourceDifferentAllergy()313 public static FhirResource getFhirResourceDifferentAllergy() { 314 return new FhirResource.Builder( 315 FHIR_RESOURCE_TYPE_ALLERGY_INTOLERANCE, 316 DIFFERENT_FHIR_RESOURCE_ID_ALLERGY, 317 DIFFERENT_FHIR_DATA_ALLERGY) 318 .build(); 319 } 320 321 /** 322 * Creates and returns a {@link MedicalResource.Builder} with default arguments. 323 * 324 * <p>By default, it contains the {@link PhrDataFactory#FHIR_DATA_IMMUNIZATION}. 325 */ getMedicalResourceBuilder()326 public static MedicalResource.Builder getMedicalResourceBuilder() { 327 return new MedicalResource.Builder( 328 MEDICAL_RESOURCE_TYPE_VACCINES, DATA_SOURCE_ID, FHIR_VERSION_R4, getFhirResource()); 329 } 330 331 /** 332 * Creates and returns a {@link MedicalResource} with default arguments. 333 * 334 * <p>By default, it contains the {@link PhrDataFactory#FHIR_DATA_IMMUNIZATION}. 335 */ getMedicalResource()336 public static MedicalResource getMedicalResource() { 337 return getMedicalResourceBuilder().build(); 338 } 339 340 /** 341 * Creates and returns a {@link MedicalResource} of type {@link 342 * MedicalResource#MEDICAL_RESOURCE_TYPE_VACCINES} which contains {@link 343 * PhrDataFactory#getFhirResource} data, with the given {@code dataSourceId}. 344 */ createVaccineMedicalResource(String dataSourceId)345 public static MedicalResource createVaccineMedicalResource(String dataSourceId) { 346 return new MedicalResource.Builder( 347 MEDICAL_RESOURCE_TYPE_VACCINES, 348 dataSourceId, 349 FHIR_VERSION_R4, 350 getFhirResource()) 351 .build(); 352 } 353 354 /** 355 * Creates and returns a {@link MedicalResource} of type {@link 356 * MedicalResource#MEDICAL_RESOURCE_TYPE_VACCINES} which contains {@link 357 * PhrDataFactory#getFhirResourceDifferentImmunization} data, with the given {@code 358 * dataSourceId}. 359 * 360 * <p>The contained FHIR data has a different resource ID than the above {@link 361 * PhrDataFactory#createVaccineMedicalResource}. 362 */ createDifferentVaccineMedicalResource(String dataSourceId)363 public static MedicalResource createDifferentVaccineMedicalResource(String dataSourceId) { 364 return new MedicalResource.Builder( 365 MEDICAL_RESOURCE_TYPE_VACCINES, 366 dataSourceId, 367 FHIR_VERSION_R4, 368 getFhirResourceDifferentImmunization()) 369 .build(); 370 } 371 372 /** 373 * Creates and returns a {@link MedicalResource} of type {@link 374 * MedicalResource#MEDICAL_RESOURCE_TYPE_VACCINES} which contains {@link 375 * PhrDataFactory#getUpdatedImmunizationFhirResource} data, with the given {@code dataSourceId}. 376 * 377 * <p>The contained FHIR data has the same resource ID as the above {@link 378 * PhrDataFactory#createVaccineMedicalResource}, but data is updated with a "status" field 379 * added. 380 */ createUpdatedVaccineMedicalResource(String dataSourceId)381 public static MedicalResource createUpdatedVaccineMedicalResource(String dataSourceId) 382 throws JSONException { 383 return new MedicalResource.Builder( 384 MEDICAL_RESOURCE_TYPE_VACCINES, 385 dataSourceId, 386 FHIR_VERSION_R4, 387 getUpdatedImmunizationFhirResource()) 388 .build(); 389 } 390 391 /** 392 * Creates and returns a {@link MedicalResource} of type {@link 393 * MedicalResource#MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES} which contains {@link 394 * PhrDataFactory#getFhirResourceAllergy} data, with the given {@code dataSourceId}. 395 */ createAllergyMedicalResource(String dataSourceId)396 public static MedicalResource createAllergyMedicalResource(String dataSourceId) { 397 return new MedicalResource.Builder( 398 MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES, 399 dataSourceId, 400 FHIR_VERSION_R4, 401 getFhirResourceAllergy()) 402 .build(); 403 } 404 405 /** 406 * Creates and returns a {@link MedicalResource} of type {@link 407 * MedicalResource#MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES} which contains {@link 408 * PhrDataFactory#getFhirResourceDifferentAllergy} data, with the given {@code dataSourceId}. 409 * 410 * <p>The contained FHIR data has a different resource ID than the above {@link 411 * PhrDataFactory#createAllergyMedicalResource}. 412 */ createDifferentAllergyMedicalResource(String dataSourceId)413 public static MedicalResource createDifferentAllergyMedicalResource(String dataSourceId) { 414 return new MedicalResource.Builder( 415 MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES, 416 dataSourceId, 417 FHIR_VERSION_R4, 418 getFhirResourceDifferentAllergy()) 419 .build(); 420 } 421 422 /** 423 * Creates and returns a {@link MedicalResource} of type {@link 424 * MedicalResource#MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES} which contains {@link 425 * PhrDataFactory#getUpdatedAllergyFhirResource} data, with the given {@code dataSourceId}. 426 * 427 * <p>The contained FHIR data has the same resource ID as the above {@link 428 * PhrDataFactory#createAllergyMedicalResource}, but data is updated with a "status" field 429 * added. 430 */ createUpdatedAllergyMedicalResource(String dataSourceId)431 public static MedicalResource createUpdatedAllergyMedicalResource(String dataSourceId) 432 throws JSONException { 433 return new MedicalResource.Builder( 434 MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES, 435 dataSourceId, 436 FHIR_VERSION_R4, 437 getUpdatedAllergyFhirResource()) 438 .build(); 439 } 440 441 /** 442 * Creates and returns a {@link UpsertMedicalResourceRequest.Builder} with default arguments. 443 */ getUpsertMedicalResourceRequestBuilder()444 public static UpsertMedicalResourceRequest.Builder getUpsertMedicalResourceRequestBuilder() { 445 return new UpsertMedicalResourceRequest.Builder( 446 DATA_SOURCE_ID, FHIR_VERSION_R4, FHIR_DATA_IMMUNIZATION); 447 } 448 449 /** Creates and returns a {@link UpsertMedicalResourceRequest} with default arguments. */ getUpsertMedicalResourceRequest()450 public static UpsertMedicalResourceRequest getUpsertMedicalResourceRequest() { 451 return getUpsertMedicalResourceRequestBuilder().build(); 452 } 453 454 /** 455 * Creates and returns a {@link MedicalResourceId} with default arguments. 456 * 457 * <p>By default, it contains the {@link FhirResource#FHIR_RESOURCE_TYPE_IMMUNIZATION} and 458 * {@link PhrDataFactory#FHIR_RESOURCE_ID_IMMUNIZATION}. 459 */ getMedicalResourceId()460 public static MedicalResourceId getMedicalResourceId() { 461 return new MedicalResourceId( 462 DATA_SOURCE_ID, FHIR_RESOURCE_TYPE_IMMUNIZATION, FHIR_RESOURCE_ID_IMMUNIZATION); 463 } 464 465 /** Returns the FHIR resource id field from the given {@code fhirJSON} string. */ getFhirResourceId(String fhirJSON)466 public static String getFhirResourceId(String fhirJSON) throws JSONException { 467 return new JSONObject(fhirJSON).getString(RESOURCE_ID_FIELD_NAME); 468 } 469 470 /** Returns an updated FHIR JSON string with an added status field. */ addCompletedStatus(String fhirJSON)471 public static String addCompletedStatus(String fhirJSON) throws JSONException { 472 JSONObject jsonObj = new JSONObject(fhirJSON); 473 jsonObj.put("status", "completed"); 474 return jsonObj.toString(); 475 } 476 477 /** 478 * Creates a number of vaccine resources based on the given {@code numOfResources} and {@code 479 * dataSourceId}. 480 */ createVaccineMedicalResources( int numOfResources, String dataSourceId)481 public static List<MedicalResource> createVaccineMedicalResources( 482 int numOfResources, String dataSourceId) { 483 FhirVersion fhirVersion = parseFhirVersion(R4_VERSION_STRING); 484 List<MedicalResource> medicalResources = new ArrayList<>(); 485 for (int i = 0; i < numOfResources; i++) { 486 String fhirResourceId = "id/" + i; 487 FhirResource fhirResource = 488 new FhirResource.Builder( 489 FhirResource.FHIR_RESOURCE_TYPE_IMMUNIZATION, 490 fhirResourceId, 491 new ImmunizationBuilder().setId(fhirResourceId).toJson()) 492 .build(); 493 MedicalResource medicalResource = 494 new MedicalResource.Builder( 495 MEDICAL_RESOURCE_TYPE_VACCINES, 496 dataSourceId, 497 fhirVersion, 498 fhirResource) 499 .build(); 500 medicalResources.add(medicalResource); 501 } 502 return medicalResources; 503 } 504 505 /** 506 * Creates a number of allergy resources based on the given {@code numOfResources} and {@code 507 * dataSourceId}. 508 */ createAllergyMedicalResources( int numOfResources, String dataSourceId)509 public static List<MedicalResource> createAllergyMedicalResources( 510 int numOfResources, String dataSourceId) { 511 FhirVersion fhirVersion = parseFhirVersion(R4_VERSION_STRING); 512 List<MedicalResource> medicalResources = new ArrayList<>(); 513 for (int i = 0; i < numOfResources; i++) { 514 FhirResource fhirResource = 515 new FhirResource.Builder( 516 FHIR_RESOURCE_TYPE_ALLERGY_INTOLERANCE, 517 "id/" + i, 518 FHIR_DATA_ALLERGY) 519 .build(); 520 MedicalResource medicalResource = 521 new MedicalResource.Builder( 522 MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES, 523 dataSourceId, 524 fhirVersion, 525 fhirResource) 526 .build(); 527 medicalResources.add(medicalResource); 528 } 529 return medicalResources; 530 } 531 532 /** 533 * Given two {@link MedicalDataSource}s, compare whether they are equal or not. This ignores the 534 * {@link MedicalDataSource#getLastDataUpdateTime()}. 535 */ isMedicalDataSourceEqual( MedicalDataSource actual, MedicalDataSource expected)536 public static boolean isMedicalDataSourceEqual( 537 MedicalDataSource actual, MedicalDataSource expected) { 538 return Objects.equals(actual.getId(), expected.getId()) 539 && Objects.equals(actual.getFhirVersion(), expected.getFhirVersion()) 540 && Objects.equals(actual.getFhirBaseUri(), expected.getFhirBaseUri()) 541 && Objects.equals(actual.getPackageName(), expected.getPackageName()) 542 && Objects.equals(actual.getDisplayName(), expected.getDisplayName()); 543 } 544 } 545