From 54b15dae509212f6661dc1f1bc4ca248cb487443 Mon Sep 17 00:00:00 2001 From: Kseniya Tomskikh Date: Fri, 20 Oct 2017 16:25:04 +0700 Subject: PDSUI-2336 Deleted api classes of play format, userhistory and message services --- .../xyz/driver/pdsuicommon/error/ErrorCode.scala | 15 +- .../driver/pdsuicommon/error/ErrorsResponse.scala | 77 +++---- .../xyz/driver/pdsuicommon/http/Directives.scala | 8 +- .../xyz/driver/pdsuicommon/json/JsResultOps.scala | 15 -- .../pdsuicommon/json/JsonValidationException.scala | 5 - .../driver/pdsuicommon/json/Serialization.scala | 46 ----- .../serialization/PlayJsonSupport.scala | 34 --- .../utils/CustomSwaggerJsonFormats.scala | 62 +++--- .../xyz/driver/pdsuicommon/utils/Implicits.scala | 8 +- .../driver/pdsuicommon/validation/package.scala | 8 - .../fakes/entities/treatmentmatching.scala | 2 +- .../pdsuidomain/formats/json/ListResponse.scala | 56 ----- .../xyz/driver/pdsuidomain/formats/json/arm.scala | 44 ++++ .../pdsuidomain/formats/json/arm/ApiArm.scala | 35 ---- .../formats/json/arm/ApiCreateArm.scala | 20 -- .../formats/json/arm/ApiPartialArm.scala | 14 -- .../formats/json/bridgeuploadqueue.scala | 68 ++++++ .../driver/pdsuidomain/formats/json/common.scala | 66 ++++++ .../pdsuidomain/formats/json/criterion.scala | 171 ++++++++++++++++ .../formats/json/criterion/ApiCriterion.scala | 59 ------ .../formats/json/criterion/ApiNewCriterion.scala | 46 ----- .../json/criterion/ApiUpdateCriterion.scala | 64 ------ .../driver/pdsuidomain/formats/json/document.scala | 197 ++++++++++++++++++ .../formats/json/document/ApiDocument.scala | 114 ----------- .../formats/json/document/ApiDocumentType.scala | 27 --- .../formats/json/document/ApiPartialDocument.scala | 131 ------------ .../formats/json/document/ApiProviderType.scala | 27 --- .../pdsuidomain/formats/json/documenthistory.scala | 29 +++ .../json/documenthistory/ApiDocumentHistory.scala | 27 --- .../pdsuidomain/formats/json/documentissue.scala | 66 ++++++ .../json/documentissue/ApiDocumentIssue.scala | 40 ---- .../documentissue/ApiPartialDocumentIssue.scala | 42 ---- .../pdsuidomain/formats/json/eligibility.scala | 103 ++++++++++ .../pdsuidomain/formats/json/eligibilityarm.scala | 108 ++++++++++ .../eligibilityarm/ApiCreateEligibilityArm.scala | 33 --- .../json/eligibilityarm/ApiEligibilityArm.scala | 57 ------ .../eligibilityarm/ApiPartialEligibilityArm.scala | 23 --- .../json/evidence/ApiPatientLabelEvidence.scala | 33 --- .../driver/pdsuidomain/formats/json/export.scala | 86 ++++++++ .../pdsuidomain/formats/json/extracteddata.scala | 150 ++++++++++++++ .../json/extracteddata/ApiExtractedData.scala | 64 ------ .../extracteddata/ApiPartialExtractedData.scala | 80 -------- .../pdsuidomain/formats/json/hypothesis.scala | 12 ++ .../formats/json/hypothesis/ApiHypothesis.scala | 35 ---- .../pdsuidomain/formats/json/intervention.scala | 146 +++++++++++++ .../json/intervention/ApiIntervention.scala | 76 ------- .../json/intervention/ApiInterventionType.scala | 26 --- .../json/intervention/ApiPartialIntervention.scala | 90 -------- .../formats/json/label/ApiCriterionLabel.scala | 54 ----- .../formats/json/label/ApiExtractedDataLabel.scala | 41 ---- .../pdsuidomain/formats/json/listresponse.scala | 45 ++++ .../formats/json/message/ApiMessage.scala | 79 ------- .../formats/json/message/ApiPartialMessage.scala | 82 -------- .../json/password/PasswordCreateRequest.scala | 9 - .../json/password/PasswordUpdateRequest.scala | 9 - .../driver/pdsuidomain/formats/json/patient.scala | 50 +++++ .../formats/json/patient/ApiPatient.scala | 86 -------- .../formats/json/patient/PatientStatus.scala | 24 --- .../eligible/ApiPartialPatientEligibleTrial.scala | 18 -- .../patient/eligible/ApiPatientEligibleTrial.scala | 51 ----- .../hypothesis/ApiPartialPatientHypothesis.scala | 27 --- .../patient/hypothesis/ApiPatientHypothesis.scala | 35 ---- .../patient/label/ApiPartialPatientLabel.scala | 43 ---- .../json/patient/label/ApiPatientLabel.scala | 55 ----- .../label/ApiPatientLabelDefiningCriteria.scala | 29 --- .../patient/trial/ApiPartialPatientCriterion.scala | 47 ----- .../trial/ApiPartialPatientCriterionList.scala | 37 ---- .../json/patient/trial/ApiPatientCriterion.scala | 75 ------- .../formats/json/patientcriterion.scala | 64 ++++++ .../formats/json/patientdefiningcriteria.scala | 19 ++ .../formats/json/patienteligibletrial.scala | 40 ++++ .../pdsuidomain/formats/json/patienthistory.scala | 30 +++ .../json/patienthistory/ApiPatientHistory.scala | 28 --- .../formats/json/patienthypothesis.scala | 49 +++++ .../pdsuidomain/formats/json/patientissue.scala | 54 +++++ .../json/patientissue/ApiPartialPatientIssue.scala | 33 --- .../json/patientissue/ApiPatientIssue.scala | 34 --- .../pdsuidomain/formats/json/patientlabel.scala | 67 ++++++ .../formats/json/queue/ApiQueueUploadItem.scala | 38 ---- .../driver/pdsuidomain/formats/json/record.scala | 228 +++++++++++++++++++++ .../formats/json/record/ApiCreateRecord.scala | 33 --- .../formats/json/record/ApiRecord.scala | 110 ---------- .../formats/json/record/ApiUpdateRecord.scala | 52 ----- .../formats/json/record/MedicalRecordStatus.scala | 34 --- .../pdsuidomain/formats/json/recordhistory.scala | 30 +++ .../json/recordhistory/ApiRecordHistory.scala | 27 --- .../pdsuidomain/formats/json/recordissue.scala | 68 ++++++ .../json/recordissue/ApiPartialRecordIssue.scala | 42 ---- .../formats/json/recordissue/ApiRecordIssue.scala | 40 ---- .../formats/json/session/NewSessionRequest.scala | 12 -- .../formats/json/session/NewSessionResponse.scala | 11 - .../driver/pdsuidomain/formats/json/slotarm.scala | 44 ++++ .../formats/json/slotarm/ApiPartialSlotArm.scala | 14 -- .../formats/json/slotarm/ApiSlotArm.scala | 35 ---- .../formats/json/slotarm/ApiSlotCreateArm.scala | 20 -- .../formats/json/sprayformats/arm.scala | 44 ---- .../json/sprayformats/bridgeuploadqueue.scala | 68 ------ .../formats/json/sprayformats/common.scala | 66 ------ .../formats/json/sprayformats/criterion.scala | 171 ---------------- .../formats/json/sprayformats/document.scala | 197 ------------------ .../json/sprayformats/documenthistory.scala | 29 --- .../formats/json/sprayformats/documentissue.scala | 66 ------ .../formats/json/sprayformats/eligibility.scala | 101 --------- .../formats/json/sprayformats/eligibilityarm.scala | 108 ---------- .../formats/json/sprayformats/export.scala | 86 -------- .../formats/json/sprayformats/extracteddata.scala | 150 -------------- .../formats/json/sprayformats/hypothesis.scala | 12 -- .../formats/json/sprayformats/intervention.scala | 146 ------------- .../formats/json/sprayformats/listresponse.scala | 45 ---- .../formats/json/sprayformats/patient.scala | 48 ----- .../json/sprayformats/patientcriterion.scala | 64 ------ .../sprayformats/patientdefiningcriteria.scala | 19 -- .../json/sprayformats/patienteligibletrial.scala | 40 ---- .../formats/json/sprayformats/patienthistory.scala | 30 --- .../json/sprayformats/patienthypothesis.scala | 49 ----- .../formats/json/sprayformats/patientissue.scala | 54 ----- .../formats/json/sprayformats/patientlabel.scala | 66 ------ .../formats/json/sprayformats/record.scala | 228 --------------------- .../formats/json/sprayformats/recordhistory.scala | 30 --- .../formats/json/sprayformats/recordissue.scala | 68 ------ .../formats/json/sprayformats/slotarm.scala | 44 ---- .../formats/json/sprayformats/studydesign.scala | 29 --- .../formats/json/sprayformats/trial.scala | 83 -------- .../formats/json/sprayformats/trialhistory.scala | 30 --- .../formats/json/sprayformats/trialissue.scala | 60 ------ .../pdsuidomain/formats/json/studydesign.scala | 29 +++ .../formats/json/studydesign/ApiStudyDesign.scala | 23 --- .../driver/pdsuidomain/formats/json/trial.scala | 85 ++++++++ .../formats/json/trial/ApiPartialTrial.scala | 44 ---- .../pdsuidomain/formats/json/trial/ApiTrial.scala | 96 --------- .../formats/json/trial/TrialStatus.scala | 30 --- .../pdsuidomain/formats/json/trialhistory.scala | 30 +++ .../json/trialhistory/ApiTrialHistory.scala | 26 --- .../pdsuidomain/formats/json/trialissue.scala | 60 ++++++ .../json/trialissue/ApiPartialTrialIssue.scala | 40 ---- .../formats/json/trialissue/ApiTrialIssue.scala | 60 ------ .../formats/json/user/ApiPartialUser.scala | 76 ------- .../pdsuidomain/formats/json/user/ApiUser.scala | 39 ---- .../pdsuidomain/formats/json/user/UserRole.scala | 37 ---- .../formats/json/userhistory/ApiUserHistory.scala | 43 ---- .../pdsuidomain/services/MessageService.scala | 88 -------- .../pdsuidomain/services/UserHistoryService.scala | 30 --- .../pdsuidomain/services/rest/RestArmService.scala | 26 +-- .../services/rest/RestCriterionService.scala | 28 +-- .../services/rest/RestDocumentService.scala | 32 +-- .../services/rest/RestDocumentTypeService.scala | 13 +- .../rest/RestEligibilityVerificationService.scala | 2 +- .../services/rest/RestExtractedDataService.scala | 28 +-- .../pdsuidomain/services/rest/RestHelper.scala | 3 +- .../services/rest/RestHypothesisService.scala | 13 +- .../services/rest/RestInterventionService.scala | 27 +-- .../rest/RestInterventionTypeService.scala | 13 +- .../services/rest/RestMedicalRecordService.scala | 33 +-- .../services/rest/RestMessageService.scala | 87 -------- .../services/rest/RestPatientService.scala | 20 +- .../services/rest/RestProviderTypeService.scala | 13 +- .../services/rest/RestStudyDesignService.scala | 13 +- .../services/rest/RestTrialService.scala | 28 +-- .../pdsuidomain/formats/json/ArmFormatSuite.scala | 37 ++++ .../json/BridgeUploadQueueFormatSuite.scala | 32 +++ .../formats/json/CriterionFormatSuite.scala | 75 +++++++ .../formats/json/DocumentFormatSuite.scala | 73 +++++++ .../formats/json/DocumentHistoryFormatSuite.scala | 31 +++ .../formats/json/DocumentIssueFormatSuite.scala | 48 +++++ .../EligibilityArmWithDiseasesFormatSuite.scala | 55 +++++ .../formats/json/ExportFormatSuite.scala | 124 +++++++++++ .../formats/json/ExtractedDataFormatSuite.scala | 97 +++++++++ .../formats/json/HypothesisFormatSuite.scala | 27 +++ .../formats/json/InterventionFormatSuite.scala | 73 +++++++ .../formats/json/ListResponseFormatSuite.scala | 101 +++++++++ .../formats/json/MedicalRecordFormatSuite.scala | 77 +++++++ .../json/MedicalRecordHistoryFormatSuite.scala | 31 +++ .../json/MedicalRecordIssueFormatSuite.scala | 47 +++++ .../formats/json/PatientCriterionFormatSuite.scala | 58 ++++++ .../json/PatientEligibleTrialFormatSuite.scala | 62 ++++++ .../formats/json/PatientFormatSuite.scala | 39 ++++ .../formats/json/PatientHistoryFormatSuite.scala | 32 +++ .../json/PatientHypothesisFormatSuite.scala | 47 +++++ .../formats/json/PatientIssueFormatSuite.scala | 45 ++++ .../formats/json/PatientLabelFormatSuite.scala | 79 +++++++ .../formats/json/SlotArmFormatSuite.scala | 36 ++++ .../formats/json/StudyDesignFormatSuite.scala | 20 ++ .../formats/json/TrialFormatSuite.scala | 49 +++++ .../formats/json/TrialHistoryFormatSuite.scala | 31 +++ .../formats/json/TrialIssueFormatSuite.scala | 49 +++++ .../formats/json/sprayformats/ArmFormatSuite.scala | 37 ---- .../sprayformats/BridgeUploadQueueFormat.scala | 32 --- .../json/sprayformats/CriterionFormatSuite.scala | 75 ------- .../json/sprayformats/DocumentFormatSuite.scala | 73 ------- .../sprayformats/DocumentHistoryFormatSuite.scala | 31 --- .../sprayformats/DocumentIssueFormatSuite.scala | 48 ----- .../EligibilityArmWithDiseasesFormatSuite.scala | 55 ----- .../json/sprayformats/ExportFormatSuite.scala | 124 ----------- .../sprayformats/ExtractedDataFormatSuite.scala | 97 --------- .../json/sprayformats/HypothesisFormatSuite.scala | 27 --- .../sprayformats/InterventionFormatSuite.scala | 73 ------- .../sprayformats/ListResponseFormatSuite.scala | 101 --------- .../sprayformats/MedicalRecordFormatSuite.scala | 77 ------- .../MedicalRecordHistoryFormatSuite.scala | 31 --- .../MedicalRecordIssueFormatSuite.scala | 47 ----- .../sprayformats/PatientCriterionFormatSuite.scala | 58 ------ .../PatientEligibleTrialFormatSuite.scala | 62 ------ .../json/sprayformats/PatientFormatSuite.scala | 39 ---- .../sprayformats/PatientHistoryFormatSuite.scala | 32 --- .../PatientHypothesisFormatSuite.scala | 47 ----- .../sprayformats/PatientIssueFormatSuite.scala | 45 ---- .../sprayformats/PatientLabelFormatSuite.scala | 79 ------- .../json/sprayformats/SlotArmFormatSuite.scala | 36 ---- .../json/sprayformats/StudyDesignFormatSuite.scala | 20 -- .../json/sprayformats/TrialFormatSuite.scala | 49 ----- .../sprayformats/TrialHistoryFormatSuite.scala | 31 --- .../json/sprayformats/TrialIssueFormatSuite.scala | 49 ----- 212 files changed, 3935 insertions(+), 7358 deletions(-) delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/json/JsonValidationException.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/json/Serialization.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/validation/package.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/arm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiCreateArm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiPartialArm.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/bridgeuploadqueue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/common.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiCriterion.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiNewCriterion.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiUpdateCriterion.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/document.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory/ApiDocumentHistory.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibility.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiCreateEligibilityArm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiEligibilityArm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiPartialEligibilityArm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/evidence/ApiPatientLabelEvidence.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/export.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis/ApiHypothesis.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiInterventionType.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiPartialIntervention.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiCriterionLabel.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiExtractedDataLabel.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/listresponse.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiPartialMessage.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordCreateRequest.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordUpdateRequest.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/ApiPatient.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/PatientStatus.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPartialPatientEligibleTrial.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPatientEligibleTrial.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPartialPatientHypothesis.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPatientHypothesis.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPartialPatientLabel.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabel.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabelDefiningCriteria.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterion.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterionList.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPatientCriterion.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patientcriterion.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patientdefiningcriteria.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patienteligibletrial.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory/ApiPatientHistory.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthypothesis.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patientlabel.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/queue/ApiQueueUploadItem.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/record.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiCreateRecord.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiRecord.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiUpdateRecord.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/record/MedicalRecordStatus.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory/ApiRecordHistory.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionRequest.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionResponse.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiPartialSlotArm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiSlotArm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiSlotCreateArm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/arm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/bridgeuploadqueue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/common.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/criterion.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenthistory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documentissue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibility.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibilityarm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/extracteddata.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/hypothesis.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/listresponse.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patient.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientcriterion.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientdefiningcriteria.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienteligibletrial.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthistory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthypothesis.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientissue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientlabel.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordhistory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordissue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/slotarm.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trial.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialhistory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialissue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/trial.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiPartialTrial.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/TrialStatus.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory/ApiTrialHistory.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiPartialTrialIssue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiTrialIssue.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/userhistory/ApiUserHistory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/ArmFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/BridgeUploadQueueFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/CriterionFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentHistoryFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentIssueFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/EligibilityArmWithDiseasesFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/ExportFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/ExtractedDataFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/HypothesisFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/InterventionFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/ListResponseFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordHistoryFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordIssueFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientCriterionFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientEligibleTrialFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientHistoryFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientHypothesisFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientIssueFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientLabelFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/SlotArmFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/StudyDesignFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialHistoryFormatSuite.scala create mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialIssueFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ArmFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/BridgeUploadQueueFormat.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/CriterionFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentHistoryFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentIssueFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/EligibilityArmWithDiseasesFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExportFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExtractedDataFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/HypothesisFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/InterventionFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ListResponseFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordHistoryFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordIssueFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientCriterionFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientEligibleTrialFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHistoryFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHypothesisFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientIssueFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientLabelFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/SlotArmFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/StudyDesignFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialHistoryFormatSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialIssueFormatSuite.scala diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala index 5574c01..748e76a 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala @@ -1,7 +1,6 @@ package xyz.driver.pdsuicommon.error -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, Reads, Writes} +import xyz.driver.core.json.EnumJsonFormat @SuppressWarnings(Array("org.wartremover.warts.Enumeration")) object ErrorCode extends Enumeration { @@ -9,9 +8,13 @@ object ErrorCode extends Enumeration { type ErrorCode = Value val Unspecified = Value(1) - private val fromJsonReads: Reads[ErrorCode] = Reads.of[Int].map(ErrorCode.apply) - private val toJsonWrites: Writes[ErrorCode] = Writes.of[Int].contramap(_.id) - - implicit val jsonFormat: Format[ErrorCode] = Format(fromJsonReads, toJsonWrites) + implicit val jsonFormat = new EnumJsonFormat[ErrorCode]( + "200" -> ErrorCode.Value(200), + "400" -> ErrorCode.Value(400), + "401" -> ErrorCode.Value(401), + "403" -> ErrorCode.Value(403), + "404" -> ErrorCode.Value(404), + "500" -> ErrorCode.Value(500) + ) } diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala index 3761cc5..540bfbb 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala @@ -1,18 +1,14 @@ package xyz.driver.pdsuicommon.error -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import ErrorCode.{ErrorCode, Unspecified} +import spray.json._ +import ErrorCode._ import ErrorsResponse.ResponseError -import xyz.driver.pdsuicommon.auth.{AnonymousRequestContext, RequestId} -import xyz.driver.pdsuicommon.utils.Utils -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import play.api.mvc.Results -import xyz.driver.pdsuicommon.validation.JsonValidationErrors +import xyz.driver.pdsuicommon.auth.RequestId final case class ErrorsResponse(errors: Seq[ResponseError], requestId: RequestId) object ErrorsResponse { + import DefaultJsonProtocol._ /** * @param data Any data that can be associated with particular error.Ex.: error field name @@ -25,59 +21,34 @@ object ErrorsResponse { object ResponseError { - implicit val responseErrorJsonFormat: Format[ResponseError] = ( - (JsPath \ "data").formatNullable[String] and - (JsPath \ "message").format[String] and - (JsPath \ "code").format[ErrorCode] - )(ResponseError.apply, unlift(ResponseError.unapply)) + implicit val responseErrorJsonFormat: RootJsonFormat[ResponseError] = jsonFormat3(ResponseError.apply) } - implicit val errorsResponseJsonFormat: Format[ErrorsResponse] = ( - (JsPath \ "errors").format[Seq[ResponseError]] and - (JsPath \ "requestId").format[String] - )((errs, req) => ErrorsResponse.apply(errs, RequestId(req)), res => (res.errors, res.requestId.value)) + implicit val errorsResponseJsonFormat: RootJsonFormat[ErrorsResponse] = new RootJsonFormat[ErrorsResponse] { + override def write(obj: ErrorsResponse): JsValue = { + JsObject( + "errors" -> obj.errors.map(_.toJson).toJson, + "requestId" -> obj.requestId.value.toJson + ) + } - // deprecated, will be removed in REP-436 - def fromString(message: String, httpStatus: Results#Status)( - implicit context: AnonymousRequestContext): ErrorsResponse = { - new ErrorsResponse( - errors = Seq( - ResponseError( - data = None, - message = message, - code = Unspecified - )), - requestId = context.requestId - ) - } + override def read(json: JsValue) = json match { + case JsObject(fields) => + val errors = fields + .get("errors") + .map(_.convertTo[Seq[ResponseError]]) + .getOrElse(deserializationError(s"ErrorsResponse json object does not contain `errors` field: $json")) - // scalastyle:off null - def fromExceptionMessage(e: Throwable, httpStatus: Results#Status = Results.InternalServerError)( - implicit context: AnonymousRequestContext): ErrorsResponse = { - val message = if (e.getMessage == null || e.getMessage.isEmpty) { - Utils.getClassSimpleName(e.getClass) - } else { - e.getMessage - } + val requestId = fields + .get("requestId") + .map(id => RequestId(id.convertTo[String])) + .getOrElse(deserializationError(s"ErrorsResponse json object does not contain `requestId` field: $json")) - fromString(message, httpStatus) - } - // scalastyle:on null + ErrorsResponse(errors, requestId) - // deprecated, will be removed in REP-436 - def fromJsonValidationErrors(validationErrors: JsonValidationErrors)( - implicit context: AnonymousRequestContext): ErrorsResponse = { - val errors = validationErrors.map { - case (path, xs) => - ResponseError( - data = Some(path.toString()), - message = xs.map(_.message).mkString("\n"), - code = Unspecified - ) + case _ => deserializationError(s"Expected json as ErrorsResponse, but got $json") } - - new ErrorsResponse(errors, context.requestId) } } diff --git a/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala b/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala index e9a4132..fd1856b 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala @@ -12,7 +12,7 @@ import xyz.driver.pdsuicommon.error.ErrorsResponse.ResponseError import xyz.driver.pdsuicommon.parsers._ import xyz.driver.pdsuicommon.db.{Pagination, Sorting, SearchFilterExpr} import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ +import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import xyz.driver.core.rest.AuthProvider import scala.util.control._ @@ -83,9 +83,9 @@ trait Directives { def domainRejectionHandler(req: RequestId): RejectionHandler = { def wrapContent(message: String) = { - import play.api.libs.json._ - val err = ErrorsResponse(Seq(ResponseError(None, message, ErrorCode.Unspecified)), req) - val text = Json.stringify(implicitly[Writes[ErrorsResponse]].writes(err)) + import ErrorsResponse._ + val err: ErrorsResponse = ErrorsResponse(Seq(ResponseError(None, message, ErrorCode.Unspecified)), req) + val text = errorsResponseJsonFormat.write(err).toString() HttpEntity(ContentTypes.`application/json`, text) } RejectionHandler.default.mapRejectionResponse { diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala b/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala deleted file mode 100644 index 4ff4034..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala +++ /dev/null @@ -1,15 +0,0 @@ -package xyz.driver.pdsuicommon.json - -import play.api.libs.json.JsResult - -import scala.util.{Failure, Success, Try} - -final class JsResultOps[T](val self: JsResult[T]) extends AnyVal { - - def toTry: Try[T] = { - self.fold[Try[T]]( - errors => Failure(new JsonValidationException(errors)), - Success(_) - ) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/JsonValidationException.scala b/src/main/scala/xyz/driver/pdsuicommon/json/JsonValidationException.scala deleted file mode 100644 index 21750b4..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/json/JsonValidationException.scala +++ /dev/null @@ -1,5 +0,0 @@ -package xyz.driver.pdsuicommon.json - -import xyz.driver.pdsuicommon.validation.JsonValidationErrors - -class JsonValidationException(val errors: JsonValidationErrors) extends Exception diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/Serialization.scala b/src/main/scala/xyz/driver/pdsuicommon/json/Serialization.scala deleted file mode 100644 index 8231ddb..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/json/Serialization.scala +++ /dev/null @@ -1,46 +0,0 @@ -package xyz.driver.pdsuicommon.json - -import java.net.URI - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities.CaseId - -object Serialization { - - // @TODO Test and check all items in an array - private def seqJsonReads[T](implicit argFormat: Reads[T]): Reads[Seq[T]] = Reads { - case JsArray(xs) => - JsSuccess(xs.map { x => - argFormat.reads(x).get - }) - case x => JsError(s"Expected JsArray, but got $x") - } - - private def seqJsonWrites[T](implicit argFormat: Writes[T]): Writes[Seq[T]] = Writes { xs => - JsArray(xs.map(argFormat.writes)) - } - - implicit def seqJsonFormat[T](implicit f: Format[T]): Format[Seq[T]] = Format(seqJsonReads[T], seqJsonWrites[T]) - - private val uriJsonReads: Reads[URI] = Reads.StringReads.map(URI.create) - private val uriJsonWrites: Writes[URI] = Writes(uri => JsString(uri.toString)) - implicit val uriJsonFormat: Format[URI] = Format(uriJsonReads, uriJsonWrites) - - private def uuidIdJsonReads[T]: Reads[UuidId[T]] = Reads.uuidReads.map(x => UuidId[T](x)) - private def uuidIdJsonWrites[T]: Writes[UuidId[T]] = Writes.UuidWrites.contramap(_.id) - implicit def uuidIdJsonFormat[T]: Format[UuidId[T]] = Format(uuidIdJsonReads, uuidIdJsonWrites) - - private def longIdJsonReads[T]: Reads[LongId[T]] = Reads.LongReads.map(x => LongId[T](x)) - private def longIdJsonWrites[T]: Writes[LongId[T]] = Writes.LongWrites.contramap(_.id) - implicit def longIdJsonFormat[T]: Format[LongId[T]] = Format(longIdJsonReads, longIdJsonWrites) - - private val emailJsonReads: Reads[Email] = Reads.email.map(Email.apply) - private val emailJsonWrites: Writes[Email] = Writes(email => JsString(email.value)) - implicit val emailJsonFormat: Format[Email] = Format(emailJsonReads, emailJsonWrites) - - private val caseIdJsonReads: Reads[CaseId] = Reads.StringReads.map(CaseId(_)) - private val caseIdJsonWrites: Writes[CaseId] = Writes(caseId => JsString(caseId.id)) - implicit val caseIdJsonFormat: Format[CaseId] = Format(caseIdJsonReads, caseIdJsonWrites) -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala b/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala deleted file mode 100644 index 5158dab..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.driver.pdsuicommon.serialization - -import akka.http.scaladsl.server.{RejectionError, ValidationRejection} -import akka.http.scaladsl.unmarshalling.Unmarshaller -import play.api.libs.json.{Reads, Writes} -import play.api.libs.json.Json -import akka.http.scaladsl.marshalling.ToEntityMarshaller -import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller -import akka.http.scaladsl.model.MediaTypes.`application/json` - -trait PlayJsonSupport { - import akka.http.scaladsl.marshalling.Marshaller - - implicit def playJsonUnmarshaller[A: Reads]: FromEntityUnmarshaller[A] = { - val reads = implicitly[Reads[A]] - Unmarshaller.stringUnmarshaller - .forContentTypes(`application/json`) - .map(Json.parse) - .map(reads.reads) - .map(_.recoverTotal { error => - throw RejectionError(ValidationRejection(s"Error reading JSON response as ${reads}.")) - }) - } - - implicit def playJsonMarshaller[A: Writes]: ToEntityMarshaller[A] = { - Marshaller - .stringMarshaller(`application/json`) - .compose(Json.prettyPrint) - .compose(implicitly[Writes[A]].writes) - } - -} - -object PlayJsonSupport extends PlayJsonSupport diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala index 34c7495..a79071e 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala @@ -6,16 +6,16 @@ import io.swagger.models.properties.Property import spray.json.JsValue import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.sprayformats.listresponse._ +import xyz.driver.pdsuidomain.formats.json.listresponse._ import xyz.driver.core.swagger.CustomSwaggerJsonConverter._ import xyz.driver.entities.patient.CancerType import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue import xyz.driver.pdsuidomain.entities.export.patient.ExportPatientWithLabels import xyz.driver.pdsuidomain.entities.export.trial.ExportTrialWithLabels import xyz.driver.pdsuidomain.fakes.entities.common -import xyz.driver.pdsuidomain.formats.json.sprayformats.bridgeuploadqueue._ -import xyz.driver.pdsuidomain.formats.json.sprayformats.record._ -import xyz.driver.pdsuidomain.formats.json.sprayformats.document._ +import xyz.driver.pdsuidomain.formats.json.bridgeuploadqueue._ +import xyz.driver.pdsuidomain.formats.json.record._ +import xyz.driver.pdsuidomain.formats.json.document._ import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData import xyz.driver.pdsuidomain.services.PatientCriterionService.{DraftPatientCriterion, RichPatientCriterion} @@ -83,17 +83,17 @@ object CustomSwaggerJsonFormats { object trialcuration { import xyz.driver.pdsuidomain.fakes.entities.trialcuration._ import xyz.driver.pdsuidomain.fakes.entities.export - import xyz.driver.pdsuidomain.formats.json.sprayformats.export._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.arm._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.slotarm._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.eligibilityarm._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.criterion._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.intervention._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.hypothesis._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.studydesign._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.trial._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.trialhistory._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.trialissue._ + import xyz.driver.pdsuidomain.formats.json.export._ + import xyz.driver.pdsuidomain.formats.json.arm._ + import xyz.driver.pdsuidomain.formats.json.slotarm._ + import xyz.driver.pdsuidomain.formats.json.eligibilityarm._ + import xyz.driver.pdsuidomain.formats.json.criterion._ + import xyz.driver.pdsuidomain.formats.json.intervention._ + import xyz.driver.pdsuidomain.formats.json.hypothesis._ + import xyz.driver.pdsuidomain.formats.json.studydesign._ + import xyz.driver.pdsuidomain.formats.json.trial._ + import xyz.driver.pdsuidomain.formats.json.trialhistory._ + import xyz.driver.pdsuidomain.formats.json.trialissue._ val customTrialCurationProperties = immutable.Map[Class[_], Property]( classOf[Trial.Status] -> stringProperty(), @@ -102,7 +102,7 @@ object CustomSwaggerJsonFormats { ) ++ customCommonProperties val customTrialCurationObjectsExamples = immutable.Map[Class[_], JsValue]( - classOf[Trial] -> trialWriter.write(nextTrial()), + classOf[Trial] -> trialFormat.write(nextTrial()), classOf[Arm] -> armFormat.write(nextArm()), classOf[TrialHistory] -> trialHistoryFormat.write(nextTrialHistory()), classOf[TrialIssue] -> trialIssueWriter.write(nextTrialIssue()), @@ -134,12 +134,12 @@ object CustomSwaggerJsonFormats { object recordprocessing { import xyz.driver.pdsuidomain.fakes.entities.recordprocessing._ import xyz.driver.pdsuidomain.fakes.entities.export - import xyz.driver.pdsuidomain.formats.json.sprayformats.export._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.documentissue._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.documenthistory._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.recordissue._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.recordhistory._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.extracteddata._ + import xyz.driver.pdsuidomain.formats.json.export._ + import xyz.driver.pdsuidomain.formats.json.documentissue._ + import xyz.driver.pdsuidomain.formats.json.documenthistory._ + import xyz.driver.pdsuidomain.formats.json.recordissue._ + import xyz.driver.pdsuidomain.formats.json.recordhistory._ + import xyz.driver.pdsuidomain.formats.json.extracteddata._ val customRecordProcessingProperties = immutable.Map[Class[_], Property]( classOf[MedicalRecord.Status] -> stringProperty(), @@ -176,14 +176,14 @@ object CustomSwaggerJsonFormats { object treatmentmatching { import xyz.driver.pdsuidomain.fakes.entities.treatmentmatching._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patient._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patientcriterion._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patientdefiningcriteria._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patienteligibletrial._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patientlabel._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patienthypothesis._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patienthistory._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patientissue._ + import xyz.driver.pdsuidomain.formats.json.patient._ + import xyz.driver.pdsuidomain.formats.json.patientcriterion._ + import xyz.driver.pdsuidomain.formats.json.patientdefiningcriteria._ + import xyz.driver.pdsuidomain.formats.json.patienteligibletrial._ + import xyz.driver.pdsuidomain.formats.json.patientlabel._ + import xyz.driver.pdsuidomain.formats.json.patienthypothesis._ + import xyz.driver.pdsuidomain.formats.json.patienthistory._ + import xyz.driver.pdsuidomain.formats.json.patientissue._ val customTreatmentMatchingProperties = immutable.Map[Class[_], Property]( classOf[Patient.Status] -> stringProperty(), @@ -192,7 +192,7 @@ object CustomSwaggerJsonFormats { ) ++ customCommonProperties val customTreatmentMatchingObjectsExamples = immutable.Map[Class[_], JsValue]( - classOf[Patient] -> patientWriter.write(nextPatient()), + classOf[Patient] -> patientFormat.write(nextPatient()), classOf[RichPatientLabel] -> richPatientLabelWriter.write(nextRichPatientLabel()), classOf[PatientLabel] -> patientLabelDefiningCriteriaWriter.write(nextPatientLabel()), classOf[RichPatientCriterion] -> patientCriterionWriter.write(nextRichPatientCriterion()), diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala index 9411beb..0b18093 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala @@ -1,8 +1,5 @@ package xyz.driver.pdsuicommon.utils -import play.api.libs.json.JsResult -import xyz.driver.pdsuicommon.json.JsResultOps - import scala.collection.generic.CanBuildFrom object Implicits { @@ -23,7 +20,6 @@ object Implicits { implicit def toMapOps[K, V](x: Map[K, V]): MapOps[K, V] = new MapOps(x) - implicit def toCharOps(self: Char): CharOps = new CharOps(self) - implicit def toStringOps(self: String): StringOps = new StringOps(self) - implicit def toJsResultOps[T](self: JsResult[T]): JsResultOps[T] = new JsResultOps(self) + implicit def toCharOps(self: Char): CharOps = new CharOps(self) + implicit def toStringOps(self: String): StringOps = new StringOps(self) } diff --git a/src/main/scala/xyz/driver/pdsuicommon/validation/package.scala b/src/main/scala/xyz/driver/pdsuicommon/validation/package.scala deleted file mode 100644 index 9a31a93..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/validation/package.scala +++ /dev/null @@ -1,8 +0,0 @@ -package xyz.driver.pdsuicommon - -import play.api.data.validation.{ValidationError => PlayValidationError} -import play.api.libs.json.JsPath - -package object validation { - type JsonValidationErrors = Seq[(JsPath, Seq[PlayValidationError])] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/treatmentmatching.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/treatmentmatching.scala index d5adc32..2a06998 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/treatmentmatching.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/treatmentmatching.scala @@ -17,7 +17,7 @@ object treatmentmatching { final case class DraftPatientCriterionList(list: List[DraftPatientCriterion]) object DraftPatientCriterionList { import spray.json._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patientcriterion._ + import xyz.driver.pdsuidomain.formats.json.patientcriterion._ implicit val draftPatientCriterionListFormat: RootJsonFormat[DraftPatientCriterionList] = new RootJsonFormat[DraftPatientCriterionList] { diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala deleted file mode 100644 index 3fbeac8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala +++ /dev/null @@ -1,56 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.db.Pagination -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ListResponse[+T](items: Seq[T], meta: ListResponse.Meta) - -object ListResponse { - - final case class Meta(itemsCount: Int, pageNumber: Int, pageSize: Int, lastUpdate: Option[LocalDateTime]) - - object Meta { - def apply(itemsCount: Int, pagination: Pagination, lastUpdate: Option[LocalDateTime]): Meta = { - Meta(itemsCount, pagination.pageNumber, pagination.pageSize, lastUpdate) - } - } - - private val listResponseMetaJsonReads: Reads[Meta] = { - ((JsPath \ "itemsCount").read[Int] and - (JsPath \ "pageNumber").read[Int] and - (JsPath \ "pageSize").read[Int] and - (JsPath \ "lastUpdate").readNullable[LocalDateTime]).apply { - (itemsCount: Int, pageNumber: Int, pageSize: Int, lastUpdate: Option[LocalDateTime]) => - Meta(itemsCount, pageNumber, pageSize, lastUpdate) - } - } - - implicit val listResponseMetaJsonWrites: Writes[Meta] = ( - (JsPath \ "itemsCount").write[Int] and - (JsPath \ "pageNumber").write[Int] and - (JsPath \ "pageSize").write[Int] and - (JsPath \ "lastUpdate").write[Option[LocalDateTime]] - )(unlift(Meta.unapply)) - - implicit val listResponseMetaJsonFormat: Format[Meta] = Format( - listResponseMetaJsonReads, - listResponseMetaJsonWrites - ) - - implicit def listResponseJsonWrites[T](implicit f: Writes[T]): Writes[ListResponse[T]] = - ( - (JsPath \ "items").write[Seq[T]] and - (JsPath \ "meta").write[Meta] - )(unlift(ListResponse.unapply[T])) - - implicit def listResponseJsonFormat[T](implicit f: Format[T]): Format[ListResponse[T]] = - ( - (JsPath \ "items").format(seqJsonFormat[T]) and - (JsPath \ "meta").format[Meta] - )(ListResponse.apply[T], unlift(ListResponse.unapply[T])) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm.scala new file mode 100644 index 0000000..0b54309 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm.scala @@ -0,0 +1,44 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities._ + +object arm { + import DefaultJsonProtocol._ + import common._ + + def applyUpdateToArm(json: JsValue, orig: Arm): Arm = json match { + case JsObject(fields) => + val name = fields + .get("name") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"Arm json object does not contain `name` field: $json")) + orig.copy(name = name) + + case _ => deserializationError(s"Expected Json Object as partial Arm, but got $json") + } + + implicit val armFormat: RootJsonFormat[Arm] = new RootJsonFormat[Arm] { + override def write(obj: Arm): JsValue = + JsObject( + "id" -> obj.id.toJson, + "name" -> obj.name.toJson, + "originalName" -> obj.originalName.toJson, + "trialId" -> obj.trialId.toJson + ) + + override def read(json: JsValue): Arm = json.asJsObject.getFields("trialId", "name") match { + case Seq(trialId, name) => + Arm( + id = LongId(0), + name = name.convertTo[String], + trialId = trialId.convertTo[StringId[Trial]], + originalName = name.convertTo[String] + ) + + case _ => deserializationError(s"Expected Json Object as Arm, but got $json") + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala deleted file mode 100644 index 32e2b54..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala +++ /dev/null @@ -1,35 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.arm - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.Arm -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiArm(id: Long, name: String, originalName: String, trialId: String) { - - def toDomain: Arm = Arm( - id = LongId(this.id), - name = this.name, - originalName = this.originalName, - trialId = StringId(this.trialId), - deleted = None // if we have an ApiArm object, the Arm itself has not been deleted - ) - -} - -object ApiArm { - - implicit val format: Format[ApiArm] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] and - (JsPath \ "originalName").format[String] and - (JsPath \ "trialId").format[String] - )(ApiArm.apply, unlift(ApiArm.unapply)) - - def fromDomain(arm: Arm): ApiArm = ApiArm( - id = arm.id.id, - name = arm.name, - originalName = arm.originalName, - trialId = arm.trialId.id - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiCreateArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiCreateArm.scala deleted file mode 100644 index 5168e94..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiCreateArm.scala +++ /dev/null @@ -1,20 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.arm - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.Arm -import play.api.libs.json.{Format, Json} - -final case class ApiCreateArm(name: String, trialId: String) { - - def toDomain = Arm( - id = LongId(0), - name = name, - trialId = StringId(trialId), - originalName = name - ) -} - -object ApiCreateArm { - - implicit val format: Format[ApiCreateArm] = Json.format[ApiCreateArm] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiPartialArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiPartialArm.scala deleted file mode 100644 index f85d7ff..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiPartialArm.scala +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.arm - -import xyz.driver.pdsuidomain.entities.Arm -import play.api.libs.json.{Format, Json} - -final case class ApiPartialArm(name: String) { - - def applyTo(arm: Arm): Arm = arm.copy(name = name) -} - -object ApiPartialArm { - - implicit val format: Format[ApiPartialArm] = Json.format -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/bridgeuploadqueue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/bridgeuploadqueue.scala new file mode 100644 index 0000000..6725a15 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/bridgeuploadqueue.scala @@ -0,0 +1,68 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue +import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue.Item + +object bridgeuploadqueue { + import DefaultJsonProtocol._ + import common._ + + implicit val queueUploadItemFormat: RootJsonFormat[BridgeUploadQueue.Item] = new RootJsonFormat[Item] { + override def write(obj: Item) = + JsObject( + "kind" -> obj.kind.toJson, + "tag" -> obj.tag.toJson, + "created" -> obj.created.toJson, + "attempts" -> obj.attempts.toJson, + "nextAttempt" -> obj.nextAttempt.toJson, + "completed" -> obj.completed.toJson + ) + + override def read(json: JsValue): Item = json match { + case JsObject(fields) => + val kind = fields + .get("kind") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"BridgeUploadQueue.Item json object does not contain `kind` field: $json")) + + val tag = fields + .get("tag") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"BridgeUploadQueue.Item json object does not contain `tag` field: $json")) + + val created = fields + .get("created") + .map(_.convertTo[LocalDateTime]) + .getOrElse( + deserializationError(s"BridgeUploadQueue.Item json object does not contain `created` field: $json")) + + val attempts = fields + .get("attempts") + .map(_.convertTo[Int]) + .getOrElse( + deserializationError(s"BridgeUploadQueue.Item json object does not contain `attempts` field: $json")) + + val nextAttempt = fields + .get("nextAttempt") + .map(_.convertTo[LocalDateTime]) + .getOrElse( + deserializationError(s"BridgeUploadQueue.Item json object does not contain `nextAttempt` field: $json")) + + BridgeUploadQueue.Item( + kind = kind, + tag = tag, + created = created, + attempts = attempts, + nextAttempt = nextAttempt, + completed = true, + dependencyKind = None, + dependencyTag = None + ) + + case _ => deserializationError(s"Expected Json Object as BridgeUploadQueue.Item, but got $json") + } + } +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/common.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/common.scala new file mode 100644 index 0000000..26adb9c --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/common.scala @@ -0,0 +1,66 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.{LocalDate, LocalDateTime, ZoneId, ZonedDateTime} + +import spray.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} + +object common { + + implicit def longIdFormat[T] = new RootJsonFormat[LongId[T]] { + override def write(id: LongId[T]): JsNumber = JsNumber(id.id) + override def read(json: JsValue): LongId[T] = json match { + case JsNumber(value) => LongId(value.toLong) + case _ => deserializationError(s"Expected number as LongId, but got $json") + } + } + + implicit def stringIdFormat[T] = new RootJsonFormat[StringId[T]] { + override def write(id: StringId[T]): JsString = JsString(id.toString) + override def read(json: JsValue): StringId[T] = json match { + case JsString(value) => StringId(value) + case _ => deserializationError(s"Expected string as StringId, but got $json") + } + } + + implicit def uuidIdFormat[T] = new RootJsonFormat[UuidId[T]] { + override def write(id: UuidId[T]): JsString = JsString(id.toString) + override def read(json: JsValue): UuidId[T] = json match { + case JsString(value) => UuidId(value) + case _ => deserializationError(s"Expected string as UuidId, but got $json") + } + } + + implicit def dateTimeFormat = new RootJsonFormat[LocalDateTime] { + override def write(date: LocalDateTime): JsString = JsString(ZonedDateTime.of(date, ZoneId.of("Z")).toString) + override def read(json: JsValue): LocalDateTime = json match { + case JsString(value) => ZonedDateTime.parse(value).toLocalDateTime + case _ => deserializationError(s"Expected date as LocalDateTime, but got $json") + } + } + + implicit def zonedDateTimeFormat = new RootJsonFormat[ZonedDateTime] { + override def write(date: ZonedDateTime): JsString = JsString(date.toString) + override def read(json: JsValue): ZonedDateTime = json match { + case JsString(value) => ZonedDateTime.parse(value) + case _ => deserializationError(s"Expected date as ZonedDateTime, but got $json") + } + } + + implicit def dateFormat = new RootJsonFormat[LocalDate] { + override def write(date: LocalDate): JsString = JsString(date.toString) + override def read(json: JsValue): LocalDate = json match { + case JsString(value) => LocalDate.parse(value) + case _ => deserializationError(s"Expected date as LocalDate, but got $json") + } + } + + implicit val integerFormat: RootJsonFormat[Integer] = new RootJsonFormat[Integer] { + override def write(obj: Integer): JsNumber = JsNumber(obj.intValue()) + override def read(json: JsValue): Integer = json match { + case JsNumber(value) => value.toInt + case _ => deserializationError(s"Expected number as Integer, but got $json") + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion.scala new file mode 100644 index 0000000..d7acfd4 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion.scala @@ -0,0 +1,171 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.entities.labels.{Label, LabelCategory} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities._ +import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion + +object criterion { + import DefaultJsonProtocol._ + import common._ + + implicit val criterionLabelWriter: RootJsonWriter[CriterionLabel] = new RootJsonWriter[CriterionLabel] { + override def write(obj: CriterionLabel) = JsObject( + "labelId" -> obj.labelId.toJson, + "categoryId" -> obj.categoryId.toJson, + "value" -> obj.value.map { + case true => "Yes" + case false => "No" + }.toJson, + "isDefining" -> obj.isDefining.toJson + ) + } + + def jsValueToCriterionLabel(json: JsValue, criterionId: LongId[Criterion]): CriterionLabel = json match { + case JsObject(fields) => + val labelId = fields + .get("labelId") + .flatMap(_.convertTo[Option[LongId[Label]]]) + + val categoryId = fields + .get("categoryId") + .flatMap(_.convertTo[Option[LongId[LabelCategory]]]) + + val value = fields + .get("value") + .flatMap(_.convertTo[Option[String]]) + .map { + case "Yes" => true + case "No" => false + case other => + deserializationError(s"Unknown `value` of CriterionLabel object: expected `yes` or `no`, but got $other") + } + + val isDefining = fields + .get("isDefining") + .map(_.convertTo[Boolean]) + .getOrElse(deserializationError(s"CriterionLabel json object does not contain `isDefining` field: $json")) + + CriterionLabel( + id = LongId(0L), + labelId = labelId, + criterionId = criterionId, + categoryId = categoryId, + value = value, + isDefining = isDefining + ) + + case _ => deserializationError(s"Expected Json Object as CriterionLabel, but got $json") + } + + def applyUpdateToCriterion(json: JsValue, orig: RichCriterion): RichCriterion = json match { + case JsObject(fields) => + val text = fields + .get("text") + .map(_.convertTo[String]) + + val isCompound = fields + .get("isCompound") + .exists(_.convertTo[Boolean]) + + val meta = fields + .get("meta") + .map(_.convertTo[Option[String]].getOrElse("{}")) + .getOrElse(orig.criterion.meta) + + val inclusion = fields + .get("inclusion") + .map(_.convertTo[Option[Boolean]]) + .getOrElse(orig.criterion.inclusion) + + val arms = fields + .get("arms") + .map(_.convertTo[Option[List[LongId[EligibilityArm]]]].getOrElse(List.empty[LongId[EligibilityArm]])) + .getOrElse(orig.armIds) + + val labels = fields + .get("labels") + .map(_.convertTo[Option[List[JsValue]]].getOrElse(List.empty[JsValue])) + .map(_.map(l => jsValueToCriterionLabel(l, orig.criterion.id))) + .getOrElse(orig.labels) + + orig.copy( + criterion = orig.criterion.copy( + meta = meta, + text = text, + isCompound = isCompound, + inclusion = inclusion + ), + armIds = arms, + labels = labels + ) + + case _ => deserializationError(s"Expected Json Object as partial Criterion, but got $json") + } + + implicit val richCriterionFormat: RootJsonFormat[RichCriterion] = new RootJsonFormat[RichCriterion] { + override def write(obj: RichCriterion): JsValue = + JsObject( + "id" -> obj.criterion.id.toJson, + "meta" -> Option(obj.criterion.meta).toJson, + "arms" -> obj.armIds.toJson, + "text" -> obj.criterion.text.toJson, + "isCompound" -> obj.criterion.isCompound.toJson, + "labels" -> obj.labels.map(_.toJson).toJson, + "trialId" -> obj.criterion.trialId.toJson, + "inclusion" -> obj.criterion.inclusion.toJson + ) + + override def read(json: JsValue): RichCriterion = json match { + case JsObject(fields) => + val trialId = fields + .get("trialId") + .map(_.convertTo[StringId[Trial]]) + .getOrElse(deserializationError(s"Criterion json object does not contain `trialId` field: $json")) + + val text = fields + .get("text") + .flatMap(_.convertTo[Option[String]]) + + val isCompound = fields + .get("isCompound") + .exists(_.convertTo[Boolean]) + + val meta = fields + .get("meta") + .flatMap(_.convertTo[Option[String]]) + + val inclusion = fields + .get("inclusion") + .flatMap(_.convertTo[Option[Boolean]]) + + val arms = fields + .get("arms") + .map(_.convertTo[Seq[LongId[EligibilityArm]]]) + .getOrElse(Seq.empty[LongId[EligibilityArm]]) + + val labels = fields + .get("labels") + .map(_.convertTo[Seq[JsValue]]) + .map(_.map(l => jsValueToCriterionLabel(l, LongId(0)))) + .getOrElse(Seq.empty[CriterionLabel]) + + RichCriterion( + criterion = Criterion( + id = LongId(0), + trialId = trialId, + text = text, + isCompound = isCompound, + meta = meta.getOrElse(""), + inclusion = inclusion + ), + armIds = arms, + labels = labels + ) + + case _ => deserializationError(s"Expected Json Object as Criterion, but got $json") + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiCriterion.scala deleted file mode 100644 index 239adb1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiCriterion.scala +++ /dev/null @@ -1,59 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.criterion - -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{EligibilityArm, Criterion, Trial} -import xyz.driver.pdsuidomain.formats.json.label.ApiCriterionLabel -import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion - -final case class ApiCriterion(id: Long, - meta: Option[String], - arms: Seq[Long], - text: Option[String], - isCompound: Boolean, - labels: Seq[ApiCriterionLabel], - trialId: String, - inclusion: Option[Boolean]) { - - def toDomain = RichCriterion( - criterion = Criterion( - id = LongId[Criterion](id), - trialId = StringId[Trial](trialId), - text, - isCompound, - meta.getOrElse(""), - inclusion - ), - armIds = arms.map(LongId[EligibilityArm]), - labels = labels.map(_.toDomain(LongId[Criterion](id))) - ) -} - -object ApiCriterion { - - implicit val format: Format[ApiCriterion] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "meta").formatNullable(Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) and - (JsPath \ "arms").format(seqJsonFormat[Long]) and - (JsPath \ "text").formatNullable[String] and - (JsPath \ "isCompound").format[Boolean] and - (JsPath \ "labels").format(seqJsonFormat[ApiCriterionLabel]) and - (JsPath \ "trialId").format[String] and - (JsPath \ "inclusion").formatNullable[Boolean] - )(ApiCriterion.apply, unlift(ApiCriterion.unapply)) - - def fromDomain(richCriterion: RichCriterion) = ApiCriterion( - id = richCriterion.criterion.id.id, - meta = Option(richCriterion.criterion.meta), - arms = richCriterion.armIds.map(_.id), - text = richCriterion.criterion.text, - isCompound = richCriterion.criterion.isCompound, - labels = richCriterion.labels.map(ApiCriterionLabel.fromDomain), - trialId = richCriterion.criterion.trialId.id, - inclusion = richCriterion.criterion.inclusion - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiNewCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiNewCriterion.scala deleted file mode 100644 index 4b85f83..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiNewCriterion.scala +++ /dev/null @@ -1,46 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.criterion - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import xyz.driver.pdsuidomain.entities._ -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuidomain.formats.json.label.ApiCriterionLabel -import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion - -final case class ApiNewCriterion(meta: Option[String], - arms: Option[Seq[Long]], - text: Option[String], - isCompound: Option[Boolean], - labels: Seq[ApiCriterionLabel], - trialId: String, - inclusion: Option[Boolean]) { - - def toDomain = RichCriterion( - criterion = Criterion( - id = LongId(0L), - meta = meta.getOrElse(""), - trialId = StringId(trialId), - isCompound = isCompound.getOrElse(false), - text = text, - inclusion = inclusion - ), - armIds = arms.getOrElse(Seq.empty).map(LongId[EligibilityArm]), - labels = labels.map(_.toDomain(LongId(Long.MaxValue))) // A developer should specify right criterionId himself - ) -} - -object ApiNewCriterion { - - implicit val format: Format[ApiNewCriterion] = ( - (JsPath \ "meta").formatNullable(Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) and - (JsPath \ "arms").formatNullable(seqJsonFormat[Long]) and - (JsPath \ "text").formatNullable[String] and - (JsPath \ "isCompound").formatNullable[Boolean] and - (JsPath \ "labels").format(seqJsonFormat[ApiCriterionLabel]) and - (JsPath \ "trialId").format[String] and - (JsPath \ "inclusion").formatNullable[Boolean] - )(ApiNewCriterion.apply, unlift(ApiNewCriterion.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiUpdateCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiUpdateCriterion.scala deleted file mode 100644 index a700309..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiUpdateCriterion.scala +++ /dev/null @@ -1,64 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.criterion - -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import xyz.driver.pdsuidomain.entities.{EligibilityArm, Criterion} -import org.davidbild.tristate._ -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuidomain.formats.json.label.ApiCriterionLabel -import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion - -final case class ApiUpdateCriterion(meta: Tristate[String], - arms: Tristate[Seq[Long]], - text: Option[String], - isCompound: Option[Boolean], - inclusion: Tristate[Boolean], - labels: Tristate[Seq[ApiCriterionLabel]]) { - - def applyTo(orig: RichCriterion): RichCriterion = RichCriterion( - criterion = applyTo(orig.criterion), - armIds = arms.cata(_.map(LongId[EligibilityArm]), Seq.empty, orig.armIds), - labels = labels.cata(_.map(_.toDomain(orig.criterion.id)), Seq.empty, orig.labels) - ) - - private def applyTo(orig: Criterion): Criterion = Criterion( - id = orig.id, - meta = meta.cata(identity, "{}", orig.meta), - text = text.orElse(orig.text), - isCompound = isCompound.getOrElse(orig.isCompound), - trialId = orig.trialId, - inclusion = inclusion.cata(x => Some(x), None, orig.inclusion) - ) -} - -object ApiUpdateCriterion { - - private val reads: Reads[ApiUpdateCriterion] = ( - (JsPath \ "meta") - .readTristate(Reads { x => - JsSuccess(Json.stringify(x)) - }) - .map { - case Tristate.Present("{}") => Tristate.Absent - case x => x - } and - (JsPath \ "arms").readTristate(seqJsonFormat[Long]) and - (JsPath \ "text").readNullable[String] and - (JsPath \ "isCompound").readNullable[Boolean] and - (JsPath \ "inclusion").readTristate[Boolean] and - (JsPath \ "labels").readTristate(seqJsonFormat[ApiCriterionLabel]) - )(ApiUpdateCriterion.apply _) - - private val writes: Writes[ApiUpdateCriterion] = ( - (JsPath \ "meta").writeTristate(Writes[String](Json.parse)) and - (JsPath \ "arms").writeTristate(seqJsonFormat[Long]) and - (JsPath \ "text").writeNullable[String] and - (JsPath \ "isCompound").writeNullable[Boolean] and - (JsPath \ "inclusion").writeTristate[Boolean] and - (JsPath \ "labels").writeTristate(seqJsonFormat[ApiCriterionLabel]) - )(unlift(ApiUpdateCriterion.unapply)) - - implicit val format: Format[ApiUpdateCriterion] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document.scala new file mode 100644 index 0000000..aaca391 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document.scala @@ -0,0 +1,197 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.{LocalDate, LocalDateTime} + +import spray.json._ +import xyz.driver.core.json.EnumJsonFormat +import xyz.driver.pdsuicommon.domain.{LongId, TextJson} +import xyz.driver.pdsuidomain.entities._ + +object document { + import DefaultJsonProtocol._ + import Document._ + import common._ + + implicit val documentStatusFormat = new EnumJsonFormat[Status]( + "New" -> Status.New, + "Organized" -> Status.Organized, + "Extracted" -> Status.Extracted, + "Done" -> Status.Done, + "Flagged" -> Status.Flagged, + "Archived" -> Status.Archived + ) + + implicit val requiredTypeFormat = new EnumJsonFormat[RequiredType]( + "OPN" -> RequiredType.OPN, + "PN" -> RequiredType.PN + ) + + implicit val documentMetaFormat: RootJsonFormat[Meta] = jsonFormat2(Meta.apply) + + implicit val documentTypeFormat: RootJsonFormat[DocumentType] = new RootJsonFormat[DocumentType] { + override def read(json: JsValue): DocumentType = json match { + case JsObject(fields) => + val name = fields + .get("name") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"Document type json object does not contain `name` field: $json")) + + DocumentType + .fromString(name) + .getOrElse(deserializationError(s"Unknown document type: $name")) + + case _ => deserializationError(s"Expected Json Object as Document type, but got $json") + } + + override def write(obj: DocumentType) = + JsObject("id" -> obj.id.toJson, "name" -> obj.name.toJson) + } + + implicit val fullDocumentMetaFormat = new RootJsonFormat[TextJson[Meta]] { + override def write(obj: TextJson[Meta]): JsValue = obj.content.toJson + override def read(json: JsValue) = TextJson(documentMetaFormat.read(json)) + } + + def applyUpdateToDocument(json: JsValue, orig: Document): Document = json match { + case JsObject(fields) => + val physician = fields + .get("physician") + .map(_.convertTo[String]) + + val typeId = fields + .get("typeId") + .map(_.convertTo[Option[LongId[DocumentType]]]) + .getOrElse(orig.typeId) + + val provider = fields + .get("provider") + .map(_.convertTo[Option[String]]) + .getOrElse(orig.providerName) + + val providerTypeId = fields + .get("providerTypeId") + .map(_.convertTo[Option[LongId[ProviderType]]]) + .getOrElse(orig.providerTypeId) + + val institutionName = fields + .get("institutionName") + .map(_.convertTo[Option[String]]) + .getOrElse(orig.institutionName) + + val meta = fields + .get("meta") + .map(_.convertTo[Option[TextJson[Meta]]]) + .getOrElse(orig.meta) + + val startDate = fields + .get("startDate") + .map(_.convertTo[Option[LocalDate]]) + .getOrElse(orig.startDate) + + val endDate = fields + .get("endDate") + .map(_.convertTo[Option[LocalDate]]) + .getOrElse(orig.endDate) + + orig.copy( + physician = physician.orElse(orig.physician), + typeId = typeId, + providerName = provider, + providerTypeId = providerTypeId, + institutionName = institutionName, + meta = meta, + startDate = startDate, + endDate = endDate + ) + + case _ => deserializationError(s"Expected Json Object as partial Document, but got $json") + } + + implicit val documentFormat: RootJsonFormat[Document] = new RootJsonFormat[Document] { + override def write(document: Document): JsValue = + JsObject( + "id" -> document.id.toJson, + "recordId" -> document.recordId.toJson, + "physician" -> document.physician.toJson, + "typeId" -> document.typeId.toJson, + "provider" -> document.providerName.toJson, + "providerTypeId" -> document.providerTypeId.toJson, + "requiredType" -> document.requiredType.toJson, + "institutionName" -> document.institutionName.toJson, + "startDate" -> document.startDate.toJson, + "endDate" -> document.endDate.toJson, + "status" -> document.status.toJson, + "previousStatus" -> document.previousStatus.toJson, + "assignee" -> document.assignee.toJson, + "previousAssignee" -> document.previousAssignee.toJson, + "meta" -> document.meta.toJson, + "lastActiveUser" -> document.lastActiveUserId.toJson, + "lastUpdate" -> document.lastUpdate.toJson, + "labelVersion" -> document.labelVersion.toJson + ) + + override def read(json: JsValue): Document = json match { + case JsObject(fields) => + val recordId = fields + .get("recordId") + .map(_.convertTo[LongId[MedicalRecord]]) + .getOrElse(deserializationError(s"Document create json object does not contain `recordId` field: $json")) + + val physician = fields + .get("physician") + .flatMap(_.convertTo[Option[String]]) + + val typeId = fields + .get("typeId") + .flatMap(_.convertTo[Option[LongId[DocumentType]]]) + + val provider = fields + .get("provider") + .flatMap(_.convertTo[Option[String]]) + + val providerTypeId = fields + .get("providerTypeId") + .flatMap(_.convertTo[Option[LongId[ProviderType]]]) + + val institutionName = fields + .get("institutionName") + .flatMap(_.convertTo[Option[String]]) + + val meta = fields + .get("meta") + .flatMap(_.convertTo[Option[TextJson[Meta]]]) + + val startDate = fields + .get("startDate") + .flatMap(_.convertTo[Option[LocalDate]]) + + val endDate = fields + .get("endDate") + .flatMap(_.convertTo[Option[LocalDate]]) + + Document( + id = LongId(0), + recordId = recordId, + status = Document.Status.New, + physician = physician, + typeId = typeId, + startDate = startDate, + endDate = endDate, + providerName = provider, + providerTypeId = providerTypeId, + requiredType = None, + institutionName = institutionName, + meta = meta, + previousStatus = None, + assignee = None, + previousAssignee = None, + lastActiveUserId = None, + lastUpdate = LocalDateTime.MIN, + labelVersion = 0 + ) + + case _ => deserializationError(s"Expected Json Object as Document, but got $json") + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala deleted file mode 100644 index 250e650..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala +++ /dev/null @@ -1,114 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.document - -import java.time.{LocalDate, ZoneId, ZonedDateTime} -import xyz.driver.pdsuicommon.domain.{LongId, StringId, TextJson} - -import xyz.driver.pdsuidomain.entities._ -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.json.JsonSerializer - -final case class ApiDocument(id: Long, - recordId: Long, - physician: Option[String], - lastUpdate: ZonedDateTime, - typeId: Option[Long], - startDate: Option[LocalDate], - endDate: Option[LocalDate], - provider: Option[String], - providerTypeId: Option[Long], - requiredType: Option[String], - institutionName: Option[String], - status: Option[String], - previousStatus: Option[String], - assignee: Option[String], - previousAssignee: Option[String], - lastActiveUser: Option[String], - meta: Option[String], - labelVersion: Int) { - - private def extractStatus(status: String): Document.Status = - Document.Status.fromString(status).getOrElse(throw new NoSuchElementException(s"Status $status unknown")) - - private def extractRequiredType(tpe: String): Document.RequiredType = - Document.RequiredType.fromString(tpe).getOrElse(throw new NoSuchElementException(s"RequitedType $tpe unknown")) - - def toDomain = Document( - id = LongId(this.id), - status = extractStatus(this.status.getOrElse("")), - previousStatus = previousStatus.map(extractStatus), - assignee = this.assignee.map(StringId(_)), - previousAssignee = this.previousAssignee.map(StringId(_)), - lastActiveUserId = this.lastActiveUser.map(StringId(_)), - recordId = LongId(this.recordId), - physician = this.physician, - typeId = this.typeId.map(LongId(_)), - providerName = this.provider, - providerTypeId = this.providerTypeId.map(LongId(_)), - requiredType = this.requiredType.map(extractRequiredType), - institutionName = this.institutionName, - meta = this.meta.map(x => TextJson(JsonSerializer.deserialize[Document.Meta](x))), - startDate = this.startDate, - endDate = this.endDate, - lastUpdate = this.lastUpdate.toLocalDateTime(), - labelVersion = this.labelVersion - ) - -} - -object ApiDocument { - - private val statusFormat = Format( - Reads.StringReads.filter(ValidationError("unknown status")) { x => - Document.Status.fromString(x).isDefined - }, - Writes.StringWrites - ) - - implicit val format: Format[ApiDocument] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "recordId").format[Long] and - (JsPath \ "physician").formatNullable[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "typeId").formatNullable[Long] and - (JsPath \ "startDate").formatNullable[LocalDate] and - (JsPath \ "endDate").formatNullable[LocalDate] and - (JsPath \ "provider").formatNullable[String] and - (JsPath \ "providerTypeId").formatNullable[Long] and - (JsPath \ "requiredType").formatNullable[String] and - (JsPath \ "institutionName").formatNullable[String] and - (JsPath \ "status").formatNullable(statusFormat) and - (JsPath \ "previousStatus").formatNullable(statusFormat) and - (JsPath \ "assignee").formatNullable[String] and - (JsPath \ "previousAssignee").formatNullable[String] and - (JsPath \ "lastActiveUser").formatNullable[String] and - (JsPath \ "meta").formatNullable(Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) and - (JsPath \ "labelVersion").format[Int] - )(ApiDocument.apply, unlift(ApiDocument.unapply)) - - def fromDomain(document: Document): ApiDocument = { - ApiDocument( - id = document.id.id, - recordId = document.recordId.id, - physician = document.physician, - lastUpdate = ZonedDateTime.of(document.lastUpdate, ZoneId.of("Z")), - typeId = document.typeId.map(_.id), - startDate = document.startDate, - endDate = document.endDate, - provider = document.providerName, - providerTypeId = document.providerTypeId.map(_.id), - requiredType = document.requiredType.map(Document.RequiredType.requiredTypeToString), - institutionName = document.institutionName, - status = Option(Document.Status.statusToString(document.status)), - previousStatus = document.previousStatus.map(Document.Status.statusToString), - assignee = document.assignee.map(_.id), - previousAssignee = document.previousAssignee.map(_.id), - lastActiveUser = document.lastActiveUserId.map(_.id), - meta = document.meta.map(meta => JsonSerializer.serialize(meta.content)), - labelVersion = document.labelVersion - ) - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala deleted file mode 100644 index 22bea6b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.document - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuidomain.entities.DocumentType - -final case class ApiDocumentType(id: Long, name: String) { - - def toDomain: DocumentType = - DocumentType - .fromString(name) - .getOrElse(throw new IllegalArgumentException(s"Unknown document type name $name")) - -} - -object ApiDocumentType { - - implicit val format: Format[ApiDocumentType] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] - )(ApiDocumentType.apply, unlift(ApiDocumentType.unapply)) - - def fromDomain(documentType: DocumentType) = ApiDocumentType( - id = documentType.id.id, - name = documentType.name - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala deleted file mode 100644 index ecbdaed..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala +++ /dev/null @@ -1,131 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.document - -import java.time.{LocalDate, LocalDateTime} - -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.data.validation._ -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, TextJson} -import xyz.driver.pdsuicommon.json.{JsonSerializer, JsonValidationException} -import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors} -import xyz.driver.pdsuidomain.entities.Document.Meta -import xyz.driver.pdsuidomain.entities._ - -import scala.collection.breakOut -import scala.util.Try - -final case class ApiPartialDocument(recordId: Option[Long], - physician: Option[String], - typeId: Tristate[Long], - startDate: Tristate[LocalDate], - endDate: Tristate[LocalDate], - provider: Tristate[String], - providerTypeId: Tristate[Long], - institutionName: Tristate[String], - status: Option[String], - assignee: Tristate[String], - meta: Tristate[String]) { - - import xyz.driver.pdsuicommon.domain.User - - def applyTo(orig: Document): Document = Document( - id = orig.id, - status = status.flatMap(Document.Status.fromString).getOrElse(orig.status), - previousStatus = orig.previousStatus, - assignee = assignee.map(StringId[User]).cata(Some(_), None, orig.assignee), - previousAssignee = orig.previousAssignee, - lastActiveUserId = orig.lastActiveUserId, - recordId = recordId.map(LongId[MedicalRecord]).getOrElse(orig.recordId), - physician = physician.orElse(orig.physician), - typeId = typeId.map(LongId[DocumentType]).cata(Some(_), None, orig.typeId), - providerName = provider.cata(Some(_), None, orig.providerName), - providerTypeId = providerTypeId.map(LongId[ProviderType]).cata(Some(_), None, orig.providerTypeId), - requiredType = orig.requiredType, - institutionName = institutionName.cata(Some(_), None, orig.institutionName), - meta = meta.cata(x => Some(TextJson(JsonSerializer.deserialize[Meta](x))), None, orig.meta), - startDate = startDate.cata(Some(_), None, orig.startDate), - endDate = endDate.cata(Some(_), None, orig.endDate), - lastUpdate = LocalDateTime.MIN, // Should update internally in a business logic module, - labelVersion = orig.labelVersion - ) - - def toDomain: Try[Document] = Try { - val validation = Map(JsPath \ "recordId" -> AdditionalConstraints.optionNonEmptyConstraint(recordId)) - - val validationErrors: JsonValidationErrors = validation.collect({ - case (fieldName, e: Invalid) => (fieldName, e.errors) - })(breakOut) - - if (validationErrors.isEmpty) { - Document( - id = LongId(0), - recordId = recordId.map(LongId[MedicalRecord]).get, - status = Document.Status.New, - physician = physician, - typeId = typeId.map(LongId[DocumentType]).toOption, - startDate = startDate.toOption, - endDate = endDate.toOption, - providerName = provider.toOption, - providerTypeId = providerTypeId.map(LongId[ProviderType]).toOption, - requiredType = None, - institutionName = institutionName.toOption, - meta = meta.map(x => TextJson(JsonSerializer.deserialize[Meta](x))).toOption, - previousStatus = None, - assignee = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.MIN, - labelVersion = 0 - ) - } else { - throw new JsonValidationException(validationErrors) - } - } -} - -object ApiPartialDocument { - - private val reads: Reads[ApiPartialDocument] = ( - (JsPath \ "recordId").readNullable[Long] and - (JsPath \ "physician").readNullable[String] and - (JsPath \ "typeId").readTristate[Long] and - (JsPath \ "startDate").readTristate[LocalDate] and - (JsPath \ "endDate").readTristate[LocalDate] and - (JsPath \ "provider").readTristate[String] and - (JsPath \ "providerTypeId").readTristate[Long] and - (JsPath \ "institutionName").readTristate[String] and - (JsPath \ "status").readNullable[String]( - Reads - .of[String] - .filter(ValidationError("unknown status"))( - Document.Status.fromString(_).isDefined - )) and - (JsPath \ "assignee").readTristate[String] and - (JsPath \ "meta") - .readTristate(Reads { x => - JsSuccess(Json.stringify(x)) - }) - .map { - case Tristate.Present("{}") => Tristate.Absent - case x => x - } - )(ApiPartialDocument.apply _) - - private val writes: Writes[ApiPartialDocument] = ( - (JsPath \ "recordId").writeNullable[Long] and - (JsPath \ "physician").writeNullable[String] and - (JsPath \ "typeId").writeTristate[Long] and - (JsPath \ "startDate").writeTristate[LocalDate] and - (JsPath \ "endDate").writeTristate[LocalDate] and - (JsPath \ "provider").writeTristate[String] and - (JsPath \ "providerTypeId").writeTristate[Long] and - (JsPath \ "institutionName").writeTristate[String] and - (JsPath \ "status").writeNullable[String] and - (JsPath \ "assignee").writeTristate[String] and - (JsPath \ "meta").writeTristate(Writes[String](Json.parse)) - )(unlift(ApiPartialDocument.unapply)) - - implicit val format: Format[ApiPartialDocument] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala deleted file mode 100644 index 9c0c216..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.document - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuidomain.entities.ProviderType - -final case class ApiProviderType(id: Long, name: String) { - - def toDomain: ProviderType = - ProviderType - .fromString(name) - .getOrElse(throw new IllegalArgumentException(s"Unknown provider type name $name")) - -} - -object ApiProviderType { - - implicit val format: Format[ApiProviderType] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] - )(ApiProviderType.apply, unlift(ApiProviderType.unapply)) - - def fromDomain(providerType: ProviderType) = ApiProviderType( - id = providerType.id.id, - name = providerType.name - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory.scala new file mode 100644 index 0000000..a0eb3f5 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory.scala @@ -0,0 +1,29 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.core.json.EnumJsonFormat +import xyz.driver.pdsuidomain.entities._ + +object documenthistory { + import DefaultJsonProtocol._ + import DocumentHistory._ + import common._ + + implicit val documentStateFormat = new EnumJsonFormat[State]( + "Extract" -> State.Extract, + "Review" -> State.Review, + "Flag" -> State.Flag + ) + + implicit val documentActionFormat = new EnumJsonFormat[Action]( + "Start" -> Action.Start, + "Submit" -> Action.Submit, + "Unassign" -> Action.Unassign, + "Resolve" -> Action.Resolve, + "Flag" -> Action.Flag, + "Archive" -> Action.Archive + ) + + implicit val documentHistoryFormat: RootJsonFormat[DocumentHistory] = jsonFormat6(DocumentHistory.apply) + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory/ApiDocumentHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory/ApiDocumentHistory.scala deleted file mode 100644 index 5aae774..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory/ApiDocumentHistory.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.documenthistory - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.json.{Format, Json} -import xyz.driver.pdsuidomain.entities.DocumentHistory - -final case class ApiDocumentHistory(id: Long, - executor: String, - documentId: Long, - state: String, - action: String, - created: ZonedDateTime) - -object ApiDocumentHistory { - implicit val format: Format[ApiDocumentHistory] = - Json.format[ApiDocumentHistory] - - def fromDomain(x: DocumentHistory) = ApiDocumentHistory( - id = x.id.id, - executor = x.executor.id, - documentId = x.documentId.id, - state = DocumentHistory.State.stateToString(x.state), - action = DocumentHistory.Action.actionToString(x.action), - created = ZonedDateTime.of(x.created, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue.scala new file mode 100644 index 0000000..082fa83 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue.scala @@ -0,0 +1,66 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} +import xyz.driver.pdsuidomain.entities._ + +object documentissue { + import DefaultJsonProtocol._ + import common._ + + def applyUpdateToDocumentIssue(json: JsValue, orig: DocumentIssue): DocumentIssue = json match { + case JsObject(fields) => + val text = fields + .get("text") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"DocumentIssue json object does not contain `text` field: $json")) + + val archiveRequired = fields + .get("archiveRequired") + .map(_.convertTo[Boolean]) + .getOrElse(deserializationError(s"DocumentIssue json object does not contain `archiveRequired` field: $json")) + + val startPage = fields.get("startPage").map(_.convertTo[Double]) + val endPage = fields.get("endPage").map(_.convertTo[Double]) + + orig.copy( + text = text, + archiveRequired = archiveRequired, + startPage = startPage, + endPage = endPage + ) + + case _ => deserializationError(s"Expected Json Object as partial DocumentIssue, but got $json") + + } + + def jsValueToDocumentIssue(json: JsValue, documentId: LongId[Document], userId: StringId[User]): DocumentIssue = + json match { + case JsObject(fields) => + val text = fields + .get("text") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"DocumentIssue json object does not contain `text` field: $json")) + + val startPage = fields.get("startPage").map(_.convertTo[Double]) + val endPage = fields.get("endPage").map(_.convertTo[Double]) + DocumentIssue( + id = LongId(0), + userId = userId, + documentId = documentId, + lastUpdate = LocalDateTime.MIN, + isDraft = true, + text = text, + archiveRequired = false, + startPage = startPage, + endPage = endPage + ) + + case _ => deserializationError(s"Expected Json Object as DocumentIssue, but got $json") + } + + implicit val documentIssueFormat: RootJsonFormat[DocumentIssue] = jsonFormat9(DocumentIssue.apply) + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala deleted file mode 100644 index f157bb2..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala +++ /dev/null @@ -1,40 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.documentissue - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuidomain.entities.DocumentIssue - -final case class ApiDocumentIssue(id: Long, - startPage: Option[Double], - endPage: Option[Double], - text: String, - lastUpdate: ZonedDateTime, - userId: String, - isDraft: Boolean, - archiveRequired: Boolean) - -object ApiDocumentIssue { - implicit val format: Format[ApiDocumentIssue] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "text").format[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "userId").format[String] and - (JsPath \ "isDraft").format[Boolean] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiDocumentIssue.apply, unlift(ApiDocumentIssue.unapply)) - - def fromDomain(x: DocumentIssue) = ApiDocumentIssue( - id = x.id.id, - startPage = x.startPage, - endPage = x.endPage, - text = x.text, - lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), - userId = x.userId.id, - isDraft = x.isDraft, - archiveRequired = x.archiveRequired - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala deleted file mode 100644 index c29b703..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala +++ /dev/null @@ -1,42 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.documentissue - -import java.time.LocalDateTime - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities.{Document, DocumentIssue} - -final case class ApiPartialDocumentIssue(startPage: Option[Double], - endPage: Option[Double], - text: String, - archiveRequired: Boolean) { - def applyTo(x: DocumentIssue): DocumentIssue = x.copy( - startPage = startPage, - endPage = endPage, - text = text, - archiveRequired = archiveRequired - ) - - def toDomain(userId: StringId[User], documentId: LongId[Document]) = - DocumentIssue( - id = LongId(0), - userId = userId, - documentId = documentId, - startPage = startPage, - endPage = endPage, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - archiveRequired = false - ) -} - -object ApiPartialDocumentIssue { - implicit val format: Format[ApiPartialDocumentIssue] = ( - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "text").format[String] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiPartialDocumentIssue.apply, unlift(ApiPartialDocumentIssue.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibility.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibility.scala new file mode 100644 index 0000000..571cbde --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibility.scala @@ -0,0 +1,103 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json.DefaultJsonProtocol._ +import spray.json._ +import DefaultJsonProtocol._ +import xyz.driver.core.Id +import xyz.driver.core.json._ +import xyz.driver.entities.labels.LabelValue +import xyz.driver.pdsuidomain.entities.eligibility._ + +object eligibility { + import export._ + import xyz.driver.formats.json.assay._ + import xyz.driver.formats.json.common._ + import xyz.driver.formats.json.labels._ + import xyz.driver.formats.json.process._ + import xyz.driver.pdsuidomain.formats.json.document._ + import xyz.driver.pdsuidomain.formats.json.record._ + import xyz.driver.pdsuidomain.formats.json.export._ + + implicit val molecularDocumentFormat: RootJsonFormat[MolecularEvidenceDocument] = jsonFormat7( + MolecularEvidenceDocument) + implicit val clinicalDocumentFormat: RootJsonFormat[ClinicalEvidenceDocument] = jsonFormat7(ClinicalEvidenceDocument) + + implicit val evidenceDocumentFormat: RootJsonFormat[EvidenceDocument] = + GadtJsonFormat.create[EvidenceDocument]("evidenceDocumentType") { + case _: MolecularEvidenceDocument => "Molecular" + case _: ClinicalEvidenceDocument => "Clinical" + } { + case "Molecular" => molecularDocumentFormat + case "Clinical" => clinicalDocumentFormat + } + + implicit object evidenceFormat extends RootJsonFormat[Evidence] { + + override def write(evidence: Evidence): JsValue = { + JsObject( + "evidenceId" -> evidence.evidenceId.toJson, + "evidenceText" -> evidence.evidenceText.toJson, + "labelValue" -> evidence.labelValue.toJson, + "document" -> evidence.document.toJson, + "isPrimaryValue" -> evidence.isPrimaryValue.toJson + ) + } + + override def read(json: JsValue): Evidence = { + json match { + case JsObject(fields) => + val evidenceId = fields + .get("evidenceId") + .map(_.convertTo[Id[Evidence]]) + + val evidenceText = fields + .get("evidenceText") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"Evidence json object do not contain 'evidenceText' field: $json")) + + val labelValue = fields + .get("labelValue") + .map(_.convertTo[LabelValue]) + .getOrElse(deserializationError(s"Evidence json object do not contain 'labelValue' field: $json")) + + val isDriverDocument = fields + .get("document") + .flatMap { + case JsObject(fieldMap) => + fieldMap + .get("isDriverDocument") + .map(_.convertTo[Boolean]) + case _ => deserializationError(s"Expected Json Object as 'isDriverDocument', but got $json") + } + .getOrElse(deserializationError(s"Evidence json object do not contain 'document' field: $json")) + + val document = customDocumentParser(isDriverDocument, fields, json) + + val isPrimaryValue = fields + .get("isPrimaryValue") + .map(_.convertTo[Option[Boolean]]) + .getOrElse(deserializationError(s"Evidence json object do not contain 'isPrimaryValue' field: $json")) + + Evidence(evidenceId, evidenceText, labelValue, document, isPrimaryValue) + case _ => deserializationError(s"Expected Json Object as 'Evidence', but got $json") + } + } + + def customDocumentParser(isDriverDocument: Boolean, + fields: Map[String, JsValue], + json: JsValue): EvidenceDocument = { + fields.get("document").fold { deserializationError(s"Expected Json Object as 'Document', but got $json") } { + document => + if (isDriverDocument) document.convertTo[MolecularEvidenceDocument] + else document.convertTo[ClinicalEvidenceDocument] + } + } + } + + implicit def labelWithEvidenceJsonFormat: RootJsonFormat[LabelEvidence] = jsonFormat2(LabelEvidence) + + implicit def labelRankingFormat: RootJsonFormat[LabelMismatchRank] = jsonFormat4(LabelMismatchRank) + implicit def labelRankingsFormat: RootJsonFormat[MismatchRankedLabels] = jsonFormat2(MismatchRankedLabels) + + implicit def matchedPatientFormat: RootJsonFormat[MatchedPatient] = jsonFormat6(MatchedPatient) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm.scala new file mode 100644 index 0000000..f31e6bd --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm.scala @@ -0,0 +1,108 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.entities.patient.CancerType +import xyz.driver.formats.json.patient._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities._ + +object eligibilityarm { + + import DefaultJsonProtocol._ + import common._ + + private def deserializationErrorFieldMessage(field: String, json: JsValue)(implicit className: String) = { + deserializationError(s"$className json object do not contain '$field' field: $json") + } + + private def deserializationErrorEntityMessage(json: JsValue)(implicit className: String) = { + deserializationError(s"Expected Json Object as $className, but got $json") + } + + implicit def eligibilityArmWithDiseasesWriter: RootJsonWriter[EligibilityArmWithDiseases] = + new RootJsonWriter[EligibilityArmWithDiseases] { + override def write(obj: EligibilityArmWithDiseases): JsValue = { + JsObject( + "id" -> obj.eligibilityArm.id.toJson, + "name" -> obj.eligibilityArm.name.toJson, + "originalName" -> obj.eligibilityArm.originalName.toJson, + "trialId" -> obj.eligibilityArm.trialId.toJson, + "diseases" -> obj.eligibilityArmDiseases.map(_.disease.toJson).toJson + ) + } + } + + implicit def eligibilityArmWithDiseasesReader: RootJsonReader[EligibilityArmWithDiseases] = { + new RootJsonReader[EligibilityArmWithDiseases] { + implicit val className: String = "create EligibilityArmWithDiseases" + + override def read(json: JsValue): EligibilityArmWithDiseases = { + json match { + case JsObject(fields) => + val name = fields + .get("name") + .map(_.convertTo[String]) + .getOrElse(deserializationErrorFieldMessage("name", json)) + + val trialId = fields + .get("trialId") + .map(_.convertTo[StringId[Trial]]) + .getOrElse(deserializationErrorFieldMessage("trialId", json)) + + val diseases = fields + .get("diseases") + .map(_.convertTo[Seq[String]]) + .getOrElse(deserializationErrorFieldMessage("diseases", json)) + + val eligibilityArm = EligibilityArm( + id = LongId(0), + name = name, + trialId = trialId, + originalName = name + ) + + EligibilityArmWithDiseases( + eligibilityArm, + diseases.map { disease => + val condition = CancerType + .fromString(disease) + .getOrElse(throw new NoSuchElementException(s"unknown condition $disease")) + EligibilityArmDisease(eligibilityArm.id, condition) + } + ) + case _ => deserializationErrorEntityMessage(json) + } + } + } + } + + def applyUpdateToEligibilityArmWithDiseases(json: JsValue, + orig: EligibilityArmWithDiseases): EligibilityArmWithDiseases = { + implicit val className: String = "update EligibilityArmWithDiseases" + json match { + case JsObject(fields) => + val name = fields + .get("name") + .map(_.convertTo[String]) + .getOrElse(orig.eligibilityArm.name) + + val diseases = fields + .get("diseases") + .map(_.convertTo[Seq[CancerType]]) + .getOrElse(orig.eligibilityArmDiseases.map(_.disease)) + + orig.copy( + eligibilityArm = orig.eligibilityArm + .copy(name = name), + eligibilityArmDiseases = orig.eligibilityArmDiseases + .zip(diseases) + .map { + case (eligibilityArmDisease, disease) => + eligibilityArmDisease.copy(disease = disease) + } + ) + + case _ => deserializationErrorEntityMessage(json) + } + } +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiCreateEligibilityArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiCreateEligibilityArm.scala deleted file mode 100644 index 087fed5..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiCreateEligibilityArm.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.eligibilityarm - -import play.api.libs.json.{Format, Json} -import xyz.driver.entities.patient.CancerType -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{EligibilityArm, EligibilityArmDisease, EligibilityArmWithDiseases} - -final case class ApiCreateEligibilityArm(name: String, trialId: String, diseases: Seq[String]) { - - def toDomain: EligibilityArmWithDiseases = { - val eligibilityArm = EligibilityArm( - id = LongId(0), - name = name, - trialId = StringId(trialId), - originalName = name - ) - - EligibilityArmWithDiseases( - eligibilityArm, - diseases.map { disease => - val condition = CancerType - .fromString(disease) - .getOrElse(throw new NoSuchElementException(s"unknown condition $disease")) - EligibilityArmDisease(eligibilityArm.id, condition) - } - ) - } -} - -object ApiCreateEligibilityArm { - - implicit val format: Format[ApiCreateEligibilityArm] = Json.format[ApiCreateEligibilityArm] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiEligibilityArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiEligibilityArm.scala deleted file mode 100644 index 71423e8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiEligibilityArm.scala +++ /dev/null @@ -1,57 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.eligibilityarm - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.entities.patient.CancerType -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{EligibilityArm, EligibilityArmDisease, EligibilityArmWithDiseases} - -final case class ApiEligibilityArm(id: Long, - name: String, - originalName: String, - trialId: String, - diseases: Seq[String]) { - - def toDomain: EligibilityArmWithDiseases = { - val eligibilityArm = EligibilityArm( - id = LongId(this.id), - name = this.name, - originalName = this.originalName, - trialId = StringId(this.trialId), - deleted = None // if we have an ApiEligibilityArm object, the EligibilityArm itself has not been deleted - ) - - EligibilityArmWithDiseases( - eligibilityArm, - this.diseases.map { disease => - val condition = CancerType - .fromString(disease) - .getOrElse(throw new NoSuchElementException(s"unknown condition $disease")) - EligibilityArmDisease(eligibilityArm.id, condition) - } - ) - } -} - -object ApiEligibilityArm { - - implicit val format: Format[ApiEligibilityArm] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] and - (JsPath \ "originalName").format[String] and - (JsPath \ "trialId").format[String] and - (JsPath \ "diseases").format[Seq[String]] - )(ApiEligibilityArm.apply, unlift(ApiEligibilityArm.unapply)) - - def fromDomain(eligibilityArmWithDiseases: EligibilityArmWithDiseases): ApiEligibilityArm = { - import eligibilityArmWithDiseases.{eligibilityArm, eligibilityArmDiseases} - - ApiEligibilityArm( - id = eligibilityArm.id.id, - name = eligibilityArm.name, - originalName = eligibilityArm.originalName, - trialId = eligibilityArm.trialId.id, - diseases = eligibilityArmDiseases.map(_.disease.toString) - ) - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiPartialEligibilityArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiPartialEligibilityArm.scala deleted file mode 100644 index aca22ef..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/eligibilityarm/ApiPartialEligibilityArm.scala +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.eligibilityarm - -import play.api.libs.json.{Format, Json} -import xyz.driver.entities.patient.CancerType -import xyz.driver.pdsuidomain.entities.{EligibilityArmDisease, EligibilityArmWithDiseases} - -final case class ApiPartialEligibilityArm(name: String, diseases: Seq[String]) { - - def applyTo(armWithDisease: EligibilityArmWithDiseases): EligibilityArmWithDiseases = { - val arm = armWithDisease.eligibilityArm.copy(name = name) - val armDiseases = diseases.map { disease => - EligibilityArmDisease( - armWithDisease.eligibilityArm.id, - CancerType.fromString(disease).getOrElse(throw new NoSuchElementException(s"unknown condition $disease"))) - } - EligibilityArmWithDiseases(arm, armDiseases) - } -} - -object ApiPartialEligibilityArm { - - implicit val format: Format[ApiPartialEligibilityArm] = Json.format -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/evidence/ApiPatientLabelEvidence.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/evidence/ApiPatientLabelEvidence.scala deleted file mode 100644 index c7a6de9..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/evidence/ApiPatientLabelEvidence.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.evidence - -import java.time.LocalDate - -import play.api.libs.json._ -import xyz.driver.pdsuidomain.entities.PatientLabelEvidenceView - -final case class ApiPatientLabelEvidence(id: Long, - value: String, - evidenceText: String, - documentId: Option[Long], - evidenceId: Option[Long], - reportId: Option[String], - documentType: String, - date: LocalDate, - providerType: String) - -object ApiPatientLabelEvidence { - - implicit val format: Format[ApiPatientLabelEvidence] = Json.format - - def fromDomain(x: PatientLabelEvidenceView) = ApiPatientLabelEvidence( - id = x.id.id, - value = x.value.toString, - evidenceText = x.evidenceText, - documentId = x.documentId.map(_.id), - evidenceId = x.evidenceId.map(_.id), - reportId = x.reportId.map(_.toString), - documentType = x.documentType.name, - date = x.date.get, - providerType = x.providerType.name - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/export.scala new file mode 100644 index 0000000..6b72cb8 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/export.scala @@ -0,0 +1,86 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.entities.labels.Label +import xyz.driver.formats.json.labels._ +import xyz.driver.pdsuidomain.entities.export.patient._ +import xyz.driver.pdsuidomain.entities.export.trial.{ExportTrialArm, ExportTrialLabelCriterion, ExportTrialWithLabels} +import xyz.driver.pdsuidomain.entities.{Criterion, EligibilityArm} + +object export { + import DefaultJsonProtocol._ + import common._ + import document._ + import record._ + + implicit val patientLabelEvidenceDocumentFormat: RootJsonFormat[ExportPatientLabelEvidenceDocument] = + jsonFormat5(ExportPatientLabelEvidenceDocument.apply) + + implicit val patientLabelEvidenceFormat: RootJsonFormat[ExportPatientLabelEvidence] = + jsonFormat(ExportPatientLabelEvidence.apply, "evidenceId", "labelValue", "evidenceText", "document") + + implicit val patientLabelFormat: RootJsonFormat[ExportPatientLabel] = + jsonFormat(ExportPatientLabel.apply, "labelId", "evidence") + + implicit val patientWithLabelsFormat: RootJsonFormat[ExportPatientWithLabels] = + jsonFormat(ExportPatientWithLabels.apply, "patientId", "labelVersion", "labels") + + implicit val trialArmFormat: RootJsonFormat[ExportTrialArm] = jsonFormat3(ExportTrialArm.apply) + + implicit val trialLabelCriterionFormat: RootJsonFormat[ExportTrialLabelCriterion] = + new RootJsonFormat[ExportTrialLabelCriterion] { + override def write(obj: ExportTrialLabelCriterion): JsValue = + JsObject( + "value" -> obj.value + .map { + case true => "Yes" + case false => "No" + } + .getOrElse("Unknown") + .toJson, + "labelId" -> obj.labelId.toJson, + "criterionId" -> obj.criterionId.toJson, + "criterionText" -> obj.criteria.toJson, + "armIds" -> obj.armIds.toJson, + "isCompound" -> obj.isCompound.toJson, + "isDefining" -> obj.isDefining.toJson + ) + + override def read(json: JsValue): ExportTrialLabelCriterion = { + + val fields = Seq("value", "labelId", "criterionId", "criterionText", "armIds", "isCompound", "isDefining") + + json.asJsObject.getFields(fields: _*) match { + case Seq(JsString(valueString), + labelId, + criterionId, + JsString(criterionText), + JsArray(armIdsVector), + JsBoolean(isCompound), + JsBoolean(isDefining)) => + val value = valueString match { + case "Yes" => Option(true) + case "No" => Option(false) + case "Unknown" => Option.empty[Boolean] + } + + ExportTrialLabelCriterion( + longIdFormat[Criterion].read(criterionId), + value, + longIdFormat[Label].read(labelId), + armIdsVector.map(longIdFormat[EligibilityArm].read).toSet, + criterionText, + isCompound, + isDefining + ) + + case _ => + deserializationError( + s"Cannot find required fields ${fields.mkString(", ")} in ExportTrialLabelCriterion object!") + } + } + } + + implicit val trialWithLabelsFormat: RootJsonFormat[ExportTrialWithLabels] = + jsonFormat(ExportTrialWithLabels.apply, "nctId", "trialId", "lastReviewed", "labelVersion", "arms", "criteria") +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata.scala new file mode 100644 index 0000000..c9ac55b --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata.scala @@ -0,0 +1,150 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.entities.labels.{Label, LabelCategory, LabelValue} +import xyz.driver.formats.json.labels._ +import xyz.driver.pdsuicommon.domain.{LongId, TextJson} +import xyz.driver.pdsuidomain.entities._ +import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData + +object extracteddata { + import DefaultJsonProtocol._ + import ExtractedData._ + import common._ + + implicit val metaKeywordFormat: RootJsonFormat[Meta.Keyword] = jsonFormat4(Meta.Keyword) + implicit val metaTextLayerPositionFormat: RootJsonFormat[Meta.TextLayerPosition] = jsonFormat3( + Meta.TextLayerPosition) + implicit val metaEvidenceFormat: RootJsonFormat[Meta.Evidence] = jsonFormat3(Meta.Evidence) + + implicit val extractedDataMetaFormat: RootJsonFormat[Meta] = jsonFormat2(Meta.apply) + implicit val fullExtractedDataMetaFormat = new RootJsonFormat[TextJson[Meta]] { + override def write(obj: TextJson[Meta]): JsValue = obj.content.toJson + override def read(json: JsValue): TextJson[Meta] = TextJson(extractedDataMetaFormat.read(json)) + } + + implicit val extractedDataLabelWriter: JsonWriter[ExtractedDataLabel] = new JsonWriter[ExtractedDataLabel] { + override def write(label: ExtractedDataLabel): JsObject = { + JsObject( + "id" -> label.labelId.toJson, + "categoryId" -> label.categoryId.toJson, + "value" -> label.value.toJson + ) + } + } + + def applyLabelsForExtractedData(json: JsValue, dataId: LongId[ExtractedData]): ExtractedDataLabel = json match { + case JsObject(fields) => + val labelId = fields + .get("id") + .flatMap(_.convertTo[Option[LongId[Label]]]) + + val categoryId = fields + .get("categoryId") + .flatMap(_.convertTo[Option[LongId[LabelCategory]]]) + + val value = fields + .get("value") + .flatMap(_.convertTo[Option[LabelValue]]) + + ExtractedDataLabel( + id = LongId(0), + dataId = dataId, + labelId = labelId, + categoryId = categoryId, + value = value + ) + + case _ => deserializationError(s"Expected Json Object as ExtractedDataLabel, but got $json") + } + + def applyUpdateToExtractedData(json: JsValue, orig: RichExtractedData): RichExtractedData = json match { + case JsObject(fields) => + val keywordId = fields + .get("keywordId") + .map(_.convertTo[Option[LongId[Keyword]]]) + .getOrElse(orig.extractedData.keywordId) + + val evidence = fields + .get("evidence") + .map(_.convertTo[Option[String]]) + .getOrElse(orig.extractedData.evidenceText) + + val meta = fields + .get("meta") + .map(_.convertTo[Option[TextJson[Meta]]]) + .getOrElse(orig.extractedData.meta) + + val labels = fields + .get("labels") + .map( + _.convertTo[Option[List[JsValue]]] + .getOrElse(List.empty[JsValue]) + .map(l => applyLabelsForExtractedData(l, orig.extractedData.id))) + .getOrElse(orig.labels) + + val extractedData = orig.extractedData.copy( + keywordId = keywordId, + evidenceText = evidence, + meta = meta + ) + + orig.copy( + extractedData = extractedData, + labels = labels + ) + + case _ => deserializationError(s"Expected Json Object as partial ExtractedData, but got $json") + } + + implicit val extractedDataFormat: RootJsonFormat[RichExtractedData] = new RootJsonFormat[RichExtractedData] { + override def write(richData: RichExtractedData): JsValue = + JsObject( + "id" -> richData.extractedData.id.toJson, + "documentId" -> richData.extractedData.documentId.toJson, + "keywordId" -> richData.extractedData.keywordId.toJson, + "evidence" -> richData.extractedData.evidenceText.toJson, + "meta" -> richData.extractedData.meta.toJson, + "labels" -> richData.labels.map(_.toJson).toJson + ) + + override def read(json: JsValue): RichExtractedData = json match { + case JsObject(fields) => + val documentId = fields + .get("documentId") + .map(_.convertTo[LongId[Document]]) + .getOrElse( + deserializationError(s"ExtractedData create json object does not contain `documentId` field: $json")) + + val keywordId = fields + .get("keywordId") + .flatMap(_.convertTo[Option[LongId[Keyword]]]) + + val evidence = fields + .get("evidence") + .flatMap(_.convertTo[Option[String]]) + + val meta = fields + .get("meta") + .flatMap(_.convertTo[Option[TextJson[Meta]]]) + + val labels = fields + .get("labels") + .map(_.convertTo[List[JsValue]]) + .getOrElse(List.empty[JsValue]) + .map(l => applyLabelsForExtractedData(l, LongId(0))) + + val extractedData = ExtractedData( + documentId = documentId, + keywordId = keywordId, + evidenceText = evidence, + meta = meta + ) + + RichExtractedData(extractedData, labels) + + case _ => deserializationError(s"Expected Json Object as ExtractedData, but got $json") + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala deleted file mode 100644 index 4182c8d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala +++ /dev/null @@ -1,64 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.extracteddata - -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities.ExtractedData -import xyz.driver.pdsuidomain.formats.json.label.ApiExtractedDataLabel -import play.api.libs.json._ -import play.api.data.validation._ -import play.api.libs.functional.syntax._ -import xyz.driver.pdsuicommon.json.JsonSerializer -import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData - -// The specification: https://driverinc.atlassian.net/wiki/pages/viewpage.action?pageId=33423387 -// Note, that there is "Extracted data object or Temporary extracted data object" in specification -// ApiExtractedData represents both types -final case class ApiExtractedData(id: Long, - documentId: Long, - keywordId: Option[Long], - evidence: Option[String], - meta: Option[String], - // An empty list and no-existent list are different cases - labels: Option[List[ApiExtractedDataLabel]]) { - - def toDomain = RichExtractedData( - extractedData = ExtractedData( - id = LongId(this.id), - documentId = LongId(this.documentId), - keywordId = this.keywordId.map(LongId(_)), - evidenceText = this.evidence, - meta = this.meta.map(x => TextJson(JsonSerializer.deserialize[ExtractedData.Meta](x))) - ), - labels = labels.getOrElse(List.empty).map(_.toDomain()) - ) - -} - -object ApiExtractedData { - - implicit val format: Format[ApiExtractedData] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "documentId").format[Long] and - (JsPath \ "keywordId").formatNullable[Long] and - (JsPath \ "evidence").formatNullable[String] and - (JsPath \ "meta").formatNullable[String] and - (JsPath \ "labels").formatNullable[List[ApiExtractedDataLabel]]( - Format( - Reads - .of[List[ApiExtractedDataLabel]] - .filter(ValidationError("empty labels"))({ - case x if x.nonEmpty => true - case _ => false - }), - Writes.of[List[ApiExtractedDataLabel]] - )) - )(ApiExtractedData.apply, unlift(ApiExtractedData.unapply)) - - def fromDomain(extractedDataWithLabels: RichExtractedData) = ApiExtractedData( - id = extractedDataWithLabels.extractedData.id.id, - documentId = extractedDataWithLabels.extractedData.documentId.id, - keywordId = extractedDataWithLabels.extractedData.keywordId.map(_.id), - evidence = extractedDataWithLabels.extractedData.evidenceText, - meta = extractedDataWithLabels.extractedData.meta.map(x => JsonSerializer.serialize(x.content)), - labels = Option(extractedDataWithLabels.labels.map(ApiExtractedDataLabel.fromDomain)) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala deleted file mode 100644 index cfd55fd..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala +++ /dev/null @@ -1,80 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.extracteddata - -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities.ExtractedData.Meta -import xyz.driver.pdsuidomain.entities._ -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.data.validation._ -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.json.{JsonSerializer, JsonValidationException} -import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors} -import xyz.driver.pdsuidomain.formats.json.label.ApiExtractedDataLabel -import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData - -import scala.collection._ - -final case class ApiPartialExtractedData(documentId: Option[Long], - keywordId: Option[Long], - evidence: Tristate[String], - meta: Tristate[String], - labels: Tristate[List[ApiExtractedDataLabel]]) { - - def applyTo(orig: RichExtractedData): RichExtractedData = RichExtractedData( - extractedData = applyTo(orig.extractedData), - labels = labels.cata(_.map(_.toDomain(orig.extractedData.id)), List.empty, orig.labels) - ) - - private def applyTo(orig: ExtractedData): ExtractedData = ExtractedData( - id = orig.id, - documentId = orig.documentId, - keywordId = keywordId.map(LongId[Keyword]).orElse(orig.keywordId), - evidenceText = evidence.cata(Some(_), None, orig.evidenceText), - meta = meta.map(x => TextJson(JsonSerializer.deserialize[Meta](x))).cata(Some(_), None, orig.meta) - ) - - def toDomain: RichExtractedData = { - val validation = Map( - JsPath \ "documentId" -> AdditionalConstraints.optionNonEmptyConstraint(documentId) - ) - - val validationErrors: JsonValidationErrors = validation.collect({ - case (fieldName, e: Invalid) => (fieldName, e.errors) - })(breakOut) - - if (validationErrors.isEmpty) { - val extractedData = ExtractedData( - documentId = documentId.map(LongId[Document]).get, - keywordId = keywordId.map(LongId[Keyword]), - evidenceText = evidence.toOption, - meta = meta.map(x => TextJson(JsonSerializer.deserialize[Meta](x))).toOption - ) - val labelList = labels.map(_.map(_.toDomain())) - RichExtractedData(extractedData, labelList.getOrElse(List.empty)) - } else { - throw new JsonValidationException(validationErrors) - } - } -} - -object ApiPartialExtractedData { - - private val reads: Reads[ApiPartialExtractedData] = ( - (JsPath \ "documentId").readNullable[Long] and - (JsPath \ "keywordId").readNullable[Long] and - (JsPath \ "evidence").readTristate[String] and - (JsPath \ "meta").readTristate[String] and - (JsPath \ "labels").readTristate[List[ApiExtractedDataLabel]] - )(ApiPartialExtractedData.apply _) - - private val writes: Writes[ApiPartialExtractedData] = ( - (JsPath \ "documentId").writeNullable[Long] and - (JsPath \ "keywordId").writeNullable[Long] and - (JsPath \ "evidence").writeTristate[String] and - (JsPath \ "meta").writeTristate[String] and - (JsPath \ "labels").writeTristate[List[ApiExtractedDataLabel]] - )(unlift(ApiPartialExtractedData.unapply)) - - implicit val format: Format[ApiPartialExtractedData] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis.scala new file mode 100644 index 0000000..c5f6141 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis.scala @@ -0,0 +1,12 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.pdsuidomain.entities._ + +object hypothesis { + import DefaultJsonProtocol._ + import common._ + + implicit val hypothesisFormat: RootJsonFormat[Hypothesis] = jsonFormat4(Hypothesis.apply) + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis/ApiHypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis/ApiHypothesis.scala deleted file mode 100644 index bf18a60..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis/ApiHypothesis.scala +++ /dev/null @@ -1,35 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.hypothesis - -import java.util.UUID - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuidomain.entities.Hypothesis - -final case class ApiHypothesis(id: UUID, name: String, treatmentType: String, description: String) { - - def toDomain = Hypothesis( - id = UuidId[Hypothesis](id), - name = name, - treatmentType = treatmentType, - description = description - ) -} - -object ApiHypothesis { - - implicit val format: Format[ApiHypothesis] = ( - (JsPath \ "id").format[UUID] and - (JsPath \ "name").format[String] and - (JsPath \ "treatmentType").format[String] and - (JsPath \ "description").format[String] - )(ApiHypothesis.apply, unlift(ApiHypothesis.unapply)) - - def fromDomain(hypothesis: Hypothesis) = ApiHypothesis( - id = hypothesis.id.id, - name = hypothesis.name, - treatmentType = hypothesis.treatmentType, - description = hypothesis.description - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention.scala new file mode 100644 index 0000000..5cd7527 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention.scala @@ -0,0 +1,146 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.InterventionType.DeliveryMethod +import xyz.driver.pdsuidomain.entities._ + +object intervention { + import DefaultJsonProtocol._ + import common._ + + implicit def interventionFormat: RootJsonFormat[InterventionWithArms] = new RootJsonFormat[InterventionWithArms] { + override def write(obj: InterventionWithArms) = + JsObject( + "id" -> obj.intervention.id.toJson, + "name" -> obj.intervention.name.toJson, + "typeId" -> obj.intervention.typeId.toJson, + "dosage" -> obj.intervention.dosage.toJson, + "isActive" -> obj.intervention.isActive.toJson, + "arms" -> obj.arms.map(_.armId).toJson, + "trialId" -> obj.intervention.trialId.toJson, + "deliveryMethod" -> obj.intervention.deliveryMethod.toJson, + "originalName" -> obj.intervention.originalName.toJson, + "originalDosage" -> obj.intervention.originalDosage.toJson, + "originalType" -> obj.intervention.originalType.toJson + ) + + override def read(json: JsValue): InterventionWithArms = json match { + case JsObject(fields) => + val trialId = fields + .get("trialId") + .map(_.convertTo[StringId[Trial]]) + .getOrElse(deserializationError(s"Intervention json object does not contain `trialId` field: $json")) + + val typeId = fields + .get("typeId") + .flatMap(_.convertTo[Option[LongId[InterventionType]]]) + + val name = fields + .get("name") + .map(_.convertTo[String]) + .getOrElse("") + + val dosage = fields + .get("dosage") + .map(_.convertTo[String]) + + val isActive = fields + .get("isActive") + .exists(_.convertTo[Boolean]) + + val deliveryMethod = fields + .get("deliveryMethod") + .flatMap(_.convertTo[Option[String]]) + + val arms = fields + .get("arms") + .map(_.convertTo[List[LongId[SlotArm]]]) + .map(_ map (x => InterventionArm(armId = x, interventionId = LongId(0L)))) + .getOrElse(List.empty[InterventionArm]) + + InterventionWithArms( + intervention = Intervention( + id = LongId(0L), + trialId = trialId, + name = name, + originalName = name, + typeId = typeId, + originalType = None, + dosage = dosage.getOrElse(""), + originalDosage = dosage.getOrElse(""), + isActive = isActive, + deliveryMethod = deliveryMethod + ), + arms = arms + ) + + case _ => deserializationError(s"Expected Json Object as create Intervention json, but got $json") + } + } + + def applyUpdateToInterventionWithArms(json: JsValue, orig: InterventionWithArms): InterventionWithArms = json match { + case JsObject(fields) => + val name = fields + .get("name") + .map(_.convertTo[String]) + + val typeId = fields + .get("typeId") + .map(_.convertTo[LongId[InterventionType]]) + + val dosage = fields + .get("dosage") + .map(_.convertTo[String]) + + val isActive = fields + .get("isActive") + .map(_.convertTo[Boolean]) + + val deliveryMethod = fields + .get("deliveryMethod") + .map(_.convertTo[String]) + + val origIntervention = orig.intervention + val arms = fields + .get("arms") + .map(_.convertTo[List[LongId[SlotArm]]].map(x => InterventionArm(x, orig.intervention.id))) + + orig.copy( + intervention = origIntervention.copy( + name = name.getOrElse(origIntervention.name), + typeId = typeId.orElse(origIntervention.typeId), + dosage = dosage.getOrElse(origIntervention.dosage), + isActive = isActive.getOrElse(origIntervention.isActive), + deliveryMethod = deliveryMethod.orElse(origIntervention.deliveryMethod) + ), + arms = arms.getOrElse(orig.arms) + ) + + case _ => deserializationError(s"Expected Json Object as partial Intervention, but got $json") + } + + implicit def interventionTypeFormat: JsonFormat[InterventionType] = new RootJsonFormat[InterventionType] { + override def read(json: JsValue): InterventionType = json match { + case JsObject(fields) => + val name = fields + .get("name") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"Intervention type json object does not contain `name` field: $json")) + + InterventionType + .typeFromString(name) + .getOrElse(deserializationError(s"Unknown intervention type: $name")) + + case _ => deserializationError(s"Expected Json Object as Intervention type, but got $json") + } + + override def write(obj: InterventionType) = + JsObject( + "id" -> obj.id.toJson, + "name" -> obj.name.toJson, + "deliveryMethods" -> obj.deliveryMethods.map(DeliveryMethod.methodToString).toJson + ) + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala deleted file mode 100644 index 072ed25..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala +++ /dev/null @@ -1,76 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.intervention - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{Intervention, InterventionArm, InterventionWithArms} -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} - -final case class ApiIntervention(id: Long, - name: String, - typeId: Option[Long], - dosage: String, - isActive: Boolean, - arms: List[Long], - trialId: String, - deliveryMethod: Option[String], - originalName: String, - originalDosage: String, - originalType: Option[String]) { - - def toDomain = { - val intervention = Intervention( - id = LongId(this.id), - trialId = StringId(this.trialId), - name = this.name, - originalName = this.originalName, - typeId = this.typeId.map(id => LongId(id)), - originalType = this.originalType.map(id => id.toString), - dosage = this.dosage, - originalDosage = this.originalDosage, - isActive = this.isActive, - deliveryMethod = this.deliveryMethod - ) - - InterventionWithArms(intervention, this.arms.map { armId => - InterventionArm(LongId(armId), intervention.id) - }) - - } - -} - -object ApiIntervention { - - implicit val format: Format[ApiIntervention] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] and - (JsPath \ "typeId").formatNullable[Long] and - (JsPath \ "dosage").format[String] and - (JsPath \ "isActive").format[Boolean] and - (JsPath \ "arms").format[List[Long]] and - (JsPath \ "trialId").format[String] and - (JsPath \ "deliveryMethod").formatNullable[String] and - (JsPath \ "originalName").format[String] and - (JsPath \ "originalDosage").format[String] and - (JsPath \ "originalType").formatNullable[String] - )(ApiIntervention.apply, unlift(ApiIntervention.unapply)) - - def fromDomain(interventionWithArms: InterventionWithArms): ApiIntervention = { - import interventionWithArms.intervention - import interventionWithArms.arms - - ApiIntervention( - id = intervention.id.id, - name = intervention.name, - typeId = intervention.typeId.map(_.id), - dosage = intervention.dosage, - isActive = intervention.isActive, - arms = arms.map(_.armId.id), - trialId = intervention.trialId.id, - deliveryMethod = intervention.deliveryMethod, - originalName = intervention.originalName, - originalDosage = intervention.originalDosage, - originalType = intervention.originalType - ) - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiInterventionType.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiInterventionType.scala deleted file mode 100644 index 3db8bfa..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiInterventionType.scala +++ /dev/null @@ -1,26 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.intervention - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuidomain.entities.InterventionType -import xyz.driver.pdsuidomain.entities.InterventionType.DeliveryMethod - -final case class ApiInterventionType(id: Long, name: String, deliveryMethods: List[String]) { - - def toDomain = InterventionType.typeFromString(name) -} - -object ApiInterventionType { - - implicit val format: Format[ApiInterventionType] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] and - (JsPath \ "deliveryMethods").format[List[String]] - )(ApiInterventionType.apply, unlift(ApiInterventionType.unapply)) - - def fromDomain(interventionType: InterventionType) = ApiInterventionType( - id = interventionType.id.id, - name = interventionType.name, - deliveryMethods = interventionType.deliveryMethods.map(DeliveryMethod.methodToString).toList - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiPartialIntervention.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiPartialIntervention.scala deleted file mode 100644 index 28a8555..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiPartialIntervention.scala +++ /dev/null @@ -1,90 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.intervention - -import play.api.data.validation.Invalid -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{Intervention, InterventionArm, InterventionWithArms, Trial} -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.json.JsonValidationException -import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors} - -import scala.collection.breakOut -import scala.util.Try - -final case class ApiPartialIntervention(name: Option[String], - trialId: Option[String], - typeId: Option[Long], - dosage: Option[String], - isActive: Option[Boolean], - deliveryMethod: Option[String], - arms: Option[List[Long]]) { - - def applyTo(orig: InterventionWithArms): InterventionWithArms = { - val origIntervention = orig.intervention - val draftArmList = arms.map(_.map(x => InterventionArm(armId = LongId(x), interventionId = orig.intervention.id))) - orig.copy( - intervention = origIntervention.copy( - name = name.getOrElse(origIntervention.name), - typeId = typeId.map(LongId(_)).orElse(origIntervention.typeId), - dosage = dosage.getOrElse(origIntervention.dosage), - isActive = isActive.getOrElse(origIntervention.isActive), - deliveryMethod = deliveryMethod.orElse(origIntervention.deliveryMethod) - ), - arms = draftArmList.getOrElse(orig.arms) - ) - } - - def toDomain: Try[InterventionWithArms] = Try { - val validation = Map(JsPath \ "trialId" -> AdditionalConstraints.optionNonEmptyConstraint(trialId)) - - val validationErrors: JsonValidationErrors = validation.collect({ - case (fieldName, e: Invalid) => (fieldName, e.errors) - })(breakOut) - - if (validationErrors.isEmpty) { - InterventionWithArms( - intervention = Intervention( - id = LongId(0), - trialId = trialId.map(StringId[Trial]).get, - name = name.getOrElse(""), - originalName = name.getOrElse(""), - typeId = typeId.map(LongId(_)), - originalType = Option(""), - dosage = dosage.getOrElse(""), - originalDosage = dosage.getOrElse(""), - isActive = isActive.getOrElse(false), - deliveryMethod = deliveryMethod - ), - arms = - arms.map(_.map(x => InterventionArm(armId = LongId(x), interventionId = LongId(0)))).getOrElse(List.empty) - ) - } else { - throw new JsonValidationException(validationErrors) - } - } -} - -object ApiPartialIntervention { - - private val reads: Reads[ApiPartialIntervention] = ( - (JsPath \ "name").readNullable[String] and - (JsPath \ "trialId").readNullable[String] and - (JsPath \ "typeId").readNullable[Long] and - (JsPath \ "dosage").readNullable[String] and - (JsPath \ "isActive").readNullable[Boolean] and - (JsPath \ "deliveryMethod").readNullable[String] and - (JsPath \ "arms").readNullable[List[Long]] - )(ApiPartialIntervention.apply _) - - private val writes: Writes[ApiPartialIntervention] = ( - (JsPath \ "name").writeNullable[String] and - (JsPath \ "trialId").writeNullable[String] and - (JsPath \ "typeId").writeNullable[Long] and - (JsPath \ "dosage").writeNullable[String] and - (JsPath \ "isActive").writeNullable[Boolean] and - (JsPath \ "deliveryMethod").writeNullable[String] and - (JsPath \ "arms").writeNullable[List[Long]] - )(unlift(ApiPartialIntervention.unapply)) - - implicit val format: Format[ApiPartialIntervention] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiCriterionLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiCriterionLabel.scala deleted file mode 100644 index edb0603..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiCriterionLabel.scala +++ /dev/null @@ -1,54 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.label - -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.{Criterion, CriterionLabel} -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.entities.labels.{Label, LabelCategory, LabelValue} - -/** - * @param value Yes|No - */ -final case class ApiCriterionLabel(labelId: Option[Long], - categoryId: Option[Long], - value: Option[String], - isDefining: Boolean) { - - def toDomain(criterionId: LongId[Criterion]) = CriterionLabel( - id = LongId(0L), - labelId = labelId.map(LongId[Label]), - criterionId = criterionId, - categoryId = categoryId.map(LongId[LabelCategory]), - value = value.map { - case "Yes" => true - case "No" => false - }, - isDefining = isDefining - ) -} - -object ApiCriterionLabel { - - def fromDomain(x: CriterionLabel) = ApiCriterionLabel( - labelId = x.labelId.map(_.id), - categoryId = x.categoryId.map(_.id), - value = x.value.map { x => - LabelValue.fromBoolean(x).toString - }, - isDefining = x.isDefining - ) - - implicit val format: Format[ApiCriterionLabel] = ( - (JsPath \ "labelId").formatNullable[Long] and - (JsPath \ "categoryId").formatNullable[Long] and - (JsPath \ "value").formatNullable[String]( - Format(Reads - .of[String] - .filter(ValidationError("unknown value"))({ x => - x == "Yes" || x == "No" - }), - Writes.of[String])) and - (JsPath \ "isDefining").format[Boolean] - )(ApiCriterionLabel.apply, unlift(ApiCriterionLabel.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiExtractedDataLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiExtractedDataLabel.scala deleted file mode 100644 index 1497679..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiExtractedDataLabel.scala +++ /dev/null @@ -1,41 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.label - -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.{ExtractedData, ExtractedDataLabel} -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.entities.labels.{Label, LabelCategory, LabelValue} - -final case class ApiExtractedDataLabel(id: Option[Long], categoryId: Option[Long], value: Option[String]) { - - def toDomain(dataId: LongId[ExtractedData] = LongId(0)) = ExtractedDataLabel( - id = LongId(0), - dataId = dataId, - labelId = id.map(LongId[Label]), - categoryId = categoryId.map(LongId[LabelCategory]), - value = value.flatMap(LabelValue.fromString) - ) -} - -object ApiExtractedDataLabel { - - implicit val format: Format[ApiExtractedDataLabel] = ( - (JsPath \ "id").formatNullable[Long] and - (JsPath \ "categoryId").formatNullable[Long] and - (JsPath \ "value").formatNullable[String]( - Format(Reads - .of[String] - .filter(ValidationError("unknown value"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), - Writes.of[String])) - )(ApiExtractedDataLabel.apply, unlift(ApiExtractedDataLabel.unapply)) - - def fromDomain(dataLabel: ExtractedDataLabel) = ApiExtractedDataLabel( - id = dataLabel.labelId.map(_.id), - categoryId = dataLabel.categoryId.map(_.id), - value = dataLabel.value.map(_.toString) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/listresponse.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/listresponse.scala new file mode 100644 index 0000000..1e359d6 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/listresponse.scala @@ -0,0 +1,45 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json.DefaultJsonProtocol._ +import spray.json._ +import xyz.driver.pdsuidomain.ListResponse +import xyz.driver.pdsuidomain.formats.json.common._ + +object listresponse { + private val itemsField = "items" + private val metaField = "meta" + + implicit val listResponseMetaFormat: RootJsonFormat[ListResponse.Meta] = jsonFormat4(ListResponse.Meta.apply) + + implicit def listResponseWriter[T: JsonWriter]: RootJsonWriter[ListResponse[T]] = + new RootJsonWriter[ListResponse[T]] { + override def write(listResponse: ListResponse[T]): JsValue = { + JsObject( + itemsField -> listResponse.items.map(_.toJson).toJson, + metaField -> listResponse.meta.toJson + ) + } + } + + implicit def listResponseReader[T: JsonReader]: RootJsonReader[ListResponse[T]] = + new RootJsonReader[ListResponse[T]] { + override def read(json: JsValue): ListResponse[T] = json match { + case JsObject(fields) => + val items = fields + .get(itemsField) + .map { + case JsArray(elements) => elements.map(_.convertTo[T])(collection.breakOut) + case x => deserializationError(s"Expected Array as JsArray, but got $x") + } + .getOrElse(deserializationError(s"ListResponse json object does not contain `$itemsField` field: $json")) + + val meta = fields + .get(metaField) + .map(_.convertTo[ListResponse.Meta]) + .getOrElse(deserializationError(s"ListResponse json object does not contain `$metaField` field: $json")) + + ListResponse(items, meta) + case _ => deserializationError(s"Expected ListResponse json object, but got $json") + } + } +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala deleted file mode 100644 index 425eeac..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala +++ /dev/null @@ -1,79 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.message - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.Message - -final case class ApiMessage(id: Long, - text: String, - lastUpdate: ZonedDateTime, - userId: String, - isDraft: Boolean, - recordId: Option[Long], - documentId: Option[Long], - patientId: Option[String], - trialId: Option[String], - startPage: Option[Double], - endPage: Option[Double], - evidence: Option[String], - archiveRequired: Option[Boolean], - meta: Option[String]) { - - def toDomain = Message( - id = LongId(this.id), - text = this.text, - lastUpdate = this.lastUpdate.toLocalDateTime(), - userId = StringId(this.userId), - isDraft = this.isDraft, - recordId = this.recordId.map(id => LongId(id)), - documentId = this.documentId.map(id => LongId(id)), - patientId = this.patientId.map(id => UuidId(id)), - trialId = this.trialId.map(id => StringId(id)), - startPage = this.startPage, - endPage = this.endPage, - evidence = this.evidence, - archiveRequired = this.archiveRequired, - meta = this.meta - ) - -} - -object ApiMessage { - - def fromDomain(domain: Message) = ApiMessage( - id = domain.id.id, - text = domain.text, - lastUpdate = ZonedDateTime.of(domain.lastUpdate, ZoneId.of("Z")), - userId = domain.userId.id, - isDraft = domain.isDraft, - recordId = domain.recordId.map(_.id), - documentId = domain.documentId.map(_.id), - patientId = domain.patientId.map(_.toString), - trialId = domain.trialId.map(_.toString), - startPage = domain.startPage, - endPage = domain.endPage, - evidence = domain.evidence, - archiveRequired = domain.archiveRequired, - meta = domain.meta - ) - - implicit val format: Format[ApiMessage] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "text").format[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "userId").format[String] and - (JsPath \ "isDraft").format[Boolean] and - (JsPath \ "recordId").formatNullable[Long] and - (JsPath \ "documentId").formatNullable[Long] and - (JsPath \ "patientId").formatNullable[String] and - (JsPath \ "trialId").formatNullable[String] and - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "evidence").formatNullable[String] and - (JsPath \ "archiveRequired").formatNullable[Boolean] and - (JsPath \ "meta").formatNullable[String] - )(ApiMessage.apply, unlift(ApiMessage.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiPartialMessage.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiPartialMessage.scala deleted file mode 100644 index a2656f2..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiPartialMessage.scala +++ /dev/null @@ -1,82 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.message - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain._ -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuidomain.entities.Message - -final case class ApiPartialMessage(text: Option[String], - recordId: Option[Long], - documentId: Option[Long], - patientId: Option[String], - trialId: Option[String], - startPage: Option[Double], - endPage: Option[Double], - evidence: Option[String], - archiveRequired: Option[Boolean], - meta: Option[String]) { - - def toDomain(userId: StringId[User]) = Message( - id = LongId(0), - text = text.getOrElse(""), - userId = userId, - isDraft = true, - recordId = recordId.map(LongId(_)), - documentId = documentId.map(LongId(_)), - patientId = patientId.map(UuidId(_)), - trialId = trialId.map(StringId(_)), - startPage = startPage, - endPage = endPage, - evidence = evidence, - archiveRequired = archiveRequired, - meta = meta, - lastUpdate = LocalDateTime.MIN - ) - - def applyTo(orig: Message): Message = { - orig.copy( - text = text.getOrElse(""), - recordId = recordId.map(LongId(_)), - documentId = documentId.map(LongId(_)), - patientId = patientId.map(UuidId(_)), - trialId = trialId.map(StringId(_)), - startPage = startPage, - endPage = endPage, - evidence = evidence, - archiveRequired = archiveRequired, - meta = meta, - lastUpdate = LocalDateTime.MIN - ) - } -} - -object ApiPartialMessage { - - implicit val format: Format[ApiPartialMessage] = ( - (JsPath \ "text").formatNullable[String] and - (JsPath \ "recordId").formatNullable[Long] and - (JsPath \ "documentId").formatNullable[Long] and - (JsPath \ "patientId").formatNullable[String] and - (JsPath \ "trialId").formatNullable[String] and - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "evidence").formatNullable[String] and - (JsPath \ "archiveRequired").formatNullable[Boolean] and - (JsPath \ "meta").formatNullable[String] - )(ApiPartialMessage.apply, unlift(ApiPartialMessage.unapply)) - - def fromDomain(domain: Message) = ApiPartialMessage( - text = Some(domain.text), - recordId = domain.recordId.map(_.id), - documentId = domain.documentId.map(_.id), - patientId = domain.patientId.map(_.toString), - trialId = domain.trialId.map(_.toString), - startPage = domain.startPage, - endPage = domain.endPage, - evidence = domain.evidence, - archiveRequired = domain.archiveRequired, - meta = domain.meta - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordCreateRequest.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordCreateRequest.scala deleted file mode 100644 index 5c12415..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordCreateRequest.scala +++ /dev/null @@ -1,9 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.password - -import play.api.libs.json.{Format, Json} - -final case class PasswordCreateRequest(password: String, key: String) - -object PasswordCreateRequest { - implicit val format: Format[PasswordCreateRequest] = Json.format[PasswordCreateRequest] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordUpdateRequest.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordUpdateRequest.scala deleted file mode 100644 index 07851ea..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordUpdateRequest.scala +++ /dev/null @@ -1,9 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.password - -import play.api.libs.json.{Format, Json} - -final case class PasswordUpdateRequest(password: String, oldPassword: String) - -object PasswordUpdateRequest { - implicit val format: Format[PasswordUpdateRequest] = Json.format[PasswordUpdateRequest] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient.scala new file mode 100644 index 0000000..75eb016 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient.scala @@ -0,0 +1,50 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.core.json.EnumJsonFormat +import xyz.driver.formats.json.common._ +import xyz.driver.formats.json.patient._ +import xyz.driver.pdsuidomain.entities._ + +object patient { + import DefaultJsonProtocol._ + import Patient._ + import common._ + + implicit val patientStatusFormat = new EnumJsonFormat[Status]( + "New" -> Status.New, + "Verified" -> Status.Verified, + "Reviewed" -> Status.Reviewed, + "Curated" -> Status.Curated, + "Done" -> Status.Done, + "Flagged" -> Status.Flagged + ) + + implicit val patientOrderIdFormat = new RootJsonFormat[PatientOrderId] { + override def write(orderId: PatientOrderId): JsString = JsString(orderId.toString) + override def read(json: JsValue): PatientOrderId = json match { + case JsString(value) => PatientOrderId(value) + case _ => deserializationError(s"Expected string as PatientOrderId, but got $json") + } + } + + implicit val patientFormat: RootJsonFormat[Patient] = new RootJsonFormat[Patient] { + override def write(patient: Patient): JsValue = + JsObject( + "id" -> patient.id.toJson, + "status" -> patient.status.toJson, + "name" -> patient.name.toJson, + "dob" -> patient.dob.toJson, + "assignee" -> patient.assignee.toJson, + "previousStatus" -> patient.previousStatus.toJson, + "previousAssignee" -> patient.previousAssignee.toJson, + "lastActiveUser" -> patient.lastActiveUserId.toJson, + "lastUpdate" -> patient.lastUpdate.toJson, + "disease" -> patient.disease.toJson, + "orderId" -> patient.orderId.toJson + ) + + override def read(json: JsValue): Patient = jsonReader[Patient].read(json) + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/ApiPatient.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/ApiPatient.scala deleted file mode 100644 index 585d4ed..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/ApiPatient.scala +++ /dev/null @@ -1,86 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient - -import java.time.{LocalDate, ZoneId, ZonedDateTime} -import java.util.UUID - -import xyz.driver.pdsuicommon.domain.{StringId, UuidId} -import xyz.driver.pdsuidomain.entities.{Patient, PatientOrderId} -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.entities.common.FullName -import xyz.driver.entities.patient - -final case class ApiPatient(id: String, - status: String, - name: String, - dob: LocalDate, - assignee: Option[String], - previousStatus: Option[String], - previousAssignee: Option[String], - lastActiveUser: Option[String], - lastUpdate: ZonedDateTime, - disease: String, - orderId: UUID) { - - private def extractStatus(status: String): Patient.Status = - PatientStatus.statusFromString - .applyOrElse(status, (s: String) => throw new NoSuchElementException(s"Unknown status $s")) - - private def parseName(name: String): FullName[Patient] = - name.split(" ") match { - case Array() => throw new NoSuchElementException(s"Patient's name cannot be empty") - case Array(first) => FullName.fromStrings[Patient](first, "", "") - case Array(first, last) => FullName.fromStrings[Patient](first, "", last) - case Array(first, middle, last) => FullName.fromStrings[Patient](first, middle, last) - case _ => throw new NoSuchElementException(s"Patient's name is ambiguous") - } - - def toDomain = Patient( - id = UuidId(this.id), - status = extractStatus(this.status), - name = parseName(this.name), - dob = this.dob, - assignee = this.assignee.map(StringId(_)), - previousStatus = this.previousStatus.map(extractStatus), - previousAssignee = this.previousAssignee.map(StringId(_)), - lastActiveUserId = this.lastActiveUser.map(StringId(_)), - isUpdateRequired = false, - disease = patient.CancerType - .fromString(this.disease) - .getOrElse(throw new IllegalArgumentException(s"Unknown cancer type ${this.disease}")), - orderId = PatientOrderId(this.orderId), - lastUpdate = this.lastUpdate.toLocalDateTime - ) - -} - -object ApiPatient { - - implicit val format: Format[ApiPatient] = ( - (JsPath \ "id").format[String] and - (JsPath \ "status").format[String] and - (JsPath \ "name").format[String] and - (JsPath \ "dob").format[LocalDate] and - (JsPath \ "assignee").formatNullable[String] and - (JsPath \ "previousStatus").formatNullable[String] and - (JsPath \ "previousAssignee").formatNullable[String] and - (JsPath \ "lastActiveUser").formatNullable[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "disease").format[String] and - (JsPath \ "orderId").format[UUID] - )(ApiPatient.apply, unlift(ApiPatient.unapply)) - - def fromDomain(patient: Patient) = ApiPatient( - id = patient.id.toString, - status = PatientStatus.statusToString(patient.status), - name = patient.name.toString(), - dob = patient.dob, - assignee = patient.assignee.map(_.id), - previousStatus = patient.previousStatus.map(PatientStatus.statusToString), - previousAssignee = patient.previousAssignee.map(_.id), - lastActiveUser = patient.lastActiveUserId.map(_.id), - lastUpdate = ZonedDateTime.of(patient.lastUpdate, ZoneId.of("Z")), - disease = patient.disease.toString, - orderId = patient.orderId.id - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/PatientStatus.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/PatientStatus.scala deleted file mode 100644 index a23a1de..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/PatientStatus.scala +++ /dev/null @@ -1,24 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient - -import xyz.driver.pdsuidomain.entities.Patient.Status - -object PatientStatus { - - val statusFromString: PartialFunction[String, Status] = { - case "New" => Status.New - case "Verified" => Status.Verified - case "Reviewed" => Status.Reviewed - case "Curated" => Status.Curated - case "Flagged" => Status.Flagged - case "Done" => Status.Done - } - - def statusToString(x: Status): String = x match { - case Status.New => "New" - case Status.Verified => "Verified" - case Status.Reviewed => "Reviewed" - case Status.Curated => "Curated" - case Status.Flagged => "Flagged" - case Status.Done => "Done" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPartialPatientEligibleTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPartialPatientEligibleTrial.scala deleted file mode 100644 index 03ff275..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPartialPatientEligibleTrial.scala +++ /dev/null @@ -1,18 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.eligible - -import xyz.driver.pdsuidomain.entities.PatientTrialArmGroupView -import play.api.libs.json.{Format, Json} - -final case class ApiPartialPatientEligibleTrial(isVerified: Option[Boolean]) { - - def applyTo(orig: PatientTrialArmGroupView): PatientTrialArmGroupView = { - orig.copy( - isVerified = isVerified.getOrElse(orig.isVerified) - ) - } -} - -object ApiPartialPatientEligibleTrial { - - implicit val format: Format[ApiPartialPatientEligibleTrial] = Json.format -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPatientEligibleTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPatientEligibleTrial.scala deleted file mode 100644 index 55c8149..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPatientEligibleTrial.scala +++ /dev/null @@ -1,51 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.eligible - -import java.util.UUID - -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuidomain.services.PatientEligibleTrialService.RichPatientEligibleTrial - -final case class ApiPatientEligibleTrial(id: Long, - patientId: String, - trialId: String, - trialTitle: String, - arms: List[String], - hypothesisId: UUID, - verifiedEligibilityStatus: Option[String], - isVerified: Boolean) - -object ApiPatientEligibleTrial { - - implicit val apiEligibleTrialJsonFormat: Format[ApiPatientEligibleTrial] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "patientId").format[String] and - (JsPath \ "trialId").format[String] and - (JsPath \ "trialTitle").format[String] and - (JsPath \ "arms").format[List[String]] and - (JsPath \ "hypothesisId").format[UUID] and - (JsPath \ "verifiedEligibilityStatus").formatNullable[String](Format( - Reads - .of[String] - .filter(ValidationError("unknown eligibility status"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), - Writes.of[String] - )) and - (JsPath \ "isVerified").format[Boolean] - )(ApiPatientEligibleTrial.apply, unlift(ApiPatientEligibleTrial.unapply)) - - def fromDomain(eligibleTrialWithTrial: RichPatientEligibleTrial) = ApiPatientEligibleTrial( - id = eligibleTrialWithTrial.group.id.id, - patientId = eligibleTrialWithTrial.group.patientId.toString, - trialId = eligibleTrialWithTrial.group.trialId.id, - trialTitle = eligibleTrialWithTrial.trial.title, - arms = eligibleTrialWithTrial.arms.map(_.armName), - hypothesisId = eligibleTrialWithTrial.group.hypothesisId.id, - eligibleTrialWithTrial.group.verifiedEligibilityStatus.map(_.toString), - eligibleTrialWithTrial.group.isVerified - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPartialPatientHypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPartialPatientHypothesis.scala deleted file mode 100644 index 0858ce1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPartialPatientHypothesis.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.hypothesis - -import xyz.driver.pdsuidomain.entities.PatientHypothesis -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiPartialPatientHypothesis(rationale: Tristate[String]) { - - def applyTo(orig: PatientHypothesis): PatientHypothesis = { - orig.copy( - rationale = rationale.cata(Some(_), None, orig.rationale) - ) - } -} - -object ApiPartialPatientHypothesis { - - implicit val reads: Reads[ApiPartialPatientHypothesis] = - (__ \ "rationale").readTristate[String].map(x => ApiPartialPatientHypothesis(x)) - - implicit val writes: Writes[ApiPartialPatientHypothesis] = - (__ \ "rationale").writeTristate[String].contramap(_.rationale) - - implicit val format: Format[ApiPartialPatientHypothesis] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPatientHypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPatientHypothesis.scala deleted file mode 100644 index 584ff72..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPatientHypothesis.scala +++ /dev/null @@ -1,35 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.hypothesis - -import java.util.UUID - -import xyz.driver.pdsuidomain.entities.PatientHypothesis -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiPatientHypothesis(id: UUID, - patientId: String, - hypothesisId: UUID, - matchedTrials: Long, - rationale: Option[String], - isRationaleRequired: Boolean) - -object ApiPatientHypothesis { - - implicit val apiPatientHypothesisJsonFormat: Format[ApiPatientHypothesis] = ( - (JsPath \ "id").format[UUID] and - (JsPath \ "patientId").format[String] and - (JsPath \ "hypothesisId").format[UUID] and - (JsPath \ "matchedTrials").format[Long] and - (JsPath \ "rationale").formatNullable[String] and - (JsPath \ "isRationaleRequired").format[Boolean] - )(ApiPatientHypothesis.apply, unlift(ApiPatientHypothesis.unapply)) - - def fromDomain(patientHypothesis: PatientHypothesis, isRationaleRequired: Boolean) = ApiPatientHypothesis( - id = patientHypothesis.id.id, - patientId = patientHypothesis.patientId.toString, - hypothesisId = patientHypothesis.hypothesisId.id, - matchedTrials = patientHypothesis.matchedTrials, - rationale = patientHypothesis.rationale, - isRationaleRequired = isRationaleRequired - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPartialPatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPartialPatientLabel.scala deleted file mode 100644 index d92872c..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPartialPatientLabel.scala +++ /dev/null @@ -1,43 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.label - -import xyz.driver.pdsuidomain.entities.PatientLabel -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.entities.labels.LabelValue - -final case class ApiPartialPatientLabel(primaryValue: Option[String], verifiedPrimaryValue: Tristate[String]) { - - def applyTo(orig: PatientLabel): PatientLabel = { - orig.copy( - primaryValue = primaryValue.flatMap(LabelValue.fromString).orElse(orig.primaryValue), - verifiedPrimaryValue = verifiedPrimaryValue.cata(x => LabelValue.fromString(x), None, orig.verifiedPrimaryValue) - ) - } -} - -object ApiPartialPatientLabel { - - implicit val format: Format[ApiPartialPatientLabel] = ( - (JsPath \ "primaryValue").formatNullable[String]( - Format(Reads - .of[String] - .filter(ValidationError("unknown primary value"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), - Writes.of[String])) and - (JsPath \ "verifiedPrimaryValue").formatTristate[String]( - Format( - Reads - .of[String] - .filter(ValidationError("unknown verified primary value"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), - Writes.of[String] - )) - )(ApiPartialPatientLabel.apply, unlift(ApiPartialPatientLabel.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabel.scala deleted file mode 100644 index cc8532d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabel.scala +++ /dev/null @@ -1,55 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.label - -import xyz.driver.pdsuidomain.entities.PatientLabel -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.entities.labels.LabelValue - -final case class ApiPatientLabel(id: Long, - labelId: Long, - primaryValue: Option[String], - verifiedPrimaryValue: Option[String], - score: Int, - isImplicitMatch: Boolean, - isVisible: Boolean, - isVerified: Boolean) - -object ApiPatientLabel { - - implicit val apiPatientLabelJsonFormat: Format[ApiPatientLabel] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "labelId").format[Long] and - (JsPath \ "primaryValue").formatNullable[String]( - Format(Reads - .of[String] - .filter(ValidationError("unknown value"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), - Writes.of[String])) and - (JsPath \ "verifiedPrimaryValue").formatNullable[String]( - Format(Reads - .of[String] - .filter(ValidationError("unknown value"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), - Writes.of[String])) and - (JsPath \ "score").format[Int] and - (JsPath \ "isImplicitMatch").format[Boolean] and - (JsPath \ "isVisible").format[Boolean] and - (JsPath \ "isVerified").format[Boolean] - )(ApiPatientLabel.apply, unlift(ApiPatientLabel.unapply)) - - def fromDomain(patientLabel: PatientLabel, isVerified: Boolean): ApiPatientLabel = ApiPatientLabel( - id = patientLabel.id.id, - labelId = patientLabel.labelId.id, - primaryValue = patientLabel.primaryValue.map(_.toString), - verifiedPrimaryValue = patientLabel.verifiedPrimaryValue.map(_.toString), - score = patientLabel.score, - isImplicitMatch = patientLabel.isImplicitMatch, - isVisible = patientLabel.isVisible, - isVerified = isVerified - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabelDefiningCriteria.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabelDefiningCriteria.scala deleted file mode 100644 index 16b9cc9..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabelDefiningCriteria.scala +++ /dev/null @@ -1,29 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.label - -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuidomain.entities.PatientLabel - -final case class ApiPatientLabelDefiningCriteria(labelId: Long, value: Option[String]) - -object ApiPatientLabelDefiningCriteria { - - implicit val format: Format[ApiPatientLabelDefiningCriteria] = ( - (JsPath \ "labelId").format[Long] and - (JsPath \ "value").formatNullable[String]( - Format(Reads - .of[String] - .filter(ValidationError("unknown value"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), - Writes.of[String])) - )(ApiPatientLabelDefiningCriteria.apply, unlift(ApiPatientLabelDefiningCriteria.unapply)) - - def fromDomain(x: PatientLabel) = ApiPatientLabelDefiningCriteria( - labelId = x.labelId.id, - value = x.verifiedPrimaryValue.map(_.toString) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterion.scala deleted file mode 100644 index 09538b8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterion.scala +++ /dev/null @@ -1,47 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.trial - -import xyz.driver.pdsuidomain.entities.PatientCriterion -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath, Reads, Writes} -import xyz.driver.entities.labels.LabelValue - -final case class ApiPartialPatientCriterion(eligibilityStatus: Option[String], - verifiedEligibilityStatus: Tristate[String]) { - - def applyTo(orig: PatientCriterion): PatientCriterion = { - orig.copy( - eligibilityStatus = eligibilityStatus.flatMap(LabelValue.fromString).orElse(orig.eligibilityStatus), - verifiedEligibilityStatus = - verifiedEligibilityStatus.cata(x => LabelValue.fromString(x), None, orig.verifiedEligibilityStatus) - ) - } -} - -object ApiPartialPatientCriterion { - - implicit val format: Format[ApiPartialPatientCriterion] = ( - (JsPath \ "eligibilityStatus").formatNullable[String]( - Format( - Reads - .of[String] - .filter(ValidationError("unknown eligibility status"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), - Writes.of[String] - )) and - (JsPath \ "verifiedEligibilityStatus").formatTristate[String]( - Format( - Reads - .of[String] - .filter(ValidationError("unknown verified eligibility status"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), - Writes.of[String] - )) - )(ApiPartialPatientCriterion.apply, unlift(ApiPartialPatientCriterion.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterionList.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterionList.scala deleted file mode 100644 index b7616a1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterionList.scala +++ /dev/null @@ -1,37 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.trial - -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.PatientCriterion -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath, Reads, Writes} -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuidomain.services.PatientCriterionService.DraftPatientCriterion - -final case class ApiPartialPatientCriterionList(id: Long, - eligibilityStatus: Option[String], - isVerified: Option[Boolean]) { - - def toDomain: DraftPatientCriterion = DraftPatientCriterion( - id = LongId[PatientCriterion](id), - eligibilityStatus = eligibilityStatus.flatMap(LabelValue.fromString), - isVerified = isVerified - ) -} - -object ApiPartialPatientCriterionList { - - implicit val format: Format[ApiPartialPatientCriterionList] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "eligibilityStatus").formatNullable[String](Format( - Reads - .of[String] - .filter(ValidationError("unknown eligibility status"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), - Writes.of[String] - )) and - (JsPath \ "isVerified").formatNullable[Boolean] - )(ApiPartialPatientCriterionList.apply, unlift(ApiPartialPatientCriterionList.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPatientCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPatientCriterion.scala deleted file mode 100644 index b9bf772..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPatientCriterion.scala +++ /dev/null @@ -1,75 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.trial - -import java.time.{ZoneId, ZonedDateTime} - -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.{PatientCriterion, PatientCriterionArm} -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath, Reads, Writes} -import xyz.driver.entities.labels.{Label, LabelValue} - -final case class ApiPatientCriterion(id: Long, - labelId: Long, - nctId: String, - criterionId: Long, - criterionText: String, - criterionValue: Option[String], - criterionIsDefining: Boolean, - criterionIsCompound: Boolean, - arms: List[String], - eligibilityStatus: Option[String], - verifiedEligibilityStatus: Option[String], - isVerified: Boolean, - isVisible: Boolean, - lastUpdate: ZonedDateTime) - -object ApiPatientCriterion { - - implicit val format: Format[ApiPatientCriterion] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "labelId").format[Long] and - (JsPath \ "nctId").format[String] and - (JsPath \ "criterionId").format[Long] and - (JsPath \ "criterionText").format[String] and - (JsPath \ "criterionValue").formatNullable[String](Format(Reads.of[String].filter(ValidationError("unknown value"))({ x => - x == "Yes" || x == "No" - }), Writes.of[String])) and - (JsPath \ "criterionIsDefining").format[Boolean] and - (JsPath \ "criterionIsCompound").format[Boolean] and - (JsPath \ "arms").format[List[String]] and - (JsPath \ "eligibilityStatus").formatNullable[String](Format(Reads.of[String].filter(ValidationError("unknown status"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), Writes.of[String])) and - (JsPath \ "verifiedEligibilityStatus").formatNullable[String](Format( - Reads.of[String].filter(ValidationError("unknown status"))({ - case x if LabelValue.fromString(x).isDefined => true - case _ => false - }), Writes.of[String])) and - (JsPath \ "isVerified").format[Boolean] and - (JsPath \ "isVisible").format[Boolean] and - (JsPath \ "lastUpdate").format[ZonedDateTime] - ) (ApiPatientCriterion.apply, unlift(ApiPatientCriterion.unapply)) - - def fromDomain(patientCriterion: PatientCriterion, - labelId: LongId[Label], - arms: List[PatientCriterionArm]) = ApiPatientCriterion( - id = patientCriterion.id.id, - labelId = labelId.id, - nctId = patientCriterion.nctId.id, - criterionId = patientCriterion.criterionId.id, - criterionText = patientCriterion.criterionText, - criterionValue = patientCriterion.criterionValue.map { x => - LabelValue.fromBoolean(x).toString - }, - criterionIsDefining = patientCriterion.criterionIsDefining, - criterionIsCompound = patientCriterion.criterionValue.isEmpty, - arms = arms.map(_.armName), - eligibilityStatus = patientCriterion.eligibilityStatus.map(_.toString), - verifiedEligibilityStatus = patientCriterion.verifiedEligibilityStatus.map(_.toString), - isVerified = patientCriterion.isVerified, - isVisible = patientCriterion.isVisible, - lastUpdate = ZonedDateTime.of(patientCriterion.lastUpdate, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientcriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientcriterion.scala new file mode 100644 index 0000000..fc0b725 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientcriterion.scala @@ -0,0 +1,64 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.entities.labels.LabelValue +import xyz.driver.formats.json.labels._ +import xyz.driver.pdsuidomain.entities._ +import xyz.driver.pdsuidomain.services.PatientCriterionService.{DraftPatientCriterion, RichPatientCriterion} + +object patientcriterion { + import DefaultJsonProtocol._ + import common._ + + def applyUpdateToPatientCriterion(json: JsValue, orig: PatientCriterion): PatientCriterion = json match { + case JsObject(fields) => + val eligibilityStatus = fields + .get("eligibilityStatus") + .map(_.convertTo[Option[LabelValue]]) + .getOrElse(orig.eligibilityStatus) + + val verifiedEligibilityStatus = fields + .get("verifiedEligibilityStatus") + .map(_.convertTo[Option[LabelValue]]) + .getOrElse(orig.verifiedEligibilityStatus) + + orig.copy( + eligibilityStatus = eligibilityStatus, + verifiedEligibilityStatus = verifiedEligibilityStatus + ) + + case _ => deserializationError(s"Expected Json Object as partial PatientCriterion, but got $json") + } + + implicit val draftPatientCriterionFormat: RootJsonFormat[DraftPatientCriterion] = jsonFormat3( + DraftPatientCriterion.apply) + implicit val draftPatientCriterionListReader = new JsonReader[List[DraftPatientCriterion]] { + override def read(json: JsValue) = json.convertTo[List[JsValue]].map(_.convertTo[DraftPatientCriterion]) + } + + implicit val patientCriterionWriter: RootJsonWriter[RichPatientCriterion] = + new RootJsonWriter[RichPatientCriterion] { + override def write(obj: RichPatientCriterion): JsValue = { + JsObject( + "id" -> obj.patientCriterion.id.toJson, + "labelId" -> obj.labelId.toJson, + "nctId" -> obj.patientCriterion.nctId.toJson, + "criterionId" -> obj.patientCriterion.criterionId.toJson, + "criterionText" -> obj.patientCriterion.criterionText.toJson, + "criterionValue" -> obj.patientCriterion.criterionValue.map { + case true => "Yes" + case false => "No" + }.toJson, + "criterionIsDefining" -> obj.patientCriterion.criterionIsDefining.toJson, + "criterionIsCompound" -> obj.patientCriterion.criterionValue.isEmpty.toJson, + "arms" -> obj.armList.map(_.armName).toJson, + "eligibilityStatus" -> obj.patientCriterion.eligibilityStatus.toJson, + "verifiedEligibilityStatus" -> obj.patientCriterion.verifiedEligibilityStatus.toJson, + "isVerified" -> obj.patientCriterion.isVerified.toJson, + "isVisible" -> obj.patientCriterion.isVisible.toJson, + "lastUpdate" -> obj.patientCriterion.lastUpdate.toJson + ) + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientdefiningcriteria.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientdefiningcriteria.scala new file mode 100644 index 0000000..0b4fbae --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientdefiningcriteria.scala @@ -0,0 +1,19 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.formats.json.labels._ +import xyz.driver.pdsuidomain.entities.PatientLabel + +object patientdefiningcriteria { + import DefaultJsonProtocol._ + import common._ + + implicit val patientLabelDefiningCriteriaWriter: RootJsonWriter[PatientLabel] = new RootJsonWriter[PatientLabel] { + override def write(obj: PatientLabel) = + JsObject( + "id" -> obj.id.toJson, + "value" -> obj.verifiedPrimaryValue.toJson + ) + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienteligibletrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienteligibletrial.scala new file mode 100644 index 0000000..4c006f9 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienteligibletrial.scala @@ -0,0 +1,40 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.formats.json.labels._ +import xyz.driver.pdsuidomain.entities._ +import xyz.driver.pdsuidomain.services.PatientEligibleTrialService.RichPatientEligibleTrial + +object patienteligibletrial { + import DefaultJsonProtocol._ + import common._ + + def applyUpdateToTrialArmGroup(json: JsValue, orig: PatientTrialArmGroupView): PatientTrialArmGroupView = + json match { + case JsObject(fields) => + val isVerified = fields + .get("isVerified") + .map(_.convertTo[Boolean]) + .getOrElse(orig.isVerified) + + orig.copy(isVerified = isVerified) + + case _ => deserializationError(s"Expected Json Object as partial PatientTrialArmGroupView, but got $json") + } + + implicit val patientEligibleTrialWriter: RootJsonWriter[RichPatientEligibleTrial] = + new RootJsonWriter[RichPatientEligibleTrial] { + override def write(obj: RichPatientEligibleTrial) = + JsObject( + "id" -> obj.group.id.toJson, + "patientId" -> obj.group.patientId.toJson, + "trialId" -> obj.group.trialId.toJson, + "trialTitle" -> obj.trial.title.toJson, + "arms" -> obj.arms.map(_.armName).toJson, + "hypothesisId" -> obj.trial.hypothesisId.toJson, + "verifiedEligibilityStatus" -> obj.group.verifiedEligibilityStatus.toJson, + "isVerified" -> obj.group.isVerified.toJson + ) + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory.scala new file mode 100644 index 0000000..bd20b27 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory.scala @@ -0,0 +1,30 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.core.json.EnumJsonFormat +import xyz.driver.pdsuidomain.entities._ + +object patienthistory { + import DefaultJsonProtocol._ + import PatientHistory._ + import common._ + + implicit val patientStateFormat = new EnumJsonFormat[State]( + "Verify" -> State.Verify, + "Curate" -> State.Curate, + "Review" -> State.Review, + "Flag" -> State.Flag + ) + + implicit val patientActionFormat = new EnumJsonFormat[Action]( + "Start" -> Action.Start, + "Submit" -> Action.Submit, + "Unassign" -> Action.Unassign, + "Resolve" -> Action.Resolve, + "Flag" -> Action.Flag, + "Archive" -> Action.Archive + ) + + implicit val patientHistoryFormat: RootJsonFormat[PatientHistory] = jsonFormat6(PatientHistory.apply) + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory/ApiPatientHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory/ApiPatientHistory.scala deleted file mode 100644 index cdcd510..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory/ApiPatientHistory.scala +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patienthistory - -import java.time.{ZoneId, ZonedDateTime} -import java.util.UUID - -import play.api.libs.json.{Format, Json} -import xyz.driver.pdsuidomain.entities.PatientHistory - -final case class ApiPatientHistory(id: Long, - executor: String, - patientId: UUID, - state: String, - action: String, - created: ZonedDateTime) - -object ApiPatientHistory { - implicit val format: Format[ApiPatientHistory] = - Json.format[ApiPatientHistory] - - def fromDomain(x: PatientHistory) = ApiPatientHistory( - id = x.id.id, - executor = x.executor.id, - patientId = x.patientId.id, - state = PatientHistory.State.stateToString(x.state), - action = PatientHistory.Action.actionToString(x.action), - created = ZonedDateTime.of(x.created, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthypothesis.scala new file mode 100644 index 0000000..a36bac2 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthypothesis.scala @@ -0,0 +1,49 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.pdsuidomain.entities._ +import xyz.driver.pdsuidomain.services.PatientHypothesisService.RichPatientHypothesis + +object patienthypothesis { + import DefaultJsonProtocol._ + import common._ + + def applyUpdateToPatientHypothesis(json: JsValue, orig: PatientHypothesis): PatientHypothesis = json match { + case JsObject(fields) => + val rationale = if (fields.contains("rationale")) { + fields.get("rationale").map(_.convertTo[String]) + } else orig.rationale + + orig.copy(rationale = rationale) + + case _ => deserializationError(s"Expected Json Object as partial PatientHypothesis, but got $json") + } + + implicit val richPatientHypothesisWriter: RootJsonWriter[RichPatientHypothesis] = + new RootJsonWriter[RichPatientHypothesis] { + override def write(obj: RichPatientHypothesis): JsValue = { + JsObject( + "id" -> obj.patientHypothesis.id.toJson, + "patientId" -> obj.patientHypothesis.patientId.toJson, + "hypothesisId" -> obj.patientHypothesis.hypothesisId.toJson, + "matchedTrials" -> obj.patientHypothesis.matchedTrials.toJson, + "rationale" -> obj.patientHypothesis.rationale.toJson, + "isRationaleRequired" -> obj.isRequired.toJson + ) + } + } + + implicit val patientHypothesisWriter: RootJsonWriter[PatientHypothesis] = + new RootJsonWriter[PatientHypothesis] { + override def write(obj: PatientHypothesis): JsValue = { + JsObject( + "id" -> obj.id.toJson, + "patientId" -> obj.patientId.toJson, + "hypothesisId" -> obj.hypothesisId.toJson, + "matchedTrials" -> obj.matchedTrials.toJson, + "rationale" -> obj.rationale.toJson + ) + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue.scala new file mode 100644 index 0000000..5a2955f --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue.scala @@ -0,0 +1,54 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId, User, UuidId} +import xyz.driver.pdsuidomain.entities._ + +object patientissue { + import DefaultJsonProtocol._ + import common._ + + def applyUpdateToPatientIssue(json: JsValue, orig: PatientIssue): PatientIssue = { + json.asJsObject.getFields("text", "archiveRequired") match { + case Seq(text, archiveRequired) => + orig.copy( + text = text.convertTo[String], + archiveRequired = archiveRequired.convertTo[Boolean] + ) + + case _ => deserializationError(s"Expected Json Object as partial PatientIssue, but got $json") + } + } + + def jsValueToPatientIssue(json: JsValue, patientId: UuidId[Patient], userId: StringId[User]): PatientIssue = { + json.asJsObject.getFields("text") match { + case Seq(text) => + PatientIssue( + id = LongId(0), + userId = userId, + patientId = patientId, + lastUpdate = LocalDateTime.MIN, + isDraft = true, + text = text.convertTo[String], + archiveRequired = false + ) + + case _ => deserializationError(s"Expected Json Object as PatientIssue, but got $json") + } + + } + + implicit val patientIssueWriter = new RootJsonWriter[PatientIssue] { + override def write(obj: PatientIssue) = JsObject( + "id" -> obj.id.toJson, + "text" -> obj.text.toJson, + "lastUpdate" -> obj.lastUpdate.toJson, + "userId" -> obj.userId.toJson, + "isDraft" -> obj.isDraft.toJson, + "archiveRequired" -> obj.archiveRequired.toJson + ) + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala deleted file mode 100644 index eadd1f8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patientissue - -import java.time.LocalDateTime - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities.{Patient, PatientIssue} - -final case class ApiPartialPatientIssue(text: String, archiveRequired: Boolean) { - def applyTo(x: PatientIssue): PatientIssue = x.copy( - text = text, - archiveRequired = archiveRequired - ) - - def toDomain(userId: StringId[User], patientId: UuidId[Patient]) = - PatientIssue( - id = LongId(0), - userId = userId, - patientId = patientId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - archiveRequired = false - ) -} - -object ApiPartialPatientIssue { - implicit val format: Format[ApiPartialPatientIssue] = ( - (JsPath \ "text").format[String] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiPartialPatientIssue.apply, unlift(ApiPartialPatientIssue.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala deleted file mode 100644 index d1a216c..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patientissue - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuidomain.entities.PatientIssue - -final case class ApiPatientIssue(id: Long, - text: String, - lastUpdate: ZonedDateTime, - userId: String, - isDraft: Boolean, - archiveRequired: Boolean) - -object ApiPatientIssue { - implicit val format: Format[ApiPatientIssue] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "text").format[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "userId").format[String] and - (JsPath \ "isDraft").format[Boolean] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiPatientIssue.apply, unlift(ApiPatientIssue.unapply)) - - def fromDomain(x: PatientIssue) = ApiPatientIssue( - id = x.id.id, - text = x.text, - lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), - userId = x.userId.id, - isDraft = x.isDraft, - archiveRequired = x.archiveRequired - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientlabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientlabel.scala new file mode 100644 index 0000000..15fec45 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientlabel.scala @@ -0,0 +1,67 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.entities.labels.LabelValue +import xyz.driver.formats.json.labels._ +import xyz.driver.pdsuidomain.entities._ +import xyz.driver.pdsuidomain.services.PatientLabelService.RichPatientLabel +import xyz.driver.formats.json.labels._ +import xyz.driver.pdsuidomain.formats.json.record._ +import xyz.driver.pdsuidomain.formats.json.document._ + +object patientlabel { + import DefaultJsonProtocol._ + import common._ + + def applyUpdateToPatientLabel(json: JsValue, orig: PatientLabel): PatientLabel = json match { + case JsObject(fields) => + val primaryValue = fields + .get("primaryValue") + .map(_.convertTo[Option[LabelValue]]) + .getOrElse(orig.primaryValue) + + val verifiedPrimaryValue = fields + .get("verifiedPrimaryValue") + .map(_.convertTo[Option[LabelValue]]) + .getOrElse(orig.verifiedPrimaryValue) + + orig.copy( + primaryValue = primaryValue, + verifiedPrimaryValue = verifiedPrimaryValue + ) + + case _ => deserializationError(s"Expected Json Object as PatientLabel, but got $json") + } + + implicit val richPatientLabelWriter: RootJsonWriter[RichPatientLabel] = new RootJsonWriter[RichPatientLabel] { + override def write(obj: RichPatientLabel): JsValue = { + JsObject( + "id" -> obj.patientLabel.id.toJson, + "labelId" -> obj.patientLabel.labelId.toJson, + "primaryValue" -> obj.patientLabel.primaryValue.toJson, + "verifiedPrimaryValue" -> obj.patientLabel.verifiedPrimaryValue.toJson, + "score" -> obj.patientLabel.score.toJson, + "isImplicitMatch" -> obj.patientLabel.isImplicitMatch.toJson, + "isVisible" -> obj.patientLabel.isVisible.toJson, + "isVerified" -> obj.isVerified.toJson + ) + } + } + + implicit val patientLabelEvidenceWriter: RootJsonWriter[PatientLabelEvidenceView] = + new RootJsonWriter[PatientLabelEvidenceView] { + override def write(evidence: PatientLabelEvidenceView): JsValue = + JsObject( + "id" -> evidence.id.toJson, + "value" -> evidence.value.toJson, + "evidenceText" -> evidence.evidenceText.toJson, + "documentId" -> evidence.documentId.toJson, + "evidenceId" -> evidence.evidenceId.toJson, + "reportId" -> evidence.reportId.toJson, + "documentType" -> evidence.documentType.toJson, + "date" -> evidence.date.toJson, + "providerType" -> evidence.providerType.toJson + ) + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/queue/ApiQueueUploadItem.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/queue/ApiQueueUploadItem.scala deleted file mode 100644 index cd76670..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/queue/ApiQueueUploadItem.scala +++ /dev/null @@ -1,38 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.queue - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue -import play.api.libs.json.{Format, Json} - -final case class ApiQueueUploadItem(kind: String, - tag: String, - created: LocalDateTime, - attempts: Int, - nextAttempt: LocalDateTime, - completed: Boolean) { - def toDomain = BridgeUploadQueue.Item( - kind = kind, - tag = tag, - created = created, - attempts = attempts, - nextAttempt = nextAttempt, - completed = true, - dependencyKind = None, - dependencyTag = None - ) -} - -object ApiQueueUploadItem { - - def fromDomain(domain: BridgeUploadQueue.Item) = ApiQueueUploadItem( - kind = domain.kind, - tag = domain.tag, - created = domain.created, - attempts = domain.attempts, - nextAttempt = domain.nextAttempt, - completed = domain.completed - ) - - implicit val format: Format[ApiQueueUploadItem] = Json.format[ApiQueueUploadItem] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record.scala new file mode 100644 index 0000000..9a8dc9c --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record.scala @@ -0,0 +1,228 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime +import java.util.UUID + +import spray.json._ +import xyz.driver.core.json.{EnumJsonFormat, GadtJsonFormat} +import xyz.driver.pdsuicommon.domain.{LongId, TextJson, UuidId} +import xyz.driver.pdsuidomain.entities.MedicalRecord.Meta._ +import xyz.driver.pdsuidomain.entities._ + +object record { + import DefaultJsonProtocol._ + import MedicalRecord._ + import common._ + + implicit val recordStatusFormat = new EnumJsonFormat[Status]( + "Unprocessed" -> Status.Unprocessed, + "PreOrganized" -> Status.PreOrganized, + "New" -> Status.New, + "Cleaned" -> Status.Cleaned, + "PreOrganized" -> Status.PreOrganized, + "PreOrganizing" -> Status.PreOrganizing, + "Reviewed" -> Status.Reviewed, + "Organized" -> Status.Organized, + "Done" -> Status.Done, + "Flagged" -> Status.Flagged, + "Archived" -> Status.Archived + ) + + implicit val requestIdFormat = new RootJsonFormat[RecordRequestId] { + override def write(requestId: RecordRequestId): JsString = JsString(requestId.toString) + override def read(json: JsValue): RecordRequestId = json match { + case JsString(value) => RecordRequestId(UUID.fromString(value)) + case _ => deserializationError(s"Expected string as RecordRequestId, but got $json") + } + } + + implicit val providerTypeFormat: RootJsonFormat[ProviderType] = new RootJsonFormat[ProviderType] { + override def read(json: JsValue): ProviderType = json match { + case JsObject(fields) => + val name = fields + .get("name") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"Provider type json object does not contain `name` field: $json")) + + ProviderType + .fromString(name) + .getOrElse(deserializationError(s"Unknown provider type: $name")) + + case _ => deserializationError(s"Expected Json Object as Provider type, but got $json") + } + + override def write(obj: ProviderType) = + JsObject("id" -> obj.id.toJson, "name" -> obj.name.toJson) + } + + implicit val caseIdFormat = new RootJsonFormat[CaseId] { + override def write(caseId: CaseId): JsString = JsString(caseId.toString) + override def read(json: JsValue): CaseId = json match { + case JsString(value) => CaseId(value) + case _ => deserializationError(s"Expected string as CaseId, but got $json") + } + } + + implicit val duplicateMetaFormat: RootJsonFormat[Duplicate] = new RootJsonFormat[Duplicate] { + override def write(obj: Duplicate) = + JsObject( + "type" -> "duplicate".toJson, + "startPage" -> obj.startPage.toJson, + "endPage" -> obj.endPage.toJson, + "startOriginalPage" -> obj.startOriginalPage.toJson, + "endOriginalPage" -> obj.endOriginalPage.toJson + ) + + override def read(json: JsValue): Duplicate = json match { + case JsObject(fields) => + val startPage = fields + .get("startPage") + .map(_.convertTo[Double]) + .getOrElse(deserializationError(s"Duplicate meta json object does not contain `startPage` field: $json")) + + val endPage = fields + .get("endPage") + .map(_.convertTo[Double]) + .getOrElse(deserializationError(s"Duplicate meta json object does not contain `endPage` field: $json")) + + val startOriginalPage = fields + .get("startOriginalPage") + .map(_.convertTo[Double]) + .getOrElse( + deserializationError(s"Duplicate meta json object does not contain `startOriginalPage` field: $json")) + + val endOriginalPage = fields + .get("endOriginalPage") + .map(_.convertTo[Double]) + + Duplicate( + startPage = startPage, + endPage = endPage, + startOriginalPage = startOriginalPage, + endOriginalPage = endOriginalPage + ) + + case _ => deserializationError(s"Expected JsObject as Duplicate meta of medical record, but got $json") + } + } + + implicit val reorderMetaFormat: RootJsonFormat[Reorder] = new RootJsonFormat[Reorder] { + override def write(obj: Reorder) = + JsObject("type" -> "reorder".toJson, "items" -> obj.items.toJson) + + override def read(json: JsValue): Reorder = json match { + case JsObject(fields) => + val items = fields + .get("items") + .map(_.convertTo[Seq[Int]]) + .getOrElse(deserializationError(s"Reorder meta json object does not contain `items` field: $json")) + + Reorder(items) + + case _ => deserializationError(s"Expected JsObject as Reorder meta of medical record, but got $json") + } + } + + implicit val rotateMetaFormat: RootJsonFormat[Rotation] = new RootJsonFormat[Rotation] { + override def write(obj: Rotation) = + JsObject("type" -> "rotation".toJson, "items" -> obj.items.toJson) + + override def read(json: JsValue): Rotation = json match { + case JsObject(fields) => + val items = fields + .get("items") + .map(_.convertTo[Map[String, Int]]) + .getOrElse(deserializationError(s"Rotation meta json object does not contain `items` field: $json")) + + Rotation(items = items) + + case _ => deserializationError(s"Expected JsObject as Rotation meta of medical record, but got $json") + } + } + + implicit val recordMetaTypeFormat: GadtJsonFormat[MedicalRecord.Meta] = { + GadtJsonFormat.create[Meta]("type")({ case m => m.metaType }) { + case "duplicate" => duplicateMetaFormat + case "reorder" => reorderMetaFormat + case "rotation" => rotateMetaFormat + } + } + + implicit val recordMetaFormat = new RootJsonFormat[TextJson[List[Meta]]] { + override def write(obj: TextJson[List[Meta]]): JsArray = JsArray(obj.content.map(_.toJson).toVector) + override def read(json: JsValue): TextJson[List[Meta]] = json match { + case JsArray(values) => TextJson[List[Meta]](values.map(_.convertTo[Meta]).toList) + case _ => deserializationError(s"Expected array as Meta, but got $json") + } + } + + implicit val recordFormat: RootJsonFormat[MedicalRecord] = + new RootJsonFormat[MedicalRecord] { + override def write(record: MedicalRecord): JsValue = + JsObject( + "id" -> record.id.toJson, + "patientId" -> record.patientId.toJson, + "caseId" -> record.caseId.toJson, + "disease" -> record.disease.toJson, + "physician" -> record.physician.toJson, + "status" -> record.status.toJson, + "previousStatus" -> record.previousStatus.toJson, + "assignee" -> record.assignee.toJson, + "previousAssignee" -> record.previousAssignee.toJson, + "requestId" -> record.requestId.toJson, + "meta" -> record.meta.getOrElse(TextJson[List[Meta]](List.empty)).toJson, + "lastActiveUser" -> record.lastActiveUserId.toJson, + "lastUpdate" -> record.lastUpdate.toJson, + "totalPages" -> record.totalPages.toJson + ) + + override def read(json: JsValue): MedicalRecord = json match { + case JsObject(fields) => + val disease = fields + .get("disease") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"MedicalRecord json object does not contain `disease` field: $json")) + + val patientId = fields + .get("patientId") + .map(_.convertTo[UuidId[Patient]]) + .getOrElse(deserializationError(s"MedicalRecord json object does not contain `patientId` field: $json")) + + val requestId = fields + .get("requestId") + .map(_.convertTo[RecordRequestId]) + .getOrElse(deserializationError(s"MedicalRecord json object does not contain `requestId` field: $json")) + + MedicalRecord( + id = LongId(0), + status = MedicalRecord.Status.New, + previousStatus = None, + assignee = None, + previousAssignee = None, + lastActiveUserId = None, + patientId = patientId, + requestId = requestId, + disease = disease, + caseId = None, + physician = None, + meta = None, + lastUpdate = LocalDateTime.now(), + totalPages = 0 + ) + + case _ => deserializationError(s"Expected Json Object as MedicalRecord, but got $json") + } + } + + def applyUpdateToMedicalRecord(json: JsValue, orig: MedicalRecord): MedicalRecord = json match { + case JsObject(fields) => + val meta = fields + .get("meta") + .map(_.convertTo[Option[TextJson[List[Meta]]]]) + .getOrElse(orig.meta) + orig.copy(meta = meta) + + case _ => deserializationError(s"Expected Json Object as partial MedicalRecord, but got $json") + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiCreateRecord.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiCreateRecord.scala deleted file mode 100644 index fd14f7c..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiCreateRecord.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.record - -import java.time.LocalDateTime -import java.util.UUID - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import play.api.libs.json._ - -final case class ApiCreateRecord(disease: String, patientId: String, requestId: UUID) { - - def toDomain = MedicalRecord( - id = LongId(0), - status = MedicalRecord.Status.New, - previousStatus = None, - assignee = None, - previousAssignee = None, - lastActiveUserId = None, - patientId = UuidId(patientId), - requestId = RecordRequestId(requestId), - disease = disease, - caseId = None, - physician = None, - meta = None, - lastUpdate = LocalDateTime.now(), - totalPages = 0 - ) -} - -object ApiCreateRecord { - - implicit val format: Format[ApiCreateRecord] = Json.format[ApiCreateRecord] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiRecord.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiRecord.scala deleted file mode 100644 index 00441a1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiRecord.scala +++ /dev/null @@ -1,110 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.record - -import java.time.{ZoneId, ZonedDateTime} -import java.util.UUID - -import xyz.driver.pdsuidomain.entities.CaseId -import xyz.driver.pdsuidomain.entities.MedicalRecord -import xyz.driver.pdsuidomain.entities.MedicalRecord.Status -import xyz.driver.pdsuidomain.entities.RecordRequestId -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.json.JsonSerializer -import xyz.driver.pdsuicommon.domain.{LongId, StringId, TextJson, UuidId} - -object ApiRecord { - - private val emptyMeta: String = - "[]" - - private val statusFormat = Format( - Reads.StringReads.filter(ValidationError("unknown status")) { - case x if MedicalRecordStatus.statusFromString.isDefinedAt(x) => true - case _ => false - }, - Writes.StringWrites - ) - - implicit val format: Format[ApiRecord] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "patientId").format[String] and - (JsPath \ "caseId").formatNullable[String] and - (JsPath \ "disease").format[String] and - (JsPath \ "physician").formatNullable[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "status").format(statusFormat) and - (JsPath \ "previousStatus").formatNullable(statusFormat) and - (JsPath \ "assignee").formatNullable[String] and - (JsPath \ "previousAssignee").formatNullable[String] and - (JsPath \ "lastActiveUser").formatNullable[String] and - (JsPath \ "requestId").format[UUID] and - (JsPath \ "meta").format(Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) and - (JsPath \ "totalPages").format[Int] - )(ApiRecord.apply, unlift(ApiRecord.unapply)) - - def fromDomain(record: MedicalRecord) = ApiRecord( - id = record.id.id, - patientId = record.patientId.toString, - caseId = record.caseId.map(_.id), - disease = record.disease, - physician = record.physician, - lastUpdate = ZonedDateTime.of(record.lastUpdate, ZoneId.of("Z")), - status = MedicalRecordStatus.statusToString(record.status), - previousStatus = record.previousStatus.map(MedicalRecordStatus.statusToString), - assignee = record.assignee.map(_.id), - previousAssignee = record.previousAssignee.map(_.id), - lastActiveUser = record.lastActiveUserId.map(_.id), - requestId = record.requestId.id, - meta = record.meta.map(x => JsonSerializer.serialize(x.content)).getOrElse(emptyMeta), - totalPages = record.totalPages - ) -} - -final case class ApiRecord(id: Long, - patientId: String, - caseId: Option[String], - disease: String, - physician: Option[String], - lastUpdate: ZonedDateTime, - status: String, - previousStatus: Option[String], - assignee: Option[String], - previousAssignee: Option[String], - lastActiveUser: Option[String], - requestId: UUID, - meta: String, - totalPages: Int) { - - private def extractStatus(status: String): Status = - Status - .fromString(status) - .getOrElse( - throw new NoSuchElementException(s"Status $status not found") - ) - - def toDomain = MedicalRecord( - id = LongId(this.id), - status = extractStatus(this.status), - previousStatus = this.previousStatus.map(extractStatus), - assignee = this.assignee.map(StringId(_)), - previousAssignee = this.previousAssignee.map(StringId(_)), - lastActiveUserId = this.lastActiveUser.map(StringId(_)), - patientId = UuidId(patientId), - requestId = RecordRequestId(this.requestId), - disease = this.disease, - caseId = caseId.map(CaseId(_)), - physician = this.physician, - meta = { - if (this.meta == ApiRecord.emptyMeta) { - None - } else { - Some(TextJson(JsonSerializer.deserialize[List[MedicalRecord.Meta]](this.meta))) - } - }, - lastUpdate = this.lastUpdate.toLocalDateTime, - totalPages = 0 - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiUpdateRecord.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiUpdateRecord.scala deleted file mode 100644 index 05d5a60..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiUpdateRecord.scala +++ /dev/null @@ -1,52 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.record - -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{StringId, TextJson, User} -import xyz.driver.pdsuicommon.json.JsonSerializer -import xyz.driver.pdsuidomain.entities.MedicalRecord.Meta -import xyz.driver.pdsuidomain.entities._ - -final case class ApiUpdateRecord(status: Option[String], assignee: Tristate[String], meta: Tristate[String]) { - - def applyTo(orig: MedicalRecord): MedicalRecord = { - orig.copy( - status = status.map(MedicalRecordStatus.statusFromString).getOrElse(orig.status), - assignee = assignee.map(StringId[User]).cata(Some(_), None, orig.assignee), - meta = meta.cata(x => Some(TextJson(JsonSerializer.deserialize[List[Meta]](x))), None, orig.meta) - ) - } -} - -object ApiUpdateRecord { - - private val reads: Reads[ApiUpdateRecord] = ( - (JsPath \ "status").readNullable[String]( - Reads - .of[String] - .filter(ValidationError("unknown status"))({ - case x if MedicalRecordStatus.statusFromString.isDefinedAt(x) => true - case _ => false - })) and - (JsPath \ "assignee").readTristate[String] and - (JsPath \ "meta") - .readTristate(Reads { x => - JsSuccess(Json.stringify(x)) - }) - .map { - case Tristate.Present("[]") => Tristate.Absent - case x => x - } - )(ApiUpdateRecord.apply _) - - private val writes: Writes[ApiUpdateRecord] = ( - (JsPath \ "status").writeNullable[String] and - (JsPath \ "assignee").writeTristate[String] and - (JsPath \ "meta").writeTristate(Writes[String](Json.parse)) - )(unlift(ApiUpdateRecord.unapply)) - - implicit val format: Format[ApiUpdateRecord] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/MedicalRecordStatus.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/MedicalRecordStatus.scala deleted file mode 100644 index a77b76b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/MedicalRecordStatus.scala +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.record - -import xyz.driver.pdsuidomain.entities.MedicalRecord.Status - -object MedicalRecordStatus { - - val statusFromString: PartialFunction[String, Status] = { - case "Unprocessed" => Status.Unprocessed - case "PreCleaning" => Status.PreCleaning - case "New" => Status.New - case "Cleaned" => Status.Cleaned - case "PreOrganized" => Status.PreOrganized - case "PreOrganizing" => Status.PreOrganizing - case "Reviewed" => Status.Reviewed - case "Organized" => Status.Organized - case "Done" => Status.Done - case "Flagged" => Status.Flagged - case "Archived" => Status.Archived - } - - def statusToString(x: Status): String = x match { - case Status.Unprocessed => "Unprocessed" - case Status.PreCleaning => "PreCleaning" - case Status.New => "New" - case Status.Cleaned => "Cleaned" - case Status.PreOrganized => "PreOrganized" - case Status.PreOrganizing => "PreOrganizing" - case Status.Reviewed => "Reviewed" - case Status.Organized => "Organized" - case Status.Done => "Done" - case Status.Flagged => "Flagged" - case Status.Archived => "Archived" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory.scala new file mode 100644 index 0000000..00071e1 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory.scala @@ -0,0 +1,30 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.core.json.EnumJsonFormat +import xyz.driver.pdsuidomain.entities._ + +object recordhistory { + import DefaultJsonProtocol._ + import MedicalRecordHistory._ + import common._ + + implicit val recordStateFormat = new EnumJsonFormat[State]( + "Clean" -> State.Clean, + "Organize" -> State.Organize, + "Review" -> State.Review, + "Flag" -> State.Flag + ) + + implicit val recordActionFormat = new EnumJsonFormat[Action]( + "Start" -> Action.Start, + "Submit" -> Action.Submit, + "Unassign" -> Action.Unassign, + "Resolve" -> Action.Resolve, + "Flag" -> Action.Flag, + "Archive" -> Action.Archive + ) + + implicit val recordHistoryFormat: RootJsonFormat[MedicalRecordHistory] = jsonFormat6(MedicalRecordHistory.apply) + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory/ApiRecordHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory/ApiRecordHistory.scala deleted file mode 100644 index c55a78f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory/ApiRecordHistory.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.recordhistory - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.json.{Format, Json} -import xyz.driver.pdsuidomain.entities.MedicalRecordHistory - -final case class ApiRecordHistory(id: Long, - executor: String, - recordId: Long, - state: String, - action: String, - created: ZonedDateTime) - -object ApiRecordHistory { - implicit val format: Format[ApiRecordHistory] = - Json.format[ApiRecordHistory] - - def fromDomain(x: MedicalRecordHistory) = ApiRecordHistory( - id = x.id.id, - executor = x.executor.id, - recordId = x.recordId.id, - state = MedicalRecordHistory.State.stateToString(x.state), - action = MedicalRecordHistory.Action.actionToString(x.action), - created = ZonedDateTime.of(x.created, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue.scala new file mode 100644 index 0000000..29b12f6 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue.scala @@ -0,0 +1,68 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} +import xyz.driver.pdsuidomain.entities._ + +object recordissue { + import DefaultJsonProtocol._ + import common._ + + def applyUpdateToRecordIssue(json: JsValue, orig: MedicalRecordIssue): MedicalRecordIssue = json match { + case JsObject(fields) => + val text = fields + .get("text") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"MedicalRecordIssue json object does not contain `text` field: $json")) + + val archiveRequired = fields + .get("archiveRequired") + .map(_.convertTo[Boolean]) + .getOrElse( + deserializationError(s"MedicalRecordIssue json object does not contain `archiveRequired` field: $json")) + + val startPage = fields.get("startPage").map(_.convertTo[Double]) + val endPage = fields.get("endPage").map(_.convertTo[Double]) + + orig.copy( + text = text, + archiveRequired = archiveRequired, + startPage = startPage, + endPage = endPage + ) + + case _ => deserializationError(s"Expected Json Object as partial MedicalRecordIssue, but got $json") + + } + + def jsValueToRecordIssue(json: JsValue, + recordId: LongId[MedicalRecord], + userId: StringId[User]): MedicalRecordIssue = json match { + case JsObject(fields) => + val text = fields + .get("text") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"MedicalRecordIssue json object does not contain `text` field: $json")) + + val startPage = fields.get("startPage").map(_.convertTo[Double]) + val endPage = fields.get("endPage").map(_.convertTo[Double]) + MedicalRecordIssue( + id = LongId(0), + userId = userId, + recordId = recordId, + lastUpdate = LocalDateTime.MIN, + isDraft = true, + text = text, + archiveRequired = false, + startPage = startPage, + endPage = endPage + ) + + case _ => deserializationError(s"Expected Json Object as MedicalRecordIssue, but got $json") + } + + implicit val recordIssueFormat = jsonFormat9(MedicalRecordIssue.apply) + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala deleted file mode 100644 index 890ad69..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala +++ /dev/null @@ -1,42 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.recordissue - -import java.time.LocalDateTime - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities.{MedicalRecord, MedicalRecordIssue} - -final case class ApiPartialRecordIssue(startPage: Option[Double], - endPage: Option[Double], - text: String, - archiveRequired: Boolean) { - def applyTo(x: MedicalRecordIssue): MedicalRecordIssue = x.copy( - startPage = startPage, - endPage = endPage, - text = text, - archiveRequired = archiveRequired - ) - - def toDomain(userId: StringId[User], recordId: LongId[MedicalRecord]) = - MedicalRecordIssue( - id = LongId(0), - userId = userId, - recordId = recordId, - startPage = startPage, - endPage = endPage, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - archiveRequired = false - ) -} - -object ApiPartialRecordIssue { - implicit val format: Format[ApiPartialRecordIssue] = ( - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "text").format[String] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiPartialRecordIssue.apply, unlift(ApiPartialRecordIssue.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala deleted file mode 100644 index 45bc469..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala +++ /dev/null @@ -1,40 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.recordissue - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuidomain.entities.MedicalRecordIssue - -final case class ApiRecordIssue(id: Long, - startPage: Option[Double], - endPage: Option[Double], - text: String, - lastUpdate: ZonedDateTime, - userId: String, - isDraft: Boolean, - archiveRequired: Boolean) - -object ApiRecordIssue { - implicit val format: Format[ApiRecordIssue] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "text").format[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "userId").format[String] and - (JsPath \ "isDraft").format[Boolean] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiRecordIssue.apply, unlift(ApiRecordIssue.unapply)) - - def fromDomain(x: MedicalRecordIssue) = ApiRecordIssue( - id = x.id.id, - startPage = x.startPage, - endPage = x.endPage, - text = x.text, - lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), - userId = x.userId.id, - isDraft = x.isDraft, - archiveRequired = x.archiveRequired - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionRequest.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionRequest.scala deleted file mode 100644 index fbe9689..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionRequest.scala +++ /dev/null @@ -1,12 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.session - -import xyz.driver.pdsuicommon.domain.Email -import play.api.libs.json._ -import xyz.driver.pdsuicommon.json.Serialization._ - -final case class NewSessionRequest(email: Email, password: String) - -object NewSessionRequest { - - implicit val format: Format[NewSessionRequest] = Json.format[NewSessionRequest] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionResponse.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionResponse.scala deleted file mode 100644 index 55e05b1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionResponse.scala +++ /dev/null @@ -1,11 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.session - -import play.api.libs.json.Json -import xyz.driver.pdsuidomain.formats.json.user.ApiUser - -final case class NewSessionResponse(token: String, user: ApiUser) - -object NewSessionResponse { - - implicit val format = Json.format[NewSessionResponse] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm.scala new file mode 100644 index 0000000..7867cd6 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm.scala @@ -0,0 +1,44 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.{SlotArm, Trial} + +object slotarm { + import DefaultJsonProtocol._ + import common._ + + def applyUpdateToArm(json: JsValue, orig: SlotArm): SlotArm = json match { + case JsObject(fields) => + val name = fields + .get("name") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"Arm json object does not contain `name` field: $json")) + orig.copy(name = name) + + case _ => deserializationError(s"Expected Json Object as partial Arm, but got $json") + } + + implicit def slotArmFormat: RootJsonFormat[SlotArm] = new RootJsonFormat[SlotArm] { + override def write(obj: SlotArm): JsValue = + JsObject( + "id" -> obj.id.toJson, + "name" -> obj.name.toJson, + "originalName" -> obj.originalName.toJson, + "trialId" -> obj.trialId.toJson + ) + + override def read(json: JsValue): SlotArm = json.asJsObject.getFields("trialId", "name") match { + case Seq(trialId, name) => + SlotArm( + id = LongId(0), + name = name.convertTo[String], + trialId = trialId.convertTo[StringId[Trial]], + originalName = name.convertTo[String] + ) + + case _ => deserializationError(s"Expected Json Object as Arm, but got $json") + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiPartialSlotArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiPartialSlotArm.scala deleted file mode 100644 index 2f8e93f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiPartialSlotArm.scala +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.slotarm - -import xyz.driver.pdsuidomain.entities.SlotArm -import play.api.libs.json.{Format, Json} - -final case class ApiPartialSlotArm(name: String) { - - def applyTo(arm: SlotArm): SlotArm = arm.copy(name = name) -} - -object ApiPartialSlotArm { - - implicit val format: Format[ApiPartialSlotArm] = Json.format -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiSlotArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiSlotArm.scala deleted file mode 100644 index 375c1a2..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiSlotArm.scala +++ /dev/null @@ -1,35 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.slotarm - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.SlotArm -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiSlotArm(id: Long, name: String, originalName: String, trialId: String) { - - def toDomain: SlotArm = SlotArm( - id = LongId(this.id), - name = this.name, - originalName = this.originalName, - trialId = StringId(this.trialId), - deleted = None // if we have an ApiSlotArm object, the SlotArm itself has not been deleted - ) - -} - -object ApiSlotArm { - - implicit val format: Format[ApiSlotArm] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] and - (JsPath \ "originalName").format[String] and - (JsPath \ "trialId").format[String] - )(ApiSlotArm.apply, unlift(ApiSlotArm.unapply)) - - def fromDomain(arm: SlotArm): ApiSlotArm = ApiSlotArm( - id = arm.id.id, - name = arm.name, - originalName = arm.originalName, - trialId = arm.trialId.id - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiSlotCreateArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiSlotCreateArm.scala deleted file mode 100644 index 3e52c13..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/slotarm/ApiSlotCreateArm.scala +++ /dev/null @@ -1,20 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.slotarm - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.SlotArm -import play.api.libs.json.{Format, Json} - -final case class ApiCreateSlotArm(name: String, trialId: String) { - - def toDomain = SlotArm( - id = LongId(0), - name = name, - trialId = StringId(trialId), - originalName = name - ) -} - -object ApiCreateSlotArm { - - implicit val format: Format[ApiCreateSlotArm] = Json.format[ApiCreateSlotArm] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/arm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/arm.scala deleted file mode 100644 index e182b4b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/arm.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities._ - -object arm { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToArm(json: JsValue, orig: Arm): Arm = json match { - case JsObject(fields) => - val name = fields - .get("name") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"Arm json object does not contain `name` field: $json")) - orig.copy(name = name) - - case _ => deserializationError(s"Expected Json Object as partial Arm, but got $json") - } - - implicit val armFormat: RootJsonFormat[Arm] = new RootJsonFormat[Arm] { - override def write(obj: Arm): JsValue = - JsObject( - "id" -> obj.id.toJson, - "name" -> obj.name.toJson, - "originalName" -> obj.originalName.toJson, - "trialId" -> obj.trialId.toJson - ) - - override def read(json: JsValue): Arm = json.asJsObject.getFields("trialId", "name") match { - case Seq(trialId, name) => - Arm( - id = LongId(0), - name = name.convertTo[String], - trialId = trialId.convertTo[StringId[Trial]], - originalName = name.convertTo[String] - ) - - case _ => deserializationError(s"Expected Json Object as Arm, but got $json") - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/bridgeuploadqueue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/bridgeuploadqueue.scala deleted file mode 100644 index 77fb4d2..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/bridgeuploadqueue.scala +++ /dev/null @@ -1,68 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue.Item - -object bridgeuploadqueue { - import DefaultJsonProtocol._ - import common._ - - implicit val queueUploadItemFormat: RootJsonFormat[BridgeUploadQueue.Item] = new RootJsonFormat[Item] { - override def write(obj: Item) = - JsObject( - "kind" -> obj.kind.toJson, - "tag" -> obj.tag.toJson, - "created" -> obj.created.toJson, - "attempts" -> obj.attempts.toJson, - "nextAttempt" -> obj.nextAttempt.toJson, - "completed" -> obj.completed.toJson - ) - - override def read(json: JsValue): Item = json match { - case JsObject(fields) => - val kind = fields - .get("kind") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"BridgeUploadQueue.Item json object does not contain `kind` field: $json")) - - val tag = fields - .get("tag") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"BridgeUploadQueue.Item json object does not contain `tag` field: $json")) - - val created = fields - .get("created") - .map(_.convertTo[LocalDateTime]) - .getOrElse( - deserializationError(s"BridgeUploadQueue.Item json object does not contain `created` field: $json")) - - val attempts = fields - .get("attempts") - .map(_.convertTo[Int]) - .getOrElse( - deserializationError(s"BridgeUploadQueue.Item json object does not contain `attempts` field: $json")) - - val nextAttempt = fields - .get("nextAttempt") - .map(_.convertTo[LocalDateTime]) - .getOrElse( - deserializationError(s"BridgeUploadQueue.Item json object does not contain `nextAttempt` field: $json")) - - BridgeUploadQueue.Item( - kind = kind, - tag = tag, - created = created, - attempts = attempts, - nextAttempt = nextAttempt, - completed = true, - dependencyKind = None, - dependencyTag = None - ) - - case _ => deserializationError(s"Expected Json Object as BridgeUploadQueue.Item, but got $json") - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/common.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/common.scala deleted file mode 100644 index 61e0e7f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/common.scala +++ /dev/null @@ -1,66 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{LocalDate, LocalDateTime, ZoneId, ZonedDateTime} - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} - -object common { - - implicit def longIdFormat[T] = new RootJsonFormat[LongId[T]] { - override def write(id: LongId[T]): JsNumber = JsNumber(id.id) - override def read(json: JsValue): LongId[T] = json match { - case JsNumber(value) => LongId(value.toLong) - case _ => deserializationError(s"Expected number as LongId, but got $json") - } - } - - implicit def stringIdFormat[T] = new RootJsonFormat[StringId[T]] { - override def write(id: StringId[T]): JsString = JsString(id.toString) - override def read(json: JsValue): StringId[T] = json match { - case JsString(value) => StringId(value) - case _ => deserializationError(s"Expected string as StringId, but got $json") - } - } - - implicit def uuidIdFormat[T] = new RootJsonFormat[UuidId[T]] { - override def write(id: UuidId[T]): JsString = JsString(id.toString) - override def read(json: JsValue): UuidId[T] = json match { - case JsString(value) => UuidId(value) - case _ => deserializationError(s"Expected string as UuidId, but got $json") - } - } - - implicit def dateTimeFormat = new RootJsonFormat[LocalDateTime] { - override def write(date: LocalDateTime): JsString = JsString(ZonedDateTime.of(date, ZoneId.of("Z")).toString) - override def read(json: JsValue): LocalDateTime = json match { - case JsString(value) => ZonedDateTime.parse(value).toLocalDateTime - case _ => deserializationError(s"Expected date as LocalDateTime, but got $json") - } - } - - implicit def zonedDateTimeFormat = new RootJsonFormat[ZonedDateTime] { - override def write(date: ZonedDateTime): JsString = JsString(date.toString) - override def read(json: JsValue): ZonedDateTime = json match { - case JsString(value) => ZonedDateTime.parse(value) - case _ => deserializationError(s"Expected date as ZonedDateTime, but got $json") - } - } - - implicit def dateFormat = new RootJsonFormat[LocalDate] { - override def write(date: LocalDate): JsString = JsString(date.toString) - override def read(json: JsValue): LocalDate = json match { - case JsString(value) => LocalDate.parse(value) - case _ => deserializationError(s"Expected date as LocalDate, but got $json") - } - } - - implicit val integerFormat: RootJsonFormat[Integer] = new RootJsonFormat[Integer] { - override def write(obj: Integer): JsNumber = JsNumber(obj.intValue()) - override def read(json: JsValue): Integer = json match { - case JsNumber(value) => value.toInt - case _ => deserializationError(s"Expected number as Integer, but got $json") - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/criterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/criterion.scala deleted file mode 100644 index acf952d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/criterion.scala +++ /dev/null @@ -1,171 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.entities.labels.{Label, LabelCategory} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion - -object criterion { - import DefaultJsonProtocol._ - import common._ - - implicit val criterionLabelWriter: RootJsonWriter[CriterionLabel] = new RootJsonWriter[CriterionLabel] { - override def write(obj: CriterionLabel) = JsObject( - "labelId" -> obj.labelId.toJson, - "categoryId" -> obj.categoryId.toJson, - "value" -> obj.value.map { - case true => "Yes" - case false => "No" - }.toJson, - "isDefining" -> obj.isDefining.toJson - ) - } - - def jsValueToCriterionLabel(json: JsValue, criterionId: LongId[Criterion]): CriterionLabel = json match { - case JsObject(fields) => - val labelId = fields - .get("labelId") - .flatMap(_.convertTo[Option[LongId[Label]]]) - - val categoryId = fields - .get("categoryId") - .flatMap(_.convertTo[Option[LongId[LabelCategory]]]) - - val value = fields - .get("value") - .flatMap(_.convertTo[Option[String]]) - .map { - case "Yes" => true - case "No" => false - case other => - deserializationError(s"Unknown `value` of CriterionLabel object: expected `yes` or `no`, but got $other") - } - - val isDefining = fields - .get("isDefining") - .map(_.convertTo[Boolean]) - .getOrElse(deserializationError(s"CriterionLabel json object does not contain `isDefining` field: $json")) - - CriterionLabel( - id = LongId(0L), - labelId = labelId, - criterionId = criterionId, - categoryId = categoryId, - value = value, - isDefining = isDefining - ) - - case _ => deserializationError(s"Expected Json Object as CriterionLabel, but got $json") - } - - def applyUpdateToCriterion(json: JsValue, orig: RichCriterion): RichCriterion = json match { - case JsObject(fields) => - val text = fields - .get("text") - .map(_.convertTo[String]) - - val isCompound = fields - .get("isCompound") - .exists(_.convertTo[Boolean]) - - val meta = fields - .get("meta") - .map(_.convertTo[Option[String]].getOrElse("{}")) - .getOrElse(orig.criterion.meta) - - val inclusion = fields - .get("inclusion") - .map(_.convertTo[Option[Boolean]]) - .getOrElse(orig.criterion.inclusion) - - val arms = fields - .get("arms") - .map(_.convertTo[Option[List[LongId[EligibilityArm]]]].getOrElse(List.empty[LongId[EligibilityArm]])) - .getOrElse(orig.armIds) - - val labels = fields - .get("labels") - .map(_.convertTo[Option[List[JsValue]]].getOrElse(List.empty[JsValue])) - .map(_.map(l => jsValueToCriterionLabel(l, orig.criterion.id))) - .getOrElse(orig.labels) - - orig.copy( - criterion = orig.criterion.copy( - meta = meta, - text = text, - isCompound = isCompound, - inclusion = inclusion - ), - armIds = arms, - labels = labels - ) - - case _ => deserializationError(s"Expected Json Object as partial Criterion, but got $json") - } - - implicit val richCriterionFormat: RootJsonFormat[RichCriterion] = new RootJsonFormat[RichCriterion] { - override def write(obj: RichCriterion): JsValue = - JsObject( - "id" -> obj.criterion.id.toJson, - "meta" -> Option(obj.criterion.meta).toJson, - "arms" -> obj.armIds.toJson, - "text" -> obj.criterion.text.toJson, - "isCompound" -> obj.criterion.isCompound.toJson, - "labels" -> obj.labels.map(_.toJson).toJson, - "trialId" -> obj.criterion.trialId.toJson, - "inclusion" -> obj.criterion.inclusion.toJson - ) - - override def read(json: JsValue): RichCriterion = json match { - case JsObject(fields) => - val trialId = fields - .get("trialId") - .map(_.convertTo[StringId[Trial]]) - .getOrElse(deserializationError(s"Criterion json object does not contain `trialId` field: $json")) - - val text = fields - .get("text") - .flatMap(_.convertTo[Option[String]]) - - val isCompound = fields - .get("isCompound") - .exists(_.convertTo[Boolean]) - - val meta = fields - .get("meta") - .flatMap(_.convertTo[Option[String]]) - - val inclusion = fields - .get("inclusion") - .flatMap(_.convertTo[Option[Boolean]]) - - val arms = fields - .get("arms") - .map(_.convertTo[Seq[LongId[EligibilityArm]]]) - .getOrElse(Seq.empty[LongId[EligibilityArm]]) - - val labels = fields - .get("labels") - .map(_.convertTo[Seq[JsValue]]) - .map(_.map(l => jsValueToCriterionLabel(l, LongId(0)))) - .getOrElse(Seq.empty[CriterionLabel]) - - RichCriterion( - criterion = Criterion( - id = LongId(0), - trialId = trialId, - text = text, - isCompound = isCompound, - meta = meta.getOrElse(""), - inclusion = inclusion - ), - armIds = arms, - labels = labels - ) - - case _ => deserializationError(s"Expected Json Object as Criterion, but got $json") - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala deleted file mode 100644 index c584b96..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala +++ /dev/null @@ -1,197 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{LocalDate, LocalDateTime} - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities._ - -object document { - import DefaultJsonProtocol._ - import Document._ - import common._ - - implicit val documentStatusFormat = new EnumJsonFormat[Status]( - "New" -> Status.New, - "Organized" -> Status.Organized, - "Extracted" -> Status.Extracted, - "Done" -> Status.Done, - "Flagged" -> Status.Flagged, - "Archived" -> Status.Archived - ) - - implicit val requiredTypeFormat = new EnumJsonFormat[RequiredType]( - "OPN" -> RequiredType.OPN, - "PN" -> RequiredType.PN - ) - - implicit val documentMetaFormat: RootJsonFormat[Meta] = jsonFormat2(Meta.apply) - - implicit val documentTypeFormat: RootJsonFormat[DocumentType] = new RootJsonFormat[DocumentType] { - override def read(json: JsValue): DocumentType = json match { - case JsObject(fields) => - val name = fields - .get("name") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"Document type json object does not contain `name` field: $json")) - - DocumentType - .fromString(name) - .getOrElse(deserializationError(s"Unknown document type: $name")) - - case _ => deserializationError(s"Expected Json Object as Document type, but got $json") - } - - override def write(obj: DocumentType) = - JsObject("id" -> obj.id.toJson, "name" -> obj.name.toJson) - } - - implicit val fullDocumentMetaFormat = new RootJsonFormat[TextJson[Meta]] { - override def write(obj: TextJson[Meta]): JsValue = obj.content.toJson - override def read(json: JsValue) = TextJson(documentMetaFormat.read(json)) - } - - def applyUpdateToDocument(json: JsValue, orig: Document): Document = json match { - case JsObject(fields) => - val physician = fields - .get("physician") - .map(_.convertTo[String]) - - val typeId = fields - .get("typeId") - .map(_.convertTo[Option[LongId[DocumentType]]]) - .getOrElse(orig.typeId) - - val provider = fields - .get("provider") - .map(_.convertTo[Option[String]]) - .getOrElse(orig.providerName) - - val providerTypeId = fields - .get("providerTypeId") - .map(_.convertTo[Option[LongId[ProviderType]]]) - .getOrElse(orig.providerTypeId) - - val institutionName = fields - .get("institutionName") - .map(_.convertTo[Option[String]]) - .getOrElse(orig.institutionName) - - val meta = fields - .get("meta") - .map(_.convertTo[Option[TextJson[Meta]]]) - .getOrElse(orig.meta) - - val startDate = fields - .get("startDate") - .map(_.convertTo[Option[LocalDate]]) - .getOrElse(orig.startDate) - - val endDate = fields - .get("endDate") - .map(_.convertTo[Option[LocalDate]]) - .getOrElse(orig.endDate) - - orig.copy( - physician = physician.orElse(orig.physician), - typeId = typeId, - providerName = provider, - providerTypeId = providerTypeId, - institutionName = institutionName, - meta = meta, - startDate = startDate, - endDate = endDate - ) - - case _ => deserializationError(s"Expected Json Object as partial Document, but got $json") - } - - implicit val documentFormat: RootJsonFormat[Document] = new RootJsonFormat[Document] { - override def write(document: Document): JsValue = - JsObject( - "id" -> document.id.toJson, - "recordId" -> document.recordId.toJson, - "physician" -> document.physician.toJson, - "typeId" -> document.typeId.toJson, - "provider" -> document.providerName.toJson, - "providerTypeId" -> document.providerTypeId.toJson, - "requiredType" -> document.requiredType.toJson, - "institutionName" -> document.institutionName.toJson, - "startDate" -> document.startDate.toJson, - "endDate" -> document.endDate.toJson, - "status" -> document.status.toJson, - "previousStatus" -> document.previousStatus.toJson, - "assignee" -> document.assignee.toJson, - "previousAssignee" -> document.previousAssignee.toJson, - "meta" -> document.meta.toJson, - "lastActiveUser" -> document.lastActiveUserId.toJson, - "lastUpdate" -> document.lastUpdate.toJson, - "labelVersion" -> document.labelVersion.toJson - ) - - override def read(json: JsValue): Document = json match { - case JsObject(fields) => - val recordId = fields - .get("recordId") - .map(_.convertTo[LongId[MedicalRecord]]) - .getOrElse(deserializationError(s"Document create json object does not contain `recordId` field: $json")) - - val physician = fields - .get("physician") - .flatMap(_.convertTo[Option[String]]) - - val typeId = fields - .get("typeId") - .flatMap(_.convertTo[Option[LongId[DocumentType]]]) - - val provider = fields - .get("provider") - .flatMap(_.convertTo[Option[String]]) - - val providerTypeId = fields - .get("providerTypeId") - .flatMap(_.convertTo[Option[LongId[ProviderType]]]) - - val institutionName = fields - .get("institutionName") - .flatMap(_.convertTo[Option[String]]) - - val meta = fields - .get("meta") - .flatMap(_.convertTo[Option[TextJson[Meta]]]) - - val startDate = fields - .get("startDate") - .flatMap(_.convertTo[Option[LocalDate]]) - - val endDate = fields - .get("endDate") - .flatMap(_.convertTo[Option[LocalDate]]) - - Document( - id = LongId(0), - recordId = recordId, - status = Document.Status.New, - physician = physician, - typeId = typeId, - startDate = startDate, - endDate = endDate, - providerName = provider, - providerTypeId = providerTypeId, - requiredType = None, - institutionName = institutionName, - meta = meta, - previousStatus = None, - assignee = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.MIN, - labelVersion = 0 - ) - - case _ => deserializationError(s"Expected Json Object as Document, but got $json") - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenthistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenthistory.scala deleted file mode 100644 index 419c252..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenthistory.scala +++ /dev/null @@ -1,29 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuidomain.entities._ - -object documenthistory { - import DefaultJsonProtocol._ - import common._ - import DocumentHistory._ - - implicit val documentStateFormat = new EnumJsonFormat[State]( - "Extract" -> State.Extract, - "Review" -> State.Review, - "Flag" -> State.Flag - ) - - implicit val documentActionFormat = new EnumJsonFormat[Action]( - "Start" -> Action.Start, - "Submit" -> Action.Submit, - "Unassign" -> Action.Unassign, - "Resolve" -> Action.Resolve, - "Flag" -> Action.Flag, - "Archive" -> Action.Archive - ) - - implicit val documentHistoryFormat: RootJsonFormat[DocumentHistory] = jsonFormat6(DocumentHistory.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documentissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documentissue.scala deleted file mode 100644 index a658cfa..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documentissue.scala +++ /dev/null @@ -1,66 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities._ - -object documentissue { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToDocumentIssue(json: JsValue, orig: DocumentIssue): DocumentIssue = json match { - case JsObject(fields) => - val text = fields - .get("text") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"DocumentIssue json object does not contain `text` field: $json")) - - val archiveRequired = fields - .get("archiveRequired") - .map(_.convertTo[Boolean]) - .getOrElse(deserializationError(s"DocumentIssue json object does not contain `archiveRequired` field: $json")) - - val startPage = fields.get("startPage").map(_.convertTo[Double]) - val endPage = fields.get("endPage").map(_.convertTo[Double]) - - orig.copy( - text = text, - archiveRequired = archiveRequired, - startPage = startPage, - endPage = endPage - ) - - case _ => deserializationError(s"Expected Json Object as partial DocumentIssue, but got $json") - - } - - def jsValueToDocumentIssue(json: JsValue, documentId: LongId[Document], userId: StringId[User]): DocumentIssue = - json match { - case JsObject(fields) => - val text = fields - .get("text") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"DocumentIssue json object does not contain `text` field: $json")) - - val startPage = fields.get("startPage").map(_.convertTo[Double]) - val endPage = fields.get("endPage").map(_.convertTo[Double]) - DocumentIssue( - id = LongId(0), - userId = userId, - documentId = documentId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - archiveRequired = false, - startPage = startPage, - endPage = endPage - ) - - case _ => deserializationError(s"Expected Json Object as DocumentIssue, but got $json") - } - - implicit val documentIssueFormat: RootJsonFormat[DocumentIssue] = jsonFormat9(DocumentIssue.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibility.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibility.scala deleted file mode 100644 index 3c2465f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibility.scala +++ /dev/null @@ -1,101 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import DefaultJsonProtocol._ -import xyz.driver.core.Id -import xyz.driver.core.json._ -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuidomain.entities.eligibility._ - -object eligibility { - import xyz.driver.formats.json.assay._ - import xyz.driver.formats.json.common._ - import xyz.driver.formats.json.labels._ - import xyz.driver.formats.json.process._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.document._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.record._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.export._ - - implicit val molecularDocumentFormat: RootJsonFormat[MolecularEvidenceDocument] = jsonFormat7( - MolecularEvidenceDocument) - implicit val clinicalDocumentFormat: RootJsonFormat[ClinicalEvidenceDocument] = jsonFormat7(ClinicalEvidenceDocument) - - implicit val evidenceDocumentFormat: RootJsonFormat[EvidenceDocument] = - GadtJsonFormat.create[EvidenceDocument]("evidenceDocumentType") { - case _: MolecularEvidenceDocument => "Molecular" - case _: ClinicalEvidenceDocument => "Clinical" - } { - case "Molecular" => molecularDocumentFormat - case "Clinical" => clinicalDocumentFormat - } - - implicit object evidenceFormat extends RootJsonFormat[Evidence] { - - override def write(evidence: Evidence): JsValue = { - JsObject( - "evidenceId" -> evidence.evidenceId.toJson, - "evidenceText" -> evidence.evidenceText.toJson, - "labelValue" -> evidence.labelValue.toJson, - "document" -> evidence.document.toJson, - "isPrimaryValue" -> evidence.isPrimaryValue.toJson - ) - } - - override def read(json: JsValue): Evidence = { - json match { - case JsObject(fields) => - val evidenceId = fields - .get("evidenceId") - .map(_.convertTo[Id[Evidence]]) - - val evidenceText = fields - .get("evidenceText") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"Evidence json object do not contain 'evidenceText' field: $json")) - - val labelValue = fields - .get("labelValue") - .map(_.convertTo[LabelValue]) - .getOrElse(deserializationError(s"Evidence json object do not contain 'labelValue' field: $json")) - - val isDriverDocument = fields - .get("document") - .flatMap { - case JsObject(fieldMap) => - fieldMap - .get("isDriverDocument") - .map(_.convertTo[Boolean]) - case _ => deserializationError(s"Expected Json Object as 'isDriverDocument', but got $json") - } - .getOrElse(deserializationError(s"Evidence json object do not contain 'document' field: $json")) - - val document = customDocumentParser(isDriverDocument, fields, json) - - val isPrimaryValue = fields - .get("isPrimaryValue") - .map(_.convertTo[Option[Boolean]]) - .getOrElse(deserializationError(s"Evidence json object do not contain 'isPrimaryValue' field: $json")) - - Evidence(evidenceId, evidenceText, labelValue, document, isPrimaryValue) - case _ => deserializationError(s"Expected Json Object as 'Evidence', but got $json") - } - } - - def customDocumentParser(isDriverDocument: Boolean, - fields: Map[String, JsValue], - json: JsValue): EvidenceDocument = { - fields.get("document").fold { deserializationError(s"Expected Json Object as 'Document', but got $json") } { - document => - if (isDriverDocument) document.convertTo[MolecularEvidenceDocument] - else document.convertTo[ClinicalEvidenceDocument] - } - } - } - - implicit def labelWithEvidenceJsonFormat: RootJsonFormat[LabelEvidence] = jsonFormat2(LabelEvidence) - - implicit def labelRankingFormat: RootJsonFormat[LabelMismatchRank] = jsonFormat4(LabelMismatchRank) - implicit def labelRankingsFormat: RootJsonFormat[MismatchRankedLabels] = jsonFormat2(MismatchRankedLabels) - - implicit def matchedPatientFormat: RootJsonFormat[MatchedPatient] = jsonFormat6(MatchedPatient) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibilityarm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibilityarm.scala deleted file mode 100644 index 039e088..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibilityarm.scala +++ /dev/null @@ -1,108 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.entities.patient.CancerType -import xyz.driver.formats.json.patient._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities._ - -object eligibilityarm { - - import DefaultJsonProtocol._ - import common._ - - private def deserializationErrorFieldMessage(field: String, json: JsValue)(implicit className: String) = { - deserializationError(s"$className json object do not contain '$field' field: $json") - } - - private def deserializationErrorEntityMessage(json: JsValue)(implicit className: String) = { - deserializationError(s"Expected Json Object as $className, but got $json") - } - - implicit def eligibilityArmWithDiseasesWriter: RootJsonWriter[EligibilityArmWithDiseases] = - new RootJsonWriter[EligibilityArmWithDiseases] { - override def write(obj: EligibilityArmWithDiseases): JsValue = { - JsObject( - "id" -> obj.eligibilityArm.id.toJson, - "name" -> obj.eligibilityArm.name.toJson, - "originalName" -> obj.eligibilityArm.originalName.toJson, - "trialId" -> obj.eligibilityArm.trialId.toJson, - "diseases" -> obj.eligibilityArmDiseases.map(_.disease.toJson).toJson - ) - } - } - - implicit def eligibilityArmWithDiseasesReader: RootJsonReader[EligibilityArmWithDiseases] = { - new RootJsonReader[EligibilityArmWithDiseases] { - implicit val className: String = "create EligibilityArmWithDiseases" - - override def read(json: JsValue): EligibilityArmWithDiseases = { - json match { - case JsObject(fields) => - val name = fields - .get("name") - .map(_.convertTo[String]) - .getOrElse(deserializationErrorFieldMessage("name", json)) - - val trialId = fields - .get("trialId") - .map(_.convertTo[StringId[Trial]]) - .getOrElse(deserializationErrorFieldMessage("trialId", json)) - - val diseases = fields - .get("diseases") - .map(_.convertTo[Seq[String]]) - .getOrElse(deserializationErrorFieldMessage("diseases", json)) - - val eligibilityArm = EligibilityArm( - id = LongId(0), - name = name, - trialId = trialId, - originalName = name - ) - - EligibilityArmWithDiseases( - eligibilityArm, - diseases.map { disease => - val condition = CancerType - .fromString(disease) - .getOrElse(throw new NoSuchElementException(s"unknown condition $disease")) - EligibilityArmDisease(eligibilityArm.id, condition) - } - ) - case _ => deserializationErrorEntityMessage(json) - } - } - } - } - - def applyUpdateToEligibilityArmWithDiseases(json: JsValue, - orig: EligibilityArmWithDiseases): EligibilityArmWithDiseases = { - implicit val className: String = "update EligibilityArmWithDiseases" - json match { - case JsObject(fields) => - val name = fields - .get("name") - .map(_.convertTo[String]) - .getOrElse(orig.eligibilityArm.name) - - val diseases = fields - .get("diseases") - .map(_.convertTo[Seq[CancerType]]) - .getOrElse(orig.eligibilityArmDiseases.map(_.disease)) - - orig.copy( - eligibilityArm = orig.eligibilityArm - .copy(name = name), - eligibilityArmDiseases = orig.eligibilityArmDiseases - .zip(diseases) - .map { - case (eligibilityArmDisease, disease) => - eligibilityArmDisease.copy(disease = disease) - } - ) - - case _ => deserializationErrorEntityMessage(json) - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala deleted file mode 100644 index 4391453..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala +++ /dev/null @@ -1,86 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.entities.labels.Label -import xyz.driver.formats.json.labels._ -import xyz.driver.pdsuidomain.entities.export.patient._ -import xyz.driver.pdsuidomain.entities.export.trial.{ExportTrialArm, ExportTrialLabelCriterion, ExportTrialWithLabels} -import xyz.driver.pdsuidomain.entities.{Criterion, EligibilityArm} - -object export { - import DefaultJsonProtocol._ - import common._ - import document._ - import record._ - - implicit val patientLabelEvidenceDocumentFormat: RootJsonFormat[ExportPatientLabelEvidenceDocument] = - jsonFormat5(ExportPatientLabelEvidenceDocument.apply) - - implicit val patientLabelEvidenceFormat: RootJsonFormat[ExportPatientLabelEvidence] = - jsonFormat(ExportPatientLabelEvidence.apply, "evidenceId", "labelValue", "evidenceText", "document") - - implicit val patientLabelFormat: RootJsonFormat[ExportPatientLabel] = - jsonFormat(ExportPatientLabel.apply, "labelId", "evidence") - - implicit val patientWithLabelsFormat: RootJsonFormat[ExportPatientWithLabels] = - jsonFormat(ExportPatientWithLabels.apply, "patientId", "labelVersion", "labels") - - implicit val trialArmFormat: RootJsonFormat[ExportTrialArm] = jsonFormat3(ExportTrialArm.apply) - - implicit val trialLabelCriterionFormat: RootJsonFormat[ExportTrialLabelCriterion] = - new RootJsonFormat[ExportTrialLabelCriterion] { - override def write(obj: ExportTrialLabelCriterion): JsValue = - JsObject( - "value" -> obj.value - .map { - case true => "Yes" - case false => "No" - } - .getOrElse("Unknown") - .toJson, - "labelId" -> obj.labelId.toJson, - "criterionId" -> obj.criterionId.toJson, - "criterionText" -> obj.criteria.toJson, - "armIds" -> obj.armIds.toJson, - "isCompound" -> obj.isCompound.toJson, - "isDefining" -> obj.isDefining.toJson - ) - - override def read(json: JsValue): ExportTrialLabelCriterion = { - - val fields = Seq("value", "labelId", "criterionId", "criterionText", "armIds", "isCompound", "isDefining") - - json.asJsObject.getFields(fields: _*) match { - case Seq(JsString(valueString), - labelId, - criterionId, - JsString(criterionText), - JsArray(armIdsVector), - JsBoolean(isCompound), - JsBoolean(isDefining)) => - val value = valueString match { - case "Yes" => Option(true) - case "No" => Option(false) - case "Unknown" => Option.empty[Boolean] - } - - ExportTrialLabelCriterion( - longIdFormat[Criterion].read(criterionId), - value, - longIdFormat[Label].read(labelId), - armIdsVector.map(longIdFormat[EligibilityArm].read).toSet, - criterionText, - isCompound, - isDefining - ) - - case _ => - deserializationError( - s"Cannot find required fields ${fields.mkString(", ")} in ExportTrialLabelCriterion object!") - } - } - } - - implicit val trialWithLabelsFormat: RootJsonFormat[ExportTrialWithLabels] = - jsonFormat(ExportTrialWithLabels.apply, "nctId", "trialId", "lastReviewed", "labelVersion", "arms", "criteria") -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/extracteddata.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/extracteddata.scala deleted file mode 100644 index 436fbe9..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/extracteddata.scala +++ /dev/null @@ -1,150 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.entities.labels.{Label, LabelCategory, LabelValue} -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData -import xyz.driver.formats.json.labels._ - -object extracteddata { - import DefaultJsonProtocol._ - import common._ - import ExtractedData._ - - implicit val metaKeywordFormat: RootJsonFormat[Meta.Keyword] = jsonFormat4(Meta.Keyword) - implicit val metaTextLayerPositionFormat: RootJsonFormat[Meta.TextLayerPosition] = jsonFormat3( - Meta.TextLayerPosition) - implicit val metaEvidenceFormat: RootJsonFormat[Meta.Evidence] = jsonFormat3(Meta.Evidence) - - implicit val extractedDataMetaFormat: RootJsonFormat[Meta] = jsonFormat2(Meta.apply) - implicit val fullExtractedDataMetaFormat = new RootJsonFormat[TextJson[Meta]] { - override def write(obj: TextJson[Meta]): JsValue = obj.content.toJson - override def read(json: JsValue): TextJson[Meta] = TextJson(extractedDataMetaFormat.read(json)) - } - - implicit val extractedDataLabelWriter: JsonWriter[ExtractedDataLabel] = new JsonWriter[ExtractedDataLabel] { - override def write(label: ExtractedDataLabel): JsObject = { - JsObject( - "id" -> label.labelId.toJson, - "categoryId" -> label.categoryId.toJson, - "value" -> label.value.toJson - ) - } - } - - def applyLabelsForExtractedData(json: JsValue, dataId: LongId[ExtractedData]): ExtractedDataLabel = json match { - case JsObject(fields) => - val labelId = fields - .get("id") - .flatMap(_.convertTo[Option[LongId[Label]]]) - - val categoryId = fields - .get("categoryId") - .flatMap(_.convertTo[Option[LongId[LabelCategory]]]) - - val value = fields - .get("value") - .flatMap(_.convertTo[Option[LabelValue]]) - - ExtractedDataLabel( - id = LongId(0), - dataId = dataId, - labelId = labelId, - categoryId = categoryId, - value = value - ) - - case _ => deserializationError(s"Expected Json Object as ExtractedDataLabel, but got $json") - } - - def applyUpdateToExtractedData(json: JsValue, orig: RichExtractedData): RichExtractedData = json match { - case JsObject(fields) => - val keywordId = fields - .get("keywordId") - .map(_.convertTo[Option[LongId[Keyword]]]) - .getOrElse(orig.extractedData.keywordId) - - val evidence = fields - .get("evidence") - .map(_.convertTo[Option[String]]) - .getOrElse(orig.extractedData.evidenceText) - - val meta = fields - .get("meta") - .map(_.convertTo[Option[TextJson[Meta]]]) - .getOrElse(orig.extractedData.meta) - - val labels = fields - .get("labels") - .map( - _.convertTo[Option[List[JsValue]]] - .getOrElse(List.empty[JsValue]) - .map(l => applyLabelsForExtractedData(l, orig.extractedData.id))) - .getOrElse(orig.labels) - - val extractedData = orig.extractedData.copy( - keywordId = keywordId, - evidenceText = evidence, - meta = meta - ) - - orig.copy( - extractedData = extractedData, - labels = labels - ) - - case _ => deserializationError(s"Expected Json Object as partial ExtractedData, but got $json") - } - - implicit val extractedDataFormat: RootJsonFormat[RichExtractedData] = new RootJsonFormat[RichExtractedData] { - override def write(richData: RichExtractedData): JsValue = - JsObject( - "id" -> richData.extractedData.id.toJson, - "documentId" -> richData.extractedData.documentId.toJson, - "keywordId" -> richData.extractedData.keywordId.toJson, - "evidence" -> richData.extractedData.evidenceText.toJson, - "meta" -> richData.extractedData.meta.toJson, - "labels" -> richData.labels.map(_.toJson).toJson - ) - - override def read(json: JsValue): RichExtractedData = json match { - case JsObject(fields) => - val documentId = fields - .get("documentId") - .map(_.convertTo[LongId[Document]]) - .getOrElse( - deserializationError(s"ExtractedData create json object does not contain `documentId` field: $json")) - - val keywordId = fields - .get("keywordId") - .flatMap(_.convertTo[Option[LongId[Keyword]]]) - - val evidence = fields - .get("evidence") - .flatMap(_.convertTo[Option[String]]) - - val meta = fields - .get("meta") - .flatMap(_.convertTo[Option[TextJson[Meta]]]) - - val labels = fields - .get("labels") - .map(_.convertTo[List[JsValue]]) - .getOrElse(List.empty[JsValue]) - .map(l => applyLabelsForExtractedData(l, LongId(0))) - - val extractedData = ExtractedData( - documentId = documentId, - keywordId = keywordId, - evidenceText = evidence, - meta = meta - ) - - RichExtractedData(extractedData, labels) - - case _ => deserializationError(s"Expected Json Object as ExtractedData, but got $json") - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/hypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/hypothesis.scala deleted file mode 100644 index c05ff23..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/hypothesis.scala +++ /dev/null @@ -1,12 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities._ - -object hypothesis { - import DefaultJsonProtocol._ - import common._ - - implicit val hypothesisFormat: RootJsonFormat[Hypothesis] = jsonFormat4(Hypothesis.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala deleted file mode 100644 index e557e47..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala +++ /dev/null @@ -1,146 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.InterventionType.DeliveryMethod -import xyz.driver.pdsuidomain.entities._ - -object intervention { - import DefaultJsonProtocol._ - import common._ - - implicit def interventionFormat: RootJsonFormat[InterventionWithArms] = new RootJsonFormat[InterventionWithArms] { - override def write(obj: InterventionWithArms) = - JsObject( - "id" -> obj.intervention.id.toJson, - "name" -> obj.intervention.name.toJson, - "typeId" -> obj.intervention.typeId.toJson, - "dosage" -> obj.intervention.dosage.toJson, - "isActive" -> obj.intervention.isActive.toJson, - "arms" -> obj.arms.map(_.armId).toJson, - "trialId" -> obj.intervention.trialId.toJson, - "deliveryMethod" -> obj.intervention.deliveryMethod.toJson, - "originalName" -> obj.intervention.originalName.toJson, - "originalDosage" -> obj.intervention.originalDosage.toJson, - "originalType" -> obj.intervention.originalType.toJson - ) - - override def read(json: JsValue): InterventionWithArms = json match { - case JsObject(fields) => - val trialId = fields - .get("trialId") - .map(_.convertTo[StringId[Trial]]) - .getOrElse(deserializationError(s"Intervention json object does not contain `trialId` field: $json")) - - val typeId = fields - .get("typeId") - .flatMap(_.convertTo[Option[LongId[InterventionType]]]) - - val name = fields - .get("name") - .map(_.convertTo[String]) - .getOrElse("") - - val dosage = fields - .get("dosage") - .map(_.convertTo[String]) - - val isActive = fields - .get("isActive") - .exists(_.convertTo[Boolean]) - - val deliveryMethod = fields - .get("deliveryMethod") - .flatMap(_.convertTo[Option[String]]) - - val arms = fields - .get("arms") - .map(_.convertTo[List[LongId[SlotArm]]]) - .map(_ map (x => InterventionArm(armId = x, interventionId = LongId(0L)))) - .getOrElse(List.empty[InterventionArm]) - - InterventionWithArms( - intervention = Intervention( - id = LongId(0L), - trialId = trialId, - name = name, - originalName = name, - typeId = typeId, - originalType = None, - dosage = dosage.getOrElse(""), - originalDosage = dosage.getOrElse(""), - isActive = isActive, - deliveryMethod = deliveryMethod - ), - arms = arms - ) - - case _ => deserializationError(s"Expected Json Object as create Intervention json, but got $json") - } - } - - def applyUpdateToInterventionWithArms(json: JsValue, orig: InterventionWithArms): InterventionWithArms = json match { - case JsObject(fields) => - val name = fields - .get("name") - .map(_.convertTo[String]) - - val typeId = fields - .get("typeId") - .map(_.convertTo[LongId[InterventionType]]) - - val dosage = fields - .get("dosage") - .map(_.convertTo[String]) - - val isActive = fields - .get("isActive") - .map(_.convertTo[Boolean]) - - val deliveryMethod = fields - .get("deliveryMethod") - .map(_.convertTo[String]) - - val origIntervention = orig.intervention - val arms = fields - .get("arms") - .map(_.convertTo[List[LongId[SlotArm]]].map(x => InterventionArm(x, orig.intervention.id))) - - orig.copy( - intervention = origIntervention.copy( - name = name.getOrElse(origIntervention.name), - typeId = typeId.orElse(origIntervention.typeId), - dosage = dosage.getOrElse(origIntervention.dosage), - isActive = isActive.getOrElse(origIntervention.isActive), - deliveryMethod = deliveryMethod.orElse(origIntervention.deliveryMethod) - ), - arms = arms.getOrElse(orig.arms) - ) - - case _ => deserializationError(s"Expected Json Object as partial Intervention, but got $json") - } - - implicit def interventionTypeFormat: JsonFormat[InterventionType] = new RootJsonFormat[InterventionType] { - override def read(json: JsValue): InterventionType = json match { - case JsObject(fields) => - val name = fields - .get("name") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"Intervention type json object does not contain `name` field: $json")) - - InterventionType - .typeFromString(name) - .getOrElse(deserializationError(s"Unknown intervention type: $name")) - - case _ => deserializationError(s"Expected Json Object as Intervention type, but got $json") - } - - override def write(obj: InterventionType) = - JsObject( - "id" -> obj.id.toJson, - "name" -> obj.name.toJson, - "deliveryMethods" -> obj.deliveryMethods.map(DeliveryMethod.methodToString).toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/listresponse.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/listresponse.scala deleted file mode 100644 index 20644dc..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/listresponse.scala +++ /dev/null @@ -1,45 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import spray.json.DefaultJsonProtocol._ -import xyz.driver.pdsuidomain.ListResponse -import xyz.driver.pdsuidomain.formats.json.sprayformats.common._ - -object listresponse { - private val itemsField = "items" - private val metaField = "meta" - - implicit val listResponseMetaFormat: RootJsonFormat[ListResponse.Meta] = jsonFormat4(ListResponse.Meta.apply) - - implicit def listResponseWriter[T: JsonWriter]: RootJsonWriter[ListResponse[T]] = - new RootJsonWriter[ListResponse[T]] { - override def write(listResponse: ListResponse[T]): JsValue = { - JsObject( - itemsField -> listResponse.items.map(_.toJson).toJson, - metaField -> listResponse.meta.toJson - ) - } - } - - implicit def listResponseReader[T: JsonReader]: RootJsonReader[ListResponse[T]] = - new RootJsonReader[ListResponse[T]] { - override def read(json: JsValue): ListResponse[T] = json match { - case JsObject(fields) => - val items = fields - .get(itemsField) - .map { - case JsArray(elements) => elements.map(_.convertTo[T])(collection.breakOut) - case x => deserializationError(s"Expected Array as JsArray, but got $x") - } - .getOrElse(deserializationError(s"ListResponse json object does not contain `$itemsField` field: $json")) - - val meta = fields - .get(metaField) - .map(_.convertTo[ListResponse.Meta]) - .getOrElse(deserializationError(s"ListResponse json object does not contain `$metaField` field: $json")) - - ListResponse(items, meta) - case _ => deserializationError(s"Expected ListResponse json object, but got $json") - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patient.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patient.scala deleted file mode 100644 index 2b0dfe5..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patient.scala +++ /dev/null @@ -1,48 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.formats.json.common._ -import xyz.driver.formats.json.patient._ - -object patient { - import DefaultJsonProtocol._ - import common._ - import Patient._ - - implicit val patientStatusFormat = new EnumJsonFormat[Status]( - "New" -> Status.New, - "Verified" -> Status.Verified, - "Reviewed" -> Status.Reviewed, - "Curated" -> Status.Curated, - "Done" -> Status.Done, - "Flagged" -> Status.Flagged - ) - - implicit val patientOrderIdFormat = new RootJsonFormat[PatientOrderId] { - override def write(orderId: PatientOrderId): JsString = JsString(orderId.toString) - override def read(json: JsValue): PatientOrderId = json match { - case JsString(value) => PatientOrderId(value) - case _ => deserializationError(s"Expected string as PatientOrderId, but got $json") - } - } - - implicit val patientWriter: RootJsonWriter[Patient] = new RootJsonWriter[Patient] { - override def write(patient: Patient): JsValue = - JsObject( - "id" -> patient.id.toJson, - "status" -> patient.status.toJson, - "name" -> patient.name.toJson, - "dob" -> patient.dob.toJson, - "assignee" -> patient.assignee.toJson, - "previousStatus" -> patient.previousStatus.toJson, - "previousAssignee" -> patient.previousAssignee.toJson, - "lastActiveUser" -> patient.lastActiveUserId.toJson, - "lastUpdate" -> patient.lastUpdate.toJson, - "disease" -> patient.disease.toJson, - "orderId" -> patient.orderId.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientcriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientcriterion.scala deleted file mode 100644 index f41c846..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientcriterion.scala +++ /dev/null @@ -1,64 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.services.PatientCriterionService.{DraftPatientCriterion, RichPatientCriterion} -import xyz.driver.formats.json.labels._ - -object patientcriterion { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToPatientCriterion(json: JsValue, orig: PatientCriterion): PatientCriterion = json match { - case JsObject(fields) => - val eligibilityStatus = fields - .get("eligibilityStatus") - .map(_.convertTo[Option[LabelValue]]) - .getOrElse(orig.eligibilityStatus) - - val verifiedEligibilityStatus = fields - .get("verifiedEligibilityStatus") - .map(_.convertTo[Option[LabelValue]]) - .getOrElse(orig.verifiedEligibilityStatus) - - orig.copy( - eligibilityStatus = eligibilityStatus, - verifiedEligibilityStatus = verifiedEligibilityStatus - ) - - case _ => deserializationError(s"Expected Json Object as partial PatientCriterion, but got $json") - } - - implicit val draftPatientCriterionFormat: RootJsonFormat[DraftPatientCriterion] = jsonFormat3( - DraftPatientCriterion.apply) - implicit val draftPatientCriterionListReader = new JsonReader[List[DraftPatientCriterion]] { - override def read(json: JsValue) = json.convertTo[List[JsValue]].map(_.convertTo[DraftPatientCriterion]) - } - - implicit val patientCriterionWriter: RootJsonWriter[RichPatientCriterion] = - new RootJsonWriter[RichPatientCriterion] { - override def write(obj: RichPatientCriterion): JsValue = { - JsObject( - "id" -> obj.patientCriterion.id.toJson, - "labelId" -> obj.labelId.toJson, - "nctId" -> obj.patientCriterion.nctId.toJson, - "criterionId" -> obj.patientCriterion.criterionId.toJson, - "criterionText" -> obj.patientCriterion.criterionText.toJson, - "criterionValue" -> obj.patientCriterion.criterionValue.map { - case true => "Yes" - case false => "No" - }.toJson, - "criterionIsDefining" -> obj.patientCriterion.criterionIsDefining.toJson, - "criterionIsCompound" -> obj.patientCriterion.criterionValue.isEmpty.toJson, - "arms" -> obj.armList.map(_.armName).toJson, - "eligibilityStatus" -> obj.patientCriterion.eligibilityStatus.toJson, - "verifiedEligibilityStatus" -> obj.patientCriterion.verifiedEligibilityStatus.toJson, - "isVerified" -> obj.patientCriterion.isVerified.toJson, - "isVisible" -> obj.patientCriterion.isVisible.toJson, - "lastUpdate" -> obj.patientCriterion.lastUpdate.toJson - ) - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientdefiningcriteria.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientdefiningcriteria.scala deleted file mode 100644 index 746c7b4..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientdefiningcriteria.scala +++ /dev/null @@ -1,19 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities.PatientLabel -import xyz.driver.formats.json.labels._ - -object patientdefiningcriteria { - import DefaultJsonProtocol._ - import common._ - - implicit val patientLabelDefiningCriteriaWriter: RootJsonWriter[PatientLabel] = new RootJsonWriter[PatientLabel] { - override def write(obj: PatientLabel) = - JsObject( - "id" -> obj.id.toJson, - "value" -> obj.verifiedPrimaryValue.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienteligibletrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienteligibletrial.scala deleted file mode 100644 index 342d3a8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienteligibletrial.scala +++ /dev/null @@ -1,40 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.services.PatientEligibleTrialService.RichPatientEligibleTrial -import xyz.driver.formats.json.labels._ - -object patienteligibletrial { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToTrialArmGroup(json: JsValue, orig: PatientTrialArmGroupView): PatientTrialArmGroupView = - json match { - case JsObject(fields) => - val isVerified = fields - .get("isVerified") - .map(_.convertTo[Boolean]) - .getOrElse(orig.isVerified) - - orig.copy(isVerified = isVerified) - - case _ => deserializationError(s"Expected Json Object as partial PatientTrialArmGroupView, but got $json") - } - - implicit val patientEligibleTrialWriter: RootJsonWriter[RichPatientEligibleTrial] = - new RootJsonWriter[RichPatientEligibleTrial] { - override def write(obj: RichPatientEligibleTrial) = - JsObject( - "id" -> obj.group.id.toJson, - "patientId" -> obj.group.patientId.toJson, - "trialId" -> obj.group.trialId.toJson, - "trialTitle" -> obj.trial.title.toJson, - "arms" -> obj.arms.map(_.armName).toJson, - "hypothesisId" -> obj.trial.hypothesisId.toJson, - "verifiedEligibilityStatus" -> obj.group.verifiedEligibilityStatus.toJson, - "isVerified" -> obj.group.isVerified.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthistory.scala deleted file mode 100644 index da7a664..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthistory.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuidomain.entities._ - -object patienthistory { - import DefaultJsonProtocol._ - import common._ - import PatientHistory._ - - implicit val patientStateFormat = new EnumJsonFormat[State]( - "Verify" -> State.Verify, - "Curate" -> State.Curate, - "Review" -> State.Review, - "Flag" -> State.Flag - ) - - implicit val patientActionFormat = new EnumJsonFormat[Action]( - "Start" -> Action.Start, - "Submit" -> Action.Submit, - "Unassign" -> Action.Unassign, - "Resolve" -> Action.Resolve, - "Flag" -> Action.Flag, - "Archive" -> Action.Archive - ) - - implicit val patientHistoryFormat: RootJsonFormat[PatientHistory] = jsonFormat6(PatientHistory.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthypothesis.scala deleted file mode 100644 index b8c0058..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthypothesis.scala +++ /dev/null @@ -1,49 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.services.PatientHypothesisService.RichPatientHypothesis - -object patienthypothesis { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToPatientHypothesis(json: JsValue, orig: PatientHypothesis): PatientHypothesis = json match { - case JsObject(fields) => - val rationale = if (fields.contains("rationale")) { - fields.get("rationale").map(_.convertTo[String]) - } else orig.rationale - - orig.copy(rationale = rationale) - - case _ => deserializationError(s"Expected Json Object as partial PatientHypothesis, but got $json") - } - - implicit val richPatientHypothesisWriter: RootJsonWriter[RichPatientHypothesis] = - new RootJsonWriter[RichPatientHypothesis] { - override def write(obj: RichPatientHypothesis): JsValue = { - JsObject( - "id" -> obj.patientHypothesis.id.toJson, - "patientId" -> obj.patientHypothesis.patientId.toJson, - "hypothesisId" -> obj.patientHypothesis.hypothesisId.toJson, - "matchedTrials" -> obj.patientHypothesis.matchedTrials.toJson, - "rationale" -> obj.patientHypothesis.rationale.toJson, - "isRationaleRequired" -> obj.isRequired.toJson - ) - } - } - - implicit val patientHypothesisWriter: RootJsonWriter[PatientHypothesis] = - new RootJsonWriter[PatientHypothesis] { - override def write(obj: PatientHypothesis): JsValue = { - JsObject( - "id" -> obj.id.toJson, - "patientId" -> obj.patientId.toJson, - "hypothesisId" -> obj.hypothesisId.toJson, - "matchedTrials" -> obj.matchedTrials.toJson, - "rationale" -> obj.rationale.toJson - ) - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientissue.scala deleted file mode 100644 index d325a53..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientissue.scala +++ /dev/null @@ -1,54 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User, UuidId} -import xyz.driver.pdsuidomain.entities._ - -object patientissue { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToPatientIssue(json: JsValue, orig: PatientIssue): PatientIssue = { - json.asJsObject.getFields("text", "archiveRequired") match { - case Seq(text, archiveRequired) => - orig.copy( - text = text.convertTo[String], - archiveRequired = archiveRequired.convertTo[Boolean] - ) - - case _ => deserializationError(s"Expected Json Object as partial PatientIssue, but got $json") - } - } - - def jsValueToPatientIssue(json: JsValue, patientId: UuidId[Patient], userId: StringId[User]): PatientIssue = { - json.asJsObject.getFields("text") match { - case Seq(text) => - PatientIssue( - id = LongId(0), - userId = userId, - patientId = patientId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text.convertTo[String], - archiveRequired = false - ) - - case _ => deserializationError(s"Expected Json Object as PatientIssue, but got $json") - } - - } - - implicit val patientIssueWriter = new RootJsonWriter[PatientIssue] { - override def write(obj: PatientIssue) = JsObject( - "id" -> obj.id.toJson, - "text" -> obj.text.toJson, - "lastUpdate" -> obj.lastUpdate.toJson, - "userId" -> obj.userId.toJson, - "isDraft" -> obj.isDraft.toJson, - "archiveRequired" -> obj.archiveRequired.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientlabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientlabel.scala deleted file mode 100644 index 57dca1e..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientlabel.scala +++ /dev/null @@ -1,66 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.services.PatientLabelService.RichPatientLabel -import xyz.driver.formats.json.labels._ -import xyz.driver.pdsuidomain.formats.json.sprayformats.record._ -import xyz.driver.pdsuidomain.formats.json.sprayformats.document._ - -object patientlabel { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToPatientLabel(json: JsValue, orig: PatientLabel): PatientLabel = json match { - case JsObject(fields) => - val primaryValue = fields - .get("primaryValue") - .map(_.convertTo[Option[LabelValue]]) - .getOrElse(orig.primaryValue) - - val verifiedPrimaryValue = fields - .get("verifiedPrimaryValue") - .map(_.convertTo[Option[LabelValue]]) - .getOrElse(orig.verifiedPrimaryValue) - - orig.copy( - primaryValue = primaryValue, - verifiedPrimaryValue = verifiedPrimaryValue - ) - - case _ => deserializationError(s"Expected Json Object as PatientLabel, but got $json") - } - - implicit val richPatientLabelWriter: RootJsonWriter[RichPatientLabel] = new RootJsonWriter[RichPatientLabel] { - override def write(obj: RichPatientLabel): JsValue = { - JsObject( - "id" -> obj.patientLabel.id.toJson, - "labelId" -> obj.patientLabel.labelId.toJson, - "primaryValue" -> obj.patientLabel.primaryValue.toJson, - "verifiedPrimaryValue" -> obj.patientLabel.verifiedPrimaryValue.toJson, - "score" -> obj.patientLabel.score.toJson, - "isImplicitMatch" -> obj.patientLabel.isImplicitMatch.toJson, - "isVisible" -> obj.patientLabel.isVisible.toJson, - "isVerified" -> obj.isVerified.toJson - ) - } - } - - implicit val patientLabelEvidenceWriter: RootJsonWriter[PatientLabelEvidenceView] = - new RootJsonWriter[PatientLabelEvidenceView] { - override def write(evidence: PatientLabelEvidenceView): JsValue = - JsObject( - "id" -> evidence.id.toJson, - "value" -> evidence.value.toJson, - "evidenceText" -> evidence.evidenceText.toJson, - "documentId" -> evidence.documentId.toJson, - "evidenceId" -> evidence.evidenceId.toJson, - "reportId" -> evidence.reportId.toJson, - "documentType" -> evidence.documentType.toJson, - "date" -> evidence.date.toJson, - "providerType" -> evidence.providerType.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala deleted file mode 100644 index 09517e6..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala +++ /dev/null @@ -1,228 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime -import java.util.UUID - -import spray.json._ -import xyz.driver.core.json.{EnumJsonFormat, GadtJsonFormat} -import xyz.driver.pdsuicommon.domain.{LongId, TextJson, UuidId} -import xyz.driver.pdsuidomain.entities.MedicalRecord.Meta._ -import xyz.driver.pdsuidomain.entities._ - -object record { - import DefaultJsonProtocol._ - import MedicalRecord._ - import common._ - - implicit val recordStatusFormat = new EnumJsonFormat[Status]( - "Unprocessed" -> Status.Unprocessed, - "PreOrganized" -> Status.PreOrganized, - "New" -> Status.New, - "Cleaned" -> Status.Cleaned, - "PreOrganized" -> Status.PreOrganized, - "PreOrganizing" -> Status.PreOrganizing, - "Reviewed" -> Status.Reviewed, - "Organized" -> Status.Organized, - "Done" -> Status.Done, - "Flagged" -> Status.Flagged, - "Archived" -> Status.Archived - ) - - implicit val requestIdFormat = new RootJsonFormat[RecordRequestId] { - override def write(requestId: RecordRequestId): JsString = JsString(requestId.toString) - override def read(json: JsValue): RecordRequestId = json match { - case JsString(value) => RecordRequestId(UUID.fromString(value)) - case _ => deserializationError(s"Expected string as RecordRequestId, but got $json") - } - } - - implicit val providerTypeFormat: RootJsonFormat[ProviderType] = new RootJsonFormat[ProviderType] { - override def read(json: JsValue): ProviderType = json match { - case JsObject(fields) => - val name = fields - .get("name") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"Provider type json object does not contain `name` field: $json")) - - ProviderType - .fromString(name) - .getOrElse(deserializationError(s"Unknown provider type: $name")) - - case _ => deserializationError(s"Expected Json Object as Provider type, but got $json") - } - - override def write(obj: ProviderType) = - JsObject("id" -> obj.id.toJson, "name" -> obj.name.toJson) - } - - implicit val caseIdFormat = new RootJsonFormat[CaseId] { - override def write(caseId: CaseId): JsString = JsString(caseId.toString) - override def read(json: JsValue): CaseId = json match { - case JsString(value) => CaseId(value) - case _ => deserializationError(s"Expected string as CaseId, but got $json") - } - } - - implicit val duplicateMetaFormat: RootJsonFormat[Duplicate] = new RootJsonFormat[Duplicate] { - override def write(obj: Duplicate) = - JsObject( - "type" -> "duplicate".toJson, - "startPage" -> obj.startPage.toJson, - "endPage" -> obj.endPage.toJson, - "startOriginalPage" -> obj.startOriginalPage.toJson, - "endOriginalPage" -> obj.endOriginalPage.toJson - ) - - override def read(json: JsValue): Duplicate = json match { - case JsObject(fields) => - val startPage = fields - .get("startPage") - .map(_.convertTo[Double]) - .getOrElse(deserializationError(s"Duplicate meta json object does not contain `startPage` field: $json")) - - val endPage = fields - .get("endPage") - .map(_.convertTo[Double]) - .getOrElse(deserializationError(s"Duplicate meta json object does not contain `endPage` field: $json")) - - val startOriginalPage = fields - .get("startOriginalPage") - .map(_.convertTo[Double]) - .getOrElse( - deserializationError(s"Duplicate meta json object does not contain `startOriginalPage` field: $json")) - - val endOriginalPage = fields - .get("endOriginalPage") - .map(_.convertTo[Double]) - - Duplicate( - startPage = startPage, - endPage = endPage, - startOriginalPage = startOriginalPage, - endOriginalPage = endOriginalPage - ) - - case _ => deserializationError(s"Expected JsObject as Duplicate meta of medical record, but got $json") - } - } - - implicit val reorderMetaFormat: RootJsonFormat[Reorder] = new RootJsonFormat[Reorder] { - override def write(obj: Reorder) = - JsObject("type" -> "reorder".toJson, "items" -> obj.items.toJson) - - override def read(json: JsValue): Reorder = json match { - case JsObject(fields) => - val items = fields - .get("items") - .map(_.convertTo[Seq[Int]]) - .getOrElse(deserializationError(s"Reorder meta json object does not contain `items` field: $json")) - - Reorder(items) - - case _ => deserializationError(s"Expected JsObject as Reorder meta of medical record, but got $json") - } - } - - implicit val rotateMetaFormat: RootJsonFormat[Rotation] = new RootJsonFormat[Rotation] { - override def write(obj: Rotation) = - JsObject("type" -> "rotation".toJson, "items" -> obj.items.toJson) - - override def read(json: JsValue): Rotation = json match { - case JsObject(fields) => - val items = fields - .get("items") - .map(_.convertTo[Map[String, Int]]) - .getOrElse(deserializationError(s"Rotation meta json object does not contain `items` field: $json")) - - Rotation(items = items) - - case _ => deserializationError(s"Expected JsObject as Rotation meta of medical record, but got $json") - } - } - - implicit val recordMetaTypeFormat: GadtJsonFormat[MedicalRecord.Meta] = { - GadtJsonFormat.create[Meta]("type")({ case m => m.metaType }) { - case "duplicate" => duplicateMetaFormat - case "reorder" => reorderMetaFormat - case "rotation" => rotateMetaFormat - } - } - - implicit val recordMetaFormat = new RootJsonFormat[TextJson[List[Meta]]] { - override def write(obj: TextJson[List[Meta]]): JsArray = JsArray(obj.content.map(_.toJson).toVector) - override def read(json: JsValue): TextJson[List[Meta]] = json match { - case JsArray(values) => TextJson[List[Meta]](values.map(_.convertTo[Meta]).toList) - case _ => deserializationError(s"Expected array as Meta, but got $json") - } - } - - implicit val recordFormat: RootJsonFormat[MedicalRecord] = - new RootJsonFormat[MedicalRecord] { - override def write(record: MedicalRecord): JsValue = - JsObject( - "id" -> record.id.toJson, - "patientId" -> record.patientId.toJson, - "caseId" -> record.caseId.toJson, - "disease" -> record.disease.toJson, - "physician" -> record.physician.toJson, - "status" -> record.status.toJson, - "previousStatus" -> record.previousStatus.toJson, - "assignee" -> record.assignee.toJson, - "previousAssignee" -> record.previousAssignee.toJson, - "requestId" -> record.requestId.toJson, - "meta" -> record.meta.getOrElse(TextJson[List[Meta]](List.empty)).toJson, - "lastActiveUser" -> record.lastActiveUserId.toJson, - "lastUpdate" -> record.lastUpdate.toJson, - "totalPages" -> record.totalPages.toJson - ) - - override def read(json: JsValue): MedicalRecord = json match { - case JsObject(fields) => - val disease = fields - .get("disease") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"MedicalRecord json object does not contain `disease` field: $json")) - - val patientId = fields - .get("patientId") - .map(_.convertTo[UuidId[Patient]]) - .getOrElse(deserializationError(s"MedicalRecord json object does not contain `patientId` field: $json")) - - val requestId = fields - .get("requestId") - .map(_.convertTo[RecordRequestId]) - .getOrElse(deserializationError(s"MedicalRecord json object does not contain `requestId` field: $json")) - - MedicalRecord( - id = LongId(0), - status = MedicalRecord.Status.New, - previousStatus = None, - assignee = None, - previousAssignee = None, - lastActiveUserId = None, - patientId = patientId, - requestId = requestId, - disease = disease, - caseId = None, - physician = None, - meta = None, - lastUpdate = LocalDateTime.now(), - totalPages = 0 - ) - - case _ => deserializationError(s"Expected Json Object as MedicalRecord, but got $json") - } - } - - def applyUpdateToMedicalRecord(json: JsValue, orig: MedicalRecord): MedicalRecord = json match { - case JsObject(fields) => - val meta = fields - .get("meta") - .map(_.convertTo[Option[TextJson[List[Meta]]]]) - .getOrElse(orig.meta) - orig.copy(meta = meta) - - case _ => deserializationError(s"Expected Json Object as partial MedicalRecord, but got $json") - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordhistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordhistory.scala deleted file mode 100644 index bd14d43..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordhistory.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuidomain.entities._ - -object recordhistory { - import DefaultJsonProtocol._ - import common._ - import MedicalRecordHistory._ - - implicit val recordStateFormat = new EnumJsonFormat[State]( - "Clean" -> State.Clean, - "Organize" -> State.Organize, - "Review" -> State.Review, - "Flag" -> State.Flag - ) - - implicit val recordActionFormat = new EnumJsonFormat[Action]( - "Start" -> Action.Start, - "Submit" -> Action.Submit, - "Unassign" -> Action.Unassign, - "Resolve" -> Action.Resolve, - "Flag" -> Action.Flag, - "Archive" -> Action.Archive - ) - - implicit val recordHistoryFormat: RootJsonFormat[MedicalRecordHistory] = jsonFormat6(MedicalRecordHistory.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordissue.scala deleted file mode 100644 index 4ac5f6d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordissue.scala +++ /dev/null @@ -1,68 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities._ - -object recordissue { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToRecordIssue(json: JsValue, orig: MedicalRecordIssue): MedicalRecordIssue = json match { - case JsObject(fields) => - val text = fields - .get("text") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"MedicalRecordIssue json object does not contain `text` field: $json")) - - val archiveRequired = fields - .get("archiveRequired") - .map(_.convertTo[Boolean]) - .getOrElse( - deserializationError(s"MedicalRecordIssue json object does not contain `archiveRequired` field: $json")) - - val startPage = fields.get("startPage").map(_.convertTo[Double]) - val endPage = fields.get("endPage").map(_.convertTo[Double]) - - orig.copy( - text = text, - archiveRequired = archiveRequired, - startPage = startPage, - endPage = endPage - ) - - case _ => deserializationError(s"Expected Json Object as partial MedicalRecordIssue, but got $json") - - } - - def jsValueToRecordIssue(json: JsValue, - recordId: LongId[MedicalRecord], - userId: StringId[User]): MedicalRecordIssue = json match { - case JsObject(fields) => - val text = fields - .get("text") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"MedicalRecordIssue json object does not contain `text` field: $json")) - - val startPage = fields.get("startPage").map(_.convertTo[Double]) - val endPage = fields.get("endPage").map(_.convertTo[Double]) - MedicalRecordIssue( - id = LongId(0), - userId = userId, - recordId = recordId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - archiveRequired = false, - startPage = startPage, - endPage = endPage - ) - - case _ => deserializationError(s"Expected Json Object as MedicalRecordIssue, but got $json") - } - - implicit val recordIssueFormat = jsonFormat9(MedicalRecordIssue.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/slotarm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/slotarm.scala deleted file mode 100644 index 1d74916..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/slotarm.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{SlotArm, Trial} - -object slotarm { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToArm(json: JsValue, orig: SlotArm): SlotArm = json match { - case JsObject(fields) => - val name = fields - .get("name") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"Arm json object does not contain `name` field: $json")) - orig.copy(name = name) - - case _ => deserializationError(s"Expected Json Object as partial Arm, but got $json") - } - - implicit def slotArmFormat: RootJsonFormat[SlotArm] = new RootJsonFormat[SlotArm] { - override def write(obj: SlotArm): JsValue = - JsObject( - "id" -> obj.id.toJson, - "name" -> obj.name.toJson, - "originalName" -> obj.originalName.toJson, - "trialId" -> obj.trialId.toJson - ) - - override def read(json: JsValue): SlotArm = json.asJsObject.getFields("trialId", "name") match { - case Seq(trialId, name) => - SlotArm( - id = LongId(0), - name = name.convertTo[String], - trialId = trialId.convertTo[StringId[Trial]], - originalName = name.convertTo[String] - ) - - case _ => deserializationError(s"Expected Json Object as Arm, but got $json") - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala deleted file mode 100644 index 3002b38..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala +++ /dev/null @@ -1,29 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities._ - -object studydesign { - import DefaultJsonProtocol._ - import common._ - - implicit val studyDesignFormat: RootJsonFormat[StudyDesign] = new RootJsonFormat[StudyDesign] { - override def read(json: JsValue): StudyDesign = json match { - case JsObject(fields) => - val name = fields - .get("name") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"Study design json object does not contain `name` field: $json")) - - StudyDesign - .fromString(name) - .getOrElse(deserializationError(s"Unknown study design: $name")) - - case _ => deserializationError(s"Expected Json Object as Study design, but got $json") - } - - override def write(obj: StudyDesign) = - JsObject("id" -> obj.id.toJson, "name" -> obj.name.toJson) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trial.scala deleted file mode 100644 index b25ed1d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trial.scala +++ /dev/null @@ -1,83 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{ZoneId, ZonedDateTime} - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuidomain.entities._ - -object trial { - import DefaultJsonProtocol._ - import Trial._ - import common._ - - implicit val trialStatusFormat = new EnumJsonFormat[Status]( - "New" -> Status.New, - "ReviewSummary" -> Status.ReviewSummary, - "Summarized" -> Status.Summarized, - "PendingUpdate" -> Status.PendingUpdate, - "Update" -> Status.Update, - "ReviewCriteria" -> Status.ReviewCriteria, - "Done" -> Status.Done, - "Flagged" -> Status.Flagged, - "Archived" -> Status.Archived - ) - - implicit val trialWriter: RootJsonWriter[Trial] = new RootJsonWriter[Trial] { - override def write(obj: Trial) = - JsObject( - "id" -> obj.id.toJson, - "externalid" -> obj.externalId.toJson, - "lastUpdate" -> ZonedDateTime.of(obj.lastUpdate, ZoneId.of("Z")).toJson, - "status" -> obj.status.toJson, - "assignee" -> obj.assignee.toJson, - "previousStatus" -> obj.previousStatus.toJson, - "previousAssignee" -> obj.previousAssignee.toJson, - "lastActiveUser" -> obj.lastActiveUserId.toJson, - "phase" -> obj.phase.toJson, - "hypothesisId" -> obj.hypothesisId.toJson, - "studyDesignId" -> obj.studyDesignId.toJson, - "originalStudyDesignId" -> obj.originalStudyDesign.toJson, - "isPartner" -> obj.isPartner.toJson, - "overview" -> obj.overview.toJson, - "overviewTemplate" -> obj.overviewTemplate.toJson, - "isUpdated" -> obj.isUpdated.toJson, - "title" -> obj.title.toJson, - "originalTitle" -> obj.originalTitle.toJson - ) - } - - def applyUpdateToTrial(json: JsValue, orig: Trial): Trial = json match { - case JsObject(fields) => - val hypothesisId = fields - .get("hypothesisId") - .map(_.convertTo[Option[UuidId[Hypothesis]]]) - .getOrElse(orig.hypothesisId) - - val studyDesignId = fields - .get("studyDesignId") - .map(_.convertTo[Option[LongId[StudyDesign]]]) - .getOrElse(orig.studyDesignId) - - val overview = fields - .get("overview") - .map(_.convertTo[Option[String]]) - .getOrElse(orig.overview) - - val title = fields - .get("title") - .map(_.convertTo[Option[String]].getOrElse("")) - .getOrElse(orig.title) - - orig.copy( - hypothesisId = hypothesisId, - studyDesignId = studyDesignId, - overview = overview, - title = title - ) - - case _ => deserializationError(s"Expected Json Object as Trial, but got $json") - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialhistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialhistory.scala deleted file mode 100644 index 844c5f5..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialhistory.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuidomain.entities._ - -object trialhistory { - import DefaultJsonProtocol._ - import common._ - import TrialHistory._ - - implicit val trialStateFormat = new EnumJsonFormat[State]( - "Summarize" -> State.Summarize, - "Criteriarize" -> State.Criteriarize, - "Review" -> State.Review, - "Flag" -> State.Flag - ) - - implicit val trialActionFormat = new EnumJsonFormat[Action]( - "Start" -> Action.Start, - "Submit" -> Action.Submit, - "Unassign" -> Action.Unassign, - "Resolve" -> Action.Resolve, - "Flag" -> Action.Flag, - "Archive" -> Action.Archive - ) - - implicit val trialHistoryFormat: RootJsonFormat[TrialHistory] = jsonFormat6(TrialHistory.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialissue.scala deleted file mode 100644 index d1ca191..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialissue.scala +++ /dev/null @@ -1,60 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities._ - -object trialissue { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToTrialIssue(json: JsValue, orig: TrialIssue): TrialIssue = { - json.asJsObject.getFields("text", "evidence", "archiveRequired", "meta") match { - case Seq(text, evidence, archiveRequired, meta) => - orig.copy( - text = text.convertTo[String], - evidence = evidence.convertTo[String], - archiveRequired = archiveRequired.convertTo[Boolean], - meta = meta.convertTo[String] - ) - - case _ => deserializationError(s"Expected Json Object as partial TrialIssue, but got $json") - } - } - - def jsValueToTrialIssue(json: JsValue, trialId: StringId[Trial], userId: StringId[User]): TrialIssue = { - json.asJsObject.getFields("text", "evidence", "meta") match { - case Seq(text, evidence, meta) => - TrialIssue( - id = LongId(0), - userId = userId, - trialId = trialId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text.convertTo[String], - evidence = evidence.convertTo[String], - archiveRequired = false, - meta = meta.convertTo[String] - ) - - case _ => deserializationError(s"Expected Json Object as TrialIssue, but got $json") - } - - } - - implicit val trialIssueWriter = new RootJsonWriter[TrialIssue] { - override def write(obj: TrialIssue) = JsObject( - "id" -> obj.id.toJson, - "text" -> obj.text.toJson, - "lastUpdate" -> obj.lastUpdate.toJson, - "userId" -> obj.userId.toJson, - "isDraft" -> obj.isDraft.toJson, - "evidence" -> obj.evidence.toJson, - "archiveRequired" -> obj.archiveRequired.toJson, - "meta" -> obj.meta.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign.scala new file mode 100644 index 0000000..60c7e70 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign.scala @@ -0,0 +1,29 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.pdsuidomain.entities._ + +object studydesign { + import DefaultJsonProtocol._ + import common._ + + implicit val studyDesignFormat: RootJsonFormat[StudyDesign] = new RootJsonFormat[StudyDesign] { + override def read(json: JsValue): StudyDesign = json match { + case JsObject(fields) => + val name = fields + .get("name") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"Study design json object does not contain `name` field: $json")) + + StudyDesign + .fromString(name) + .getOrElse(deserializationError(s"Unknown study design: $name")) + + case _ => deserializationError(s"Expected Json Object as Study design, but got $json") + } + + override def write(obj: StudyDesign) = + JsObject("id" -> obj.id.toJson, "name" -> obj.name.toJson) + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala deleted file mode 100644 index 12d40df..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.studydesign - -import xyz.driver.pdsuidomain.entities.StudyDesign -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} - -final case class ApiStudyDesign(id: Long, name: String) { - - def toDomain: Option[StudyDesign] = StudyDesign.fromString(name) -} - -object ApiStudyDesign { - - implicit val format: Format[ApiStudyDesign] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] - )(ApiStudyDesign.apply, unlift(ApiStudyDesign.unapply)) - - def fromDomain(studyDesign: StudyDesign) = ApiStudyDesign( - id = studyDesign.id.id, - name = studyDesign.name - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial.scala new file mode 100644 index 0000000..6cc2560 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial.scala @@ -0,0 +1,85 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.{ZoneId, ZonedDateTime} + +import spray.json._ +import xyz.driver.core.json.EnumJsonFormat +import xyz.driver.pdsuicommon.domain.{LongId, UuidId} +import xyz.driver.pdsuidomain.entities._ + +object trial { + import DefaultJsonProtocol._ + import Trial._ + import common._ + + implicit val trialStatusFormat = new EnumJsonFormat[Status]( + "New" -> Status.New, + "ReviewSummary" -> Status.ReviewSummary, + "Summarized" -> Status.Summarized, + "PendingUpdate" -> Status.PendingUpdate, + "Update" -> Status.Update, + "ReviewCriteria" -> Status.ReviewCriteria, + "Done" -> Status.Done, + "Flagged" -> Status.Flagged, + "Archived" -> Status.Archived + ) + + implicit val trialFormat: RootJsonFormat[Trial] = new RootJsonFormat[Trial] { + override def write(obj: Trial) = + JsObject( + "id" -> obj.id.toJson, + "externalid" -> obj.externalId.toJson, + "lastUpdate" -> ZonedDateTime.of(obj.lastUpdate, ZoneId.of("Z")).toJson, + "status" -> obj.status.toJson, + "assignee" -> obj.assignee.toJson, + "previousStatus" -> obj.previousStatus.toJson, + "previousAssignee" -> obj.previousAssignee.toJson, + "lastActiveUser" -> obj.lastActiveUserId.toJson, + "phase" -> obj.phase.toJson, + "hypothesisId" -> obj.hypothesisId.toJson, + "studyDesignId" -> obj.studyDesignId.toJson, + "originalStudyDesignId" -> obj.originalStudyDesign.toJson, + "isPartner" -> obj.isPartner.toJson, + "overview" -> obj.overview.toJson, + "overviewTemplate" -> obj.overviewTemplate.toJson, + "isUpdated" -> obj.isUpdated.toJson, + "title" -> obj.title.toJson, + "originalTitle" -> obj.originalTitle.toJson + ) + + override def read(json: JsValue): Trial = jsonReader[Trial].read(json) + } + + def applyUpdateToTrial(json: JsValue, orig: Trial): Trial = json match { + case JsObject(fields) => + val hypothesisId = fields + .get("hypothesisId") + .map(_.convertTo[Option[UuidId[Hypothesis]]]) + .getOrElse(orig.hypothesisId) + + val studyDesignId = fields + .get("studyDesignId") + .map(_.convertTo[Option[LongId[StudyDesign]]]) + .getOrElse(orig.studyDesignId) + + val overview = fields + .get("overview") + .map(_.convertTo[Option[String]]) + .getOrElse(orig.overview) + + val title = fields + .get("title") + .map(_.convertTo[Option[String]].getOrElse("")) + .getOrElse(orig.title) + + orig.copy( + hypothesisId = hypothesisId, + studyDesignId = studyDesignId, + overview = overview, + title = title + ) + + case _ => deserializationError(s"Expected Json Object as Trial, but got $json") + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiPartialTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiPartialTrial.scala deleted file mode 100644 index f89f181..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiPartialTrial.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trial - -import java.util.UUID - -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuidomain.entities.Trial -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiPartialTrial(hypothesisId: Tristate[UUID], - studyDesignId: Tristate[Long], - overview: Tristate[String], - title: Tristate[String]) { - - def applyTo(orig: Trial): Trial = { - orig.copy( - hypothesisId = hypothesisId.map(UuidId(_)).cata(Some(_), None, orig.hypothesisId), - studyDesignId = studyDesignId.map(LongId(_)).cata(Some(_), None, orig.studyDesignId), - overview = overview.cata(Some(_), None, orig.overview), - title = title.cata(Some(_).getOrElse(""), "", orig.title) - ) - } -} - -object ApiPartialTrial { - - private val reads: Reads[ApiPartialTrial] = ( - (JsPath \ "hypothesisId").readTristate[UUID] and - (JsPath \ "studyDesignId").readTristate[Long] and - (JsPath \ "overview").readTristate[String] and - (JsPath \ "title").readTristate[String] - )(ApiPartialTrial.apply _) - - private val writes: Writes[ApiPartialTrial] = ( - (JsPath \ "hypothesisId").writeTristate[UUID] and - (JsPath \ "studyDesignId").writeTristate[Long] and - (JsPath \ "overview").writeTristate[String] and - (JsPath \ "title").writeTristate[String] - )(unlift(ApiPartialTrial.unapply)) - - implicit val format: Format[ApiPartialTrial] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala deleted file mode 100644 index 133a2c8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala +++ /dev/null @@ -1,96 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trial - -import java.time.{ZoneId, ZonedDateTime} -import java.util.UUID - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.Trial - -final case class ApiTrial(id: String, - externalId: UUID, - lastUpdate: ZonedDateTime, - status: String, - assignee: Option[String], - previousStatus: Option[String], - previousAssignee: Option[String], - lastActiveUser: Option[String], - phase: String, - hypothesisId: Option[UUID], - studyDesignId: Option[Long], - originalStudyDesign: Option[String], - isPartner: Boolean, - overview: Option[String], - overviewTemplate: String, - isUpdated: Boolean, - title: String, - originalTitle: String) { - - def toDomain = Trial( - id = StringId(this.id), - externalId = UuidId(this.externalId), - status = TrialStatus.statusFromString(this.status), - assignee = this.assignee.map(id => StringId(id)), - previousStatus = this.previousStatus.map(s => TrialStatus.statusFromString(s)), - previousAssignee = this.previousAssignee.map(id => StringId(id)), - lastActiveUserId = this.lastActiveUser.map(id => StringId(id)), - lastUpdate = this.lastUpdate.toLocalDateTime, - phase = this.phase, - hypothesisId = this.hypothesisId.map(id => UuidId(id)), - studyDesignId = this.studyDesignId.map(id => LongId(id)), - originalStudyDesign = this.originalStudyDesign, - isPartner = this.isPartner, - overview = this.overview, - overviewTemplate = this.overviewTemplate, - isUpdated = this.isUpdated, - title = this.title, - originalTitle = this.originalTitle - ) - -} - -object ApiTrial { - - implicit val format: Format[ApiTrial] = ( - (JsPath \ "id").format[String] and - (JsPath \ "externalid").format[UUID] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "status").format[String] and - (JsPath \ "assignee").formatNullable[String] and - (JsPath \ "previousStatus").formatNullable[String] and - (JsPath \ "previousAssignee").formatNullable[String] and - (JsPath \ "lastActiveUser").formatNullable[String] and - (JsPath \ "phase").format[String] and - (JsPath \ "hypothesisId").formatNullable[UUID] and - (JsPath \ "studyDesignId").formatNullable[Long] and - (JsPath \ "originalStudyDesignId").formatNullable[String] and - (JsPath \ "isPartner").format[Boolean] and - (JsPath \ "overview").formatNullable[String] and - (JsPath \ "overviewTemplate").format[String] and - (JsPath \ "isUpdated").format[Boolean] and - (JsPath \ "title").format[String] and - (JsPath \ "originalTitle").format[String] - )(ApiTrial.apply, unlift(ApiTrial.unapply)) - - def fromDomain(trial: Trial): ApiTrial = ApiTrial( - id = trial.id.id, - externalId = trial.externalId.id, - status = TrialStatus.statusToString(trial.status), - assignee = trial.assignee.map(_.id), - previousStatus = trial.previousStatus.map(TrialStatus.statusToString), - previousAssignee = trial.previousAssignee.map(_.id), - lastActiveUser = trial.lastActiveUserId.map(_.id), - lastUpdate = ZonedDateTime.of(trial.lastUpdate, ZoneId.of("Z")), - phase = trial.phase, - hypothesisId = trial.hypothesisId.map(_.id), - studyDesignId = trial.studyDesignId.map(_.id), - originalStudyDesign = trial.originalStudyDesign, - isPartner = trial.isPartner, - overview = trial.overview, - overviewTemplate = trial.overviewTemplate, - isUpdated = trial.isUpdated, - title = trial.title, - originalTitle = trial.originalTitle - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/TrialStatus.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/TrialStatus.scala deleted file mode 100644 index a5b557b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/TrialStatus.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trial - -import xyz.driver.pdsuidomain.entities.Trial.Status - -object TrialStatus { - - val statusFromString: PartialFunction[String, Status] = { - case "New" => Status.New - case "ReviewSummary" => Status.ReviewSummary - case "Summarized" => Status.Summarized - case "PendingUpdate" => Status.PendingUpdate - case "Update" => Status.Update - case "ReviewCriteria" => Status.ReviewCriteria - case "Done" => Status.Done - case "Flagged" => Status.Flagged - case "Archived" => Status.Archived - } - - def statusToString(x: Status): String = x match { - case Status.New => "New" - case Status.ReviewSummary => "ReviewSummary" - case Status.Summarized => "Summarized" - case Status.PendingUpdate => "PendingUpdate" - case Status.Update => "Update" - case Status.ReviewCriteria => "ReviewCriteria" - case Status.Done => "Done" - case Status.Flagged => "Flagged" - case Status.Archived => "Archived" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory.scala new file mode 100644 index 0000000..6185d5a --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory.scala @@ -0,0 +1,30 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import xyz.driver.core.json.EnumJsonFormat +import xyz.driver.pdsuidomain.entities._ + +object trialhistory { + import DefaultJsonProtocol._ + import TrialHistory._ + import common._ + + implicit val trialStateFormat = new EnumJsonFormat[State]( + "Summarize" -> State.Summarize, + "Criteriarize" -> State.Criteriarize, + "Review" -> State.Review, + "Flag" -> State.Flag + ) + + implicit val trialActionFormat = new EnumJsonFormat[Action]( + "Start" -> Action.Start, + "Submit" -> Action.Submit, + "Unassign" -> Action.Unassign, + "Resolve" -> Action.Resolve, + "Flag" -> Action.Flag, + "Archive" -> Action.Archive + ) + + implicit val trialHistoryFormat: RootJsonFormat[TrialHistory] = jsonFormat6(TrialHistory.apply) + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory/ApiTrialHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory/ApiTrialHistory.scala deleted file mode 100644 index 38faeb8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory/ApiTrialHistory.scala +++ /dev/null @@ -1,26 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trialhistory - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.json.{Format, Json} -import xyz.driver.pdsuidomain.entities.TrialHistory - -final case class ApiTrialHistory(id: Long, - executor: String, - trialId: String, - state: String, - action: String, - created: ZonedDateTime) - -object ApiTrialHistory { - implicit val format: Format[ApiTrialHistory] = Json.format[ApiTrialHistory] - - def fromDomain(x: TrialHistory) = ApiTrialHistory( - id = x.id.id, - executor = x.executor.id, - trialId = x.trialId.id, - state = TrialHistory.State.stateToString(x.state), - action = TrialHistory.Action.actionToString(x.action), - created = ZonedDateTime.of(x.created, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue.scala new file mode 100644 index 0000000..b2a3023 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue.scala @@ -0,0 +1,60 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} +import xyz.driver.pdsuidomain.entities._ + +object trialissue { + import DefaultJsonProtocol._ + import common._ + + def applyUpdateToTrialIssue(json: JsValue, orig: TrialIssue): TrialIssue = { + json.asJsObject.getFields("text", "evidence", "archiveRequired", "meta") match { + case Seq(text, evidence, archiveRequired, meta) => + orig.copy( + text = text.convertTo[String], + evidence = evidence.convertTo[String], + archiveRequired = archiveRequired.convertTo[Boolean], + meta = meta.convertTo[String] + ) + + case _ => deserializationError(s"Expected Json Object as partial TrialIssue, but got $json") + } + } + + def jsValueToTrialIssue(json: JsValue, trialId: StringId[Trial], userId: StringId[User]): TrialIssue = { + json.asJsObject.getFields("text", "evidence", "meta") match { + case Seq(text, evidence, meta) => + TrialIssue( + id = LongId(0), + userId = userId, + trialId = trialId, + lastUpdate = LocalDateTime.MIN, + isDraft = true, + text = text.convertTo[String], + evidence = evidence.convertTo[String], + archiveRequired = false, + meta = meta.convertTo[String] + ) + + case _ => deserializationError(s"Expected Json Object as TrialIssue, but got $json") + } + + } + + implicit val trialIssueWriter = new RootJsonWriter[TrialIssue] { + override def write(obj: TrialIssue) = JsObject( + "id" -> obj.id.toJson, + "text" -> obj.text.toJson, + "lastUpdate" -> obj.lastUpdate.toJson, + "userId" -> obj.userId.toJson, + "isDraft" -> obj.isDraft.toJson, + "evidence" -> obj.evidence.toJson, + "archiveRequired" -> obj.archiveRequired.toJson, + "meta" -> obj.meta.toJson + ) + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiPartialTrialIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiPartialTrialIssue.scala deleted file mode 100644 index fc31371..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiPartialTrialIssue.scala +++ /dev/null @@ -1,40 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trialissue - -import java.time.LocalDateTime - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities.{Trial, TrialIssue} - -final case class ApiPartialTrialIssue(text: String, evidence: String, archiveRequired: Boolean, meta: String) { - def applyTo(x: TrialIssue): TrialIssue = x.copy( - text = text, - evidence = evidence, - archiveRequired = archiveRequired, - meta = meta - ) - - def toDomain(userId: StringId[User], trialId: StringId[Trial]) = TrialIssue( - id = LongId(0), - userId = userId, - trialId = trialId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - evidence = evidence, - archiveRequired = false, - meta = meta - ) -} - -object ApiPartialTrialIssue { - implicit val format: Format[ApiPartialTrialIssue] = ( - (JsPath \ "text").format[String] and - (JsPath \ "evidence").format[String] and - (JsPath \ "archiveRequired").format[Boolean] and - (JsPath \ "meta").format[String](Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) - )(ApiPartialTrialIssue.apply, unlift(ApiPartialTrialIssue.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiTrialIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiTrialIssue.scala deleted file mode 100644 index c9475c6..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiTrialIssue.scala +++ /dev/null @@ -1,60 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trialissue - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities.TrialIssue - -final case class ApiTrialIssue(id: Long, - trialId: String, - text: String, - lastUpdate: ZonedDateTime, - userId: String, - isDraft: Boolean, - evidence: String, - archiveRequired: Boolean, - meta: String) { - - def toDomain = TrialIssue( - id = LongId(this.id), - trialId = StringId(this.trialId), - text = this.text, - userId = StringId(this.userId), - lastUpdate = this.lastUpdate.toLocalDateTime, - isDraft = this.isDraft, - evidence = this.evidence, - archiveRequired = this.archiveRequired, - meta = this.meta - ) - -} - -object ApiTrialIssue { - implicit val format: Format[ApiTrialIssue] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "trialId").format[String] and - (JsPath \ "text").format[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "userId").format[String] and - (JsPath \ "isDraft").format[Boolean] and - (JsPath \ "evidence").format[String] and - (JsPath \ "archiveRequired").format[Boolean] and - (JsPath \ "meta").format[String](Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) - )(ApiTrialIssue.apply, unlift(ApiTrialIssue.unapply)) - - def fromDomain(x: TrialIssue) = ApiTrialIssue( - id = x.id.id, - trialId = x.trialId.id, - text = x.text, - lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), - userId = x.userId.id, - isDraft = x.isDraft, - evidence = x.evidence, - archiveRequired = x.archiveRequired, - meta = x.meta - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala deleted file mode 100644 index cf20d32..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala +++ /dev/null @@ -1,76 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.user - -import java.util.UUID - -import xyz.driver.pdsuicommon.domain._ -import play.api.data.validation._ -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -import scala.collection._ -import scala.util.Try -import xyz.driver.pdsuicommon.json.JsonValidationException -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors} - -final case class ApiPartialUser(email: Option[String], name: Option[String], roles: Option[Seq[String]]) { - - def applyTo(orig: User): Try[User] = Try { - val validation = Map( - JsPath \ "name" -> AdditionalConstraints.optionNonEmptyConstraint(name) - ) - - val validationErrors: JsonValidationErrors = validation.collect({ - case (fieldName, e: Invalid) => (fieldName, e.errors) - })(breakOut) - - if (validationErrors.isEmpty) { - orig.copy(name = name.get) - } else { - throw new JsonValidationException(validationErrors) - } - } - - def toDomain(id: StringId[User] = StringId(UUID.randomUUID().toString)): Try[User] = Try { - val validation = Map( - JsPath \ "email" -> AdditionalConstraints.optionNonEmptyConstraint(email), - JsPath \ "name" -> AdditionalConstraints.optionNonEmptyConstraint(name), - JsPath \ "roles" -> AdditionalConstraints.optionNonEmptyConstraint(roles) - ) - - val validationErrors: JsonValidationErrors = validation.collect({ - case (fieldName, e: Invalid) => (fieldName, e.errors) - })(breakOut) - - if (validationErrors.isEmpty) { - val userEmail = email.map(x => Email(x.toLowerCase)).get - User( - id = id, - email = userEmail, - name = name.get, - roles = roles.toSeq.flatMap(_.map(UserRole.roleFromString)).toSet, - latestActivity = None, - deleted = None - ) - } else { - throw new JsonValidationException(validationErrors) - } - } -} - -object ApiPartialUser { - - implicit val format: Format[ApiPartialUser] = ( - (JsPath \ "email").formatNullable[String](Format(Reads.email, Writes.StringWrites)) and - (JsPath \ "name").formatNullable[String]( - Format( - Reads.filterNot[String](ValidationError("Username is too long (max length is 255 chars)", 255))( - _.length > 255), - Writes.StringWrites - )) and - (JsPath \ "roles").formatNullable[Seq[String]]( - Format(seqJsonFormat[String].filter(ValidationError("unknown roles"))( - _.forall(UserRole.roleFromString.isDefinedAt)), - Writes.of[Seq[String]])) - )(ApiPartialUser.apply, unlift(ApiPartialUser.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala deleted file mode 100644 index c21edd1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala +++ /dev/null @@ -1,39 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.user - -import java.time.{ZoneId, ZonedDateTime} - -import xyz.driver.pdsuicommon.domain.User -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -import scala.collection.Seq - -final case class ApiUser(id: String, - email: String, - name: String, - roles: Seq[String], - latestActivity: Option[ZonedDateTime]) - -object ApiUser { - - implicit val format: Format[ApiUser] = ( - (JsPath \ "id").format[String] and - (JsPath \ "email").format[String](Reads.email) and - (JsPath \ "name").format[String] and - (JsPath \ "roles").format( - Format( - seqJsonFormat[String].filter(ValidationError("unknown role"))(_.forall(UserRole.roleFromString.isDefinedAt)), - Writes.of[Seq[String]])) and - (JsPath \ "latestActivity").formatNullable[ZonedDateTime] - )(ApiUser.apply, unlift(ApiUser.unapply)) - - def fromDomain(user: User) = ApiUser( - user.id.id, - user.email.value, - user.name, - user.roles.map(UserRole.roleToString).toSeq, - user.latestActivity.map(ZonedDateTime.of(_, ZoneId.of("Z"))) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala deleted file mode 100644 index 412a969..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala +++ /dev/null @@ -1,37 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.user - -import xyz.driver.pdsuicommon.domain.User.Role - -object UserRole { - - val roleFromString: PartialFunction[String, Role] = { - case "Cleaner" => Role.RecordCleaner - case "Organizer" => Role.RecordOrganizer - case "Extractor" => Role.DocumentExtractor - case "RecordAdmin" => Role.RecordAdmin - case "TrialSummarizer" => Role.TrialSummarizer - case "CriteriaCurator" => Role.CriteriaCurator - case "TrialAdmin" => Role.TrialAdmin - case "EligibilityVerifier" => Role.EligibilityVerifier - case "TreatmentMatchingAdmin" => Role.TreatmentMatchingAdmin - case "RoutesCurator" => Role.RoutesCurator - case "SystemUser" => Role.SystemUser - case "ResearchOncologist" => Role.ResearchOncologist - // No Mixed at this time - } - - def roleToString(x: Role): String = x match { - case Role.RecordCleaner => "Cleaner" - case Role.RecordOrganizer => "Organizer" - case Role.DocumentExtractor => "Extractor" - case Role.RecordAdmin => "RecordAdmin" - case Role.TrialSummarizer => "TrialSummarizer" - case Role.CriteriaCurator => "CriteriaCurator" - case Role.TrialAdmin => "TrialAdmin" - case Role.EligibilityVerifier => "EligibilityVerifier" - case Role.TreatmentMatchingAdmin => "TreatmentMatchingAdmin" - case Role.RoutesCurator => "RoutesCurator" - case Role.SystemUser => "SystemUser" - case Role.ResearchOncologist => "ResearchOncologist" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/userhistory/ApiUserHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/userhistory/ApiUserHistory.scala deleted file mode 100644 index 127337f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/userhistory/ApiUserHistory.scala +++ /dev/null @@ -1,43 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.userhistory - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuidomain.entities.UserHistory - -final case class ApiUserHistory(id: Long, - executor: String, - recordId: Option[Long], - documentId: Option[Long], - trialId: Option[String], - patientId: Option[String], - state: String, - action: String, - created: ZonedDateTime) - -object ApiUserHistory { - implicit val format: Format[ApiUserHistory] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "executor").format[String] and - (JsPath \ "recordId").formatNullable[Long] and - (JsPath \ "documentId").formatNullable[Long] and - (JsPath \ "trialId").formatNullable[String] and - (JsPath \ "patientId").formatNullable[String] and - (JsPath \ "state").format[String] and - (JsPath \ "action").format[String] and - (JsPath \ "created").format[ZonedDateTime] - )(ApiUserHistory.apply, unlift(ApiUserHistory.unapply)) - - def fromDomain(x: UserHistory) = ApiUserHistory( - id = x.id.id, - executor = x.executor.id, - recordId = x.recordId.map(_.id), - documentId = x.documentId.map(_.id), - trialId = x.trialId.map(_.id), - patientId = x.patientId.map(_.id.toString), - state = UserHistory.State.stateToString(x.state), - action = UserHistory.Action.actionToString(x.action), - created = ZonedDateTime.of(x.created, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala deleted file mode 100644 index 6718f26..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala +++ /dev/null @@ -1,88 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.Message - -import scala.concurrent.Future - -object MessageService { - - trait DefaultNotFoundError { - def userMessage: String = "Message not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait CreateReply - object CreateReply { - type Error = CreateReply with DomainError - final case class Created(x: Message) extends CreateReply - case object AuthorizationError - extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends CreateReply with DomainError - } - - sealed trait GetByIdReply - object GetByIdReply { - type Error = GetByIdReply with DomainError - final case class Entity(x: Message) extends GetByIdReply - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetListReply - object GetListReply { - type Error = GetListReply with DomainError - final case class EntityList(xs: Seq[Message], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - final case class Updated(updated: Message) extends UpdateReply - case object AuthorizationError - extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } - - sealed trait DeleteReply - object DeleteReply { - type Error = DeleteReply with DomainError - case object Deleted extends DeleteReply - case object AuthorizationError - extends DeleteReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends DeleteReply with DomainError - } -} - -trait MessageService { - - import MessageService._ - - def create(draftMessage: Message)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def getById(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def update(origMessage: Message, draftMessage: Message)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def delete(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala deleted file mode 100644 index a29e041..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.UserHistory - -import scala.concurrent.Future - -object UserHistoryService { - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[UserHistory], totalFound: Int) extends GetListReply - - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError { - def userMessage: String = "Access denied" - } - } -} - -trait UserHistoryService { - - import UserHistoryService._ - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala index 2b4e858..e5eb18f 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala @@ -1,7 +1,6 @@ package xyz.driver.pdsuidomain.services.rest import scala.concurrent.{ExecutionContext, Future} - import akka.http.scaladsl.marshalling.Marshal import akka.http.scaladsl.model._ import akka.stream.Materializer @@ -9,16 +8,17 @@ import xyz.driver.core.rest.{Pagination => _, _} import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuidomain.ListResponse import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.arm.ApiArm import xyz.driver.pdsuidomain.services.ArmService class RestArmService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: Materializer, protected val exec: ExecutionContext) extends ArmService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.arm._ import xyz.driver.pdsuidomain.services.ArmService._ def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, @@ -30,9 +30,9 @@ class RestArmService(transport: ServiceTransport, baseUri: Uri)(implicit protect endpointUri(baseUri, "/v1/arm", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiArm]](response) + reply <- apiResponse[ListResponse[Arm]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) + GetListReply.EntityList(reply.items, reply.meta.itemsCount) } } @@ -40,20 +40,20 @@ class RestArmService(transport: ServiceTransport, baseUri: Uri)(implicit protect val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/arm/$armId")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiArm](response) + reply <- apiResponse[Arm](response) } yield { - GetByIdReply.Entity(reply.toDomain) + GetByIdReply.Entity(reply) } } def create(draftArm: Arm)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { for { - entity <- Marshal(ApiArm.fromDomain(draftArm)).to[RequestEntity] + entity <- Marshal(draftArm).to[RequestEntity] request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/arm")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiArm](response) + reply <- apiResponse[Arm](response) } yield { - CreateReply.Created(reply.toDomain) + CreateReply.Created(reply) } } @@ -62,9 +62,9 @@ class RestArmService(transport: ServiceTransport, baseUri: Uri)(implicit protect val request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/arm/$id")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiArm](response) + reply <- apiResponse[Arm](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala index f0f4de8..6e2da61 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala @@ -1,7 +1,6 @@ package xyz.driver.pdsuidomain.services.rest import scala.concurrent.{ExecutionContext, Future} - import akka.http.scaladsl.marshalling.Marshal import akka.http.scaladsl.model._ import akka.stream.Materializer @@ -9,8 +8,8 @@ import xyz.driver.core.rest.{Pagination => _, _} import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuidomain.ListResponse import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse import xyz.driver.pdsuidomain.services.CriterionService class RestCriterionService(transport: ServiceTransport, baseUri: Uri)( @@ -18,19 +17,20 @@ class RestCriterionService(transport: ServiceTransport, baseUri: Uri)( protected val exec: ExecutionContext) extends CriterionService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.formats.json.criterion.ApiCriterion + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.criterion._ import xyz.driver.pdsuidomain.services.CriterionService._ def create(draftRichCriterion: RichCriterion)( implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { for { - entity <- Marshal(ApiCriterion.fromDomain(draftRichCriterion)).to[RequestEntity] + entity <- Marshal(draftRichCriterion).to[RequestEntity] request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/criterion")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiCriterion](response) + reply <- apiResponse[RichCriterion](response) } yield { - CreateReply.Created(reply.toDomain) + CreateReply.Created(reply) } } @@ -38,9 +38,9 @@ class RestCriterionService(transport: ServiceTransport, baseUri: Uri)( val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/criterion/$id")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiCriterion](response) + reply <- apiResponse[RichCriterion](response) } yield { - GetByIdReply.Entity(reply.toDomain) + GetByIdReply.Entity(reply) } } @@ -54,9 +54,9 @@ class RestCriterionService(transport: ServiceTransport, baseUri: Uri)( filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiCriterion]](response) + reply <- apiResponse[ListResponse[RichCriterion]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) + GetListReply.EntityList(reply.items, reply.meta.itemsCount, reply.meta.lastUpdate) } } @@ -64,12 +64,12 @@ class RestCriterionService(transport: ServiceTransport, baseUri: Uri)( implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { val id = origRichCriterion.criterion.id for { - entity <- Marshal(ApiCriterion.fromDomain(draftRichCriterion)).to[RequestEntity] + entity <- Marshal(draftRichCriterion).to[RequestEntity] request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/criterion/$id")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiCriterion](response) + reply <- apiResponse[RichCriterion](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentService.scala index 68fdde1..dcd7721 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentService.scala @@ -1,7 +1,6 @@ package xyz.driver.pdsuidomain.services.rest import scala.concurrent.{ExecutionContext, Future} - import akka.http.scaladsl.marshalling.Marshal import akka.http.scaladsl.model._ import akka.stream.Materializer @@ -9,25 +8,26 @@ import xyz.driver.core.rest.{Pagination => _, _} import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuidomain.ListResponse import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.document.ApiDocument import xyz.driver.pdsuidomain.services.DocumentService class RestDocumentService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: Materializer, protected val exec: ExecutionContext) extends DocumentService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.document._ import xyz.driver.pdsuidomain.services.DocumentService._ def getById(id: LongId[Document])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/document/$id")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiDocument](response) + reply <- apiResponse[Document](response) } yield { - GetByIdReply.Entity(reply.toDomain) + GetByIdReply.Entity(reply) } } @@ -42,32 +42,32 @@ class RestDocumentService(transport: ServiceTransport, baseUri: Uri)(implicit pr filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiDocument]](response) + reply <- apiResponse[ListResponse[Document]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) + GetListReply.EntityList(reply.items, reply.meta.itemsCount, reply.meta.lastUpdate) } } def create(draftDocument: Document)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { for { - entity <- Marshal(ApiDocument.fromDomain(draftDocument)).to[RequestEntity] + entity <- Marshal(draftDocument).to[RequestEntity] request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/document")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiDocument](response) + reply <- apiResponse[Document](response) } yield { - CreateReply.Created(reply.toDomain) + CreateReply.Created(reply) } } def update(orig: Document, draft: Document)( implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { for { - entity <- Marshal(ApiDocument.fromDomain(draft)).to[RequestEntity] + entity <- Marshal(draft).to[RequestEntity] request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/document/${orig.id}")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiDocument](response) + reply <- apiResponse[Document](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } @@ -87,9 +87,9 @@ class RestDocumentService(transport: ServiceTransport, baseUri: Uri)(implicit pr val request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, s"/v1/document/$id/$action")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiDocument](response) + reply <- apiResponse[Document](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentTypeService.scala index caa0042..6ddc022 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentTypeService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentTypeService.scala @@ -1,22 +1,23 @@ package xyz.driver.pdsuidomain.services.rest import scala.concurrent.{ExecutionContext, Future} - import akka.http.scaladsl.model._ import akka.stream.Materializer import xyz.driver.core.rest.{Pagination => _, _} import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuidomain.formats.json.ListResponse +import xyz.driver.pdsuidomain.ListResponse +import xyz.driver.pdsuidomain.entities.DocumentType import xyz.driver.pdsuidomain.services.DocumentTypeService -import xyz.driver.pdsuidomain.formats.json.document.ApiDocumentType class RestDocumentTypeService(transport: ServiceTransport, baseUri: Uri)( implicit protected val materializer: Materializer, protected val exec: ExecutionContext) extends DocumentTypeService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.document.documentTypeFormat import xyz.driver.pdsuidomain.services.DocumentTypeService._ def getAll(sorting: Option[Sorting] = None)( @@ -24,9 +25,9 @@ class RestDocumentTypeService(transport: ServiceTransport, baseUri: Uri)( val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/document-type", sortingQuery(sorting))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiDocumentType]](response) + reply <- apiResponse[ListResponse[DocumentType]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) + GetListReply.EntityList(reply.items, reply.meta.itemsCount) } } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala index 93ee2ab..e057c55 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala @@ -24,7 +24,7 @@ class RestEligibilityVerificationService(transport: ServiceTransport, baseUri: U import DefaultJsonProtocol._ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.eligibility._ + import xyz.driver.pdsuidomain.formats.json.eligibility._ override def getMatchedPatients()( implicit ctx: AuthorizedServiceRequestContext[AuthUserInfo]): ListT[Future, eligibility.MatchedPatient] = { diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestExtractedDataService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestExtractedDataService.scala index a65e1f4..8c07968 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestExtractedDataService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestExtractedDataService.scala @@ -10,27 +10,27 @@ import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ import xyz.driver.pdsuidomain.entities._ import xyz.driver.pdsuidomain.entities.export.patient.ExportPatientWithLabels -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.extracteddata.ApiExtractedData import xyz.driver.pdsuidomain.services.ExtractedDataService import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ -import xyz.driver.pdsuidomain.formats.json.sprayformats.export._ +import xyz.driver.pdsuidomain.ListResponse +import xyz.driver.pdsuidomain.formats.json.export._ class RestExtractedDataService(transport: ServiceTransport, baseUri: Uri)( implicit protected val materializer: Materializer, protected val exec: ExecutionContext) extends ExtractedDataService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.extracteddata._ import xyz.driver.pdsuidomain.services.ExtractedDataService._ def getById(id: LongId[ExtractedData])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/extracted-data/$id")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiExtractedData](response) + reply <- apiResponse[RichExtractedData](response) } yield { - GetByIdReply.Entity(reply.toDomain) + GetByIdReply.Entity(reply) } } @@ -44,33 +44,33 @@ class RestExtractedDataService(transport: ServiceTransport, baseUri: Uri)( filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiExtractedData]](response) + reply <- apiResponse[ListResponse[RichExtractedData]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) + GetListReply.EntityList(reply.items, reply.meta.itemsCount) } } def create(draftRichExtractedData: RichExtractedData)( implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { for { - entity <- Marshal(ApiExtractedData.fromDomain(draftRichExtractedData)).to[RequestEntity] + entity <- Marshal(draftRichExtractedData).to[RequestEntity] request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/extracted-data")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiExtractedData](response) + reply <- apiResponse[RichExtractedData](response) } yield { - CreateReply.Created(reply.toDomain) + CreateReply.Created(reply) } } def update(origRichExtractedData: RichExtractedData, draftRichExtractedData: RichExtractedData)( implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { val id = origRichExtractedData.extractedData.id for { - entity <- Marshal(ApiExtractedData.fromDomain(draftRichExtractedData)).to[RequestEntity] + entity <- Marshal(draftRichExtractedData).to[RequestEntity] request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/extracted-data/$id")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiExtractedData](response) + reply <- apiResponse[RichExtractedData](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala index 0ff29ef..bf42f40 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala @@ -17,6 +17,8 @@ import xyz.driver.pdsuicommon.db.{ import xyz.driver.pdsuicommon.error._ trait RestHelper { + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import ErrorsResponse._ implicit protected val materializer: Materializer implicit protected val exec: ExecutionContext @@ -89,7 +91,6 @@ trait RestHelper { implicit unmarshaller: Unmarshaller[ResponseEntity, ApiReply]): Future[ApiReply] = { def extractErrorMessage(response: HttpResponse): Future[String] = { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ Unmarshal(response.entity) .to[ErrorsResponse] .transform( diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala index 1b8c943..a352053 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala @@ -1,14 +1,13 @@ package xyz.driver.pdsuidomain.services.rest import scala.concurrent.{ExecutionContext, Future} - import akka.http.scaladsl.model._ import akka.stream.Materializer import xyz.driver.core.rest._ import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.hypothesis.ApiHypothesis +import xyz.driver.pdsuidomain.ListResponse +import xyz.driver.pdsuidomain.entities.Hypothesis import xyz.driver.pdsuidomain.services.HypothesisService class RestHypothesisService(transport: ServiceTransport, baseUri: Uri)( @@ -16,7 +15,9 @@ class RestHypothesisService(transport: ServiceTransport, baseUri: Uri)( protected val exec: ExecutionContext) extends HypothesisService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.hypothesis._ import xyz.driver.pdsuidomain.services.HypothesisService._ def getAll(sorting: Option[Sorting] = None)( @@ -24,9 +25,9 @@ class RestHypothesisService(transport: ServiceTransport, baseUri: Uri)( val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/hypothesis", sortingQuery(sorting))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiHypothesis]](response) + reply <- apiResponse[ListResponse[Hypothesis]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) + GetListReply.EntityList(reply.items, reply.meta.itemsCount) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala index 025a48a..93036be 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala @@ -8,9 +8,8 @@ import xyz.driver.core.rest.{Pagination => _, _} import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuidomain.ListResponse import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.intervention.ApiIntervention import xyz.driver.pdsuidomain.services.InterventionService class RestInterventionService(transport: ServiceTransport, baseUri: Uri)( @@ -18,7 +17,9 @@ class RestInterventionService(transport: ServiceTransport, baseUri: Uri)( protected val exec: ExecutionContext) extends InterventionService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.intervention._ import xyz.driver.pdsuidomain.services.InterventionService._ def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, @@ -31,9 +32,9 @@ class RestInterventionService(transport: ServiceTransport, baseUri: Uri)( filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiIntervention]](response) + reply <- apiResponse[ListResponse[InterventionWithArms]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) + GetListReply.EntityList(reply.items, reply.meta.itemsCount) } } @@ -41,9 +42,9 @@ class RestInterventionService(transport: ServiceTransport, baseUri: Uri)( val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/intervention/$id")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiIntervention](response) + reply <- apiResponse[InterventionWithArms](response) } yield { - GetByIdReply.Entity(reply.toDomain) + GetByIdReply.Entity(reply) } } @@ -51,24 +52,24 @@ class RestInterventionService(transport: ServiceTransport, baseUri: Uri)( implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { val id = origIntervention.intervention.id for { - entity <- Marshal(ApiIntervention.fromDomain(draftIntervention)).to[RequestEntity] + entity <- Marshal(draftIntervention).to[RequestEntity] request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/intervention/$id")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiIntervention](response) + reply <- apiResponse[InterventionWithArms](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } def create(draftIntervention: InterventionWithArms)( implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { for { - entity <- Marshal(ApiIntervention.fromDomain(draftIntervention)).to[RequestEntity] + entity <- Marshal(draftIntervention).to[RequestEntity] request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/intervention")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiIntervention](response) + reply <- apiResponse[InterventionWithArms](response) } yield { - CreateReply.Created(reply.toDomain) + CreateReply.Created(reply) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala index ce7ac10..004d6c4 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala @@ -1,13 +1,13 @@ package xyz.driver.pdsuidomain.services.rest import scala.concurrent.{ExecutionContext, Future} - import akka.http.scaladsl.model._ import akka.stream.Materializer import xyz.driver.core.rest._ import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuidomain.formats.json.intervention.ApiInterventionType +import xyz.driver.pdsuidomain.ListResponse +import xyz.driver.pdsuidomain.entities.InterventionType import xyz.driver.pdsuidomain.services.InterventionTypeService class RestInterventionTypeService(transport: ServiceTransport, baseUri: Uri)( @@ -15,8 +15,9 @@ class RestInterventionTypeService(transport: ServiceTransport, baseUri: Uri)( protected val exec: ExecutionContext) extends InterventionTypeService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.formats.json.ListResponse + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.intervention.interventionTypeFormat import xyz.driver.pdsuidomain.services.InterventionTypeService._ def getAll(sorting: Option[Sorting] = None)( @@ -24,10 +25,10 @@ class RestInterventionTypeService(transport: ServiceTransport, baseUri: Uri)( val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/intervention-type", sortingQuery(sorting))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiInterventionType]](response) + reply <- apiResponse[ListResponse[InterventionType]](response) } yield { { - val domain = reply.items.flatMap(_.toDomain) + val domain = reply.items GetListReply.EntityList(domain.toList, reply.meta.itemsCount) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMedicalRecordService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMedicalRecordService.scala index f2b0f2d..0627521 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMedicalRecordService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMedicalRecordService.scala @@ -3,8 +3,8 @@ package xyz.driver.pdsuidomain.services.rest import akka.NotUsed import akka.stream.scaladsl.Source import akka.util.ByteString -import scala.concurrent.{ExecutionContext, Future} +import scala.concurrent.{ExecutionContext, Future} import akka.http.scaladsl.marshalling.Marshal import akka.http.scaladsl.model._ import akka.stream.Materializer @@ -12,9 +12,8 @@ import xyz.driver.core.rest.{Pagination => _, _} import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuidomain.ListResponse import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.record.ApiRecord import xyz.driver.pdsuidomain.services.MedicalRecordService class RestMedicalRecordService(transport: ServiceTransport, baseUri: Uri)( @@ -22,7 +21,9 @@ class RestMedicalRecordService(transport: ServiceTransport, baseUri: Uri)( protected val exec: ExecutionContext) extends MedicalRecordService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.record._ import xyz.driver.pdsuidomain.services.MedicalRecordService._ def getById(recordId: LongId[MedicalRecord])( @@ -30,9 +31,9 @@ class RestMedicalRecordService(transport: ServiceTransport, baseUri: Uri)( val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/record/$recordId")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiRecord](response) + reply <- apiResponse[MedicalRecord](response) } yield { - GetByIdReply.Entity(reply.toDomain) + GetByIdReply.Entity(reply) } } @@ -59,20 +60,20 @@ class RestMedicalRecordService(transport: ServiceTransport, baseUri: Uri)( endpointUri(baseUri, "/v1/record", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiRecord]](response) + reply <- apiResponse[ListResponse[MedicalRecord]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) + GetListReply.EntityList(reply.items, reply.meta.itemsCount, reply.meta.lastUpdate) } } def create(draftRecord: MedicalRecord)(implicit requestContext: AnonymousRequestContext): Future[CreateReply] = { for { - entity <- Marshal(ApiRecord.fromDomain(draftRecord)).to[RequestEntity] + entity <- Marshal(draftRecord).to[RequestEntity] request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/record")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiRecord](response) + reply <- apiResponse[MedicalRecord](response) } yield { - CreateReply.Created(reply.toDomain) + CreateReply.Created(reply) } } @@ -80,12 +81,12 @@ class RestMedicalRecordService(transport: ServiceTransport, baseUri: Uri)( implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { val id = origRecord.id.toString for { - entity <- Marshal(ApiRecord.fromDomain(draftRecord)).to[RequestEntity] + entity <- Marshal(draftRecord).to[RequestEntity] request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/record/$id")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiRecord](response) + reply <- apiResponse[MedicalRecord](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } @@ -95,9 +96,9 @@ class RestMedicalRecordService(transport: ServiceTransport, baseUri: Uri)( val request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, s"/v1/record/$id/$action")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiRecord](response) + reply <- apiResponse[MedicalRecord](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala deleted file mode 100644 index e133825..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala +++ /dev/null @@ -1,87 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.message.ApiMessage -import xyz.driver.pdsuidomain.services.MessageService - -class RestMessageService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends MessageService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.MessageService._ - - def create(draftMessage: Message)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { - for { - entity <- Marshal(ApiMessage.fromDomain(draftMessage)).to[RequestEntity] - request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/message")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiMessage](response) - } yield { - CreateReply.Created(reply.toDomain) - } - } - - def getById(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { - import xyz.driver.pdsuicommon.db.SearchFilterBinaryOperation._ - import xyz.driver.pdsuicommon.db.SearchFilterExpr._ - val filter = Atom.Binary("id", Eq, messageId) - getAll(filter).map({ - case GetListReply.EntityList(messages, _, _) if messages.isEmpty => - GetByIdReply.NotFoundError - case GetListReply.EntityList(messages, _, _) => - GetByIdReply.Entity(messages.head) - case GetListReply.AuthorizationError => - GetByIdReply.AuthorizationError - }) - } - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest( - HttpMethods.GET, - endpointUri(baseUri, "/v1/message", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiMessage]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) - } - } - - def update(origMessage: Message, draftMessage: Message)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - for { - entity <- Marshal(ApiMessage.fromDomain(draftMessage)).to[RequestEntity] - id = origMessage.id.id - request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/message/$id")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiMessage](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - def delete(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] = { - val request = HttpRequest(HttpMethods.DELETE, endpointUri(baseUri, s"/v1/message/${messageId.id}")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - _ <- apiResponse[HttpEntity](response) - } yield { - DeleteReply.Deleted - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestPatientService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestPatientService.scala index b9cbec8..af3c782 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestPatientService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestPatientService.scala @@ -8,25 +8,27 @@ import xyz.driver.core.rest.{Pagination => _, _} import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuidomain.ListResponse import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.patient.ApiPatient import xyz.driver.pdsuidomain.services.PatientService class RestPatientService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: Materializer, protected val exec: ExecutionContext) extends PatientService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.patient._ + import xyz.driver.pdsuidomain.services.PatientService._ def getById(id: UuidId[Patient])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/patient/$id")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiPatient](response) + reply <- apiResponse[Patient](response) } yield { - GetByIdReply.Entity(reply.toDomain) + GetByIdReply.Entity(reply) } } @@ -39,9 +41,9 @@ class RestPatientService(transport: ServiceTransport, baseUri: Uri)(implicit pro endpointUri(baseUri, "/v1/patient", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiPatient]](response) + reply <- apiResponse[ListResponse[Patient]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) + GetListReply.EntityList(reply.items, reply.meta.itemsCount, reply.meta.lastUpdate) } } @@ -51,9 +53,9 @@ class RestPatientService(transport: ServiceTransport, baseUri: Uri)(implicit pro val request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, s"/v1/patient/$id/$action")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiPatient](response) + reply <- apiResponse[Patient](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestProviderTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestProviderTypeService.scala index f82ec40..f038c95 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestProviderTypeService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestProviderTypeService.scala @@ -1,22 +1,23 @@ package xyz.driver.pdsuidomain.services.rest import scala.concurrent.{ExecutionContext, Future} - import akka.http.scaladsl.model._ import akka.stream.Materializer import xyz.driver.core.rest.{Pagination => _, _} import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuidomain.formats.json.ListResponse +import xyz.driver.pdsuidomain.ListResponse +import xyz.driver.pdsuidomain.entities.ProviderType import xyz.driver.pdsuidomain.services.ProviderTypeService -import xyz.driver.pdsuidomain.formats.json.document.ApiProviderType class RestProviderTypeService(transport: ServiceTransport, baseUri: Uri)( implicit protected val materializer: Materializer, protected val exec: ExecutionContext) extends ProviderTypeService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.record.providerTypeFormat import xyz.driver.pdsuidomain.services.ProviderTypeService._ def getAll(sorting: Option[Sorting] = None)( @@ -24,9 +25,9 @@ class RestProviderTypeService(transport: ServiceTransport, baseUri: Uri)( val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/provider-type", sortingQuery(sorting))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiProviderType]](response) + reply <- apiResponse[ListResponse[ProviderType]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) + GetListReply.EntityList(reply.items, reply.meta.itemsCount) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala index b1684eb..d3f0eb7 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala @@ -1,14 +1,13 @@ package xyz.driver.pdsuidomain.services.rest import scala.concurrent.{ExecutionContext, Future} - import akka.http.scaladsl.model._ import akka.stream.Materializer import xyz.driver.core.rest._ import xyz.driver.pdsuicommon.auth._ import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.studydesign.ApiStudyDesign +import xyz.driver.pdsuidomain.ListResponse +import xyz.driver.pdsuidomain.entities.StudyDesign import xyz.driver.pdsuidomain.services.StudyDesignService class RestStudyDesignService(transport: ServiceTransport, baseUri: Uri)( @@ -16,7 +15,9 @@ class RestStudyDesignService(transport: ServiceTransport, baseUri: Uri)( protected val exec: ExecutionContext) extends StudyDesignService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.studydesign._ import xyz.driver.pdsuidomain.services.StudyDesignService._ def getAll(sorting: Option[Sorting] = None)( @@ -24,9 +25,9 @@ class RestStudyDesignService(transport: ServiceTransport, baseUri: Uri)( val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/study-design", sortingQuery(sorting))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiStudyDesign]](response) + reply <- apiResponse[ListResponse[StudyDesign]](response) } yield { - GetListReply.EntityList(reply.items.flatMap(_.toDomain), reply.meta.itemsCount) + GetListReply.EntityList(reply.items, reply.meta.itemsCount) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala index ea719e1..04b45fb 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala @@ -13,28 +13,28 @@ import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ import xyz.driver.pdsuidomain.entities._ import xyz.driver.pdsuidomain.entities.export.trial.ExportTrialWithLabels -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.trial.ApiTrial import xyz.driver.pdsuidomain.services.TrialService import spray.json.DefaultJsonProtocol._ -import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import xyz.driver.entities.patient.CancerType -import xyz.driver.pdsuidomain.formats.json.sprayformats.export._ +import xyz.driver.pdsuidomain.ListResponse +import xyz.driver.pdsuidomain.formats.json.export._ class RestTrialService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: Materializer, protected val exec: ExecutionContext) extends TrialService with RestHelper { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.listresponse._ + import xyz.driver.pdsuidomain.formats.json.trial._ import xyz.driver.pdsuidomain.services.TrialService._ def getById(id: StringId[Trial])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/trial/$id")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiTrial](response) + reply <- apiResponse[Trial](response) } yield { - GetByIdReply.Entity(reply.toDomain) + GetByIdReply.Entity(reply) } } @@ -80,9 +80,9 @@ class RestTrialService(transport: ServiceTransport, baseUri: Uri)(implicit prote endpointUri(baseUri, "/v1/trial", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiTrial]](response) + reply <- apiResponse[ListResponse[Trial]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) + GetListReply.EntityList(reply.items, reply.meta.itemsCount, reply.meta.lastUpdate) } } @@ -90,12 +90,12 @@ class RestTrialService(transport: ServiceTransport, baseUri: Uri)(implicit prote implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { val id = origTrial.id.id for { - entity <- Marshal(ApiTrial.fromDomain(draftTrial)).to[RequestEntity] + entity <- Marshal(draftTrial).to[RequestEntity] request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/trial/$id")).withEntity(entity) response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiTrial](response) + reply <- apiResponse[Trial](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } @@ -105,9 +105,9 @@ class RestTrialService(transport: ServiceTransport, baseUri: Uri)(implicit prote val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/trial/$id/$action")) for { response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiTrial](response) + reply <- apiResponse[Trial](response) } yield { - UpdateReply.Updated(reply.toDomain) + UpdateReply.Updated(reply) } } diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/ArmFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ArmFormatSuite.scala new file mode 100644 index 0000000..3cab4a1 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ArmFormatSuite.scala @@ -0,0 +1,37 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.Arm + +class ArmFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.arm._ + + "Json format for Arm" should "read and write correct JSON" in { + val arm = Arm( + id = LongId(10), + trialId = StringId("NCT000001"), + name = "arm name", + originalName = "orig arm name" + ) + val writtenJson = armFormat.write(arm) + + writtenJson should be( + """{"id":10,"trialId":"NCT000001","name":"arm name","originalName":"orig arm name"}""".parseJson) + + val createArmJson = """{"trialId":"NCT000001","name":"arm name"}""".parseJson + val parsedArm = armFormat.read(createArmJson) + val expectedCreatedArm = arm.copy( + id = LongId(0), + originalName = "arm name" + ) + parsedArm should be(expectedCreatedArm) + + val updateArmJson = """{"name":"new arm name"}""".parseJson + val expectedUpdatedArm = arm.copy(name = "new arm name") + val parsedUpdateArm = applyUpdateToArm(updateArmJson, arm) + parsedUpdateArm should be(expectedUpdatedArm) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/BridgeUploadQueueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/BridgeUploadQueueFormatSuite.scala new file mode 100644 index 0000000..9aaecae --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/BridgeUploadQueueFormatSuite.scala @@ -0,0 +1,32 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue + +class BridgeUploadQueueFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.bridgeuploadqueue._ + + "Json format for BridgeUploadQueue.Item" should "read and write correct JSON" in { + val item = BridgeUploadQueue.Item( + kind = "kind", + tag = "tag", + created = LocalDateTime.parse("2017-08-10T18:00:00"), + attempts = 0, + nextAttempt = LocalDateTime.parse("2017-08-10T18:10:00"), + completed = false, + dependencyKind = Some("dependency king"), + dependencyTag = None + ) + val writtenJson = queueUploadItemFormat.write(item) + + writtenJson should be( + """{"kind":"kind","tag":"tag","created":"2017-08-10T18:00Z","attempts":0,"nextAttempt":"2017-08-10T18:10Z","completed":false}""".parseJson) + + val parsedItem = queueUploadItemFormat.read(writtenJson) + parsedItem should be(item.copy(dependencyKind = None, completed = true)) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/CriterionFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/CriterionFormatSuite.scala new file mode 100644 index 0000000..a227afa --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/CriterionFormatSuite.scala @@ -0,0 +1,75 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.{EligibilityArm, Criterion, CriterionLabel} +import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion + +class CriterionFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.criterion._ + + "Json format for Criterion" should "read and write correct JSON" in { + val criterion = Criterion( + id = LongId(10), + trialId = StringId("NCT000001"), + text = Some("text"), + isCompound = false, + meta = "{}", + inclusion = None + ) + val labels = List( + CriterionLabel( + id = LongId(1L), + labelId = Some(LongId(101)), + criterionId = criterion.id, + categoryId = Some(LongId(3)), + value = Some(true), + isDefining = true + ), + CriterionLabel( + id = LongId(2L), + labelId = Some(LongId(102)), + criterionId = criterion.id, + categoryId = Some(LongId(3)), + value = Some(false), + isDefining = true + ) + ) + val arms = List(LongId[EligibilityArm](20), LongId[EligibilityArm](21), LongId[EligibilityArm](21)) + val richCriterion = RichCriterion( + criterion = criterion, + armIds = arms, + labels = labels + ) + val writtenJson = richCriterionFormat.write(richCriterion) + + writtenJson should be( + """{"text":"text","isCompound":false,"trialId":"NCT000001","inclusion":null,"arms":[20,21,21],"id":10,"meta":"{}", + "labels":[{"labelId":101,"categoryId":3,"value":"Yes","isDefining":true}, + {"labelId":102,"categoryId":3,"value":"No","isDefining":true}]}""".parseJson) + + val createCriterionJson = + """{"text":"text","isCompound":false,"trialId":"NCT000001","inclusion":null, + "arms":[20,21,21],"meta":"{}","labels":[{"labelId":101,"categoryId":3,"value":"Yes","isDefining":true}, + {"labelId":102,"categoryId":3,"value":"No","isDefining":true}]}""".parseJson + val parsedRichCriterion = richCriterionFormat.read(createCriterionJson) + val expectedRichCriterion = richCriterion.copy( + criterion = criterion.copy(id = LongId(0)), + labels = labels.map(_.copy(id = LongId(0), criterionId = LongId(0))) + ) + parsedRichCriterion should be(expectedRichCriterion) + + val updateCriterionJson = """{"meta":null,"text":"new text","isCompound":true,"inclusion":true}""".parseJson + val expectedUpdatedCriterion = richCriterion.copy( + criterion = criterion.copy( + text = Some("new text"), + isCompound = true, + meta = "{}", + inclusion = Some(true) + )) + val parsedUpdateCriterion = applyUpdateToCriterion(updateCriterionJson, richCriterion) + parsedUpdateCriterion should be(expectedUpdatedCriterion) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentFormatSuite.scala new file mode 100644 index 0000000..5e33805 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentFormatSuite.scala @@ -0,0 +1,73 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.{LocalDate, LocalDateTime} + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, TextJson} +import xyz.driver.pdsuidomain.entities.Document + +class DocumentFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.document._ + + "Json format for Document" should "read and write correct JSON" in { + val orig = Document( + id = LongId(1), + status = Document.Status.New, + assignee = None, + previousStatus = None, + previousAssignee = None, + lastActiveUserId = None, + lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), + recordId = LongId(101), + physician = Some("physician"), + typeId = Some(LongId(10)), + providerName = Some("provider 21"), + providerTypeId = Some(LongId(21)), + institutionName = Some("institution name"), + requiredType = Some(Document.RequiredType.OPN), + meta = None, + startDate = None, + endDate = None, + labelVersion = 0 + ) + val writtenJson = documentFormat.write(orig) + + writtenJson should be( + """{"id":1,"recordId":101,"physician":"physician","typeId":10,"provider":"provider 21","providerTypeId":21, + "requiredType":"OPN","institutionName":"institution name","startDate":null,"endDate":null,"status":"New","assignee":null,"previousStatus":null, + "previousAssignee":null,"lastActiveUser":null,"lastUpdate":"2017-08-10T18:00Z","meta":null,"labelVersion":0}""".parseJson) + + val createDocumentJson = + """{"recordId":101,"physician":"physician","typeId":10,"provider":"provider 21","providerTypeId":21}""".parseJson + val expectedCreatedDocument = orig.copy( + id = LongId(0), + lastUpdate = LocalDateTime.MIN, + requiredType = None, + institutionName = None + ) + val parsedCreatedDocument = documentFormat.read(createDocumentJson) + parsedCreatedDocument should be(expectedCreatedDocument) + + val updateDocumentJson = + """{"startDate":"2017-08-10","endDate":"2018-08-10","meta":{"startPage":1.0,"endPage":2.0}}""".parseJson + val expectedUpdatedDocument = orig.copy( + startDate = Some(LocalDate.parse("2017-08-10")), + endDate = Some(LocalDate.parse("2018-08-10")), + meta = Some(TextJson(Document.Meta(startPage = 1.0, endPage = 2.0))) + ) + val parsedUpdatedDocument = applyUpdateToDocument(updateDocumentJson, orig) + parsedUpdatedDocument should be(expectedUpdatedDocument) + } + + "Json format for Document.Meta" should "read and write correct JSON" in { + val meta = Document.Meta(startPage = 1.0, endPage = 2.0) + val writtenJson = documentMetaFormat.write(meta) + writtenJson should be("""{"startPage":1.0,"endPage":2.0}""".parseJson) + + val metaJson = """{"startPage":1.0,"endPage":2.0}""".parseJson + val parsedMeta = documentMetaFormat.read(metaJson) + parsedMeta should be(meta) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentHistoryFormatSuite.scala new file mode 100644 index 0000000..e4a0733 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentHistoryFormatSuite.scala @@ -0,0 +1,31 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.DocumentHistory + +class DocumentHistoryFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.documenthistory._ + + "Json format for DocumentHistory" should "read and write correct JSON" in { + val documentHistory = DocumentHistory( + id = LongId(10), + documentId = LongId(1), + executor = StringId("userId-001"), + state = DocumentHistory.State.Extract, + action = DocumentHistory.Action.Start, + created = LocalDateTime.parse("2017-08-10T18:00:00") + ) + val writtenJson = documentHistoryFormat.write(documentHistory) + + writtenJson should be("""{"id":10,"executor":"userId-001","documentId":1,"state":"Extract", + "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) + + val parsedDocumentHistory = documentHistoryFormat.read(writtenJson) + parsedDocumentHistory should be(documentHistory) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentIssueFormatSuite.scala new file mode 100644 index 0000000..7f34725 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/DocumentIssueFormatSuite.scala @@ -0,0 +1,48 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.DocumentIssue + +class DocumentIssueFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.documentissue._ + + "Json format for DocumentIssue" should "read and write correct JSON" in { + val documentIssue = DocumentIssue( + id = LongId(10), + documentId = LongId(1), + userId = StringId("userId-001"), + lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), + isDraft = false, + text = "message text", + archiveRequired = false, + startPage = Some(1.0), + endPage = Some(2.0) + ) + val writtenJson = documentIssueFormat.write(documentIssue) + + writtenJson should be( + """{"id":10,"userId":"userId-001","documentId":1,"lastUpdate":"2017-08-10T18:00Z","isDraft":false, + "text":"message text","archiveRequired":false,"startPage":1.0,"endPage":2.0}""".parseJson) + + val createDocumentIssueJson = """{"text":"message text","startPage":1.0,"endPage":2.0}""".parseJson + val expectedCreatedDocumentIssue = + documentIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) + val parsedCreateDocumentIssue = jsValueToDocumentIssue(createDocumentIssueJson, LongId(1), StringId("userId-001")) + parsedCreateDocumentIssue should be(expectedCreatedDocumentIssue) + + val updateDocumentIssueJson = + """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true,"startPage":1.0,"endPage":4.0}""".parseJson + val expectedUpdatedDocumentIssue = documentIssue.copy( + text = "new issue text", + archiveRequired = true, + endPage = Some(4.0) + ) + val parsedUpdateDocumentIssue = applyUpdateToDocumentIssue(updateDocumentIssueJson, documentIssue) + parsedUpdateDocumentIssue should be(expectedUpdatedDocumentIssue) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/EligibilityArmWithDiseasesFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/EligibilityArmWithDiseasesFormatSuite.scala new file mode 100644 index 0000000..054f2f6 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/EligibilityArmWithDiseasesFormatSuite.scala @@ -0,0 +1,55 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.entities.patient.CancerType +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.{EligibilityArm, EligibilityArmDisease, EligibilityArmWithDiseases} + +class EligibilityArmWithDiseasesFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.eligibilityarm._ + + "Json format for EligibilityArmWithDiseases" should "read and write correct JSON" in { + val name = "arm name" + + val arm = EligibilityArm( + id = LongId(0), + trialId = StringId("NCT000001"), + name = name, + originalName = name + ) + + val disease = EligibilityArmDisease( + arm.id, + disease = CancerType.Lung + ) + + val eligibilityArmWithDiseases = + EligibilityArmWithDiseases( + arm, + Seq(disease) + ) + + val writtenJson = eligibilityArmWithDiseasesWriter.write(eligibilityArmWithDiseases) + + writtenJson should be( + """{"id":0,"trialId":"NCT000001","name":"arm name","originalName":"arm name","diseases":["Lung"]}""".parseJson) + + val createArmWithDiseasesJson = """{"trialId":"NCT000001","name":"arm name","diseases":["Lung"]}""".parseJson + val parsedArmWithDiseases = eligibilityArmWithDiseasesReader.read(createArmWithDiseasesJson) + parsedArmWithDiseases should be(eligibilityArmWithDiseases) + + val updateArmWithDiseasesJson = """{"name":"new arm name"}""".parseJson + val expectedUpdatedArmWithDiseases = eligibilityArmWithDiseases.copy( + eligibilityArm = eligibilityArmWithDiseases.eligibilityArm.copy(name = "new arm name") + ) + + val parsedUpdateArmWithDiseases = + applyUpdateToEligibilityArmWithDiseases( + updateArmWithDiseasesJson, + eligibilityArmWithDiseases + ) + + parsedUpdateArmWithDiseases should be(expectedUpdatedArmWithDiseases) + } +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/ExportFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ExportFormatSuite.scala new file mode 100644 index 0000000..1f024c3 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ExportFormatSuite.scala @@ -0,0 +1,124 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.{LocalDate, LocalDateTime} +import java.util.UUID + +import org.scalatest.{FlatSpec, Matchers} +import spray.json._ +import xyz.driver.entities.labels.LabelValue +import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} +import xyz.driver.pdsuidomain.entities.{DocumentType, ProviderType, RecordRequestId} + +class ExportFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.export._ + + "Json format for ExportPatientWithLabels" should "read and write correct JSON" in { + import xyz.driver.pdsuidomain.entities.export.patient._ + val document = ExportPatientLabelEvidenceDocument( + documentId = LongId(101), + requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), + documentType = DocumentType.OutpatientPhysicianNote, + providerType = ProviderType.Surgery, + date = LocalDate.parse("2017-08-10") + ) + + val labels = List( + ExportPatientLabel( + id = LongId(1), + evidences = List( + ExportPatientLabelEvidence( + id = LongId(11), + value = LabelValue.Yes, + evidenceText = "evidence text 11", + document = document + ), + ExportPatientLabelEvidence( + id = LongId(12), + value = LabelValue.No, + evidenceText = "evidence text 12", + document = document + ) + ) + ), + ExportPatientLabel( + id = LongId(2), + evidences = List( + ExportPatientLabelEvidence( + id = LongId(12), + value = LabelValue.Yes, + evidenceText = "evidence text 12", + document = document + ), + ExportPatientLabelEvidence( + id = LongId(13), + value = LabelValue.Yes, + evidenceText = "evidence text 13", + document = document + ) + ) + ) + ) + val patientWithLabels = ExportPatientWithLabels( + patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + labelVersion = 1L, + labels = labels + ) + + val writtenJson = patientWithLabelsFormat.write(patientWithLabels) + writtenJson should be( + """{"patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","labelVersion":1,"labels":[{"labelId":1,"evidence":[{"evidenceId":11, + "labelValue":"Yes","evidenceText":"evidence text 11","document":{"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9", + "documentType":{"id":1,"name":"Outpatient Physician Note"},"providerType":{"id":2,"name":"Surgery"},"date":"2017-08-10"}}, + {"evidenceId":12,"labelValue":"No","evidenceText":"evidence text 12","document":{"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9", + "documentType":{"id":1,"name":"Outpatient Physician Note"},"providerType":{"id":2,"name":"Surgery"},"date":"2017-08-10"}}]}, + {"labelId":2,"evidence":[{"evidenceId":12,"labelValue":"Yes","evidenceText":"evidence text 12","document": + {"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","documentType":{"id":1,"name":"Outpatient Physician Note"}, + "providerType":{"id":2,"name":"Surgery"},"date":"2017-08-10"}},{"evidenceId":13,"labelValue":"Yes","evidenceText":"evidence text 13", + "document":{"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","documentType":{"id":1,"name":"Outpatient Physician Note"}, + "providerType":{"id":2,"name":"Surgery"},"date":"2017-08-10"}}]}]}""".parseJson) + } + + "Json format for ApiExportTrialWithLabels" should "read and write correct JSON" in { + import xyz.driver.pdsuidomain.entities.export.trial._ + val arms = List( + ExportTrialArm(armId = LongId(1), armName = "arm 1", diseaseList = Seq("Breast")), + ExportTrialArm(armId = LongId(2), armName = "arm 2", diseaseList = Seq("Breast")) + ) + val criteriaList = List( + ExportTrialLabelCriterion( + criterionId = LongId(10), + value = Some(true), + labelId = LongId(21), + armIds = Set(LongId(1), LongId(2)), + criteria = "criteria 10 text", + isCompound = false, + isDefining = false + ), + ExportTrialLabelCriterion( + criterionId = LongId(11), + value = None, + labelId = LongId(21), + armIds = Set(LongId(2)), + criteria = "criteria 11 text", + isCompound = true, + isDefining = false + ) + ) + val trialWithLabels = ExportTrialWithLabels( + nctId = StringId("NCT000001"), + trialId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), + lastReviewed = LocalDateTime.parse("2017-08-10T18:00:00"), + labelVersion = 1L, + arms = arms, + criteria = criteriaList + ) + + val writtenJson = trialWithLabelsFormat.write(trialWithLabels) + writtenJson should be( + """{"nctId":"NCT000001","trialId":"40892a07-c638-49d2-9795-1edfefbbcc7c","lastReviewed":"2017-08-10T18:00Z", + "labelVersion":1,"arms":[{"armId":1,"armName":"arm 1","diseaseList":["Breast"]},{"armId":2,"armName":"arm 2","diseaseList":["Breast"]}],"criteria":[ + {"value":"Yes","labelId":21,"criterionId":10,"criterionText":"criteria 10 text","armIds":[1,2],"isCompound":false,"isDefining":false}, + {"value":"Unknown","labelId":21,"criterionId":11,"criterionText":"criteria 11 text","armIds":[2],"isCompound":true,"isDefining":false}]}""".parseJson) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/ExtractedDataFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ExtractedDataFormatSuite.scala new file mode 100644 index 0000000..bc20280 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ExtractedDataFormatSuite.scala @@ -0,0 +1,97 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.entities.labels.LabelValue +import xyz.driver.pdsuicommon.domain.{LongId, TextJson} +import xyz.driver.pdsuidomain.entities.ExtractedData.Meta +import xyz.driver.pdsuidomain.entities.{ExtractedData, ExtractedDataLabel} +import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData + +class ExtractedDataFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.extracteddata._ + + "Json format for ExtractedData" should "read and write correct JSON" in { + val extractedData = ExtractedData( + id = LongId(1), + documentId = LongId(101), + keywordId = Some(LongId(201)), + evidenceText = Some("evidence text"), + meta = None + ) + val extractedDataLabels = List( + ExtractedDataLabel( + id = LongId(1), + dataId = extractedData.id, + labelId = None, + categoryId = None, + value = Some(LabelValue.Yes) + ), + ExtractedDataLabel( + id = LongId(2), + dataId = extractedData.id, + labelId = Some(LongId(12)), + categoryId = Some(LongId(1)), + value = Some(LabelValue.No) + ) + ) + val origRichExtractedData = RichExtractedData( + extractedData = extractedData, + labels = extractedDataLabels + ) + val writtenJson = extractedDataFormat.write(origRichExtractedData) + + writtenJson should be( + """{"id":1,"documentId":101,"keywordId":201,"evidence":"evidence text","meta":null, + "labels":[{"id":null,"categoryId":null,"value":"Yes"},{"id":12,"categoryId":1,"value":"No"}]}""".parseJson) + + val createExtractedDataJson = + """{"documentId":101,"keywordId":201,"evidence":"evidence text", + "labels":[{"value":"Yes"},{"id":12,"categoryId":1,"value":"No"}]}""".parseJson + val expectedCreatedExtractedData = origRichExtractedData.copy( + extractedData = extractedData.copy(id = LongId(0)), + labels = extractedDataLabels.map(_.copy(id = LongId(0), dataId = LongId(0))) + ) + val parsedCreatedExtractedData = extractedDataFormat.read(createExtractedDataJson) + parsedCreatedExtractedData should be(expectedCreatedExtractedData) + + val updateExtractedDataJson = + """{"evidence":"new evidence text","meta":{"keyword":{"page":1,"index":2,"sortIndex":"ASC"}, + "evidence":{"pageRatio":1.0,"start":{"page":1,"index":3,"offset":2},"end":{"page":2,"index":3,"offset":10}}}, + "labels":[{"id":20,"categoryId":1,"value":"Yes"},{"id":12,"categoryId":1,"value":"No"}]}""".parseJson + val updatedExtractedDataLabels = List( + ExtractedDataLabel( + id = LongId(0), + dataId = extractedData.id, + labelId = Some(LongId(20)), + categoryId = Some(LongId(1)), + value = Some(LabelValue.Yes) + ), + ExtractedDataLabel( + id = LongId(0), + dataId = extractedData.id, + labelId = Some(LongId(12)), + categoryId = Some(LongId(1)), + value = Some(LabelValue.No) + ) + ) + val expectedUpdatedExtractedData = origRichExtractedData.copy( + extractedData = extractedData.copy( + evidenceText = Some("new evidence text"), + meta = Some( + TextJson(Meta( + keyword = Meta.Keyword(page = 1, pageRatio = None, index = 2, sortIndex = "ASC"), + evidence = Meta.Evidence( + pageRatio = 1.0, + start = Meta.TextLayerPosition(page = 1, index = 3, offset = 2), + end = Meta.TextLayerPosition(page = 2, index = 3, offset = 10) + ) + ))) + ), + labels = updatedExtractedDataLabels + ) + val parsedUpdatedExtractedData = applyUpdateToExtractedData(updateExtractedDataJson, origRichExtractedData) + parsedUpdatedExtractedData should be(expectedUpdatedExtractedData) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/HypothesisFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/HypothesisFormatSuite.scala new file mode 100644 index 0000000..6d51873 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/HypothesisFormatSuite.scala @@ -0,0 +1,27 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.UuidId +import xyz.driver.pdsuidomain.entities.Hypothesis + +class HypothesisFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.hypothesis._ + + "Json format for Hypothesis" should "read and write correct JSON" in { + val hypothesis = Hypothesis( + id = UuidId("3b80b2e2-5372-4cf5-a342-6e4ebe10fafd"), + name = "hypothesis name", + treatmentType = "treatment type", + description = "descr" + ) + val writtenJson = hypothesisFormat.write(hypothesis) + + writtenJson should be("""{"id":"3b80b2e2-5372-4cf5-a342-6e4ebe10fafd","name":"hypothesis name", + "treatmentType":"treatment type","description":"descr"}""".parseJson) + + val parsedHypothesis = hypothesisFormat.read(writtenJson) + parsedHypothesis should be(hypothesis) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/InterventionFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/InterventionFormatSuite.scala new file mode 100644 index 0000000..ac01c34 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/InterventionFormatSuite.scala @@ -0,0 +1,73 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.{Intervention, InterventionArm, InterventionType, InterventionWithArms} + +class InterventionFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.intervention._ + + "Json format for Intervention" should "read and write correct JSON" in { + val intervention = Intervention( + id = LongId(1), + trialId = StringId("NCT000001"), + name = "intervention name", + originalName = "orig name", + typeId = Some(LongId(10)), + originalType = Some("orig type"), + dosage = "", + originalDosage = "", + isActive = true, + deliveryMethod = Some("pill") + ) + val arms = List( + InterventionArm(interventionId = intervention.id, armId = LongId(20)), + InterventionArm(interventionId = intervention.id, armId = LongId(21)), + InterventionArm(interventionId = intervention.id, armId = LongId(22)) + ) + val orig = InterventionWithArms( + intervention = intervention, + arms = arms + ) + val writtenJson = interventionFormat.write(orig) + + writtenJson should be( + """{"id":1,"name":"intervention name","typeId":10,"dosage":"","isActive":true,"arms":[20,21,22], + "trialId":"NCT000001","deliveryMethod":"pill","originalName":"orig name","originalDosage":"","originalType":"orig type"}""".parseJson) + + val createInterventionJson = + """{"id":1,"name":"intervention name","typeId":10,"dosage":"","isActive":true,"arms":[20,21,22], + "trialId":"NCT000001","deliveryMethod":"pill"}""".parseJson + val parsedCreateIntervention = interventionFormat.read(createInterventionJson) + val expectedCreateIntervention = parsedCreateIntervention.copy( + intervention = intervention.copy(id = LongId(0), originalType = None, originalName = "intervention name"), + arms = arms.map(_.copy(interventionId = LongId(0))) + ) + parsedCreateIntervention should be(expectedCreateIntervention) + + val updateInterventionJson = """{"dosage":"descr","arms":[21,22]}""".parseJson + val expectedUpdatedIntervention = orig.copy( + intervention = intervention.copy(dosage = "descr"), + arms = List( + InterventionArm(interventionId = intervention.id, armId = LongId(21)), + InterventionArm(interventionId = intervention.id, armId = LongId(22)) + ) + ) + val parsedUpdateIntervention = applyUpdateToInterventionWithArms(updateInterventionJson, orig) + parsedUpdateIntervention should be(expectedUpdatedIntervention) + } + + "Json format for InterventionType" should "read and write correct JSON" in { + val interventionType = InterventionType.SurgeryProcedure + val writtenJson = interventionTypeFormat.write(interventionType) + + writtenJson should be( + """{"id":9,"name":"Surgery/Procedure","deliveryMethods":["Radio-Frequency Ablation (RFA)", + "Cryoablation","Therapeutic Conventional Surgery","Robotic Assisted Laparoscopic Surgery"]}""".parseJson) + + val parsedInterventionType = interventionTypeFormat.read(writtenJson) + parsedInterventionType should be(interventionType) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/ListResponseFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ListResponseFormatSuite.scala new file mode 100644 index 0000000..c561412 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ListResponseFormatSuite.scala @@ -0,0 +1,101 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime +import java.util.UUID + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, UuidId} +import xyz.driver.pdsuidomain.ListResponse +import xyz.driver.pdsuidomain.entities.MedicalRecord.Status +import xyz.driver.pdsuidomain.entities._ +import xyz.driver.pdsuidomain.formats.json.record.recordFormat +import xyz.driver.pdsuidomain.formats.json.listresponse._ + + +class ListResponseFormatSuite extends FlatSpec with Matchers { + + private val lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00") + private val lastUpdateToLocal = "2017-08-10T18:00Z" + + def metaJsonObjectAsString(meta: ListResponse.Meta) = { + import meta._ + val lastUpdate = meta.lastUpdate + .map(_ => s""","lastUpdate":"$lastUpdateToLocal"""") + .getOrElse("") + + s"""{"itemsCount":$itemsCount,"pageNumber":$pageNumber,"pageSize":$pageSize$lastUpdate}""" + } + + "Json format for ListResponse.Meta" should "read and write correct JSON" in { + val meta1 = + ListResponse.Meta( + itemsCount = 5, + pageNumber = 6, + pageSize = 7, + lastUpdate = None + ) + + val writtenJson1 = listResponseMetaFormat.write(meta1) + + writtenJson1 should be(metaJsonObjectAsString(meta1).parseJson) + + val parsedItem1: ListResponse.Meta = listResponseMetaFormat.read(writtenJson1) + + meta1 shouldBe parsedItem1 + + val meta2 = + ListResponse.Meta( + itemsCount = 1, + pageNumber = 4, + pageSize = 3, + lastUpdate = Some(lastUpdate) + ) + + val writtenJson2 = listResponseMetaFormat.write(meta2) + + writtenJson2 should be(metaJsonObjectAsString(meta2).parseJson) + + val parsedItem2: ListResponse.Meta = listResponseMetaFormat.read(writtenJson2) + + meta2 shouldBe parsedItem2 + } + + "Json format for ListResponse" should "write correct JSON" in { + + val orig = MedicalRecord( + id = LongId(1), + status = Status.New, + assignee = None, + previousStatus = None, + previousAssignee = None, + lastActiveUserId = None, + lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), + physician = Some("physician"), + meta = None, + disease = "Breast", + requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), + caseId = None, + patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + totalPages = 10 + ) + + val recordJsonAsString = recordFormat.write(orig) + + val meta = + ListResponse.Meta( + itemsCount = 5, + pageNumber = 6, + pageSize = 7, + lastUpdate = None + ) + + val listResponse = ListResponse(Seq(orig), meta) + + val writtenJson = listResponseWriter[MedicalRecord].write(listResponse) + val expectedJson = s"""{"items":[$recordJsonAsString],"meta":${listResponseMetaFormat.write(meta)}}""" + + writtenJson should be(expectedJson.parseJson) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordFormatSuite.scala new file mode 100644 index 0000000..e811a29 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordFormatSuite.scala @@ -0,0 +1,77 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime +import java.util.UUID + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, TextJson, UuidId} +import xyz.driver.pdsuidomain.entities.{MedicalRecord, RecordRequestId} + +class MedicalRecordFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.record._ + import MedicalRecord._ + + "Json format for MedicalRecord" should "read and write correct JSON" in { + val orig = MedicalRecord( + id = LongId(1), + status = Status.New, + assignee = None, + previousStatus = None, + previousAssignee = None, + lastActiveUserId = None, + lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), + physician = Some("physician"), + meta = None, + disease = "Breast", + requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), + caseId = None, + patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + totalPages = 10 + ) + val writtenJson = recordFormat.write(orig) + + writtenJson should be( + """{"id":1,"status":"New","assignee":null,"previousStatus":null,"previousAssignee":null,"lastActiveUser":null, + "lastUpdate":"2017-08-10T18:00Z","meta":[],"patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","caseId":null, + "requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","disease":"Breast","physician":"physician","totalPages":10}""".parseJson) + + val createRecordJson = + """{"disease":"Breast","patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9"}""".parseJson + val expectedCreatedRecord = MedicalRecord( + id = LongId(0), + status = MedicalRecord.Status.New, + previousStatus = None, + assignee = None, + previousAssignee = None, + lastActiveUserId = None, + patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), + disease = "Breast", + caseId = None, + physician = None, + meta = None, + lastUpdate = LocalDateTime.now(), + totalPages = 0 + ) + val parsedCreatedRecord = recordFormat.read(createRecordJson).copy(lastUpdate = expectedCreatedRecord.lastUpdate) + parsedCreatedRecord should be(expectedCreatedRecord) + + val updateRecordJson = + """{"meta":[{"type":"duplicate","startPage":1.0,"endPage":2.0,"startOriginalPage":1.0}, + {"type":"reorder","items":[1,2]}, + {"type":"rotation","items":{"item1":1,"item2":2}}]}""".parseJson + val expectedUpdatedRecord = orig.copy( + meta = Some( + TextJson( + List( + Meta.Duplicate(startPage = 1.0, endPage = 2.0, startOriginalPage = 1.0, endOriginalPage = None), + Meta.Reorder(Seq(1, 2)), + Meta.Rotation(Map("item1" -> 1, "item2" -> 2)) + ))) + ) + val parsedUpdatedRecord = applyUpdateToMedicalRecord(updateRecordJson, orig) + parsedUpdatedRecord should be(expectedUpdatedRecord) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordHistoryFormatSuite.scala new file mode 100644 index 0000000..ca4058e --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordHistoryFormatSuite.scala @@ -0,0 +1,31 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.MedicalRecordHistory + +class MedicalRecordHistoryFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.recordhistory._ + + "Json format for MedicalRecordHistory" should "read and write correct JSON" in { + val recordHistory = MedicalRecordHistory( + id = LongId(10), + recordId = LongId(1), + executor = StringId("userId-001"), + state = MedicalRecordHistory.State.Clean, + action = MedicalRecordHistory.Action.Start, + created = LocalDateTime.parse("2017-08-10T18:00:00") + ) + val writtenJson = recordHistoryFormat.write(recordHistory) + + writtenJson should be("""{"id":10,"executor":"userId-001","recordId":1,"state":"Clean", + "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) + + val parsedRecordHistory = recordHistoryFormat.read(writtenJson) + parsedRecordHistory should be(recordHistory) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordIssueFormatSuite.scala new file mode 100644 index 0000000..c7c82a4 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/MedicalRecordIssueFormatSuite.scala @@ -0,0 +1,47 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.MedicalRecordIssue + +class MedicalRecordIssueFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.recordissue._ + + "Json format for MedicalRecordIssue" should "read and write correct JSON" in { + val recordIssue = MedicalRecordIssue( + id = LongId(10), + recordId = LongId(1), + userId = StringId("userId-001"), + lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), + isDraft = false, + text = "message text", + archiveRequired = false, + startPage = Some(1.0), + endPage = Some(2.0) + ) + val writtenJson = recordIssueFormat.write(recordIssue) + + writtenJson should be( + """{"id":10,"recordId":1,"userId":"userId-001","lastUpdate":"2017-08-10T18:00Z","isDraft":false, + "text":"message text","archiveRequired":false,"startPage":1.0,"endPage":2.0}""".parseJson) + + val createRecordIssueJson = """{"text":"message text","startPage":1.0,"endPage":2.0}""".parseJson + val expectedCreatedRecordIssue = recordIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) + val parsedCreateRecordIssue = jsValueToRecordIssue(createRecordIssueJson, LongId(1), StringId("userId-001")) + parsedCreateRecordIssue should be(expectedCreatedRecordIssue) + + val updateRecordIssueJson = + """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true,"startPage":1.0,"endPage":4.0}""".parseJson + val expectedUpdatedRecordIssue = recordIssue.copy( + text = "new issue text", + archiveRequired = true, + endPage = Some(4.0) + ) + val parsedUpdateRecordIssue = applyUpdateToRecordIssue(updateRecordIssueJson, recordIssue) + parsedUpdateRecordIssue should be(expectedUpdatedRecordIssue) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientCriterionFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientCriterionFormatSuite.scala new file mode 100644 index 0000000..2e193c7 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientCriterionFormatSuite.scala @@ -0,0 +1,58 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.entities.labels.LabelValue +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.{PatientCriterion, PatientCriterionArm} +import xyz.driver.pdsuidomain.services.PatientCriterionService.{DraftPatientCriterion, RichPatientCriterion} + +class PatientCriterionFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.patientcriterion._ + + "Json format for PatientCriterion" should "read and write correct JSON" in { + val orig = PatientCriterion( + id = LongId(1), + patientLabelId = LongId(1), + trialId = 0L, + nctId = StringId("NCT00001"), + criterionId = LongId(101), + criterionText = "criterion text", + criterionValue = Some(true), + criterionIsDefining = false, + eligibilityStatus = Some(LabelValue.Yes), + verifiedEligibilityStatus = None, + isVisible = true, + isVerified = true, + lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00") + ) + val arms = List( + PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(31), armName = "arm 31"), + PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(32), armName = "arm 32") + ) + val richPatientCriterion = RichPatientCriterion(orig, LongId(21), arms) + val writtenJson = patientCriterionWriter.write(richPatientCriterion) + + writtenJson should be( + """{"id":1,"labelId":21,"nctId":"NCT00001","criterionId":101,"criterionText":"criterion text","criterionValue":"Yes", + "criterionIsDefining":false,"criterionIsCompound":false,"eligibilityStatus":"Yes","verifiedEligibilityStatus":null, + "isVisible":true,"isVerified":true,"lastUpdate":"2017-08-10T18:00Z","arms":["arm 31","arm 32"]}""".parseJson) + + val updatePatientCriterionJson = """{"verifiedEligibilityStatus":"No"}""".parseJson + val expectedUpdatedPatientCriterion = orig.copy(verifiedEligibilityStatus = Some(LabelValue.No)) + val parsedUpdatePatientCriterion = applyUpdateToPatientCriterion(updatePatientCriterionJson, orig) + parsedUpdatePatientCriterion should be(expectedUpdatedPatientCriterion) + + val updateBulkPatientCriterionJson = + """[{"id":1,"eligibilityStatus":"No"},{"id":2,"isVerified":false}]""".parseJson + val expectedDraftPatientCriterionList = List( + DraftPatientCriterion(id = LongId(1), eligibilityStatus = Some(LabelValue.No), isVerified = None), + DraftPatientCriterion(id = LongId(2), eligibilityStatus = None, isVerified = Some(false)) + ) + val parsedDraftPatientCriterionList = draftPatientCriterionListReader.read(updateBulkPatientCriterionJson) + parsedDraftPatientCriterionList should be(expectedDraftPatientCriterionList) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientEligibleTrialFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientEligibleTrialFormatSuite.scala new file mode 100644 index 0000000..b5fbf3f --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientEligibleTrialFormatSuite.scala @@ -0,0 +1,62 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import org.scalatest.{FlatSpec, Matchers} +import spray.json._ +import xyz.driver.entities.labels.LabelValue +import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} +import xyz.driver.pdsuidomain.entities.{PatientCriterionArm, PatientTrialArmGroupView, Trial} +import xyz.driver.pdsuidomain.services.PatientEligibleTrialService.RichPatientEligibleTrial + +class PatientEligibleTrialFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.patienteligibletrial._ + + "Json format for PatientEligibleTrial" should "read and write correct JSON" in { + val trial = Trial( + id = StringId("NCT000001"), + externalId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), + status = Trial.Status.Done, + assignee = None, + previousStatus = None, + previousAssignee = None, + lastActiveUserId = None, + lastUpdate = LocalDateTime.parse("2017-08-10T18:16:19"), + phase = "", + hypothesisId = Some(UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4")), + studyDesignId = Some(LongId(321)), + originalStudyDesign = None, + isPartner = false, + overview = None, + overviewTemplate = "", + isUpdated = false, + title = "trial title", + originalTitle = "orig trial title" + ) + val group = PatientTrialArmGroupView( + id = LongId(1), + patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + trialId = StringId("NCT000001"), + hypothesisId = UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4"), + eligibilityStatus = Some(LabelValue.Yes), + verifiedEligibilityStatus = Some(LabelValue.Yes), + isVerified = false + ) + val arms = List( + PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(31), armName = "arm 31"), + PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(32), armName = "arm 32") + ) + val orig = RichPatientEligibleTrial(trial, group, arms) + val writtenJson = patientEligibleTrialWriter.write(orig) + + writtenJson should be( + """{"id":1,"patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","trialId":"NCT000001","trialTitle":"trial title", + "hypothesisId":"e76e2fc4-a29c-44fb-a81b-8856d06bb1d4","verifiedEligibilityStatus":"Yes","isVerified":false,"arms":["arm 31","arm 32"]}""".parseJson) + + val updatePatientEligibleTrialJson = """{"isVerified":true}""".parseJson + val expectedUpdatedPatientTrialArmGroup = group.copy(isVerified = true) + val parsedUpdatePatientTrialArmGroup = applyUpdateToTrialArmGroup(updatePatientEligibleTrialJson, group) + parsedUpdatePatientTrialArmGroup should be(expectedUpdatedPatientTrialArmGroup) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientFormatSuite.scala new file mode 100644 index 0000000..c296f84 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientFormatSuite.scala @@ -0,0 +1,39 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.{LocalDate, LocalDateTime} + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.entities.common.FullName +import xyz.driver.entities.patient.CancerType +import xyz.driver.pdsuicommon.domain.UuidId +import xyz.driver.pdsuidomain.entities.{Patient, PatientOrderId} + +class PatientFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.patient._ + + "Json format for Patient" should "read and write correct JSON" in { + val orig = Patient( + id = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + status = Patient.Status.New, + name = FullName.fromStrings("John", "", "Doe"), + dob = LocalDate.parse("1980-06-30"), + assignee = None, + previousStatus = None, + previousAssignee = None, + lastActiveUserId = None, + isUpdateRequired = false, + disease = CancerType.Breast, + orderId = PatientOrderId("7b54a75d-4197-4b27-9045-b9b6cb131be9"), + lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00") + ) + val writtenJson = patientFormat.write(orig) + + writtenJson should be( + """{"id":"748b5884-3528-4cb9-904b-7a8151d6e343","dob":"1980-06-30", + "name":{"firstName":"John","middleName":"","lastName":"Doe"},"status":"New","assignee":null, + "previousStatus":null,"previousAssignee":null,"lastActiveUser":null,"lastUpdate":"2017-08-10T18:00Z", + "orderId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","disease":"Breast"}""".parseJson) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientHistoryFormatSuite.scala new file mode 100644 index 0000000..e46cf50 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientHistoryFormatSuite.scala @@ -0,0 +1,32 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} +import xyz.driver.pdsuidomain.entities.PatientHistory + +class PatientHistoryFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.patienthistory._ + + "Json format for PatientHistory" should "read and write correct JSON" in { + val patientHistory = PatientHistory( + id = LongId(10), + patientId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), + executor = StringId("userId-001"), + state = PatientHistory.State.Verify, + action = PatientHistory.Action.Start, + created = LocalDateTime.parse("2017-08-10T18:00:00") + ) + val writtenJson = patientHistoryFormat.write(patientHistory) + + writtenJson should be( + """{"id":10,"executor":"userId-001","patientId":"40892a07-c638-49d2-9795-1edfefbbcc7c","state":"Verify", + "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) + + val parsedPatientHistory = patientHistoryFormat.read(writtenJson) + parsedPatientHistory should be(patientHistory) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientHypothesisFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientHypothesisFormatSuite.scala new file mode 100644 index 0000000..270a04d --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientHypothesisFormatSuite.scala @@ -0,0 +1,47 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.UuidId +import xyz.driver.pdsuidomain.entities.PatientHypothesis +import xyz.driver.pdsuidomain.services.PatientHypothesisService.RichPatientHypothesis + +class PatientHypothesisFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.patienthypothesis._ + + "Json format for RichPatientHypothesis" should "read and write correct JSON" in { + val orig = PatientHypothesis( + id = UuidId("815d9715-1089-4775-b120-3afb983b9a97"), + patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + hypothesisId = UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4"), + rationale = None, + matchedTrials = 1 + ) + val writtenJson = richPatientHypothesisWriter.write(RichPatientHypothesis(orig, isRequired = true)) + + writtenJson should be( + """{"id":"815d9715-1089-4775-b120-3afb983b9a97","patientId":"748b5884-3528-4cb9-904b-7a8151d6e343", + "hypothesisId":"e76e2fc4-a29c-44fb-a81b-8856d06bb1d4","rationale":null,"matchedTrials":1,"isRationaleRequired":true}""".parseJson) + + val updatePatientHypothesisJson = """{"rationale":"rationale"}""".parseJson + val expectedUpdatedPatientHypothesis = orig.copy(rationale = Some("rationale")) + val parsedUpdatePatientHypothesis = applyUpdateToPatientHypothesis(updatePatientHypothesisJson, orig) + parsedUpdatePatientHypothesis should be(expectedUpdatedPatientHypothesis) + } + + "Json format for patientHypothesis" should "read and write correct JSON" in { + val orig = PatientHypothesis( + id = UuidId("815d9715-1089-4775-b120-3afb983b9a97"), + patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + hypothesisId = UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4"), + rationale = None, + matchedTrials = 1 + ) + val writtenJson = patientHypothesisWriter.write(orig) + + writtenJson should be( + """{"id":"815d9715-1089-4775-b120-3afb983b9a97","patientId":"748b5884-3528-4cb9-904b-7a8151d6e343", + "hypothesisId":"e76e2fc4-a29c-44fb-a81b-8856d06bb1d4","rationale":null,"matchedTrials":1}""".parseJson) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientIssueFormatSuite.scala new file mode 100644 index 0000000..0d56918 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientIssueFormatSuite.scala @@ -0,0 +1,45 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} +import xyz.driver.pdsuidomain.entities.PatientIssue + +class PatientIssueFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.patientissue._ + + "Json format for PatientIssue" should "read and write correct JSON" in { + val patientIssue = PatientIssue( + id = LongId(10), + patientId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), + userId = StringId("userId-001"), + lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), + isDraft = false, + text = "message text", + archiveRequired = false + ) + val writtenJson = patientIssueWriter.write(patientIssue) + + writtenJson should be("""{"id":10,"userId":"userId-001","lastUpdate":"2017-08-10T18:00Z","isDraft":false, + "text":"message text","archiveRequired":false}""".parseJson) + + val createPatientIssueJson = """{"text":"message text"}""".parseJson + val expectedCreatedPatientIssue = patientIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) + val parsedCreatePatientIssue = jsValueToPatientIssue(createPatientIssueJson, + UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), + StringId("userId-001")) + parsedCreatePatientIssue should be(expectedCreatedPatientIssue) + + val updatePatientIssueJson = + """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true}""".parseJson + val expectedUpdatedPatientIssue = patientIssue.copy( + text = "new issue text", + archiveRequired = true + ) + val parsedUpdatePatientIssue = applyUpdateToPatientIssue(updatePatientIssueJson, patientIssue) + parsedUpdatePatientIssue should be(expectedUpdatedPatientIssue) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientLabelFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientLabelFormatSuite.scala new file mode 100644 index 0000000..95dfa68 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/PatientLabelFormatSuite.scala @@ -0,0 +1,79 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDate + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.entities.labels.LabelValue +import xyz.driver.pdsuicommon.domain.{LongId, UuidId} +import xyz.driver.pdsuidomain.entities._ +import xyz.driver.pdsuidomain.services.PatientLabelService.RichPatientLabel + +class PatientLabelFormatSuite extends FlatSpec with Matchers { + + "Json format for RichPatientLabel" should "read and write correct JSON" in { + import xyz.driver.pdsuidomain.formats.json.patientlabel._ + val orig = PatientLabel( + id = LongId(1), + patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + labelId = LongId(20), + primaryValue = Some(LabelValue.Yes), + verifiedPrimaryValue = None, + isVisible = true, + score = 1, + isImplicitMatch = false + ) + val writtenJson = richPatientLabelWriter.write(RichPatientLabel(orig, isVerified = true)) + + writtenJson should be( + """{"id":1,"labelId":20,"primaryValue":"Yes","verifiedPrimaryValue":null,"isVisible":true,"isVerified":true, + "score":1,"isImplicitMatch":false}""".parseJson) + + val updatePatientLabelJson = """{"verifiedPrimaryValue":"No"}""".parseJson + val expectedUpdatedPatientLabel = orig.copy(verifiedPrimaryValue = Some(LabelValue.No)) + val parsedUpdatePatientLabel = applyUpdateToPatientLabel(updatePatientLabelJson, orig) + parsedUpdatePatientLabel should be(expectedUpdatedPatientLabel) + } + + "Json format for PatientLabelEvidence" should "read and write correct JSON" in { + import xyz.driver.pdsuidomain.formats.json.patientlabel._ + val orig = PatientLabelEvidenceView( + id = LongId(1), + value = LabelValue.Maybe, + evidenceText = "evidence text", + documentId = Some(LongId(21)), + evidenceId = Some(LongId(10)), + reportId = None, + documentType = DocumentType.LaboratoryReport, + date = Some(LocalDate.parse("2017-08-10")), + providerType = ProviderType.EmergencyMedicine, + patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + labelId = LongId(20), + isImplicitMatch = false + ) + val writtenJson = patientLabelEvidenceWriter.write(orig) + + writtenJson should be( + """{"id":1,"value":"Maybe","evidenceText":"evidence text","documentId":21,"evidenceId":10,"reportId":null, + "documentType":{"id":3,"name":"Laboratory Report"},"date":"2017-08-10", + "providerType":{"id":26,"name":"Emergency Medicine"}}""".parseJson) + } + + "Json format for PatientLabelDefiningCriteria" should "read and write correct JSON" in { + import xyz.driver.pdsuidomain.formats.json.patientdefiningcriteria._ + val orig = PatientLabel( + id = LongId(1), + patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), + labelId = LongId(20), + primaryValue = Some(LabelValue.Yes), + verifiedPrimaryValue = Some(LabelValue.Yes), + isVisible = true, + score = 1, + isImplicitMatch = false + ) + val writtenJson = patientLabelDefiningCriteriaWriter.write(orig) + + writtenJson should be("""{"id":1,"value":"Yes"}""".parseJson) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/SlotArmFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/SlotArmFormatSuite.scala new file mode 100644 index 0000000..95853f6 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/SlotArmFormatSuite.scala @@ -0,0 +1,36 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.SlotArm + +class SlotArmFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.slotarm._ + + "Json format for SlotArm" should "read and write correct JSON" in { + val arm = SlotArm( + id = LongId(10), + trialId = StringId("NCT000001"), + name = "arm name", + originalName = "orig arm name" + ) + val writtenJson = slotArmFormat.write(arm) + + writtenJson should be( + """{"id":10,"trialId":"NCT000001","name":"arm name","originalName":"orig arm name"}""".parseJson) + + val createArmJson = """{"trialId":"NCT000001","name":"arm name"}""".parseJson + val parsedArm = slotArmFormat.read(createArmJson) + val expectedCreatedArm = arm.copy( + id = LongId(0), + originalName = "arm name" + ) + parsedArm should be(expectedCreatedArm) + + val updateArmJson = """{"name":"new arm name"}""".parseJson + val expectedUpdatedArm = arm.copy(name = "new arm name") + val parsedUpdateArm = applyUpdateToArm(updateArmJson, arm) + parsedUpdateArm should be(expectedUpdatedArm) + } +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/StudyDesignFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/StudyDesignFormatSuite.scala new file mode 100644 index 0000000..f3a4c83 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/StudyDesignFormatSuite.scala @@ -0,0 +1,20 @@ +package xyz.driver.pdsuidomain.formats.json + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuidomain.entities.StudyDesign + +class StudyDesignFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.studydesign._ + + "Json format for StudyDesign" should "read and write correct JSON" in { + val studyDesign = StudyDesign.Randomized + val writtenJson = studyDesignFormat.write(studyDesign) + + writtenJson should be("""{"id":1,"name":"Randomized"}""".parseJson) + + val parsedStudyDesign = studyDesignFormat.read(writtenJson) + parsedStudyDesign should be(studyDesign) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialFormatSuite.scala new file mode 100644 index 0000000..b832733 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialFormatSuite.scala @@ -0,0 +1,49 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import org.scalatest.{FlatSpec, Matchers} +import spray.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} +import xyz.driver.pdsuidomain.entities.Trial + +class TrialFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.trial._ + + "Json format for Trial" should "read and write correct JSON" in { + val orig = Trial( + id = StringId("NCT000001"), + externalId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), + status = Trial.Status.New, + assignee = None, + previousStatus = None, + previousAssignee = None, + lastActiveUserId = None, + lastUpdate = LocalDateTime.parse("2017-08-10T18:16:19"), + phase = "", + hypothesisId = Some(UuidId("3b80b2e2-5372-4cf5-a342-6e4ebe10fafd")), + studyDesignId = Some(LongId(321)), + originalStudyDesign = None, + isPartner = false, + overview = None, + overviewTemplate = "", + isUpdated = false, + title = "trial title", + originalTitle = "orig trial title" + ) + val writtenJson = trialFormat.write(orig) + + writtenJson should be( + """{"isPartner":false,"assignee":null,"lastUpdate":"2017-08-10T18:16:19Z","previousStatus":null, + "isUpdated":false,"overviewTemplate":"","phase":"","originalStudyDesignId":null, + "hypothesisId":"3b80b2e2-5372-4cf5-a342-6e4ebe10fafd","originalTitle":"orig trial title", + "studyDesignId":321,"lastActiveUser":null,"externalid":"40892a07-c638-49d2-9795-1edfefbbcc7c", + "id":"NCT000001","status":"New","overview":null,"previousAssignee":null,"title":"trial title"}""".parseJson) + + val updateTrialJson = """{"hypothesisId":null,"overview":"new overview"}""".parseJson + val expectedUpdatedTrial = orig.copy(hypothesisId = None, overview = Some("new overview")) + val parsedUpdateTrial = applyUpdateToTrial(updateTrialJson, orig) + parsedUpdateTrial should be(expectedUpdatedTrial) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialHistoryFormatSuite.scala new file mode 100644 index 0000000..aa0b404 --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialHistoryFormatSuite.scala @@ -0,0 +1,31 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.TrialHistory + +class TrialHistoryFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.trialhistory._ + + "Json format for TrialHistory" should "read and write correct JSON" in { + val trialHistory = TrialHistory( + id = LongId(10), + trialId = StringId("NCT000001"), + executor = StringId("userId-001"), + state = TrialHistory.State.Summarize, + action = TrialHistory.Action.Start, + created = LocalDateTime.parse("2017-08-10T18:00:00") + ) + val writtenJson = trialHistoryFormat.write(trialHistory) + + writtenJson should be("""{"id":10,"executor":"userId-001","trialId":"NCT000001","state":"Summarize", + "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) + + val parsedTrialHistory = trialHistoryFormat.read(writtenJson) + parsedTrialHistory should be(trialHistory) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialIssueFormatSuite.scala new file mode 100644 index 0000000..5c6aa8d --- /dev/null +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/TrialIssueFormatSuite.scala @@ -0,0 +1,49 @@ +package xyz.driver.pdsuidomain.formats.json + +import java.time.LocalDateTime + +import spray.json._ +import org.scalatest.{FlatSpec, Matchers} +import xyz.driver.pdsuicommon.domain.{LongId, StringId} +import xyz.driver.pdsuidomain.entities.TrialIssue + +class TrialIssueFormatSuite extends FlatSpec with Matchers { + import xyz.driver.pdsuidomain.formats.json.trialissue._ + + "Json format for TrialIssue" should "read and write correct JSON" in { + val trialIssue = TrialIssue( + id = LongId(10), + trialId = StringId("NCT000001"), + userId = StringId("userId-001"), + lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), + isDraft = false, + text = "message text", + evidence = "evidence", + archiveRequired = false, + meta = "{}" + ) + val writtenJson = trialIssueWriter.write(trialIssue) + + writtenJson should be("""{"id":10,"userId":"userId-001","lastUpdate":"2017-08-10T18:00Z","isDraft":false, + "text":"message text","evidence":"evidence","archiveRequired":false,"meta":"{}"}""".parseJson) + + val createTrialIssueJson = """{"text":"message text","evidence":"evidence","meta":"{}"}""".parseJson + val expectedCreatedTrialIssue = trialIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) + val parsedCreateTrialIssue = + jsValueToTrialIssue(createTrialIssueJson, StringId("NCT000001"), StringId("userId-001")) + parsedCreateTrialIssue should be(expectedCreatedTrialIssue) + + val updateTrialIssueJson = + """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true, + "meta":"{\"startPage\":1.0,\"endPage\":2.0}"}""".parseJson + val expectedUpdatedTrialIssue = trialIssue.copy( + text = "new issue text", + evidence = "issue evidence", + archiveRequired = true, + meta = """{"startPage":1.0,"endPage":2.0}""" + ) + val parsedUpdateTrialIssue = applyUpdateToTrialIssue(updateTrialIssueJson, trialIssue) + parsedUpdateTrialIssue should be(expectedUpdatedTrialIssue) + } + +} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ArmFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ArmFormatSuite.scala deleted file mode 100644 index 35b0fad..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ArmFormatSuite.scala +++ /dev/null @@ -1,37 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.Arm - -class ArmFormatSuite extends FlatSpec with Matchers { - import arm._ - - "Json format for Arm" should "read and write correct JSON" in { - val arm = Arm( - id = LongId(10), - trialId = StringId("NCT000001"), - name = "arm name", - originalName = "orig arm name" - ) - val writtenJson = armFormat.write(arm) - - writtenJson should be( - """{"id":10,"trialId":"NCT000001","name":"arm name","originalName":"orig arm name"}""".parseJson) - - val createArmJson = """{"trialId":"NCT000001","name":"arm name"}""".parseJson - val parsedArm = armFormat.read(createArmJson) - val expectedCreatedArm = arm.copy( - id = LongId(0), - originalName = "arm name" - ) - parsedArm should be(expectedCreatedArm) - - val updateArmJson = """{"name":"new arm name"}""".parseJson - val expectedUpdatedArm = arm.copy(name = "new arm name") - val parsedUpdateArm = applyUpdateToArm(updateArmJson, arm) - parsedUpdateArm should be(expectedUpdatedArm) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/BridgeUploadQueueFormat.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/BridgeUploadQueueFormat.scala deleted file mode 100644 index 854f51f..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/BridgeUploadQueueFormat.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue - -class BridgeUploadQueueFormat extends FlatSpec with Matchers { - import bridgeuploadqueue._ - - "Json format for BridgeUploadQueue.Item" should "read and write correct JSON" in { - val item = BridgeUploadQueue.Item( - kind = "kind", - tag = "tag", - created = LocalDateTime.parse("2017-08-10T18:00:00"), - attempts = 0, - nextAttempt = LocalDateTime.parse("2017-08-10T18:10:00"), - completed = false, - dependencyKind = Some("dependency king"), - dependencyTag = None - ) - val writtenJson = queueUploadItemFormat.write(item) - - writtenJson should be( - """{"kind":"kind","tag":"tag","created":"2017-08-10T18:00Z","attempts":0,"nextAttempt":"2017-08-10T18:10Z","completed":false}""".parseJson) - - val parsedItem = queueUploadItemFormat.read(writtenJson) - parsedItem should be(item.copy(dependencyKind = None, completed = true)) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/CriterionFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/CriterionFormatSuite.scala deleted file mode 100644 index 51665d2..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/CriterionFormatSuite.scala +++ /dev/null @@ -1,75 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{EligibilityArm, Criterion, CriterionLabel} -import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion - -class CriterionFormatSuite extends FlatSpec with Matchers { - import criterion._ - - "Json format for Criterion" should "read and write correct JSON" in { - val criterion = Criterion( - id = LongId(10), - trialId = StringId("NCT000001"), - text = Some("text"), - isCompound = false, - meta = "{}", - inclusion = None - ) - val labels = List( - CriterionLabel( - id = LongId(1L), - labelId = Some(LongId(101)), - criterionId = criterion.id, - categoryId = Some(LongId(3)), - value = Some(true), - isDefining = true - ), - CriterionLabel( - id = LongId(2L), - labelId = Some(LongId(102)), - criterionId = criterion.id, - categoryId = Some(LongId(3)), - value = Some(false), - isDefining = true - ) - ) - val arms = List(LongId[EligibilityArm](20), LongId[EligibilityArm](21), LongId[EligibilityArm](21)) - val richCriterion = RichCriterion( - criterion = criterion, - armIds = arms, - labels = labels - ) - val writtenJson = richCriterionFormat.write(richCriterion) - - writtenJson should be( - """{"text":"text","isCompound":false,"trialId":"NCT000001","inclusion":null,"arms":[20,21,21],"id":10,"meta":"{}", - "labels":[{"labelId":101,"categoryId":3,"value":"Yes","isDefining":true}, - {"labelId":102,"categoryId":3,"value":"No","isDefining":true}]}""".parseJson) - - val createCriterionJson = - """{"text":"text","isCompound":false,"trialId":"NCT000001","inclusion":null, - "arms":[20,21,21],"meta":"{}","labels":[{"labelId":101,"categoryId":3,"value":"Yes","isDefining":true}, - {"labelId":102,"categoryId":3,"value":"No","isDefining":true}]}""".parseJson - val parsedRichCriterion = richCriterionFormat.read(createCriterionJson) - val expectedRichCriterion = richCriterion.copy( - criterion = criterion.copy(id = LongId(0)), - labels = labels.map(_.copy(id = LongId(0), criterionId = LongId(0))) - ) - parsedRichCriterion should be(expectedRichCriterion) - - val updateCriterionJson = """{"meta":null,"text":"new text","isCompound":true,"inclusion":true}""".parseJson - val expectedUpdatedCriterion = richCriterion.copy( - criterion = criterion.copy( - text = Some("new text"), - isCompound = true, - meta = "{}", - inclusion = Some(true) - )) - val parsedUpdateCriterion = applyUpdateToCriterion(updateCriterionJson, richCriterion) - parsedUpdateCriterion should be(expectedUpdatedCriterion) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala deleted file mode 100644 index 111da6e..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala +++ /dev/null @@ -1,73 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{LocalDate, LocalDateTime} - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities.Document - -class DocumentFormatSuite extends FlatSpec with Matchers { - import document._ - - "Json format for Document" should "read and write correct JSON" in { - val orig = Document( - id = LongId(1), - status = Document.Status.New, - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - recordId = LongId(101), - physician = Some("physician"), - typeId = Some(LongId(10)), - providerName = Some("provider 21"), - providerTypeId = Some(LongId(21)), - institutionName = Some("institution name"), - requiredType = Some(Document.RequiredType.OPN), - meta = None, - startDate = None, - endDate = None, - labelVersion = 0 - ) - val writtenJson = documentFormat.write(orig) - - writtenJson should be( - """{"id":1,"recordId":101,"physician":"physician","typeId":10,"provider":"provider 21","providerTypeId":21, - "requiredType":"OPN","institutionName":"institution name","startDate":null,"endDate":null,"status":"New","assignee":null,"previousStatus":null, - "previousAssignee":null,"lastActiveUser":null,"lastUpdate":"2017-08-10T18:00Z","meta":null,"labelVersion":0}""".parseJson) - - val createDocumentJson = - """{"recordId":101,"physician":"physician","typeId":10,"provider":"provider 21","providerTypeId":21}""".parseJson - val expectedCreatedDocument = orig.copy( - id = LongId(0), - lastUpdate = LocalDateTime.MIN, - requiredType = None, - institutionName = None - ) - val parsedCreatedDocument = documentFormat.read(createDocumentJson) - parsedCreatedDocument should be(expectedCreatedDocument) - - val updateDocumentJson = - """{"startDate":"2017-08-10","endDate":"2018-08-10","meta":{"startPage":1.0,"endPage":2.0}}""".parseJson - val expectedUpdatedDocument = orig.copy( - startDate = Some(LocalDate.parse("2017-08-10")), - endDate = Some(LocalDate.parse("2018-08-10")), - meta = Some(TextJson(Document.Meta(startPage = 1.0, endPage = 2.0))) - ) - val parsedUpdatedDocument = applyUpdateToDocument(updateDocumentJson, orig) - parsedUpdatedDocument should be(expectedUpdatedDocument) - } - - "Json format for Document.Meta" should "read and write correct JSON" in { - val meta = Document.Meta(startPage = 1.0, endPage = 2.0) - val writtenJson = documentMetaFormat.write(meta) - writtenJson should be("""{"startPage":1.0,"endPage":2.0}""".parseJson) - - val metaJson = """{"startPage":1.0,"endPage":2.0}""".parseJson - val parsedMeta = documentMetaFormat.read(metaJson) - parsedMeta should be(meta) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentHistoryFormatSuite.scala deleted file mode 100644 index 5975919..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentHistoryFormatSuite.scala +++ /dev/null @@ -1,31 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.DocumentHistory - -class DocumentHistoryFormatSuite extends FlatSpec with Matchers { - import documenthistory._ - - "Json format for DocumentHistory" should "read and write correct JSON" in { - val documentHistory = DocumentHistory( - id = LongId(10), - documentId = LongId(1), - executor = StringId("userId-001"), - state = DocumentHistory.State.Extract, - action = DocumentHistory.Action.Start, - created = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val writtenJson = documentHistoryFormat.write(documentHistory) - - writtenJson should be("""{"id":10,"executor":"userId-001","documentId":1,"state":"Extract", - "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) - - val parsedDocumentHistory = documentHistoryFormat.read(writtenJson) - parsedDocumentHistory should be(documentHistory) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentIssueFormatSuite.scala deleted file mode 100644 index 54cfe90..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentIssueFormatSuite.scala +++ /dev/null @@ -1,48 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.DocumentIssue - -class DocumentIssueFormatSuite extends FlatSpec with Matchers { - import documentissue._ - - "Json format for DocumentIssue" should "read and write correct JSON" in { - val documentIssue = DocumentIssue( - id = LongId(10), - documentId = LongId(1), - userId = StringId("userId-001"), - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - isDraft = false, - text = "message text", - archiveRequired = false, - startPage = Some(1.0), - endPage = Some(2.0) - ) - val writtenJson = documentIssueFormat.write(documentIssue) - - writtenJson should be( - """{"id":10,"userId":"userId-001","documentId":1,"lastUpdate":"2017-08-10T18:00Z","isDraft":false, - "text":"message text","archiveRequired":false,"startPage":1.0,"endPage":2.0}""".parseJson) - - val createDocumentIssueJson = """{"text":"message text","startPage":1.0,"endPage":2.0}""".parseJson - val expectedCreatedDocumentIssue = - documentIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) - val parsedCreateDocumentIssue = jsValueToDocumentIssue(createDocumentIssueJson, LongId(1), StringId("userId-001")) - parsedCreateDocumentIssue should be(expectedCreatedDocumentIssue) - - val updateDocumentIssueJson = - """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true,"startPage":1.0,"endPage":4.0}""".parseJson - val expectedUpdatedDocumentIssue = documentIssue.copy( - text = "new issue text", - archiveRequired = true, - endPage = Some(4.0) - ) - val parsedUpdateDocumentIssue = applyUpdateToDocumentIssue(updateDocumentIssueJson, documentIssue) - parsedUpdateDocumentIssue should be(expectedUpdatedDocumentIssue) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/EligibilityArmWithDiseasesFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/EligibilityArmWithDiseasesFormatSuite.scala deleted file mode 100644 index 22adc98..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/EligibilityArmWithDiseasesFormatSuite.scala +++ /dev/null @@ -1,55 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.entities.patient.CancerType -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{EligibilityArm, EligibilityArmDisease, EligibilityArmWithDiseases} - -class EligibilityArmWithDiseasesFormatSuite extends FlatSpec with Matchers { - import eligibilityarm._ - - "Json format for EligibilityArmWithDiseases" should "read and write correct JSON" in { - val name = "arm name" - - val arm = EligibilityArm( - id = LongId(0), - trialId = StringId("NCT000001"), - name = name, - originalName = name - ) - - val disease = EligibilityArmDisease( - arm.id, - disease = CancerType.Lung - ) - - val eligibilityArmWithDiseases = - EligibilityArmWithDiseases( - arm, - Seq(disease) - ) - - val writtenJson = eligibilityArmWithDiseasesWriter.write(eligibilityArmWithDiseases) - - writtenJson should be( - """{"id":0,"trialId":"NCT000001","name":"arm name","originalName":"arm name","diseases":["Lung"]}""".parseJson) - - val createArmWithDiseasesJson = """{"trialId":"NCT000001","name":"arm name","diseases":["Lung"]}""".parseJson - val parsedArmWithDiseases = eligibilityArmWithDiseasesReader.read(createArmWithDiseasesJson) - parsedArmWithDiseases should be(eligibilityArmWithDiseases) - - val updateArmWithDiseasesJson = """{"name":"new arm name"}""".parseJson - val expectedUpdatedArmWithDiseases = eligibilityArmWithDiseases.copy( - eligibilityArm = eligibilityArmWithDiseases.eligibilityArm.copy(name = "new arm name") - ) - - val parsedUpdateArmWithDiseases = - applyUpdateToEligibilityArmWithDiseases( - updateArmWithDiseasesJson, - eligibilityArmWithDiseases - ) - - parsedUpdateArmWithDiseases should be(expectedUpdatedArmWithDiseases) - } -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExportFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExportFormatSuite.scala deleted file mode 100644 index d78e754..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExportFormatSuite.scala +++ /dev/null @@ -1,124 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{LocalDate, LocalDateTime} -import java.util.UUID - -import org.scalatest.{FlatSpec, Matchers} -import spray.json._ -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.{DocumentType, ProviderType, RecordRequestId} - -class ExportFormatSuite extends FlatSpec with Matchers { - import export._ - - "Json format for ExportPatientWithLabels" should "read and write correct JSON" in { - import xyz.driver.pdsuidomain.entities.export.patient._ - val document = ExportPatientLabelEvidenceDocument( - documentId = LongId(101), - requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), - documentType = DocumentType.OutpatientPhysicianNote, - providerType = ProviderType.Surgery, - date = LocalDate.parse("2017-08-10") - ) - - val labels = List( - ExportPatientLabel( - id = LongId(1), - evidences = List( - ExportPatientLabelEvidence( - id = LongId(11), - value = LabelValue.Yes, - evidenceText = "evidence text 11", - document = document - ), - ExportPatientLabelEvidence( - id = LongId(12), - value = LabelValue.No, - evidenceText = "evidence text 12", - document = document - ) - ) - ), - ExportPatientLabel( - id = LongId(2), - evidences = List( - ExportPatientLabelEvidence( - id = LongId(12), - value = LabelValue.Yes, - evidenceText = "evidence text 12", - document = document - ), - ExportPatientLabelEvidence( - id = LongId(13), - value = LabelValue.Yes, - evidenceText = "evidence text 13", - document = document - ) - ) - ) - ) - val patientWithLabels = ExportPatientWithLabels( - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - labelVersion = 1L, - labels = labels - ) - - val writtenJson = patientWithLabelsFormat.write(patientWithLabels) - writtenJson should be( - """{"patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","labelVersion":1,"labels":[{"labelId":1,"evidence":[{"evidenceId":11, - "labelValue":"Yes","evidenceText":"evidence text 11","document":{"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9", - "documentType":{"id":1,"name":"Outpatient Physician Note"},"providerType":{"id":2,"name":"Surgery"},"date":"2017-08-10"}}, - {"evidenceId":12,"labelValue":"No","evidenceText":"evidence text 12","document":{"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9", - "documentType":{"id":1,"name":"Outpatient Physician Note"},"providerType":{"id":2,"name":"Surgery"},"date":"2017-08-10"}}]}, - {"labelId":2,"evidence":[{"evidenceId":12,"labelValue":"Yes","evidenceText":"evidence text 12","document": - {"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","documentType":{"id":1,"name":"Outpatient Physician Note"}, - "providerType":{"id":2,"name":"Surgery"},"date":"2017-08-10"}},{"evidenceId":13,"labelValue":"Yes","evidenceText":"evidence text 13", - "document":{"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","documentType":{"id":1,"name":"Outpatient Physician Note"}, - "providerType":{"id":2,"name":"Surgery"},"date":"2017-08-10"}}]}]}""".parseJson) - } - - "Json format for ApiExportTrialWithLabels" should "read and write correct JSON" in { - import xyz.driver.pdsuidomain.entities.export.trial._ - val arms = List( - ExportTrialArm(armId = LongId(1), armName = "arm 1", diseaseList = Seq("Breast")), - ExportTrialArm(armId = LongId(2), armName = "arm 2", diseaseList = Seq("Breast")) - ) - val criteriaList = List( - ExportTrialLabelCriterion( - criterionId = LongId(10), - value = Some(true), - labelId = LongId(21), - armIds = Set(LongId(1), LongId(2)), - criteria = "criteria 10 text", - isCompound = false, - isDefining = false - ), - ExportTrialLabelCriterion( - criterionId = LongId(11), - value = None, - labelId = LongId(21), - armIds = Set(LongId(2)), - criteria = "criteria 11 text", - isCompound = true, - isDefining = false - ) - ) - val trialWithLabels = ExportTrialWithLabels( - nctId = StringId("NCT000001"), - trialId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - lastReviewed = LocalDateTime.parse("2017-08-10T18:00:00"), - labelVersion = 1L, - arms = arms, - criteria = criteriaList - ) - - val writtenJson = trialWithLabelsFormat.write(trialWithLabels) - writtenJson should be( - """{"nctId":"NCT000001","trialId":"40892a07-c638-49d2-9795-1edfefbbcc7c","lastReviewed":"2017-08-10T18:00Z", - "labelVersion":1,"arms":[{"armId":1,"armName":"arm 1","diseaseList":["Breast"]},{"armId":2,"armName":"arm 2","diseaseList":["Breast"]}],"criteria":[ - {"value":"Yes","labelId":21,"criterionId":10,"criterionText":"criteria 10 text","armIds":[1,2],"isCompound":false,"isDefining":false}, - {"value":"Unknown","labelId":21,"criterionId":11,"criterionText":"criteria 11 text","armIds":[2],"isCompound":true,"isDefining":false}]}""".parseJson) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExtractedDataFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExtractedDataFormatSuite.scala deleted file mode 100644 index 1feca6a..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExtractedDataFormatSuite.scala +++ /dev/null @@ -1,97 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities.ExtractedData.Meta -import xyz.driver.pdsuidomain.entities.{ExtractedData, ExtractedDataLabel} -import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData - -class ExtractedDataFormatSuite extends FlatSpec with Matchers { - import extracteddata._ - - "Json format for ExtractedData" should "read and write correct JSON" in { - val extractedData = ExtractedData( - id = LongId(1), - documentId = LongId(101), - keywordId = Some(LongId(201)), - evidenceText = Some("evidence text"), - meta = None - ) - val extractedDataLabels = List( - ExtractedDataLabel( - id = LongId(1), - dataId = extractedData.id, - labelId = None, - categoryId = None, - value = Some(LabelValue.Yes) - ), - ExtractedDataLabel( - id = LongId(2), - dataId = extractedData.id, - labelId = Some(LongId(12)), - categoryId = Some(LongId(1)), - value = Some(LabelValue.No) - ) - ) - val origRichExtractedData = RichExtractedData( - extractedData = extractedData, - labels = extractedDataLabels - ) - val writtenJson = extractedDataFormat.write(origRichExtractedData) - - writtenJson should be( - """{"id":1,"documentId":101,"keywordId":201,"evidence":"evidence text","meta":null, - "labels":[{"id":null,"categoryId":null,"value":"Yes"},{"id":12,"categoryId":1,"value":"No"}]}""".parseJson) - - val createExtractedDataJson = - """{"documentId":101,"keywordId":201,"evidence":"evidence text", - "labels":[{"value":"Yes"},{"id":12,"categoryId":1,"value":"No"}]}""".parseJson - val expectedCreatedExtractedData = origRichExtractedData.copy( - extractedData = extractedData.copy(id = LongId(0)), - labels = extractedDataLabels.map(_.copy(id = LongId(0), dataId = LongId(0))) - ) - val parsedCreatedExtractedData = extractedDataFormat.read(createExtractedDataJson) - parsedCreatedExtractedData should be(expectedCreatedExtractedData) - - val updateExtractedDataJson = - """{"evidence":"new evidence text","meta":{"keyword":{"page":1,"index":2,"sortIndex":"ASC"}, - "evidence":{"pageRatio":1.0,"start":{"page":1,"index":3,"offset":2},"end":{"page":2,"index":3,"offset":10}}}, - "labels":[{"id":20,"categoryId":1,"value":"Yes"},{"id":12,"categoryId":1,"value":"No"}]}""".parseJson - val updatedExtractedDataLabels = List( - ExtractedDataLabel( - id = LongId(0), - dataId = extractedData.id, - labelId = Some(LongId(20)), - categoryId = Some(LongId(1)), - value = Some(LabelValue.Yes) - ), - ExtractedDataLabel( - id = LongId(0), - dataId = extractedData.id, - labelId = Some(LongId(12)), - categoryId = Some(LongId(1)), - value = Some(LabelValue.No) - ) - ) - val expectedUpdatedExtractedData = origRichExtractedData.copy( - extractedData = extractedData.copy( - evidenceText = Some("new evidence text"), - meta = Some( - TextJson(Meta( - keyword = Meta.Keyword(page = 1, pageRatio = None, index = 2, sortIndex = "ASC"), - evidence = Meta.Evidence( - pageRatio = 1.0, - start = Meta.TextLayerPosition(page = 1, index = 3, offset = 2), - end = Meta.TextLayerPosition(page = 2, index = 3, offset = 10) - ) - ))) - ), - labels = updatedExtractedDataLabels - ) - val parsedUpdatedExtractedData = applyUpdateToExtractedData(updateExtractedDataJson, origRichExtractedData) - parsedUpdatedExtractedData should be(expectedUpdatedExtractedData) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/HypothesisFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/HypothesisFormatSuite.scala deleted file mode 100644 index 76d90f5..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/HypothesisFormatSuite.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuidomain.entities.Hypothesis - -class HypothesisFormatSuite extends FlatSpec with Matchers { - import hypothesis._ - - "Json format for Hypothesis" should "read and write correct JSON" in { - val hypothesis = Hypothesis( - id = UuidId("3b80b2e2-5372-4cf5-a342-6e4ebe10fafd"), - name = "hypothesis name", - treatmentType = "treatment type", - description = "descr" - ) - val writtenJson = hypothesisFormat.write(hypothesis) - - writtenJson should be("""{"id":"3b80b2e2-5372-4cf5-a342-6e4ebe10fafd","name":"hypothesis name", - "treatmentType":"treatment type","description":"descr"}""".parseJson) - - val parsedHypothesis = hypothesisFormat.read(writtenJson) - parsedHypothesis should be(hypothesis) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/InterventionFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/InterventionFormatSuite.scala deleted file mode 100644 index 4532da4..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/InterventionFormatSuite.scala +++ /dev/null @@ -1,73 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{Intervention, InterventionArm, InterventionType, InterventionWithArms} - -class InterventionFormatSuite extends FlatSpec with Matchers { - import intervention._ - - "Json format for Intervention" should "read and write correct JSON" in { - val intervention = Intervention( - id = LongId(1), - trialId = StringId("NCT000001"), - name = "intervention name", - originalName = "orig name", - typeId = Some(LongId(10)), - originalType = Some("orig type"), - dosage = "", - originalDosage = "", - isActive = true, - deliveryMethod = Some("pill") - ) - val arms = List( - InterventionArm(interventionId = intervention.id, armId = LongId(20)), - InterventionArm(interventionId = intervention.id, armId = LongId(21)), - InterventionArm(interventionId = intervention.id, armId = LongId(22)) - ) - val orig = InterventionWithArms( - intervention = intervention, - arms = arms - ) - val writtenJson = interventionFormat.write(orig) - - writtenJson should be( - """{"id":1,"name":"intervention name","typeId":10,"dosage":"","isActive":true,"arms":[20,21,22], - "trialId":"NCT000001","deliveryMethod":"pill","originalName":"orig name","originalDosage":"","originalType":"orig type"}""".parseJson) - - val createInterventionJson = - """{"id":1,"name":"intervention name","typeId":10,"dosage":"","isActive":true,"arms":[20,21,22], - "trialId":"NCT000001","deliveryMethod":"pill"}""".parseJson - val parsedCreateIntervention = interventionFormat.read(createInterventionJson) - val expectedCreateIntervention = parsedCreateIntervention.copy( - intervention = intervention.copy(id = LongId(0), originalType = None, originalName = "intervention name"), - arms = arms.map(_.copy(interventionId = LongId(0))) - ) - parsedCreateIntervention should be(expectedCreateIntervention) - - val updateInterventionJson = """{"dosage":"descr","arms":[21,22]}""".parseJson - val expectedUpdatedIntervention = orig.copy( - intervention = intervention.copy(dosage = "descr"), - arms = List( - InterventionArm(interventionId = intervention.id, armId = LongId(21)), - InterventionArm(interventionId = intervention.id, armId = LongId(22)) - ) - ) - val parsedUpdateIntervention = applyUpdateToInterventionWithArms(updateInterventionJson, orig) - parsedUpdateIntervention should be(expectedUpdatedIntervention) - } - - "Json format for InterventionType" should "read and write correct JSON" in { - val interventionType = InterventionType.SurgeryProcedure - val writtenJson = interventionTypeFormat.write(interventionType) - - writtenJson should be( - """{"id":9,"name":"Surgery/Procedure","deliveryMethods":["Radio-Frequency Ablation (RFA)", - "Cryoablation","Therapeutic Conventional Surgery","Robotic Assisted Laparoscopic Surgery"]}""".parseJson) - - val parsedInterventionType = interventionTypeFormat.read(writtenJson) - parsedInterventionType should be(interventionType) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ListResponseFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ListResponseFormatSuite.scala deleted file mode 100644 index d6752d6..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ListResponseFormatSuite.scala +++ /dev/null @@ -1,101 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime -import java.util.UUID - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuidomain.ListResponse -import xyz.driver.pdsuidomain.entities.MedicalRecord.Status -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.sprayformats.record.recordFormat -import xyz.driver.pdsuidomain.formats.json.sprayformats.listresponse._ - - -class ListResponseFormatSuite extends FlatSpec with Matchers { - - private val lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00") - private val lastUpdateToLocal = "2017-08-10T18:00Z" - - def metaJsonObjectAsString(meta: ListResponse.Meta) = { - import meta._ - val lastUpdate = meta.lastUpdate - .map(_ => s""","lastUpdate":"$lastUpdateToLocal"""") - .getOrElse("") - - s"""{"itemsCount":$itemsCount,"pageNumber":$pageNumber,"pageSize":$pageSize$lastUpdate}""" - } - - "Json format for ListResponse.Meta" should "read and write correct JSON" in { - val meta1 = - ListResponse.Meta( - itemsCount = 5, - pageNumber = 6, - pageSize = 7, - lastUpdate = None - ) - - val writtenJson1 = listResponseMetaFormat.write(meta1) - - writtenJson1 should be(metaJsonObjectAsString(meta1).parseJson) - - val parsedItem1: ListResponse.Meta = listResponseMetaFormat.read(writtenJson1) - - meta1 shouldBe parsedItem1 - - val meta2 = - ListResponse.Meta( - itemsCount = 1, - pageNumber = 4, - pageSize = 3, - lastUpdate = Some(lastUpdate) - ) - - val writtenJson2 = listResponseMetaFormat.write(meta2) - - writtenJson2 should be(metaJsonObjectAsString(meta2).parseJson) - - val parsedItem2: ListResponse.Meta = listResponseMetaFormat.read(writtenJson2) - - meta2 shouldBe parsedItem2 - } - - "Json format for ListResponse" should "write correct JSON" in { - - val orig = MedicalRecord( - id = LongId(1), - status = Status.New, - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - physician = Some("physician"), - meta = None, - disease = "Breast", - requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), - caseId = None, - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - totalPages = 10 - ) - - val recordJsonAsString = recordFormat.write(orig) - - val meta = - ListResponse.Meta( - itemsCount = 5, - pageNumber = 6, - pageSize = 7, - lastUpdate = None - ) - - val listResponse = ListResponse(Seq(orig), meta) - - val writtenJson = listResponseWriter[MedicalRecord].write(listResponse) - val expectedJson = s"""{"items":[$recordJsonAsString],"meta":${listResponseMetaFormat.write(meta)}}""" - - writtenJson should be(expectedJson.parseJson) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordFormatSuite.scala deleted file mode 100644 index 9616e70..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordFormatSuite.scala +++ /dev/null @@ -1,77 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime -import java.util.UUID - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, TextJson, UuidId} -import xyz.driver.pdsuidomain.entities.{MedicalRecord, RecordRequestId} - -class MedicalRecordFormatSuite extends FlatSpec with Matchers { - import record._ - import MedicalRecord._ - - "Json format for MedicalRecord" should "read and write correct JSON" in { - val orig = MedicalRecord( - id = LongId(1), - status = Status.New, - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - physician = Some("physician"), - meta = None, - disease = "Breast", - requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), - caseId = None, - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - totalPages = 10 - ) - val writtenJson = recordFormat.write(orig) - - writtenJson should be( - """{"id":1,"status":"New","assignee":null,"previousStatus":null,"previousAssignee":null,"lastActiveUser":null, - "lastUpdate":"2017-08-10T18:00Z","meta":[],"patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","caseId":null, - "requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","disease":"Breast","physician":"physician","totalPages":10}""".parseJson) - - val createRecordJson = - """{"disease":"Breast","patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9"}""".parseJson - val expectedCreatedRecord = MedicalRecord( - id = LongId(0), - status = MedicalRecord.Status.New, - previousStatus = None, - assignee = None, - previousAssignee = None, - lastActiveUserId = None, - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), - disease = "Breast", - caseId = None, - physician = None, - meta = None, - lastUpdate = LocalDateTime.now(), - totalPages = 0 - ) - val parsedCreatedRecord = recordFormat.read(createRecordJson).copy(lastUpdate = expectedCreatedRecord.lastUpdate) - parsedCreatedRecord should be(expectedCreatedRecord) - - val updateRecordJson = - """{"meta":[{"type":"duplicate","startPage":1.0,"endPage":2.0,"startOriginalPage":1.0}, - {"type":"reorder","items":[1,2]}, - {"type":"rotation","items":{"item1":1,"item2":2}}]}""".parseJson - val expectedUpdatedRecord = orig.copy( - meta = Some( - TextJson( - List( - Meta.Duplicate(startPage = 1.0, endPage = 2.0, startOriginalPage = 1.0, endOriginalPage = None), - Meta.Reorder(Seq(1, 2)), - Meta.Rotation(Map("item1" -> 1, "item2" -> 2)) - ))) - ) - val parsedUpdatedRecord = applyUpdateToMedicalRecord(updateRecordJson, orig) - parsedUpdatedRecord should be(expectedUpdatedRecord) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordHistoryFormatSuite.scala deleted file mode 100644 index a8634d9..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordHistoryFormatSuite.scala +++ /dev/null @@ -1,31 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.MedicalRecordHistory - -class MedicalRecordHistoryFormatSuite extends FlatSpec with Matchers { - import recordhistory._ - - "Json format for MedicalRecordHistory" should "read and write correct JSON" in { - val recordHistory = MedicalRecordHistory( - id = LongId(10), - recordId = LongId(1), - executor = StringId("userId-001"), - state = MedicalRecordHistory.State.Clean, - action = MedicalRecordHistory.Action.Start, - created = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val writtenJson = recordHistoryFormat.write(recordHistory) - - writtenJson should be("""{"id":10,"executor":"userId-001","recordId":1,"state":"Clean", - "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) - - val parsedRecordHistory = recordHistoryFormat.read(writtenJson) - parsedRecordHistory should be(recordHistory) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordIssueFormatSuite.scala deleted file mode 100644 index 5fa740b..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordIssueFormatSuite.scala +++ /dev/null @@ -1,47 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.MedicalRecordIssue - -class MedicalRecordIssueFormatSuite extends FlatSpec with Matchers { - import recordissue._ - - "Json format for MedicalRecordIssue" should "read and write correct JSON" in { - val recordIssue = MedicalRecordIssue( - id = LongId(10), - recordId = LongId(1), - userId = StringId("userId-001"), - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - isDraft = false, - text = "message text", - archiveRequired = false, - startPage = Some(1.0), - endPage = Some(2.0) - ) - val writtenJson = recordIssueFormat.write(recordIssue) - - writtenJson should be( - """{"id":10,"recordId":1,"userId":"userId-001","lastUpdate":"2017-08-10T18:00Z","isDraft":false, - "text":"message text","archiveRequired":false,"startPage":1.0,"endPage":2.0}""".parseJson) - - val createRecordIssueJson = """{"text":"message text","startPage":1.0,"endPage":2.0}""".parseJson - val expectedCreatedRecordIssue = recordIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) - val parsedCreateRecordIssue = jsValueToRecordIssue(createRecordIssueJson, LongId(1), StringId("userId-001")) - parsedCreateRecordIssue should be(expectedCreatedRecordIssue) - - val updateRecordIssueJson = - """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true,"startPage":1.0,"endPage":4.0}""".parseJson - val expectedUpdatedRecordIssue = recordIssue.copy( - text = "new issue text", - archiveRequired = true, - endPage = Some(4.0) - ) - val parsedUpdateRecordIssue = applyUpdateToRecordIssue(updateRecordIssueJson, recordIssue) - parsedUpdateRecordIssue should be(expectedUpdatedRecordIssue) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientCriterionFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientCriterionFormatSuite.scala deleted file mode 100644 index b254013..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientCriterionFormatSuite.scala +++ /dev/null @@ -1,58 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{PatientCriterion, PatientCriterionArm} -import xyz.driver.pdsuidomain.services.PatientCriterionService.{DraftPatientCriterion, RichPatientCriterion} - -class PatientCriterionFormatSuite extends FlatSpec with Matchers { - import patientcriterion._ - - "Json format for PatientCriterion" should "read and write correct JSON" in { - val orig = PatientCriterion( - id = LongId(1), - patientLabelId = LongId(1), - trialId = 0L, - nctId = StringId("NCT00001"), - criterionId = LongId(101), - criterionText = "criterion text", - criterionValue = Some(true), - criterionIsDefining = false, - eligibilityStatus = Some(LabelValue.Yes), - verifiedEligibilityStatus = None, - isVisible = true, - isVerified = true, - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val arms = List( - PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(31), armName = "arm 31"), - PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(32), armName = "arm 32") - ) - val richPatientCriterion = RichPatientCriterion(orig, LongId(21), arms) - val writtenJson = patientCriterionWriter.write(richPatientCriterion) - - writtenJson should be( - """{"id":1,"labelId":21,"nctId":"NCT00001","criterionId":101,"criterionText":"criterion text","criterionValue":"Yes", - "criterionIsDefining":false,"criterionIsCompound":false,"eligibilityStatus":"Yes","verifiedEligibilityStatus":null, - "isVisible":true,"isVerified":true,"lastUpdate":"2017-08-10T18:00Z","arms":["arm 31","arm 32"]}""".parseJson) - - val updatePatientCriterionJson = """{"verifiedEligibilityStatus":"No"}""".parseJson - val expectedUpdatedPatientCriterion = orig.copy(verifiedEligibilityStatus = Some(LabelValue.No)) - val parsedUpdatePatientCriterion = applyUpdateToPatientCriterion(updatePatientCriterionJson, orig) - parsedUpdatePatientCriterion should be(expectedUpdatedPatientCriterion) - - val updateBulkPatientCriterionJson = - """[{"id":1,"eligibilityStatus":"No"},{"id":2,"isVerified":false}]""".parseJson - val expectedDraftPatientCriterionList = List( - DraftPatientCriterion(id = LongId(1), eligibilityStatus = Some(LabelValue.No), isVerified = None), - DraftPatientCriterion(id = LongId(2), eligibilityStatus = None, isVerified = Some(false)) - ) - val parsedDraftPatientCriterionList = draftPatientCriterionListReader.read(updateBulkPatientCriterionJson) - parsedDraftPatientCriterionList should be(expectedDraftPatientCriterionList) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientEligibleTrialFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientEligibleTrialFormatSuite.scala deleted file mode 100644 index b8f6f8e..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientEligibleTrialFormatSuite.scala +++ /dev/null @@ -1,62 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import org.scalatest.{FlatSpec, Matchers} -import spray.json._ -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.{PatientCriterionArm, PatientTrialArmGroupView, Trial} -import xyz.driver.pdsuidomain.services.PatientEligibleTrialService.RichPatientEligibleTrial - -class PatientEligibleTrialFormatSuite extends FlatSpec with Matchers { - import patienteligibletrial._ - - "Json format for PatientEligibleTrial" should "read and write correct JSON" in { - val trial = Trial( - id = StringId("NCT000001"), - externalId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - status = Trial.Status.Done, - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.parse("2017-08-10T18:16:19"), - phase = "", - hypothesisId = Some(UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4")), - studyDesignId = Some(LongId(321)), - originalStudyDesign = None, - isPartner = false, - overview = None, - overviewTemplate = "", - isUpdated = false, - title = "trial title", - originalTitle = "orig trial title" - ) - val group = PatientTrialArmGroupView( - id = LongId(1), - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - trialId = StringId("NCT000001"), - hypothesisId = UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4"), - eligibilityStatus = Some(LabelValue.Yes), - verifiedEligibilityStatus = Some(LabelValue.Yes), - isVerified = false - ) - val arms = List( - PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(31), armName = "arm 31"), - PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(32), armName = "arm 32") - ) - val orig = RichPatientEligibleTrial(trial, group, arms) - val writtenJson = patientEligibleTrialWriter.write(orig) - - writtenJson should be( - """{"id":1,"patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","trialId":"NCT000001","trialTitle":"trial title", - "hypothesisId":"e76e2fc4-a29c-44fb-a81b-8856d06bb1d4","verifiedEligibilityStatus":"Yes","isVerified":false,"arms":["arm 31","arm 32"]}""".parseJson) - - val updatePatientEligibleTrialJson = """{"isVerified":true}""".parseJson - val expectedUpdatedPatientTrialArmGroup = group.copy(isVerified = true) - val parsedUpdatePatientTrialArmGroup = applyUpdateToTrialArmGroup(updatePatientEligibleTrialJson, group) - parsedUpdatePatientTrialArmGroup should be(expectedUpdatedPatientTrialArmGroup) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientFormatSuite.scala deleted file mode 100644 index 128cad1..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientFormatSuite.scala +++ /dev/null @@ -1,39 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{LocalDate, LocalDateTime} - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.entities.common.FullName -import xyz.driver.entities.patient.CancerType -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuidomain.entities.{Patient, PatientOrderId} - -class PatientFormatSuite extends FlatSpec with Matchers { - import patient._ - - "Json format for Patient" should "read and write correct JSON" in { - val orig = Patient( - id = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - status = Patient.Status.New, - name = FullName.fromStrings("John", "", "Doe"), - dob = LocalDate.parse("1980-06-30"), - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - isUpdateRequired = false, - disease = CancerType.Breast, - orderId = PatientOrderId("7b54a75d-4197-4b27-9045-b9b6cb131be9"), - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val writtenJson = patientWriter.write(orig) - - writtenJson should be( - """{"id":"748b5884-3528-4cb9-904b-7a8151d6e343","dob":"1980-06-30", - "name":{"firstName":"John","middleName":"","lastName":"Doe"},"status":"New","assignee":null, - "previousStatus":null,"previousAssignee":null,"lastActiveUser":null,"lastUpdate":"2017-08-10T18:00Z", - "orderId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","disease":"Breast"}""".parseJson) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHistoryFormatSuite.scala deleted file mode 100644 index c6a5a9f..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHistoryFormatSuite.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.PatientHistory - -class PatientHistoryFormatSuite extends FlatSpec with Matchers { - import patienthistory._ - - "Json format for PatientHistory" should "read and write correct JSON" in { - val patientHistory = PatientHistory( - id = LongId(10), - patientId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - executor = StringId("userId-001"), - state = PatientHistory.State.Verify, - action = PatientHistory.Action.Start, - created = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val writtenJson = patientHistoryFormat.write(patientHistory) - - writtenJson should be( - """{"id":10,"executor":"userId-001","patientId":"40892a07-c638-49d2-9795-1edfefbbcc7c","state":"Verify", - "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) - - val parsedPatientHistory = patientHistoryFormat.read(writtenJson) - parsedPatientHistory should be(patientHistory) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHypothesisFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHypothesisFormatSuite.scala deleted file mode 100644 index 71cbbad..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHypothesisFormatSuite.scala +++ /dev/null @@ -1,47 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuidomain.entities.PatientHypothesis -import xyz.driver.pdsuidomain.services.PatientHypothesisService.RichPatientHypothesis - -class PatientHypothesisFormatSuite extends FlatSpec with Matchers { - import patienthypothesis._ - - "Json format for RichPatientHypothesis" should "read and write correct JSON" in { - val orig = PatientHypothesis( - id = UuidId("815d9715-1089-4775-b120-3afb983b9a97"), - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - hypothesisId = UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4"), - rationale = None, - matchedTrials = 1 - ) - val writtenJson = richPatientHypothesisWriter.write(RichPatientHypothesis(orig, isRequired = true)) - - writtenJson should be( - """{"id":"815d9715-1089-4775-b120-3afb983b9a97","patientId":"748b5884-3528-4cb9-904b-7a8151d6e343", - "hypothesisId":"e76e2fc4-a29c-44fb-a81b-8856d06bb1d4","rationale":null,"matchedTrials":1,"isRationaleRequired":true}""".parseJson) - - val updatePatientHypothesisJson = """{"rationale":"rationale"}""".parseJson - val expectedUpdatedPatientHypothesis = orig.copy(rationale = Some("rationale")) - val parsedUpdatePatientHypothesis = applyUpdateToPatientHypothesis(updatePatientHypothesisJson, orig) - parsedUpdatePatientHypothesis should be(expectedUpdatedPatientHypothesis) - } - - "Json format for patientHypothesis" should "read and write correct JSON" in { - val orig = PatientHypothesis( - id = UuidId("815d9715-1089-4775-b120-3afb983b9a97"), - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - hypothesisId = UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4"), - rationale = None, - matchedTrials = 1 - ) - val writtenJson = patientHypothesisWriter.write(orig) - - writtenJson should be( - """{"id":"815d9715-1089-4775-b120-3afb983b9a97","patientId":"748b5884-3528-4cb9-904b-7a8151d6e343", - "hypothesisId":"e76e2fc4-a29c-44fb-a81b-8856d06bb1d4","rationale":null,"matchedTrials":1}""".parseJson) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientIssueFormatSuite.scala deleted file mode 100644 index 2776dcc..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientIssueFormatSuite.scala +++ /dev/null @@ -1,45 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.PatientIssue - -class PatientIssueFormatSuite extends FlatSpec with Matchers { - import patientissue._ - - "Json format for PatientIssue" should "read and write correct JSON" in { - val patientIssue = PatientIssue( - id = LongId(10), - patientId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - userId = StringId("userId-001"), - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - isDraft = false, - text = "message text", - archiveRequired = false - ) - val writtenJson = patientIssueWriter.write(patientIssue) - - writtenJson should be("""{"id":10,"userId":"userId-001","lastUpdate":"2017-08-10T18:00Z","isDraft":false, - "text":"message text","archiveRequired":false}""".parseJson) - - val createPatientIssueJson = """{"text":"message text"}""".parseJson - val expectedCreatedPatientIssue = patientIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) - val parsedCreatePatientIssue = jsValueToPatientIssue(createPatientIssueJson, - UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - StringId("userId-001")) - parsedCreatePatientIssue should be(expectedCreatedPatientIssue) - - val updatePatientIssueJson = - """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true}""".parseJson - val expectedUpdatedPatientIssue = patientIssue.copy( - text = "new issue text", - archiveRequired = true - ) - val parsedUpdatePatientIssue = applyUpdateToPatientIssue(updatePatientIssueJson, patientIssue) - parsedUpdatePatientIssue should be(expectedUpdatedPatientIssue) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientLabelFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientLabelFormatSuite.scala deleted file mode 100644 index 2122777..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientLabelFormatSuite.scala +++ /dev/null @@ -1,79 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDate - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.entities.labels.LabelValue -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.services.PatientLabelService.RichPatientLabel - -class PatientLabelFormatSuite extends FlatSpec with Matchers { - - "Json format for RichPatientLabel" should "read and write correct JSON" in { - import patientlabel._ - val orig = PatientLabel( - id = LongId(1), - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - labelId = LongId(20), - primaryValue = Some(LabelValue.Yes), - verifiedPrimaryValue = None, - isVisible = true, - score = 1, - isImplicitMatch = false - ) - val writtenJson = richPatientLabelWriter.write(RichPatientLabel(orig, isVerified = true)) - - writtenJson should be( - """{"id":1,"labelId":20,"primaryValue":"Yes","verifiedPrimaryValue":null,"isVisible":true,"isVerified":true, - "score":1,"isImplicitMatch":false}""".parseJson) - - val updatePatientLabelJson = """{"verifiedPrimaryValue":"No"}""".parseJson - val expectedUpdatedPatientLabel = orig.copy(verifiedPrimaryValue = Some(LabelValue.No)) - val parsedUpdatePatientLabel = applyUpdateToPatientLabel(updatePatientLabelJson, orig) - parsedUpdatePatientLabel should be(expectedUpdatedPatientLabel) - } - - "Json format for PatientLabelEvidence" should "read and write correct JSON" in { - import patientlabel._ - val orig = PatientLabelEvidenceView( - id = LongId(1), - value = LabelValue.Maybe, - evidenceText = "evidence text", - documentId = Some(LongId(21)), - evidenceId = Some(LongId(10)), - reportId = None, - documentType = DocumentType.LaboratoryReport, - date = Some(LocalDate.parse("2017-08-10")), - providerType = ProviderType.EmergencyMedicine, - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - labelId = LongId(20), - isImplicitMatch = false - ) - val writtenJson = patientLabelEvidenceWriter.write(orig) - - writtenJson should be( - """{"id":1,"value":"Maybe","evidenceText":"evidence text","documentId":21,"evidenceId":10,"reportId":null, - "documentType":{"id":3,"name":"Laboratory Report"},"date":"2017-08-10", - "providerType":{"id":26,"name":"Emergency Medicine"}}""".parseJson) - } - - "Json format for PatientLabelDefiningCriteria" should "read and write correct JSON" in { - import patientdefiningcriteria._ - val orig = PatientLabel( - id = LongId(1), - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - labelId = LongId(20), - primaryValue = Some(LabelValue.Yes), - verifiedPrimaryValue = Some(LabelValue.Yes), - isVisible = true, - score = 1, - isImplicitMatch = false - ) - val writtenJson = patientLabelDefiningCriteriaWriter.write(orig) - - writtenJson should be("""{"id":1,"value":"Yes"}""".parseJson) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/SlotArmFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/SlotArmFormatSuite.scala deleted file mode 100644 index 7dd085c..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/SlotArmFormatSuite.scala +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.SlotArm - -class SlotArmFormatSuite extends FlatSpec with Matchers { - import slotarm._ - - "Json format for SlotArm" should "read and write correct JSON" in { - val arm = SlotArm( - id = LongId(10), - trialId = StringId("NCT000001"), - name = "arm name", - originalName = "orig arm name" - ) - val writtenJson = slotArmFormat.write(arm) - - writtenJson should be( - """{"id":10,"trialId":"NCT000001","name":"arm name","originalName":"orig arm name"}""".parseJson) - - val createArmJson = """{"trialId":"NCT000001","name":"arm name"}""".parseJson - val parsedArm = slotArmFormat.read(createArmJson) - val expectedCreatedArm = arm.copy( - id = LongId(0), - originalName = "arm name" - ) - parsedArm should be(expectedCreatedArm) - - val updateArmJson = """{"name":"new arm name"}""".parseJson - val expectedUpdatedArm = arm.copy(name = "new arm name") - val parsedUpdateArm = applyUpdateToArm(updateArmJson, arm) - parsedUpdateArm should be(expectedUpdatedArm) - } -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/StudyDesignFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/StudyDesignFormatSuite.scala deleted file mode 100644 index e847445..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/StudyDesignFormatSuite.scala +++ /dev/null @@ -1,20 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuidomain.entities.StudyDesign - -class StudyDesignFormatSuite extends FlatSpec with Matchers { - import studydesign._ - - "Json format for StudyDesign" should "read and write correct JSON" in { - val studyDesign = StudyDesign.Randomized - val writtenJson = studyDesignFormat.write(studyDesign) - - writtenJson should be("""{"id":1,"name":"Randomized"}""".parseJson) - - val parsedStudyDesign = studyDesignFormat.read(writtenJson) - parsedStudyDesign should be(studyDesign) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialFormatSuite.scala deleted file mode 100644 index c9dc85f..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialFormatSuite.scala +++ /dev/null @@ -1,49 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import org.scalatest.{FlatSpec, Matchers} -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.Trial - -class TrialFormatSuite extends FlatSpec with Matchers { - import trial._ - - "Json format for Trial" should "read and write correct JSON" in { - val orig = Trial( - id = StringId("NCT000001"), - externalId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - status = Trial.Status.New, - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.parse("2017-08-10T18:16:19"), - phase = "", - hypothesisId = Some(UuidId("3b80b2e2-5372-4cf5-a342-6e4ebe10fafd")), - studyDesignId = Some(LongId(321)), - originalStudyDesign = None, - isPartner = false, - overview = None, - overviewTemplate = "", - isUpdated = false, - title = "trial title", - originalTitle = "orig trial title" - ) - val writtenJson = trialWriter.write(orig) - - writtenJson should be( - """{"isPartner":false,"assignee":null,"lastUpdate":"2017-08-10T18:16:19Z","previousStatus":null, - "isUpdated":false,"overviewTemplate":"","phase":"","originalStudyDesignId":null, - "hypothesisId":"3b80b2e2-5372-4cf5-a342-6e4ebe10fafd","originalTitle":"orig trial title", - "studyDesignId":321,"lastActiveUser":null,"externalid":"40892a07-c638-49d2-9795-1edfefbbcc7c", - "id":"NCT000001","status":"New","overview":null,"previousAssignee":null,"title":"trial title"}""".parseJson) - - val updateTrialJson = """{"hypothesisId":null,"overview":"new overview"}""".parseJson - val expectedUpdatedTrial = orig.copy(hypothesisId = None, overview = Some("new overview")) - val parsedUpdateTrial = applyUpdateToTrial(updateTrialJson, orig) - parsedUpdateTrial should be(expectedUpdatedTrial) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialHistoryFormatSuite.scala deleted file mode 100644 index d5ad2ec..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialHistoryFormatSuite.scala +++ /dev/null @@ -1,31 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.TrialHistory - -class TrialHistoryFormatSuite extends FlatSpec with Matchers { - import trialhistory._ - - "Json format for TrialHistory" should "read and write correct JSON" in { - val trialHistory = TrialHistory( - id = LongId(10), - trialId = StringId("NCT000001"), - executor = StringId("userId-001"), - state = TrialHistory.State.Summarize, - action = TrialHistory.Action.Start, - created = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val writtenJson = trialHistoryFormat.write(trialHistory) - - writtenJson should be("""{"id":10,"executor":"userId-001","trialId":"NCT000001","state":"Summarize", - "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) - - val parsedTrialHistory = trialHistoryFormat.read(writtenJson) - parsedTrialHistory should be(trialHistory) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialIssueFormatSuite.scala deleted file mode 100644 index 4a9ea4f..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialIssueFormatSuite.scala +++ /dev/null @@ -1,49 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.TrialIssue - -class TrialIssueFormatSuite extends FlatSpec with Matchers { - import trialissue._ - - "Json format for TrialIssue" should "read and write correct JSON" in { - val trialIssue = TrialIssue( - id = LongId(10), - trialId = StringId("NCT000001"), - userId = StringId("userId-001"), - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - isDraft = false, - text = "message text", - evidence = "evidence", - archiveRequired = false, - meta = "{}" - ) - val writtenJson = trialIssueWriter.write(trialIssue) - - writtenJson should be("""{"id":10,"userId":"userId-001","lastUpdate":"2017-08-10T18:00Z","isDraft":false, - "text":"message text","evidence":"evidence","archiveRequired":false,"meta":"{}"}""".parseJson) - - val createTrialIssueJson = """{"text":"message text","evidence":"evidence","meta":"{}"}""".parseJson - val expectedCreatedTrialIssue = trialIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) - val parsedCreateTrialIssue = - jsValueToTrialIssue(createTrialIssueJson, StringId("NCT000001"), StringId("userId-001")) - parsedCreateTrialIssue should be(expectedCreatedTrialIssue) - - val updateTrialIssueJson = - """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true, - "meta":"{\"startPage\":1.0,\"endPage\":2.0}"}""".parseJson - val expectedUpdatedTrialIssue = trialIssue.copy( - text = "new issue text", - evidence = "issue evidence", - archiveRequired = true, - meta = """{"startPage":1.0,"endPage":2.0}""" - ) - val parsedUpdateTrialIssue = applyUpdateToTrialIssue(updateTrialIssueJson, trialIssue) - parsedUpdateTrialIssue should be(expectedUpdatedTrialIssue) - } - -} -- cgit v1.2.3 From 1d2131e98330284ce5a3dcfc0cfd13e012914d6a Mon Sep 17 00:00:00 2001 From: Kseniya Tomskikh Date: Fri, 20 Oct 2017 16:34:13 +0700 Subject: PDSUI-2336 Deleted play dependencies --- build.sbt | 3 -- .../pdsuicommon/utils/WriteableImplicits.scala | 17 ----------- .../xyz/driver/pdsuicommon/utils/WritesUtils.scala | 21 -------------- .../validation/AdditionalConstraints.scala | 33 ---------------------- 4 files changed, 74 deletions(-) delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/utils/WriteableImplicits.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/utils/WritesUtils.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/validation/AdditionalConstraints.scala diff --git a/build.sbt b/build.sbt index d68a8f5..da7b511 100644 --- a/build.sbt +++ b/build.sbt @@ -12,12 +12,9 @@ lazy val core = (project in file(".")) "com.github.pureconfig" %% "pureconfig" % "0.7.2", "com.lihaoyi" %% "fastparse" % "0.3.7", "com.typesafe.akka" %% "akka-http" % "10.0.10", - "com.typesafe.play" %% "play" % "2.5.15", "com.typesafe.scala-logging" %% "scala-logging" % "3.5.0", "io.getquill" %% "quill-jdbc" % "1.2.1", "io.github.cloudify" %% "spdf" % "1.4.0", - "org.davidbild" %% "tristate-core" % "0.2.0", - "org.davidbild" %% "tristate-play" % "0.2.0" exclude ("com.typesafe.play", "play-json"), "xyz.driver" %% "core" % "1.2.2", "xyz.driver" %% "domain-model" % "0.17.8", "ch.qos.logback" % "logback-classic" % "1.1.7", diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/WriteableImplicits.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/WriteableImplicits.scala deleted file mode 100644 index 6c04dfa..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/WriteableImplicits.scala +++ /dev/null @@ -1,17 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import play.api.http.{ContentTypes, Writeable} -import play.api.libs.json.{Json, Writes} - -// @TODO this should be an object with a method, that gets HTTP-headers and returns suitable Writeable -trait WriteableImplicits { - - // Write JSON by default at now - implicit def defaultWriteable[T](implicit inner: Writes[T]) = Writeable[T]( - { x: T => - Writeable.writeableOf_JsValue.transform(Json.toJson(x)) - }, - Option(ContentTypes.JSON) - ) - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/WritesUtils.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/WritesUtils.scala deleted file mode 100644 index 3476a1e..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/WritesUtils.scala +++ /dev/null @@ -1,21 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import play.api.libs.json._ - -object WritesUtils { - - def filterKeys[T](p: String => Boolean)(implicit w: Writes[T]): Writes[T] = { - filter { - case (key, _) => p(key) - } - } - - def filter[T](p: (String, JsValue) => Boolean)(implicit w: Writes[T]): Writes[T] = { - w.transform { input: JsValue => - input match { - case JsObject(map) => JsObject(map.filter(Function.tupled(p))) - case x => x - } - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/validation/AdditionalConstraints.scala b/src/main/scala/xyz/driver/pdsuicommon/validation/AdditionalConstraints.scala deleted file mode 100644 index cb1082f..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/validation/AdditionalConstraints.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuicommon.validation - -import org.davidbild.tristate.Tristate -import play.api.data.validation._ - -object AdditionalConstraints { - - val nonNegativePrintedNumber: Constraint[String] = { - Constraints.pattern("^\\d+$".r, "printedInt.nonNegative", "must be a non-negative number") - } - - val positivePrintedNumber: Constraint[String] = { - Constraints.pattern("^[1-9]\\d*$".r, "printedInt.positive", "must be a positive number") - } - - val optionNonEmptyConstraint: Constraint[Option[Any]] = { - Constraint("option.nonEmpty") { - case Some(x) => Valid - case None => Invalid("is empty") - } - } - - val tristateSpecifiedConstraint: Constraint[Tristate[Any]] = { - Constraint("tristate.specified") { - case Tristate.Unspecified => Invalid("unspecified") - case _ => Valid - } - } - - val uuid: Constraint[String] = { - Constraints.pattern("""[\da-z]{8}-[\da-z]{4}-[\da-z]{4}-[\da-z]{4}-[\da-z]{12}""".r, "uuid", "invalid uuid") - } -} -- cgit v1.2.3 From e3b8e6ce8f659bff81b9a4bc3a79e3d2c3dd734f Mon Sep 17 00:00:00 2001 From: Kseniya Tomskikh Date: Mon, 23 Oct 2017 15:34:13 +0700 Subject: Removed quill query builder --- .../BridgeUploadQueueRepositoryAdapter.scala | 140 --------- .../xyz/driver/pdsuicommon/db/DbCommand.scala | 15 - .../driver/pdsuicommon/db/DbCommandFactory.scala | 14 - .../scala/xyz/driver/pdsuicommon/db/DbIo.scala | 13 - .../pdsuicommon/db/EntityExtractorDerivation.scala | 66 ---- .../scala/xyz/driver/pdsuicommon/db/FakeDbIo.scala | 9 - .../scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala | 28 -- .../xyz/driver/pdsuicommon/db/MySqlContext.scala | 90 ------ .../driver/pdsuicommon/db/MysqlQueryBuilder.scala | 88 ------ .../driver/pdsuicommon/db/PostgresContext.scala | 27 +- .../pdsuicommon/db/PostgresQueryBuilder.scala | 108 ------- .../xyz/driver/pdsuicommon/db/QueryBuilder.scala | 340 --------------------- .../driver/pdsuicommon/db/SlickQueryBuilder.scala | 2 +- .../repositories/BridgeUploadQueueRepository.scala | 21 -- .../pdsuicommon/db/repositories/Repository.scala | 4 - .../db/repositories/RepositoryLogging.scala | 62 ---- .../scala/xyz/driver/pdsuicommon/BaseSuite.scala | 12 - src/test/scala/xyz/driver/pdsuicommon/Mocks.scala | 51 +--- .../BridgeUploadQueueRepositoryAdapterSuite.scala | 285 ----------------- .../db/QueryBuilderParametersSuite.scala | 310 ------------------- 20 files changed, 14 insertions(+), 1671 deletions(-) delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/DbCommand.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/DbCommandFactory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/EntityExtractorDerivation.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/FakeDbIo.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/MysqlQueryBuilder.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/PostgresQueryBuilder.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/repositories/BridgeUploadQueueRepository.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala delete mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala delete mode 100644 src/test/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapterSuite.scala delete mode 100644 src/test/scala/xyz/driver/pdsuicommon/db/QueryBuilderParametersSuite.scala diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala deleted file mode 100644 index 3bf9192..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala +++ /dev/null @@ -1,140 +0,0 @@ -package xyz.driver.pdsuicommon.concurrent - -import java.time.LocalDateTime -import java.time.temporal.ChronoUnit - -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue.Item -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueueRepositoryAdapter.Strategy -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.db.repositories.BridgeUploadQueueRepository -import xyz.driver.pdsuicommon.logging._ - -import scala.concurrent.duration.{Duration, FiniteDuration} -import scala.concurrent.{ExecutionContext, Future} -import scala.util.Try - -object BridgeUploadQueueRepositoryAdapter { - - /** - * Defines how we work with queue, when an user attempts to remove/tryRetry an item. - */ - sealed trait Strategy { - - def onComplete: Strategy.OnComplete - - def on(attempt: Int): Strategy.OnAttempt - - } - - object Strategy { - - /** - * Works forever, but has a limit for intervals. - */ - final case class LimitExponential(startInterval: FiniteDuration, - intervalFactor: Double, - maxInterval: FiniteDuration, - onComplete: OnComplete) - extends Strategy { - - override def on(attempt: Int): OnAttempt = { - OnAttempt.Continue(intervalFor(attempt).min(maxInterval)) - } - - private def intervalFor(attempt: Int): Duration = { - Try(startInterval * Math.pow(intervalFactor, attempt.toDouble)) - .getOrElse(maxInterval) - } - } - - /** - * Used only in tests. - */ - final case class Stop(onComplete: OnComplete = OnComplete.Delete) extends Strategy { - - override def on(attempt: Int) = OnAttempt.Complete - - } - - /** - * Used only in tests. - */ - final case class Constant(interval: FiniteDuration) extends Strategy { - - override val onComplete = OnComplete.Delete - - override def on(attempt: Int) = OnAttempt.Continue(interval) - - } - - sealed trait OnComplete - object OnComplete { - case object Delete extends OnComplete - case object Mark extends OnComplete - - implicit def toPhiString(x: OnAttempt): PhiString = Unsafe(x.toString) - } - - sealed trait OnAttempt - object OnAttempt { - case object Complete extends OnAttempt - final case class Continue(interval: Duration) extends OnAttempt - - implicit def toPhiString(x: OnAttempt): PhiString = Unsafe(x.toString) - } - } -} - -class BridgeUploadQueueRepositoryAdapter(strategy: Strategy, repository: BridgeUploadQueueRepository, dbIo: DbIo)( - implicit executionContext: ExecutionContext) - extends BridgeUploadQueue with PhiLogging { - - override def add(item: Item): Future[Item] = dbIo.runAsync(repository.add(item)) - - override def get(kind: String): Future[Option[Item]] = dbIo.runAsync(repository.getOne(kind)) - - override def complete(kind: String, tag: String): Future[Unit] = { - import Strategy.OnComplete._ - - strategy.onComplete match { - case Delete => dbIo.runAsync(repository.delete(kind, tag)) - case Mark => - dbIo.runAsyncTx { - repository.getById(kind, tag) match { - case Some(x) => repository.update(x.copy(completed = true)) - case None => throw new RuntimeException(s"Can not find the task: kind=$kind, tag=$tag") - } - } - } - } - - /** - * Tries to continue the task or complete it - */ - override def tryRetry(item: Item): Future[Option[Item]] = { - import Strategy.OnAttempt._ - - logger.trace(phi"tryRetry($item)") - - val newAttempts = item.attempts + 1 - val action = strategy.on(newAttempts) - logger.debug(phi"Action for ${Unsafe(newAttempts)}: $action") - - action match { - case Continue(newInterval) => - val draftItem = item.copy( - attempts = newAttempts, - nextAttempt = LocalDateTime.now().plus(newInterval.toMillis, ChronoUnit.MILLIS) - ) - - logger.debug(draftItem) - dbIo.runAsync { - Some(repository.update(draftItem)) - } - - case Complete => - logger.warn(phi"All attempts are out for $item, complete the task") - complete(item.kind, item.tag).map(_ => None) - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/DbCommand.scala b/src/main/scala/xyz/driver/pdsuicommon/db/DbCommand.scala deleted file mode 100644 index 0af104e..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/DbCommand.scala +++ /dev/null @@ -1,15 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import scala.concurrent.Future - -trait DbCommand { - def runSync(): Unit - def runAsync(transactions: DbIo): Future[Unit] -} - -object DbCommand { - val Empty: DbCommand = new DbCommand { - override def runSync(): Unit = {} - override def runAsync(transactions: DbIo): Future[Unit] = Future.successful(()) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/DbCommandFactory.scala b/src/main/scala/xyz/driver/pdsuicommon/db/DbCommandFactory.scala deleted file mode 100644 index 1e2fb74..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/DbCommandFactory.scala +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import scala.concurrent.{ExecutionContext, Future} - -trait DbCommandFactory[T] { - def createCommand(orig: T)(implicit ec: ExecutionContext): Future[DbCommand] -} - -object DbCommandFactory { - def empty[T]: DbCommandFactory[T] = new DbCommandFactory[T] { - override def createCommand(orig: T)(implicit ec: ExecutionContext): Future[DbCommand] = - Future.successful(DbCommand.Empty) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala b/src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala deleted file mode 100644 index 7c290d1..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala +++ /dev/null @@ -1,13 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import scala.concurrent.Future - -/** - * Where queries should run - */ -trait DbIo { - def runAsync[T](f: => T): Future[T] - def runSync[T](f: => T): T = f - def runAsyncTx[T](f: => T): Future[T] - def runSyncTx[T](f: => T): Unit -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/EntityExtractorDerivation.scala b/src/main/scala/xyz/driver/pdsuicommon/db/EntityExtractorDerivation.scala deleted file mode 100644 index 02ba322..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/EntityExtractorDerivation.scala +++ /dev/null @@ -1,66 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.sql.ResultSet - -import io.getquill.NamingStrategy -import io.getquill.dsl.EncodingDsl - -import scala.language.experimental.macros -import scala.reflect.macros.blackbox - -trait EntityExtractorDerivation[Naming <: NamingStrategy] { this: EncodingDsl => - - /* - Simple Quill extractor derivation for [[T]] - Only case classes available. Type parameters is not supported - */ - def entityExtractor[T]: (ResultSet => T) = macro EntityExtractorDerivation.impl[T] -} - -object EntityExtractorDerivation { - def impl[T: c.WeakTypeTag](c: blackbox.Context): c.Tree = { - import c.universe._ - val namingStrategy = c.prefix.actualType - .baseType(c.weakTypeOf[EntityExtractorDerivation[NamingStrategy]].typeSymbol) - .typeArgs - .head - .typeSymbol - .companion - val functionBody = { - val tpe = weakTypeOf[T] - val resultOpt = tpe.decls.collectFirst { - // Find first constructor of T - case cons: MethodSymbol if cons.isConstructor => - // Create param list for constructor - val params = cons.paramLists.flatten.map { param => - val t = param.typeSignature - val paramName = param.name.toString - val col = q"$namingStrategy.column($paramName)" - // Resolve implicit decoders (from SqlContext) and apply ResultSet for each - val d = q"implicitly[${c.prefix}.Decoder[$t]]" - // Minus 1 cause Quill JDBC decoders make plus one. - // ¯\_(ツ)_/¯ - val i = q"row.findColumn($col) - 1" - val decoderName = TermName(paramName + "Decoder") - val valueName = TermName(paramName + "Value") - ( - q"val $decoderName = $d", - q"val $valueName = $decoderName($i, row)", - valueName - ) - } - // Call constructor with param list - q""" - ..${params.map(_._1)} - ..${params.map(_._2)} - new $tpe(..${params.map(_._3)}) - """ - } - resultOpt match { - case Some(result) => result - case None => c.abort(c.enclosingPosition, s"Can not derive extractor for $tpe. Constructor not found.") - } - } - q"(row: java.sql.ResultSet) => $functionBody" - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/FakeDbIo.scala b/src/main/scala/xyz/driver/pdsuicommon/db/FakeDbIo.scala deleted file mode 100644 index ac42a34..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/FakeDbIo.scala +++ /dev/null @@ -1,9 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import scala.concurrent.Future - -object FakeDbIo extends DbIo { - override def runAsync[T](f: => T): Future[T] = Future.successful(f) - override def runAsyncTx[T](f: => T): Future[T] = Future.successful(f) - override def runSyncTx[T](f: => T): Unit = f -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala b/src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala deleted file mode 100644 index 44f177c..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import xyz.driver.pdsuicommon.logging._ - -import scala.concurrent.Future -import scala.util.{Failure, Success, Try} - -class JdbcDbIo(sqlContext: TransactionalContext) extends DbIo with PhiLogging { - - override def runAsync[T](f: => T): Future[T] = { - Future(f)(sqlContext.executionContext) - } - - override def runAsyncTx[T](f: => T): Future[T] = { - import sqlContext.executionContext - - Future(sqlContext.transaction(f)).andThen { - case Failure(e) => logger.error(phi"Can't run a transaction: $e") - } - } - - override def runSyncTx[T](f: => T): Unit = { - Try(sqlContext.transaction(f)) match { - case Success(_) => - case Failure(e) => logger.error(phi"Can't run a transaction: $e") - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala b/src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala deleted file mode 100644 index 9d2664d..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala +++ /dev/null @@ -1,90 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.io.Closeable -import java.time._ -import java.util.concurrent.Executors -import javax.sql.DataSource - -import com.typesafe.config.Config -import io.getquill._ -import xyz.driver.pdsuicommon.concurrent.MdcExecutionContext -import xyz.driver.pdsuicommon.db.MySqlContext.Settings -import xyz.driver.pdsuicommon.error.IncorrectIdException -import xyz.driver.pdsuicommon.logging._ - -import scala.concurrent.ExecutionContext -import scala.util.control.NonFatal -import scala.util.{Failure, Success, Try} - -object MySqlContext extends PhiLogging { - - final case class DbCredentials(user: String, - password: String, - host: String, - port: Int, - dbName: String, - dbCreateFlag: Boolean, - dbContext: String, - connectionParams: String, - url: String) - - final case class Settings(credentials: DbCredentials, connection: Config, threadPoolSize: Int) - - def apply(settings: Settings): MySqlContext = { - // Prevent leaking credentials to a log - Try(JdbcContextConfig(settings.connection).dataSource) match { - case Success(dataSource) => new MySqlContext(dataSource, settings) - case Failure(NonFatal(e)) => - logger.error(phi"Can not load dataSource, error: ${Unsafe(e.getClass.getName)}") - throw new IllegalArgumentException("Can not load dataSource from config. Check your database and config") - } - } -} - -class MySqlContext(dataSource: DataSource with Closeable, settings: Settings) - extends MysqlJdbcContext[MysqlEscape](dataSource) with TransactionalContext - with EntityExtractorDerivation[Literal] { - - private val tpe = Executors.newFixedThreadPool(settings.threadPoolSize) - - implicit val executionContext: ExecutionContext = { - val orig = ExecutionContext.fromExecutor(tpe) - MdcExecutionContext.from(orig) - } - - override def close(): Unit = { - super.close() - tpe.shutdownNow() - } - - /** - * Overrode, because Quill JDBC optionDecoder pass null inside decoders. - * If custom decoder don't have special null handler, it will failed. - * - * @see https://github.com/getquill/quill/issues/535 - */ - implicit override def optionDecoder[T](implicit d: Decoder[T]): Decoder[Option[T]] = - decoder( - sqlType = d.sqlType, - row => - index => { - try { - val res = d(index - 1, row) - if (row.wasNull) { - None - } else { - Some(res) - } - } catch { - case _: NullPointerException => None - case _: IncorrectIdException => None - } - } - ) - - final implicit class LocalDateTimeDbOps(val left: LocalDateTime) { - - // scalastyle:off - def <=(right: LocalDateTime): Quoted[Boolean] = quote(infix"$left <= $right".as[Boolean]) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/MysqlQueryBuilder.scala b/src/main/scala/xyz/driver/pdsuicommon/db/MysqlQueryBuilder.scala deleted file mode 100644 index e2936e3..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/MysqlQueryBuilder.scala +++ /dev/null @@ -1,88 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.sql.ResultSet - -import xyz.driver.pdsuicommon.logging._ -import io.getquill.{MySQLDialect, MysqlEscape} - -import scala.collection.breakOut - -object MysqlQueryBuilder extends PhiLogging { - import xyz.driver.pdsuicommon.db.QueryBuilder._ - - def apply[T](tableName: String, - lastUpdateFieldName: Option[String], - nullableFields: Set[String], - links: Set[TableLink], - runner: Runner[T], - countRunner: CountRunner): MysqlQueryBuilder[T] = { - val parameters = MysqlQueryBuilderParameters( - tableData = TableData(tableName, lastUpdateFieldName, nullableFields), - links = links.map(x => x.foreignTableName -> x)(breakOut) - ) - new MysqlQueryBuilder[T](parameters)(runner, countRunner) - } - - def apply[T](tableName: String, - lastUpdateFieldName: Option[String], - nullableFields: Set[String], - links: Set[TableLink], - extractor: (ResultSet) => T)(implicit sqlContext: MySqlContext): MysqlQueryBuilder[T] = { - - val runner: Runner[T] = { parameters => - val (sql, binder) = parameters.toSql(namingStrategy = MysqlEscape) - logger.trace(phi"Query for execute: ${Unsafe(sql)}") - sqlContext.executeQuery[T](sql, binder, { resultSet => - extractor(resultSet) - }) - } - - val countRunner: CountRunner = { parameters => - val (sql, binder) = parameters.toSql(countQuery = true, namingStrategy = MysqlEscape) - logger.trace(phi"Query for execute: ${Unsafe(sql)}") - sqlContext - .executeQuery[CountResult]( - sql, - binder, { resultSet => - val count = resultSet.getInt(1) - val lastUpdate = if (parameters.tableData.lastUpdateFieldName.isDefined) { - Option(sqlContext.localDateTimeDecoder.decoder(2, resultSet)) - } else None - - (count, lastUpdate) - } - ) - .head - } - - apply[T]( - tableName = tableName, - lastUpdateFieldName = lastUpdateFieldName, - nullableFields = nullableFields, - links = links, - runner = runner, - countRunner = countRunner - ) - } -} - -class MysqlQueryBuilder[T](parameters: MysqlQueryBuilderParameters)(implicit runner: QueryBuilder.Runner[T], - countRunner: QueryBuilder.CountRunner) - extends QueryBuilder[T, MySQLDialect, MysqlEscape](parameters) { - - def withFilter(newFilter: SearchFilterExpr): QueryBuilder[T, MySQLDialect, MysqlEscape] = { - new MysqlQueryBuilder[T](parameters.copy(filter = newFilter)) - } - - def withSorting(newSorting: Sorting): QueryBuilder[T, MySQLDialect, MysqlEscape] = { - new MysqlQueryBuilder[T](parameters.copy(sorting = newSorting)) - } - - def withPagination(newPagination: Pagination): QueryBuilder[T, MySQLDialect, MysqlEscape] = { - new MysqlQueryBuilder[T](parameters.copy(pagination = Some(newPagination))) - } - - def resetPagination: QueryBuilder[T, MySQLDialect, MysqlEscape] = { - new MysqlQueryBuilder[T](parameters.copy(pagination = None)) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/PostgresContext.scala b/src/main/scala/xyz/driver/pdsuicommon/db/PostgresContext.scala index 7bdfd1b..bb8d322 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/db/PostgresContext.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/db/PostgresContext.scala @@ -1,15 +1,12 @@ package xyz.driver.pdsuicommon.db import java.io.Closeable -import java.time._ -import java.util.UUID import java.util.concurrent.Executors import javax.sql.DataSource import io.getquill._ import xyz.driver.pdsuicommon.concurrent.MdcExecutionContext import xyz.driver.pdsuicommon.db.PostgresContext.Settings -import xyz.driver.pdsuicommon.domain.UuidId import xyz.driver.pdsuicommon.logging._ import scala.concurrent.ExecutionContext @@ -35,8 +32,7 @@ object PostgresContext extends PhiLogging { } class PostgresContext(val dataSource: DataSource with Closeable, settings: Settings) - extends PostgresJdbcContext[SnakeCase](dataSource) with TransactionalContext - with EntityExtractorDerivation[SnakeCase] { + extends PostgresJdbcContext[SnakeCase](dataSource) with TransactionalContext { private val tpe = Executors.newFixedThreadPool(settings.threadPoolSize) @@ -49,25 +45,4 @@ class PostgresContext(val dataSource: DataSource with Closeable, settings: Setti super.close() tpe.shutdownNow() } - - /** - * Usable for QueryBuilder's extractors - */ - def timestampToLocalDateTime(timestamp: java.sql.Timestamp): LocalDateTime = { - LocalDateTime.ofInstant(timestamp.toInstant, ZoneOffset.UTC) - } - - implicit def encodeUuidId[T] = MappedEncoding[UuidId[T], String](_.toString) - implicit def decodeUuidId[T] = MappedEncoding[String, UuidId[T]] { uuid => - UuidId[T](UUID.fromString(uuid)) - } - - def decodeOptUuidId[T] = MappedEncoding[Option[String], Option[UuidId[T]]] { - case Some(x) => Option(x).map(y => UuidId[T](UUID.fromString(y))) - case None => None - } - - implicit def decodeUuid[T] = MappedEncoding[String, UUID] { uuid => - UUID.fromString(uuid) - } } diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/PostgresQueryBuilder.scala b/src/main/scala/xyz/driver/pdsuicommon/db/PostgresQueryBuilder.scala deleted file mode 100644 index 0ddf811..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/PostgresQueryBuilder.scala +++ /dev/null @@ -1,108 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.sql.ResultSet - -import io.getquill.{PostgresDialect, PostgresEscape} -import xyz.driver.pdsuicommon.db.PostgresQueryBuilder.SmartPostgresEscape - -import scala.collection.breakOut - -object PostgresQueryBuilder { - - import xyz.driver.pdsuicommon.db.QueryBuilder._ - - trait SmartPostgresEscape extends PostgresEscape { - override def column(s: String): String = - if (s.startsWith("$")) s else super.column(s) - override def default(s: String): String = - s.split("\\.").map(ss => s""""$ss"""").mkString(".") - } - - object SmartPostgresEscape extends SmartPostgresEscape - - type Escape = SmartPostgresEscape - val Escape = SmartPostgresEscape - - def apply[T](tableName: String, - lastUpdateFieldName: Option[String], - nullableFields: Set[String], - links: Set[TableLink], - runner: Runner[T], - countRunner: CountRunner): PostgresQueryBuilder[T] = { - val parameters = PostgresQueryBuilderParameters( - tableData = TableData(tableName, lastUpdateFieldName, nullableFields), - links = links.map(x => x.foreignTableName -> x)(breakOut) - ) - new PostgresQueryBuilder[T](parameters)(runner, countRunner) - } - - def apply[T](tableName: String, - lastUpdateFieldName: Option[String], - nullableFields: Set[String], - links: Set[TableLink], - extractor: ResultSet => T)(implicit sqlContext: PostgresContext): PostgresQueryBuilder[T] = { - apply(tableName, QueryBuilderParameters.AllFields, lastUpdateFieldName, nullableFields, links, extractor) - } - - def apply[T](tableName: String, - fields: Set[String], - lastUpdateFieldName: Option[String], - nullableFields: Set[String], - links: Set[TableLink], - extractor: ResultSet => T)(implicit sqlContext: PostgresContext): PostgresQueryBuilder[T] = { - - val runner: Runner[T] = { parameters => - val (sql, binder) = parameters.toSql(countQuery = false, fields = fields, namingStrategy = SmartPostgresEscape) - sqlContext.executeQuery[T](sql, binder, { resultSet => - extractor(resultSet) - }) - } - - val countRunner: CountRunner = { parameters => - val (sql, binder) = parameters.toSql(countQuery = true, namingStrategy = SmartPostgresEscape) - sqlContext - .executeQuery[CountResult]( - sql, - binder, { resultSet => - val count = resultSet.getInt(1) - val lastUpdate = if (parameters.tableData.lastUpdateFieldName.isDefined) { - Option(resultSet.getTimestamp(2)).map(sqlContext.timestampToLocalDateTime) - } else None - - (count, lastUpdate) - } - ) - .head - } - - apply[T]( - tableName = tableName, - lastUpdateFieldName = lastUpdateFieldName, - nullableFields = nullableFields, - links = links, - runner = runner, - countRunner = countRunner - ) - } -} - -class PostgresQueryBuilder[T](parameters: PostgresQueryBuilderParameters)(implicit runner: QueryBuilder.Runner[T], - countRunner: QueryBuilder.CountRunner) - extends QueryBuilder[T, PostgresDialect, PostgresQueryBuilder.Escape](parameters) { - - def withFilter(newFilter: SearchFilterExpr): QueryBuilder[T, PostgresDialect, SmartPostgresEscape] = { - new PostgresQueryBuilder[T](parameters.copy(filter = newFilter)) - } - - def withSorting(newSorting: Sorting): QueryBuilder[T, PostgresDialect, SmartPostgresEscape] = { - new PostgresQueryBuilder[T](parameters.copy(sorting = newSorting)) - } - - def withPagination(newPagination: Pagination): QueryBuilder[T, PostgresDialect, SmartPostgresEscape] = { - new PostgresQueryBuilder[T](parameters.copy(pagination = Some(newPagination))) - } - - def resetPagination: QueryBuilder[T, PostgresDialect, SmartPostgresEscape] = { - new PostgresQueryBuilder[T](parameters.copy(pagination = None)) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala b/src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala deleted file mode 100644 index 0bf1ed6..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala +++ /dev/null @@ -1,340 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.sql.PreparedStatement -import java.time.LocalDateTime - -import io.getquill.NamingStrategy -import io.getquill.context.sql.idiom.SqlIdiom -import xyz.driver.pdsuicommon.db.Sorting.{Dimension, Sequential} -import xyz.driver.pdsuicommon.db.SortingOrder.{Ascending, Descending} - -import scala.collection.mutable.ListBuffer - -object QueryBuilder { - - type Runner[T] = QueryBuilderParameters => Seq[T] - - type CountResult = (Int, Option[LocalDateTime]) - - type CountRunner = QueryBuilderParameters => CountResult - - /** - * Binder for PreparedStatement - */ - type Binder = PreparedStatement => PreparedStatement - - final case class TableData(tableName: String, - lastUpdateFieldName: Option[String] = None, - nullableFields: Set[String] = Set.empty) - - val AllFields = Set("*") - -} - -final case class TableLink(keyColumnName: String, foreignTableName: String, foreignKeyColumnName: String) - -object QueryBuilderParameters { - val AllFields = Set("*") -} - -sealed trait QueryBuilderParameters { - - def tableData: QueryBuilder.TableData - def links: Map[String, TableLink] - def filter: SearchFilterExpr - def sorting: Sorting - def pagination: Option[Pagination] - - def findLink(tableName: String): TableLink = links.get(tableName) match { - case None => throw new IllegalArgumentException(s"Cannot find a link for `$tableName`") - case Some(link) => link - } - - def toSql(countQuery: Boolean = false, namingStrategy: NamingStrategy): (String, QueryBuilder.Binder) = { - toSql(countQuery, QueryBuilderParameters.AllFields, namingStrategy) - } - - def toSql(countQuery: Boolean, fields: Set[String], namingStrategy: NamingStrategy): (String, QueryBuilder.Binder) = { - val escapedTableName = namingStrategy.table(tableData.tableName) - val fieldsSql: String = if (countQuery) { - val suffix: String = tableData.lastUpdateFieldName match { - case Some(lastUpdateField) => s", max($escapedTableName.${namingStrategy.column(lastUpdateField)})" - case None => "" - } - "count(*)" + suffix - } else { - if (fields == QueryBuilderParameters.AllFields) { - s"$escapedTableName.*" - } else { - fields - .map { field => - s"$escapedTableName.${namingStrategy.column(field)}" - } - .mkString(", ") - } - } - val (where, bindings) = filterToSql(escapedTableName, filter, namingStrategy) - val orderBy = sortingToSql(escapedTableName, sorting, namingStrategy) - - val limitSql = limitToSql() - - val sql = new StringBuilder() - sql.append("select ") - sql.append(fieldsSql) - sql.append("\nfrom ") - sql.append(escapedTableName) - - val filtersTableLinks: Seq[TableLink] = { - import SearchFilterExpr._ - def aux(expr: SearchFilterExpr): Seq[TableLink] = expr match { - case Atom.TableName(tableName) => List(findLink(tableName)) - case Intersection(xs) => xs.flatMap(aux) - case Union(xs) => xs.flatMap(aux) - case _ => Nil - } - aux(filter) - } - - val sortingTableLinks: Seq[TableLink] = Sorting.collect(sorting) { - case Dimension(Some(foreignTableName), _, _) => findLink(foreignTableName) - } - - // Combine links from sorting and filter without duplicates - val foreignTableLinks = (filtersTableLinks ++ sortingTableLinks).distinct - - foreignTableLinks.foreach { - case TableLink(keyColumnName, foreignTableName, foreignKeyColumnName) => - val escapedForeignTableName = namingStrategy.table(foreignTableName) - - sql.append("\ninner join ") - sql.append(escapedForeignTableName) - sql.append(" on ") - - sql.append(escapedTableName) - sql.append('.') - sql.append(namingStrategy.column(keyColumnName)) - - sql.append(" = ") - - sql.append(escapedForeignTableName) - sql.append('.') - sql.append(namingStrategy.column(foreignKeyColumnName)) - } - - if (where.nonEmpty) { - sql.append("\nwhere ") - sql.append(where) - } - - if (orderBy.nonEmpty && !countQuery) { - sql.append("\norder by ") - sql.append(orderBy) - } - - if (limitSql.nonEmpty && !countQuery) { - sql.append("\n") - sql.append(limitSql) - } - - (sql.toString, binder(bindings)) - } - - /** - * Converts filter expression to SQL expression. - * - * @return Returns SQL string and list of values for binding in prepared statement. - */ - protected def filterToSql(escapedTableName: String, - filter: SearchFilterExpr, - namingStrategy: NamingStrategy): (String, List[AnyRef]) = { - import SearchFilterBinaryOperation._ - import SearchFilterExpr._ - - def isNull(string: AnyRef) = Option(string).isEmpty || string.toString.toLowerCase == "null" - - def placeholder(field: String) = "?" - - def escapeDimension(dimension: SearchFilterExpr.Dimension) = { - val tableName = dimension.tableName.fold(escapedTableName)(namingStrategy.table) - s"$tableName.${namingStrategy.column(dimension.name)}" - } - - def filterToSqlMultiple(operands: Seq[SearchFilterExpr]) = operands.collect { - case x if !SearchFilterExpr.isEmpty(x) => filterToSql(escapedTableName, x, namingStrategy) - } - - filter match { - case x if isEmpty(x) => - ("", List.empty) - - case AllowAll => - ("1", List.empty) - - case DenyAll => - ("0", List.empty) - - case Atom.Binary(dimension, Eq, value) if isNull(value) => - (s"${escapeDimension(dimension)} is NULL", List.empty) - - case Atom.Binary(dimension, NotEq, value) if isNull(value) => - (s"${escapeDimension(dimension)} is not NULL", List.empty) - - case Atom.Binary(dimension, NotEq, value) if tableData.nullableFields.contains(dimension.name) => - // In MySQL NULL <> Any === NULL - // So, to handle NotEq for nullable fields we need to use more complex SQL expression. - // http://dev.mysql.com/doc/refman/5.7/en/working-with-null.html - val escapedColumn = escapeDimension(dimension) - val sql = s"($escapedColumn is null or $escapedColumn != ${placeholder(dimension.name)})" - (sql, List(value)) - - case Atom.Binary(dimension, op, value) => - val operator = op match { - case Eq => "=" - case NotEq => "!=" - case Like => "like" - case Gt => ">" - case GtEq => ">=" - case Lt => "<" - case LtEq => "<=" - } - (s"${escapeDimension(dimension)} $operator ${placeholder(dimension.name)}", List(value)) - - case Atom.NAry(dimension, op, values) => - val sqlOp = op match { - case SearchFilterNAryOperation.In => "in" - case SearchFilterNAryOperation.NotIn => "not in" - } - - val bindings = ListBuffer[AnyRef]() - val sqlPlaceholder = placeholder(dimension.name) - val formattedValues = if (values.nonEmpty) { - values - .map { value => - bindings += value - sqlPlaceholder - } - .mkString(", ") - } else "NULL" - (s"${escapeDimension(dimension)} $sqlOp ($formattedValues)", bindings.toList) - - case Intersection(operands) => - val (sql, bindings) = filterToSqlMultiple(operands).unzip - (sql.mkString("(", " and ", ")"), bindings.flatten.toList) - - case Union(operands) => - val (sql, bindings) = filterToSqlMultiple(operands).unzip - (sql.mkString("(", " or ", ")"), bindings.flatten.toList) - } - } - - protected def limitToSql(): String - - /** - * @param escapedMainTableName Should be escaped - */ - protected def sortingToSql(escapedMainTableName: String, sorting: Sorting, namingStrategy: NamingStrategy): String = { - sorting match { - case Dimension(optSortingTableName, field, order) => - val sortingTableName = optSortingTableName.map(namingStrategy.table).getOrElse(escapedMainTableName) - val fullName = s"$sortingTableName.${namingStrategy.column(field)}" - - s"$fullName ${orderToSql(order)}" - - case Sequential(xs) => - xs.map(sortingToSql(escapedMainTableName, _, namingStrategy)).mkString(", ") - } - } - - protected def orderToSql(x: SortingOrder): String = x match { - case Ascending => "asc" - case Descending => "desc" - } - - protected def binder(bindings: List[AnyRef])(bind: PreparedStatement): PreparedStatement = { - bindings.zipWithIndex.foreach { - case (binding, index) => - bind.setObject(index + 1, binding) - } - - bind - } - -} - -final case class PostgresQueryBuilderParameters(tableData: QueryBuilder.TableData, - links: Map[String, TableLink] = Map.empty, - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Sorting = Sorting.Empty, - pagination: Option[Pagination] = None) - extends QueryBuilderParameters { - - def limitToSql(): String = { - pagination.map { pagination => - val startFrom = (pagination.pageNumber - 1) * pagination.pageSize - s"limit ${pagination.pageSize} OFFSET $startFrom" - } getOrElse "" - } - -} - -/** - * @param links Links to another tables grouped by foreignTableName - */ -final case class MysqlQueryBuilderParameters(tableData: QueryBuilder.TableData, - links: Map[String, TableLink] = Map.empty, - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Sorting = Sorting.Empty, - pagination: Option[Pagination] = None) - extends QueryBuilderParameters { - - def limitToSql(): String = - pagination - .map { pagination => - val startFrom = (pagination.pageNumber - 1) * pagination.pageSize - s"limit $startFrom, ${pagination.pageSize}" - } - .getOrElse("") - -} - -abstract class QueryBuilder[T, D <: SqlIdiom, N <: NamingStrategy](val parameters: QueryBuilderParameters)( - implicit runner: QueryBuilder.Runner[T], - countRunner: QueryBuilder.CountRunner) { - - def run: Seq[T] = runner(parameters) - - def runCount: QueryBuilder.CountResult = countRunner(parameters) - - /** - * Runs the query and returns total found rows without considering of pagination. - */ - def runWithCount: (Seq[T], Int, Option[LocalDateTime]) = { - val (total, lastUpdate) = runCount - (run, total, lastUpdate) - } - - def withFilter(newFilter: SearchFilterExpr): QueryBuilder[T, D, N] - - def withFilter(filter: Option[SearchFilterExpr]): QueryBuilder[T, D, N] = { - filter.fold(this)(withFilter) - } - - def resetFilter: QueryBuilder[T, D, N] = withFilter(SearchFilterExpr.Empty) - - def withSorting(newSorting: Sorting): QueryBuilder[T, D, N] - - def withSorting(sorting: Option[Sorting]): QueryBuilder[T, D, N] = { - sorting.fold(this)(withSorting) - } - - def resetSorting: QueryBuilder[T, D, N] = withSorting(Sorting.Empty) - - def withPagination(newPagination: Pagination): QueryBuilder[T, D, N] - - def withPagination(pagination: Option[Pagination]): QueryBuilder[T, D, N] = { - pagination.fold(this)(withPagination) - } - - def resetPagination: QueryBuilder[T, D, N] - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/SlickQueryBuilder.scala b/src/main/scala/xyz/driver/pdsuicommon/db/SlickQueryBuilder.scala index dc03a52..7366151 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/db/SlickQueryBuilder.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/db/SlickQueryBuilder.scala @@ -70,7 +70,7 @@ sealed trait SlickQueryBuilderParameters { } def toSql(countQuery: Boolean = false)(implicit profile: JdbcProfile): SQLActionBuilder = { - toSql(countQuery, QueryBuilderParameters.AllFields) + toSql(countQuery, SlickQueryBuilderParameters.AllFields) } def toSql(countQuery: Boolean, fields: Set[String])(implicit profile: JdbcProfile): SQLActionBuilder = { diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/BridgeUploadQueueRepository.scala b/src/main/scala/xyz/driver/pdsuicommon/db/repositories/BridgeUploadQueueRepository.scala deleted file mode 100644 index 4c25afa..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/BridgeUploadQueueRepository.scala +++ /dev/null @@ -1,21 +0,0 @@ -package xyz.driver.pdsuicommon.db.repositories - -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue -import xyz.driver.pdsuicommon.db.MysqlQueryBuilder - -trait BridgeUploadQueueRepository extends Repository { - - type EntityT = BridgeUploadQueue.Item - - def add(draft: EntityT): EntityT - - def getById(kind: String, tag: String): Option[EntityT] - - def getOne(kind: String): Option[BridgeUploadQueue.Item] - - def update(entity: EntityT): EntityT - - def delete(kind: String, tag: String): Unit - - def buildQuery: MysqlQueryBuilder[EntityT] -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala b/src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala deleted file mode 100644 index d671e80..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala +++ /dev/null @@ -1,4 +0,0 @@ -package xyz.driver.pdsuicommon.db.repositories - -// For further usage and migration to Postgres and slick -trait Repository extends RepositoryLogging diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala b/src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala deleted file mode 100644 index d1ec1da..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala +++ /dev/null @@ -1,62 +0,0 @@ -package xyz.driver.pdsuicommon.db.repositories - -import xyz.driver.pdsuicommon.logging._ - -trait RepositoryLogging extends PhiLogging { - - protected def logCreatedOne[T](x: T)(implicit toPhiString: T => PhiString): T = { - logger.info(phi"An entity was created: $x") - x - } - - protected def logCreatedMultiple[T <: Iterable[_]](xs: T)(implicit toPhiString: T => PhiString): T = { - if (xs.nonEmpty) { - logger.info(phi"Entities were created: $xs") - } - xs - } - - protected def logUpdatedOne(rowsAffected: Long): Long = { - rowsAffected match { - case 0 => logger.trace(phi"The entity is up to date") - case 1 => logger.info(phi"The entity was updated") - case x => logger.warn(phi"The ${Unsafe(x)} entities were updated") - } - rowsAffected - } - - protected def logUpdatedOneUnimportant(rowsAffected: Long): Long = { - rowsAffected match { - case 0 => logger.trace(phi"The entity is up to date") - case 1 => logger.trace(phi"The entity was updated") - case x => logger.warn(phi"The ${Unsafe(x)} entities were updated") - } - rowsAffected - } - - protected def logUpdatedMultiple(rowsAffected: Long): Long = { - rowsAffected match { - case 0 => logger.trace(phi"All entities are up to date") - case x => logger.info(phi"The ${Unsafe(x)} entities were updated") - } - rowsAffected - } - - protected def logDeletedOne(rowsAffected: Long): Long = { - rowsAffected match { - case 0 => logger.trace(phi"The entity does not exist") - case 1 => logger.info(phi"The entity was deleted") - case x => logger.warn(phi"Deleted ${Unsafe(x)} entities, expected one") - } - rowsAffected - } - - protected def logDeletedMultiple(rowsAffected: Long): Long = { - rowsAffected match { - case 0 => logger.trace(phi"Entities do not exist") - case x => logger.info(phi"Deleted ${Unsafe(x)} entities") - } - rowsAffected - } - -} diff --git a/src/test/scala/xyz/driver/pdsuicommon/BaseSuite.scala b/src/test/scala/xyz/driver/pdsuicommon/BaseSuite.scala index 7c9d8c4..29e7610 100644 --- a/src/test/scala/xyz/driver/pdsuicommon/BaseSuite.scala +++ b/src/test/scala/xyz/driver/pdsuicommon/BaseSuite.scala @@ -5,15 +5,12 @@ import java.time.{LocalDateTime, ZoneId} import org.scalatest.FreeSpecLike import org.scalatest.concurrent.ScalaFutures import org.scalatest.time.{Millis, Span} -import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.error.UnexpectedFilterException import xyz.driver.pdsuicommon.utils.DiffUtils trait BaseSuite extends FreeSpecLike with DiffUtils with ScalaFutures { implicit val defaultPatience = PatienceConfig(timeout = Span(1000, Millis), interval = Span(20, Millis)) - implicit val sqlContext = new MockMySqlContext() def sampleUser(role: User.Role, email: String = "test@example.com", password: String = "123") = User( id = StringId("2001"), @@ -23,13 +20,4 @@ trait BaseSuite extends FreeSpecLike with DiffUtils with ScalaFutures { latestActivity = Some(LocalDateTime.now(ZoneId.of("Z"))), deleted = None ) - - def createMockQueryBuilder[T](isExpectedFilter: SearchFilterExpr => Boolean): MysqlQueryBuilder[T] = { - MockQueryBuilder[T] { - case (filter, _, _) if isExpectedFilter(filter) => Seq.empty - case (filter, _, _) => throw new UnexpectedFilterException(s"Filter is unexpected: $filter") - } { - case _ => (0, Option.empty[LocalDateTime]) - } - } } diff --git a/src/test/scala/xyz/driver/pdsuicommon/Mocks.scala b/src/test/scala/xyz/driver/pdsuicommon/Mocks.scala index 51d39e5..699020c 100644 --- a/src/test/scala/xyz/driver/pdsuicommon/Mocks.scala +++ b/src/test/scala/xyz/driver/pdsuicommon/Mocks.scala @@ -6,7 +6,7 @@ import java.sql.Connection import java.util.logging.Logger import javax.sql.DataSource -import com.typesafe.config.ConfigFactory +import xyz.driver.pdsuicommon.db.SlickQueryBuilder.TableData import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.http.HttpFetcher @@ -27,32 +27,7 @@ class MockDataSource extends DataSource with Closeable { override def isWrapperFor(iface: Class[_]): Boolean = throw new NotImplementedError("MockDataSource.isWrapperFor") } -object MockMySqlContext { - - val Settings = MySqlContext.Settings( - credentials = MySqlContext.DbCredentials( - user = "test", - password = "test", - host = "localhost", - port = 3248, - dbName = "test", - dbCreateFlag = false, - dbContext = "test", - connectionParams = "", - url = "" - ), - connection = ConfigFactory.empty(), - threadPoolSize = 10 - ) -} - -class MockMySqlContext() extends MySqlContext(new MockDataSource, MockMySqlContext.Settings) { - override protected def withConnection[T](f: Connection => T): Nothing = { - throw new NotImplementedError("MockSqlContext.withConnection") - } -} - -class MockFactory()(implicit val sqlContext: MySqlContext) { +class MockFactory()(implicit val sqlContext: PostgresContext) { val MockHttpFetcher: HttpFetcher = { (url: URL) => Future.successful(Array.empty[Byte]) } @@ -61,28 +36,26 @@ class MockFactory()(implicit val sqlContext: MySqlContext) { object MockQueryBuilder { type MockRunnerIn = (SearchFilterExpr, Sorting, Option[Pagination]) - type MockRunnerOut[T] = Seq[T] - type MockCountRunnerOut = QueryBuilder.CountResult + type MockRunnerOut[T] = Future[Seq[T]] + type MockCountRunnerOut = SlickQueryBuilder.CountResult def apply[T](matcher: PartialFunction[MockRunnerIn, MockRunnerOut[T]])( countMatcher: PartialFunction[MockRunnerIn, MockCountRunnerOut])( - implicit context: MySqlContext): MysqlQueryBuilder[T] = { + implicit context: PostgresContext): SlickQueryBuilder[T] = { - val runner: QueryBuilder.Runner[T] = { parameters => + val runner: SlickQueryBuilder.Runner[T] = { parameters => matcher((parameters.filter, parameters.sorting, parameters.pagination)) } - val countRunner: QueryBuilder.CountRunner = { parameters => + val countRunner: SlickQueryBuilder.CountRunner = { parameters => countMatcher((parameters.filter, parameters.sorting, parameters.pagination)) } - MysqlQueryBuilder[T]( - tableName = "", - lastUpdateFieldName = Option.empty[String], - nullableFields = Set.empty[String], - links = Set.empty[TableLink], - runner = runner, - countRunner = countRunner + val parameters = SlickPostgresQueryBuilderParameters( + databaseName = "test", + tableData = TableData("", None, Set.empty[String]), + links = Map.empty ) + new SlickPostgresQueryBuilder(parameters)(runner, countRunner) } } diff --git a/src/test/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapterSuite.scala b/src/test/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapterSuite.scala deleted file mode 100644 index 8b38316..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapterSuite.scala +++ /dev/null @@ -1,285 +0,0 @@ -package xyz.driver.pdsuicommon.concurrent - -import java.util.concurrent.ThreadLocalRandom - -import xyz.driver.pdsuicommon.BaseSuite -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueueRepositoryAdapter.Strategy -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueueRepositoryAdapter.Strategy.{OnAttempt, OnComplete} -import xyz.driver.pdsuicommon.db.{FakeDbIo, MysqlQueryBuilder} -import xyz.driver.pdsuicommon.db.repositories.BridgeUploadQueueRepository - -import scala.concurrent.Future -import scala.concurrent.duration.DurationInt - -class BridgeUploadQueueRepositoryAdapterSuite extends BaseSuite { - - // IDEA have some issue here with imports - private implicit val executionContext = scala.concurrent.ExecutionContext.global - - "Strategy" - { - "LimitExponential" - { - "on" - { - val strategy = Strategy.LimitExponential( - startInterval = 10.seconds, - intervalFactor = 1.4, - maxInterval = 50.seconds, - onComplete = OnComplete.Delete - ) - - "a new interval should be greater than the previous one if the limit not reached" in { - val previous = strategy.on(1) - val current = strategy.on(2) - - (previous, current) match { - case (OnAttempt.Continue(a), OnAttempt.Continue(b)) => assert(a < b) - case x => fail(s"Unexpected result: $x") - } - } - - "should limit intervals" in { - assert(strategy.on(20) == OnAttempt.Continue(strategy.maxInterval)) - } - - "should not fail, if there is many attempts" in { - assert(strategy.on(1000) == OnAttempt.Continue(strategy.maxInterval)) - } - } - } - } - - "complete" - { - "onComplete == mark" - { - "should update the item" in { - var done = false - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - - override def delete(kind: String, tag: String): Unit = throw new IllegalStateException("Impossible call") - - override def update(entity: EntityT): EntityT = { - assert(entity.kind == item.kind, "repository.delete, kind") - assert(entity.tag == item.tag, "repository.delete, tag") - done = true - entity - } - - override def getById(kind: String, tag: String): Option[EntityT] = Some(item) - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = Strategy.Stop(OnComplete.Mark), - repository = repository, - dbIo = FakeDbIo - ) - - assert(adapter.complete(item.kind, item.tag).isReadyWithin(100.millis)) - assert(done) - } - } - - "onComplete == delete" - { - "should delete the item" in { - var done = false - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - - override def delete(kind: String, tag: String): Unit = { - assert(kind == item.kind, "repository.delete, kind") - assert(tag == item.tag, "repository.delete, tag") - done = true - } - override def update(entity: EntityT): EntityT = throw new IllegalStateException("Impossible call") - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = Strategy.Stop(OnComplete.Delete), - repository = repository, - dbIo = FakeDbIo - ) - - assert(adapter.complete(item.kind, item.tag).isReadyWithin(100.millis)) - assert(done) - } - } - } - - "tryRetry" - { - - "when all attempts are not out" - { - - val defaultStrategy = Strategy.Constant(10.seconds) - - "should return an updated item" in { - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - - override def update(draft: EntityT): EntityT = draft - override def delete(kind: String, tag: String): Unit = throw new IllegalAccessError(s"kind=$kind, tag=$tag") - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) - - val item = defaultItem - val r = adapter.tryRetry(item).futureValue - assert(r.isDefined) - assert(!r.contains(item)) - } - - "should update an item with increased attempts" in { - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - - override def update(draft: EntityT): EntityT = { - assert(draft.attempts === (item.attempts + 1), "repository.add") - draft - } - override def delete(kind: String, tag: String): Unit = throw new IllegalAccessError(s"kind=$kind, tag=$tag") - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) - - assert(adapter.tryRetry(item).isReadyWithin(100.millis)) - } - - "should remove an old item" in { - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - override def update(draft: EntityT): EntityT = draft - override def delete(kind: String, tag: String): Unit = { - assert(kind == item.kind, "repository.delete, kind") - assert(tag == item.tag, "repository.delete, kind") - } - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) - - assert(adapter.tryRetry(item).isReadyWithin(100.millis)) - } - - "should update time of the next attempt" in { - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - - override def update(draft: EntityT): EntityT = { - assert(draft.nextAttempt.isAfter(item.nextAttempt), "repository.add") - draft - } - override def delete(kind: String, tag: String): Unit = throw new IllegalAccessError(s"kind=$kind, tag=$tag") - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) - - assert(adapter.tryRetry(item).isReadyWithin(100.millis)) - } - - } - - "when all attempts are out" - { - - val defaultStrategy = Strategy.Stop() - - "should not return an item" in { - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - override def update(entity: EntityT): EntityT = fail("update should not be used!") - - override def delete(kind: String, tag: String): Unit = {} - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) - - val r = adapter.tryRetry(defaultItem).futureValue - assert(r.isEmpty) - } - - "should complete the item" in { - var taskWasCompleted = false - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - override def update(entity: EntityT): EntityT = fail("update should not be used!") - - override def delete(kind: String, tag: String): Unit = {} - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) { - override def complete(kind: String, tag: String): Future[Unit] = Future { - assert(kind == item.kind, "adapter.complete, kind") - assert(tag == item.tag, "adapter.complete, tag") - taskWasCompleted = true - } - } - - val r = adapter.tryRetry(item).futureValue - assert(r.isEmpty) - assert(taskWasCompleted) - } - - } - - } - - private def defaultItem = BridgeUploadQueue.Item( - "test", - ThreadLocalRandom.current().nextInt().toString - ) - -} diff --git a/src/test/scala/xyz/driver/pdsuicommon/db/QueryBuilderParametersSuite.scala b/src/test/scala/xyz/driver/pdsuicommon/db/QueryBuilderParametersSuite.scala deleted file mode 100644 index 2c23b92..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/db/QueryBuilderParametersSuite.scala +++ /dev/null @@ -1,310 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.time.LocalDateTime - -import io.getquill.MysqlEscape -import org.scalatest.FreeSpecLike -import xyz.driver.pdsuicommon.db.QueryBuilder.TableData -import xyz.driver.pdsuicommon.domain._ - -class QueryBuilderParametersSuite extends FreeSpecLike { - - import SearchFilterBinaryOperation._ - import SearchFilterExpr.{Dimension => _, _} - import SearchFilterNAryOperation._ - import Sorting._ - import SortingOrder._ - - val tableName = "Entity" - - case class Entity(id: LongId[Entity], - name: String, - email: Email, - optionUser: Option[StringId[User]], - date: LocalDateTime, - optionDate: Option[LocalDateTime], - kindId: Long) - - def queryBuilderParameters = MysqlQueryBuilderParameters( - tableData = TableData( - tableName = tableName, - nullableFields = Set("optionUser", "optionDate") - ), - links = Map( - "Kind" -> TableLink("kindId", "Kind", "id"), - "User" -> TableLink("optionUser", "User", "id") - ) - ) - - val queryBasis = - s"""select `$tableName`.* - |from `$tableName`""".stripMargin.trim - - "toSql" - { - "should generate correct SQL query" - { - "with default parameters" in { - val (sql, _) = queryBuilderParameters.toSql(namingStrategy = MysqlEscape) - assert(sql == queryBasis) - } - - "with filtering: " - { - "single atom filter" in { - val (sql, _) = - queryBuilderParameters.copy(filter = Atom.Binary("name", Eq, "x")).toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where `$tableName`.`name` = ?""".stripMargin) - } - - "single atom filter for optional field with NotEq operation" in { - val (sql, _) = queryBuilderParameters - .copy(filter = Atom.Binary("optionUser", NotEq, "x")) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where (`$tableName`.`optionUser` is null or `$tableName`.`optionUser` != ?)""".stripMargin) - } - - "single atom filter for field with IN operation" in { - val (sql, _) = queryBuilderParameters - .copy(filter = Atom.NAry("date", In, Seq("x", "x", "x"))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where `$tableName`.`date` in (?, ?, ?)""".stripMargin) - } - - "multiple intersected filters" in { - val (sql, _) = queryBuilderParameters - .copy( - filter = Intersection( - Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x") - ))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where (`$tableName`.`name` > ? and `$tableName`.`optionDate` >= ?)""".stripMargin) - } - - "multiple intersected nested filters" in { - val (sql, _) = queryBuilderParameters - .copy( - filter = Intersection( - Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x"), - Intersection(Seq( - Atom.Binary("optionUser", Eq, "x"), - Atom.Binary("date", LtEq, "x") - )) - ))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"$queryBasis\nwhere (`$tableName`.`name` > ? and `$tableName`.`optionDate` >= ?" + - s" and (`$tableName`.`optionUser` = ? and `$tableName`.`date` <= ?))") - } - - "multiple unionized filters" in { - val (sql, _) = queryBuilderParameters - .copy( - filter = Union( - Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x") - ))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where (`$tableName`.`name` > ? or `$tableName`.`optionDate` >= ?)""".stripMargin.trim) - } - - "multiple unionized nested filters" in { - val (sql, _) = queryBuilderParameters - .copy( - filter = Union( - Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x"), - Union(Seq( - Atom.Binary("optionUser", Eq, "x"), - Atom.Binary("date", LtEq, "x") - )) - ))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where (`$tableName`.`name` > ? or `$tableName`.`optionDate` >= ? or (`$tableName`.`optionUser` = ? or `$tableName`.`date` <= ?))""".stripMargin) - } - - "multiple unionized and intersected nested filters" in { - val (sql, _) = queryBuilderParameters - .copy(filter = Union(Seq( - Intersection(Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x") - )), - Intersection(Seq( - Atom.Binary("optionUser", Eq, "x"), - Atom.Binary("date", LtEq, "x") - )) - ))) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"$queryBasis\nwhere ((`$tableName`.`name` > ? and `$tableName`.`optionDate` >= ?) " + - s"or (`$tableName`.`optionUser` = ? and `$tableName`.`date` <= ?))") - } - - "single field from foreign table" in { - val (sql, _) = queryBuilderParameters - .copy(filter = Atom.Binary(SearchFilterExpr.Dimension(Some("Kind"), "name"), Eq, "x")) - .toSql(namingStrategy = MysqlEscape) - val pattern = - s"""select `$tableName`.* - |from `$tableName` - |inner join `Kind` on `Entity`.`kindId` = `Kind`.`id` - |where `Kind`.`name` = ?""".stripMargin - assert(sql == pattern) - } - } - - "with sorting:" - { - "single field sorting" in { - val (sql, _) = queryBuilderParameters - .copy(sorting = Dimension(None, "name", Ascending)) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"""$queryBasis - |order by `$tableName`.`name` asc""".stripMargin) - } - - "single foreign sorting field" in { - val (sql, _) = queryBuilderParameters - .copy(sorting = Dimension(Some("Kind"), "name", Ascending)) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"""select `$tableName`.* - |from `$tableName` - |inner join `Kind` on `Entity`.`kindId` = `Kind`.`id` - |order by `Kind`.`name` asc""".stripMargin) - } - - "multiple fields sorting" in { - val (sql, _) = queryBuilderParameters - .copy( - sorting = Sequential( - Seq( - Dimension(None, "name", Ascending), - Dimension(None, "date", Descending) - ))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |order by `$tableName`.`name` asc, `$tableName`.`date` desc""".stripMargin) - } - - "multiple foreign sorting field" in { - val (sql, _) = queryBuilderParameters - .copy( - sorting = Sequential( - Seq( - Dimension(Some("Kind"), "name", Ascending), - Dimension(Some("User"), "name", Descending) - ))) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"""select `$tableName`.* - |from `$tableName` - |inner join `Kind` on `$tableName`.`kindId` = `Kind`.`id` - |inner join `User` on `$tableName`.`optionUser` = `User`.`id` - |order by `Kind`.`name` asc, `User`.`name` desc""".stripMargin) - } - - "multiple field sorting (including foreign tables)" in { - val (sql, _) = queryBuilderParameters - .copy( - sorting = Sequential( - Seq( - Dimension(Some("Kind"), "name", Ascending), - Dimension(None, "date", Descending) - ))) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"""select `$tableName`.* - |from `$tableName` - |inner join `Kind` on `$tableName`.`kindId` = `Kind`.`id` - |order by `Kind`.`name` asc, `$tableName`.`date` desc""".stripMargin) - } - } - - "with pagination" in { - val (sql, _) = - queryBuilderParameters.copy(pagination = Some(Pagination(5, 3))).toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |limit 10, 5""".stripMargin) - } - - "combined" in { - val filter = Union( - Seq( - Intersection( - Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x") - )), - Intersection( - Seq( - Atom.Binary("optionUser", Eq, "x"), - Atom.Binary("date", LtEq, "x") - )) - )) - val sorting = Sequential( - Seq( - Dimension(Some("Kind"), "name", Ascending), - Dimension(None, "name", Ascending), - Dimension(None, "date", Descending) - )) - - val (sql, _) = queryBuilderParameters - .copy( - filter = filter, - sorting = sorting, - pagination = Some(Pagination(5, 3)) - ) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"""select `$tableName`.* - |from `$tableName` - |inner join `Kind` on `$tableName`.`kindId` = `Kind`.`id` - |where ((`$tableName`.`name` > ? and `$tableName`.`optionDate` >= ?) or (`$tableName`.`optionUser` = ? and `$tableName`.`date` <= ?)) - |order by `Kind`.`name` asc, `$tableName`.`name` asc, `$tableName`.`date` desc - |limit 10, 5""".stripMargin) - } - - } - } - -} -- cgit v1.2.3 From b27ba47906e48e9fc59d65893c71309303f73fc8 Mon Sep 17 00:00:00 2001 From: Kseniya Tomskikh Date: Fri, 27 Oct 2017 12:02:49 +0700 Subject: Restore base repository --- .../pdsuicommon/db/repositories/Repository.scala | 3 ++ .../db/repositories/RepositoryLogging.scala | 62 ++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala create mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala b/src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala new file mode 100644 index 0000000..e62238e --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala @@ -0,0 +1,3 @@ +package xyz.driver.pdsuicommon.db.repositories + +trait Repository extends RepositoryLogging diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala b/src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala new file mode 100644 index 0000000..d1ec1da --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala @@ -0,0 +1,62 @@ +package xyz.driver.pdsuicommon.db.repositories + +import xyz.driver.pdsuicommon.logging._ + +trait RepositoryLogging extends PhiLogging { + + protected def logCreatedOne[T](x: T)(implicit toPhiString: T => PhiString): T = { + logger.info(phi"An entity was created: $x") + x + } + + protected def logCreatedMultiple[T <: Iterable[_]](xs: T)(implicit toPhiString: T => PhiString): T = { + if (xs.nonEmpty) { + logger.info(phi"Entities were created: $xs") + } + xs + } + + protected def logUpdatedOne(rowsAffected: Long): Long = { + rowsAffected match { + case 0 => logger.trace(phi"The entity is up to date") + case 1 => logger.info(phi"The entity was updated") + case x => logger.warn(phi"The ${Unsafe(x)} entities were updated") + } + rowsAffected + } + + protected def logUpdatedOneUnimportant(rowsAffected: Long): Long = { + rowsAffected match { + case 0 => logger.trace(phi"The entity is up to date") + case 1 => logger.trace(phi"The entity was updated") + case x => logger.warn(phi"The ${Unsafe(x)} entities were updated") + } + rowsAffected + } + + protected def logUpdatedMultiple(rowsAffected: Long): Long = { + rowsAffected match { + case 0 => logger.trace(phi"All entities are up to date") + case x => logger.info(phi"The ${Unsafe(x)} entities were updated") + } + rowsAffected + } + + protected def logDeletedOne(rowsAffected: Long): Long = { + rowsAffected match { + case 0 => logger.trace(phi"The entity does not exist") + case 1 => logger.info(phi"The entity was deleted") + case x => logger.warn(phi"Deleted ${Unsafe(x)} entities, expected one") + } + rowsAffected + } + + protected def logDeletedMultiple(rowsAffected: Long): Long = { + rowsAffected match { + case 0 => logger.trace(phi"Entities do not exist") + case x => logger.info(phi"Deleted ${Unsafe(x)} entities") + } + rowsAffected + } + +} -- cgit v1.2.3 From a8882aebc2f9ebe5c0d2503d7fbab2a320b6c0d3 Mon Sep 17 00:00:00 2001 From: Kseniya Tomskikh Date: Fri, 27 Oct 2017 14:24:43 +0700 Subject: Fixed bug --- .../scala/xyz/driver/pdsuicommon/db/DbIo.scala | 13 ++++++++++ .../scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala | 28 ++++++++++++++++++++++ .../driver/pdsuicommon/db/PostgresContext.scala | 24 +++++++++++++++++++ .../driver/pdsuicommon/error/ErrorsResponse.scala | 3 +-- .../xyz/driver/pdsuicommon/http/Directives.scala | 4 ++-- 5 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala create mode 100644 src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala b/src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala new file mode 100644 index 0000000..7c290d1 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala @@ -0,0 +1,13 @@ +package xyz.driver.pdsuicommon.db + +import scala.concurrent.Future + +/** + * Where queries should run + */ +trait DbIo { + def runAsync[T](f: => T): Future[T] + def runSync[T](f: => T): T = f + def runAsyncTx[T](f: => T): Future[T] + def runSyncTx[T](f: => T): Unit +} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala b/src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala new file mode 100644 index 0000000..44f177c --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala @@ -0,0 +1,28 @@ +package xyz.driver.pdsuicommon.db + +import xyz.driver.pdsuicommon.logging._ + +import scala.concurrent.Future +import scala.util.{Failure, Success, Try} + +class JdbcDbIo(sqlContext: TransactionalContext) extends DbIo with PhiLogging { + + override def runAsync[T](f: => T): Future[T] = { + Future(f)(sqlContext.executionContext) + } + + override def runAsyncTx[T](f: => T): Future[T] = { + import sqlContext.executionContext + + Future(sqlContext.transaction(f)).andThen { + case Failure(e) => logger.error(phi"Can't run a transaction: $e") + } + } + + override def runSyncTx[T](f: => T): Unit = { + Try(sqlContext.transaction(f)) match { + case Success(_) => + case Failure(e) => logger.error(phi"Can't run a transaction: $e") + } + } +} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/PostgresContext.scala b/src/main/scala/xyz/driver/pdsuicommon/db/PostgresContext.scala index bb8d322..0098a64 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/db/PostgresContext.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/db/PostgresContext.scala @@ -1,12 +1,15 @@ package xyz.driver.pdsuicommon.db import java.io.Closeable +import java.time.{LocalDateTime, ZoneOffset} +import java.util.UUID import java.util.concurrent.Executors import javax.sql.DataSource import io.getquill._ import xyz.driver.pdsuicommon.concurrent.MdcExecutionContext import xyz.driver.pdsuicommon.db.PostgresContext.Settings +import xyz.driver.pdsuicommon.domain.UuidId import xyz.driver.pdsuicommon.logging._ import scala.concurrent.ExecutionContext @@ -45,4 +48,25 @@ class PostgresContext(val dataSource: DataSource with Closeable, settings: Setti super.close() tpe.shutdownNow() } + + /** + * Usable for QueryBuilder's extractors + */ + def timestampToLocalDateTime(timestamp: java.sql.Timestamp): LocalDateTime = { + LocalDateTime.ofInstant(timestamp.toInstant, ZoneOffset.UTC) + } + + implicit def encodeUuidId[T] = MappedEncoding[UuidId[T], String](_.toString) + implicit def decodeUuidId[T] = MappedEncoding[String, UuidId[T]] { uuid => + UuidId[T](UUID.fromString(uuid)) + } + + def decodeOptUuidId[T] = MappedEncoding[Option[String], Option[UuidId[T]]] { + case Some(x) => Option(x).map(y => UuidId[T](UUID.fromString(y))) + case None => None + } + + implicit def decodeUuid[T] = MappedEncoding[String, UUID] { uuid => + UUID.fromString(uuid) + } } diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala index 540bfbb..ccb84c2 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala @@ -1,7 +1,6 @@ package xyz.driver.pdsuicommon.error import spray.json._ -import ErrorCode._ import ErrorsResponse.ResponseError import xyz.driver.pdsuicommon.auth.RequestId @@ -17,7 +16,7 @@ object ErrorsResponse { * * @see https://driverinc.atlassian.net/wiki/display/RA/REST+API+Specification#RESTAPISpecification-HTTPStatuscodes */ - final case class ResponseError(data: Option[String], message: String, code: ErrorCode) + final case class ResponseError(data: Option[String], message: String, code: Int) object ResponseError { diff --git a/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala b/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala index 37e7687..c3c60bd 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala @@ -72,7 +72,7 @@ trait Directives { def domainExceptionHandler(req: RequestId): ExceptionHandler = { def errorResponse(ex: Throwable) = - ErrorsResponse(Seq(ResponseError(None, ex.getMessage, ErrorCode.Unspecified)), req) + ErrorsResponse(Seq(ResponseError(None, ex.getMessage, 1)), req) ExceptionHandler { case ex: AuthenticationException => complete(StatusCodes.Unauthorized -> errorResponse(ex)) case ex: AuthorizationException => complete(StatusCodes.Forbidden -> errorResponse(ex)) @@ -85,7 +85,7 @@ trait Directives { def domainRejectionHandler(req: RequestId): RejectionHandler = { def wrapContent(message: String) = { import ErrorsResponse._ - val err: ErrorsResponse = ErrorsResponse(Seq(ResponseError(None, message, ErrorCode.Unspecified)), req) + val err: ErrorsResponse = ErrorsResponse(Seq(ResponseError(None, message, 1)), req) val text = errorsResponseJsonFormat.write(err).toString() HttpEntity(ContentTypes.`application/json`, text) } -- cgit v1.2.3