From 994e49057df7d4b5bc12c8c47ad8386968b951ba Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Sun, 21 Dec 2014 18:13:37 -0500 Subject: [PATCH] Lots of work on DSTU2 server --- .../ca/uhn/fhir/context/ModelScanner.java | 9 +- .../java/ca/uhn/fhir/model/api/IResource.java | 8 +- .../composite/BaseResourceReferenceDt.java | 2 +- .../uhn/fhir/model/dstu/resource/Binary.java | 8 +- .../java/ca/uhn/fhir/parser/ParserState.java | 12 +- .../rest/client/IRestfulClientFactory.java | 10 +- hapi-fhir-base/testmindeps/pom.xml | 5 + .../uhn/fhir/testmindeps/FhirContextTest.java | 36 + hapi-fhir-jpaserver-base/.classpath | 10 + .../org.eclipse.core.resources.prefs | 2 + .../org.eclipse.wst.common.component | 2 + hapi-fhir-jpaserver-base/pom.xml | 59 + .../java/ca/uhn/fhir/jpa/dao/BaseFhirDao.java | 1254 +++---- .../fhir/jpa/dao/ISearchParamExtractor.java | 26 + .../fhir/jpa/dao/SearchParamExtractorDev.java | 504 +++ .../jpa/dao/SearchParamExtractorDstu1.java | 474 +++ .../uhn/fhir/jpa/entity/BaseHasResource.java | 15 +- .../ca/uhn/fhir/jpa/entity/ResourceTable.java | 1 + .../jpa/provider/JpaResourceProvider.java | 1 - .../fhir-jpabase-spring-test-config.xml | 11 +- hapi-fhir-jpaserver-test/.classpath | 1 - hapi-fhir-jpaserver-test/pom.xml | 40 - .../resources/fhir-spring-test-config.xml | 40 - .../test/CompleteResourceProviderTest.java | 112 +- .../fhir/jpa/test/MultiFhirVersionTest.java | 190 ++ .../java/ca/uhn/fhir/jpa/test/SystemTest.java | 18 +- hapi-fhir-jpaserver-uhnfhirtest/.gitignore | 1 + .../org.eclipse.wst.common.component | 5 +- hapi-fhir-jpaserver-uhnfhirtest/pom.xml | 96 +- .../ca/uhn/fhirtest/TestRestfulServer.java | 29 +- .../WEB-INF/hapi-fhir-tester-config.xml | 17 +- .../src/main/webapp/WEB-INF/web.xml | 37 +- hapi-fhir-structures-dev/.classpath | 1 + hapi-fhir-structures-dev/.project | 13 + .../.settings/org.eclipse.jdt.core.prefs | 3 + hapi-fhir-structures-dev/pom.xml | 2 +- .../fhir/model/dev/api/BaseResourceDev.java | 8 + .../model/dev/ModelInstantiationTest.java | 42 + .../ca/uhn/fhir/parser/JsonParserTest.java | 10 + .../fhir/rest/client/GenericClientTest.java | 73 + .../fhir/model/dstu/api/BaseResourceDstu.java | 8 + .../fhir/context/ResourceWithExtensionsA.java | 6 +- .../server/ServerInvalidDefinitionTest.java | 6 + .../java/ca/uhn/fhir/testmodel/Patient.java | 5 + hapi-fhir-testpage-overlay/pom.xml | 5 + .../main/java/ca/uhn/fhir/to/Controller.java | 377 +- .../java/ca/uhn/fhir/to/TesterConfig.java | 48 +- .../ca/uhn/fhir/to/model/HomeRequest.java | 9 + .../WEB-INF/hapi-fhir-tester-config.xml | 14 +- .../WEB-INF/templates/tmpl-navbar-left.html | 8 +- .../ca/uhn/fhir/jpa/test/OverlayTestApp.java | 174 +- .../java/ca/uhn/fhir/jpa/test/WebUiTest_.java | 224 -- .../fhir/model/dev/composite/AddressDt.java | 42 +- .../uhn/fhir/model/dev/resource/Account.java | 1081 ------ .../model/dev/resource/AdverseReaction.java | 1248 ------- .../dev/resource/AdverseReactionRisk.java | 2050 ----------- .../ca/uhn/fhir/model/dev/resource/Alert.java | 657 ---- .../dev/resource/AllergyIntolerance.java | 2071 ----------- .../fhir/model/dev/resource/Appointment.java | 1626 --------- .../dev/resource/AppointmentResponse.java | 1048 ------ .../fhir/model/dev/resource/Availability.java | 731 ---- .../uhn/fhir/model/dev/resource/CarePlan.java | 2402 ------------- .../fhir/model/dev/resource/Composition.java | 2127 ------------ .../fhir/model/dev/resource/ConceptMap.java | 2345 ------------- .../fhir/model/dev/resource/Condition.java | 2289 ------------- .../fhir/model/dev/resource/Conformance.java | 237 +- .../uhn/fhir/model/dev/resource/Contract.java | 3039 ----------------- .../model/dev/resource/Contraindication.java | 1176 ------- .../uhn/fhir/model/dev/resource/Coverage.java | 1163 ------- .../fhir/model/dev/resource/DataElement.java | 2402 +++++++++++++ .../uhn/fhir/model/dev/resource/Device.java | 1288 ------- .../dev/resource/DeviceObservationReport.java | 1050 ------ .../model/dev/resource/DiagnosticOrder.java | 1938 ----------- .../model/dev/resource/DiagnosticReport.java | 1670 --------- .../model/dev/resource/DocumentManifest.java | 1337 -------- .../model/dev/resource/DocumentReference.java | 2999 ---------------- .../fhir/model/dev/resource/Encounter.java | 2680 --------------- .../model/dev/resource/EpisodeOfCare.java | 1439 -------- .../model/dev/resource/FamilyHistory.java | 1263 ------- .../model/dev/resource/GeneExpression.java | 1394 -------- .../model/dev/resource/GeneticAnalysis.java | 2771 --------------- .../ca/uhn/fhir/model/dev/resource/Group.java | 1173 ------- .../fhir/model/dev/resource/ImagingStudy.java | 2751 --------------- .../fhir/model/dev/resource/Immunization.java | 2573 -------------- .../resource/ImmunizationRecommendation.java | 1644 --------- .../fhir/model/dev/resource/ListResource.java | 1268 ------- .../uhn/fhir/model/dev/resource/Location.java | 1493 -------- .../ca/uhn/fhir/model/dev/resource/Media.java | 1252 ------- .../fhir/model/dev/resource/Medication.java | 1324 ------- .../resource/MedicationAdministration.java | 1508 -------- .../dev/resource/MedicationDispense.java | 2087 ----------- .../dev/resource/MedicationPrescription.java | 1827 ---------- .../dev/resource/MedicationStatement.java | 1213 ------- .../model/dev/resource/MessageHeader.java | 1922 ----------- .../fhir/model/dev/resource/Microarray.java | 1900 ----------- .../fhir/model/dev/resource/Namespace.java | 1355 -------- .../model/dev/resource/NutritionOrder.java | 2879 ---------------- .../fhir/model/dev/resource/Observation.java | 2200 ------------ .../dev/resource/OperationDefinition.java | 223 +- .../model/dev/resource/OperationOutcome.java | 641 ---- .../ca/uhn/fhir/model/dev/resource/Order.java | 1072 ------ .../model/dev/resource/OrderResponse.java | 904 ----- .../fhir/model/dev/resource/Organization.java | 229 +- .../ca/uhn/fhir/model/dev/resource/Other.java | 656 ---- .../uhn/fhir/model/dev/resource/Patient.java | 2437 ------------- .../fhir/model/dev/resource/Practitioner.java | 1718 ---------- .../fhir/model/dev/resource/Procedure.java | 1441 -------- .../uhn/fhir/model/dev/resource/Profile.java | 234 +- .../fhir/model/dev/resource/Provenance.java | 1574 --------- .../ca/uhn/fhir/model/dev/resource/Query.java | 1143 ------- .../model/dev/resource/Questionnaire.java | 1985 ----------- .../dev/resource/QuestionnaireAnswers.java | 1675 --------- .../model/dev/resource/ReferralRequest.java | 1230 ------- .../model/dev/resource/RelatedPerson.java | 960 ------ .../fhir/model/dev/resource/Remittance.java | 768 ----- .../model/dev/resource/RiskAssessment.java | 1245 ------- .../uhn/fhir/model/dev/resource/Schedule.java | 731 ---- .../model/dev/resource/SecurityClaim.java | 799 ----- .../model/dev/resource/SecurityEvent.java | 3032 ---------------- .../model/dev/resource/SecurityGroup.java | 846 ----- .../model/dev/resource/SecurityPrincipal.java | 1444 -------- .../dev/resource/SequencingAnalysis.java | 933 ----- .../model/dev/resource/SequencingLab.java | 1353 -------- .../ca/uhn/fhir/model/dev/resource/Slot.java | 987 ------ .../uhn/fhir/model/dev/resource/Specimen.java | 2090 ------------ .../fhir/model/dev/resource/Subscription.java | 1532 --------- .../fhir/model/dev/resource/Substance.java | 943 ----- .../uhn/fhir/model/dev/resource/Supply.java | 1255 ------- .../ca/uhn/fhir/model/dev/resource/User.java | 920 ----- .../uhn/fhir/model/dev/resource/ValueSet.java | 232 +- .../valueset/DataElementGranularityEnum.java | 109 + .../ResourceDataElementStatusEnum.java | 123 + .../valueset/ResourceVersionPolicyEnum.java | 126 + .../model/dstu/resource/AdverseReaction.java | 4 + .../uhn/fhir/model/dstu/resource/Alert.java | 4 + .../dstu/resource/AllergyIntolerance.java | 4 + .../fhir/model/dstu/resource/Appointment.java | 4 + .../dstu/resource/AppointmentResponse.java | 4 + .../model/dstu/resource/Availability.java | 4 + .../fhir/model/dstu/resource/CarePlan.java | 4 + .../uhn/fhir/model/dstu/resource/Claim.java | 4 + .../fhir/model/dstu/resource/Composition.java | 4 + .../fhir/model/dstu/resource/ConceptMap.java | 4 + .../fhir/model/dstu/resource/Condition.java | 4 + .../fhir/model/dstu/resource/Conformance.java | 4 + .../fhir/model/dstu/resource/Coverage.java | 4 + .../uhn/fhir/model/dstu/resource/Device.java | 4 + .../resource/DeviceObservationReport.java | 4 + .../model/dstu/resource/DiagnosticOrder.java | 4 + .../model/dstu/resource/DiagnosticReport.java | 4 + .../model/dstu/resource/DocumentManifest.java | 4 + .../dstu/resource/DocumentReference.java | 4 + .../fhir/model/dstu/resource/Encounter.java | 4 + .../model/dstu/resource/FamilyHistory.java | 4 + .../uhn/fhir/model/dstu/resource/GVFMeta.java | 4 + .../fhir/model/dstu/resource/GVFVariant.java | 4 + .../model/dstu/resource/GeneExpression.java | 4 + .../model/dstu/resource/GeneticAnalysis.java | 4 + .../uhn/fhir/model/dstu/resource/Group.java | 4 + .../model/dstu/resource/ImagingStudy.java | 4 + .../model/dstu/resource/Immunization.java | 4 + .../resource/ImmunizationRecommendation.java | 4 + .../model/dstu/resource/ListResource.java | 4 + .../fhir/model/dstu/resource/Location.java | 4 + .../uhn/fhir/model/dstu/resource/Media.java | 4 + .../fhir/model/dstu/resource/Medication.java | 4 + .../resource/MedicationAdministration.java | 4 + .../dstu/resource/MedicationDispense.java | 4 + .../dstu/resource/MedicationPrescription.java | 4 + .../dstu/resource/MedicationStatement.java | 4 + .../model/dstu/resource/MessageHeader.java | 4 + .../fhir/model/dstu/resource/Microarray.java | 4 + .../fhir/model/dstu/resource/Observation.java | 4 + .../model/dstu/resource/OperationOutcome.java | 4 + .../uhn/fhir/model/dstu/resource/Order.java | 4 + .../model/dstu/resource/OrderResponse.java | 4 + .../model/dstu/resource/Organization.java | 4 + .../uhn/fhir/model/dstu/resource/Other.java | 4 + .../uhn/fhir/model/dstu/resource/Patient.java | 4 + .../model/dstu/resource/Practitioner.java | 4 + .../fhir/model/dstu/resource/Procedure.java | 4 + .../uhn/fhir/model/dstu/resource/Profile.java | 4 + .../fhir/model/dstu/resource/Provenance.java | 4 + .../uhn/fhir/model/dstu/resource/Query.java | 4 + .../model/dstu/resource/Questionnaire.java | 4 + .../model/dstu/resource/RelatedPerson.java | 4 + .../fhir/model/dstu/resource/Remittance.java | 4 + .../model/dstu/resource/SecurityEvent.java | 4 + .../dstu/resource/SequencingAnalysis.java | 4 + .../model/dstu/resource/SequencingLab.java | 4 + .../ca/uhn/fhir/model/dstu/resource/Slot.java | 4 + .../fhir/model/dstu/resource/Specimen.java | 4 + .../fhir/model/dstu/resource/Substance.java | 4 + .../uhn/fhir/model/dstu/resource/Supply.java | 4 + .../ca/uhn/fhir/model/dstu/resource/User.java | 4 + .../fhir/model/dstu/resource/ValueSet.java | 4 + .../fhir/tinder/TinderJpaRestServerMojo.java | 85 +- .../uhn/fhir/tinder/TinderStructuresMojo.java | 3 +- .../tinder/parser/BaseStructureParser.java | 15 + .../uhn/fhir/model/dev/fhirversion.properties | 63 +- .../res/dev/statusresponse-spreadsheet.xml | 2 + .../resources/vm/jpa_resource_provider.vm | 7 +- .../src/main/resources/vm/jpa_spring_beans.vm | 28 +- .../src/main/resources/vm/resource.vm | 4 + .../src/main/resources/vm/resource_dstu.vm | 4 + src/changes/changes.xml | 6 + 206 files changed, 5814 insertions(+), 114248 deletions(-) create mode 100644 hapi-fhir-base/testmindeps/src/test/java/ca/uhn/fhir/testmindeps/FhirContextTest.java create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchParamExtractor.java create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchParamExtractorDev.java create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchParamExtractorDstu1.java create mode 100644 hapi-fhir-jpaserver-test/src/test/java/ca/uhn/fhir/jpa/test/MultiFhirVersionTest.java create mode 100644 hapi-fhir-structures-dev/src/main/java/ca/uhn/fhir/model/dev/api/BaseResourceDev.java create mode 100644 hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/model/dev/ModelInstantiationTest.java create mode 100644 hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java create mode 100644 hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/model/dstu/api/BaseResourceDstu.java delete mode 100644 hapi-fhir-testpage-overlay/src/test/java/ca/uhn/fhir/jpa/test/WebUiTest_.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Account.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/AdverseReaction.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/AdverseReactionRisk.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Alert.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/AllergyIntolerance.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Appointment.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/AppointmentResponse.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Availability.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/CarePlan.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Composition.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/ConceptMap.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Condition.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Contract.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Contraindication.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Coverage.java create mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/DataElement.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Device.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/DeviceObservationReport.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/DiagnosticOrder.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/DiagnosticReport.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/DocumentManifest.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/DocumentReference.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Encounter.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/EpisodeOfCare.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/FamilyHistory.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/GeneExpression.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/GeneticAnalysis.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Group.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/ImagingStudy.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Immunization.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/ImmunizationRecommendation.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/ListResource.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Location.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Media.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Medication.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/MedicationAdministration.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/MedicationDispense.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/MedicationPrescription.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/MedicationStatement.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/MessageHeader.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Microarray.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Namespace.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/NutritionOrder.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Observation.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/OperationOutcome.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Order.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/OrderResponse.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Other.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Patient.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Practitioner.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Procedure.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Provenance.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Query.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Questionnaire.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/QuestionnaireAnswers.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/ReferralRequest.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/RelatedPerson.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Remittance.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/RiskAssessment.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Schedule.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/SecurityClaim.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/SecurityEvent.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/SecurityGroup.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/SecurityPrincipal.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/SequencingAnalysis.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/SequencingLab.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Slot.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Specimen.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Subscription.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Substance.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/Supply.java delete mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/resource/User.java create mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/valueset/DataElementGranularityEnum.java create mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/valueset/ResourceDataElementStatusEnum.java create mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/model/dev/valueset/ResourceVersionPolicyEnum.java diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java index 2ab15156db0..e3058bff9be 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java @@ -709,7 +709,14 @@ class ModelScanner { RuntimeResourceDefinition resourceDef = new RuntimeResourceDefinition(myContext, resourceName, theClass, resourceDefinition); myClassToElementDefinitions.put(theClass, resourceDef); if (primaryNameProvider) { - myNameToResourceDefinitions.put(resourceName, resourceDef); + try { + IResource res = (IResource) theClass.newInstance(); + if (res.getStructureFhirVersionEnum() == myContext.getVersion().getVersion()) { + myNameToResourceDefinitions.put(resourceName, resourceDef); + } + } catch (Exception e) { + ourLog.error("Failed to instantiate type[" +theClass.getName() +"]", e); + } } scanCompositeElementForChildren(theClass, resourceDef); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/IResource.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/IResource.java index a4fcf296533..acdb3544a81 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/IResource.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/IResource.java @@ -20,8 +20,6 @@ package ca.uhn.fhir.model.api; * #L% */ -import java.util.Map; - import ca.uhn.fhir.model.api.annotation.ResourceDef; import ca.uhn.fhir.model.base.resource.ResourceMetadataMap; import ca.uhn.fhir.model.dstu.composite.ContainedDt; @@ -134,4 +132,10 @@ public interface IResource extends ICompositeElement, org.hl7.fhir.instance.mode */ String getResourceName(); + /** + * Returns the FHIR version represented by this structure + */ + public ca.uhn.fhir.context.FhirVersionEnum getStructureFhirVersionEnum(); + + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/base/composite/BaseResourceReferenceDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/base/composite/BaseResourceReferenceDt.java index 8487750c273..4c098ebd0af 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/base/composite/BaseResourceReferenceDt.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/base/composite/BaseResourceReferenceDt.java @@ -61,7 +61,7 @@ public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement { setReference(theResource.getId()); } - protected abstract IdDt getReference(); + public abstract IdDt getReference(); /** * Gets the actual loaded and parsed resource instance, if it is already present. This method will return the resource instance only if it has previously been loaded using diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/Binary.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/Binary.java index af3bfa54056..43f111e7eff 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/Binary.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/Binary.java @@ -23,8 +23,7 @@ package ca.uhn.fhir.model.dstu.resource; import java.util.Collections; import java.util.List; -import org.apache.commons.lang3.StringUtils; - +import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.model.api.BaseResource; import ca.uhn.fhir.model.api.IElement; import ca.uhn.fhir.model.api.IResource; @@ -105,4 +104,9 @@ public class Binary extends BaseResource implements IResource { return Binary.class.getName(); } + @Override + public FhirVersionEnum getStructureFhirVersionEnum() { + return FhirVersionEnum.DSTU1; + } + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java index f36e7e40149..803d7958c91 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java @@ -1834,12 +1834,14 @@ class ParserState { @Override public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException { - throw new Error("Element " + theLocalPart + " in primitive!"); // TODO: - // can - // this - // happen? + if (false) {// TODO: make this configurable + throw new Error("Element " + theLocalPart + " in primitive!"); // TODO: + } + ourLog.warn("Ignoring element {} in primitive tag", theLocalPart); + push(new SwallowChildrenWholeState(getPreResourceState())); + return; } - + @Override protected IBase getCurrentElement() { return myInstance; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IRestfulClientFactory.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IRestfulClientFactory.java index a7a7aa81a84..e48a6f17aa0 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IRestfulClientFactory.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IRestfulClientFactory.java @@ -66,13 +66,21 @@ public interface IRestfulClientFactory { */ IGenericClient newGenericClient(String theServerBase); - + /** + * Sets the socket timeout (in milliseconds) + */ void setSocketTimeout(int theSocketTimeout); + /** + * Sets the connection timeout (in milliseconds) + */ void setConnectTimeout(int theConnectTimeout); + /** + * Sets the connection request timeout (in milliseconds) + */ void setConnectionRequestTimeout(int theConnectionRequestTimeout); /** diff --git a/hapi-fhir-base/testmindeps/pom.xml b/hapi-fhir-base/testmindeps/pom.xml index 37f30181671..540c18c815b 100644 --- a/hapi-fhir-base/testmindeps/pom.xml +++ b/hapi-fhir-base/testmindeps/pom.xml @@ -47,6 +47,11 @@ hapi-fhir-structures-dstu 0.9-SNAPSHOT + + ca.uhn.hapi.fhir + hapi-fhir-structures-dev + 0.9-SNAPSHOT + diff --git a/hapi-fhir-base/testmindeps/src/test/java/ca/uhn/fhir/testmindeps/FhirContextTest.java b/hapi-fhir-base/testmindeps/src/test/java/ca/uhn/fhir/testmindeps/FhirContextTest.java new file mode 100644 index 00000000000..50886713f6d --- /dev/null +++ b/hapi-fhir-base/testmindeps/src/test/java/ca/uhn/fhir/testmindeps/FhirContextTest.java @@ -0,0 +1,36 @@ +package ca.uhn.fhir.testmindeps; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.RuntimeResourceDefinition; +import ca.uhn.fhir.model.dstu.resource.Patient; + +public class FhirContextTest { + + @Test + public void testWrongVersionDoesntGetInContext1() { + + FhirContext ctx = FhirContext.forDstu1(); + RuntimeResourceDefinition def = ctx.getResourceDefinition("Patient"); + assertEquals(Patient.class, def.getImplementingClass()); + } + + @Test + public void testWrongVersionDoesntGetInContext2() { + + FhirContext ctx = FhirContext.forDstu1(); + RuntimeResourceDefinition def = ctx.getResourceDefinition("Patient"); + assertEquals(Patient.class, def.getImplementingClass()); + + ctx = FhirContext.forDstu1(); + def = ctx.getResourceDefinition(ca.uhn.fhir.model.dev.resource.Patient.class); + assertEquals(ca.uhn.fhir.model.dev.resource.Patient.class, def.getImplementingClass()); + def = ctx.getResourceDefinition("Patient"); + assertEquals(Patient.class, def.getImplementingClass()); + + } + +} diff --git a/hapi-fhir-jpaserver-base/.classpath b/hapi-fhir-jpaserver-base/.classpath index caa2612fd4f..77ae23ab4aa 100644 --- a/hapi-fhir-jpaserver-base/.classpath +++ b/hapi-fhir-jpaserver-base/.classpath @@ -26,5 +26,15 @@ + + + + + + + + + + diff --git a/hapi-fhir-jpaserver-base/.settings/org.eclipse.core.resources.prefs b/hapi-fhir-jpaserver-base/.settings/org.eclipse.core.resources.prefs index 29abf999564..e35473ebaf9 100644 --- a/hapi-fhir-jpaserver-base/.settings/org.eclipse.core.resources.prefs +++ b/hapi-fhir-jpaserver-base/.settings/org.eclipse.core.resources.prefs @@ -3,4 +3,6 @@ encoding//src/main/java=UTF-8 encoding//src/main/resources=UTF-8 encoding//src/test/java=UTF-8 encoding//src/test/resources=UTF-8 +encoding//target/generated-resources/tinder=UTF-8 +encoding//target/generated-sources/tinder=UTF-8 encoding/=UTF-8 diff --git a/hapi-fhir-jpaserver-base/.settings/org.eclipse.wst.common.component b/hapi-fhir-jpaserver-base/.settings/org.eclipse.wst.common.component index 4e5bc0108c7..dc4d46e13ac 100644 --- a/hapi-fhir-jpaserver-base/.settings/org.eclipse.wst.common.component +++ b/hapi-fhir-jpaserver-base/.settings/org.eclipse.wst.common.component @@ -2,5 +2,7 @@ + + diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index c3b3a9c565c..4e2a36abb46 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -48,6 +48,11 @@ hapi-fhir-structures-dstu 0.9-SNAPSHOT + + ca.uhn.hapi.fhir + hapi-fhir-structures-dev + 0.9-SNAPSHOT + org.slf4j @@ -318,6 +323,49 @@ + + ca.uhn.hapi.fhir + hapi-tinder-plugin + 0.9-SNAPSHOT + + + build_dstu1 + + generate-jparest-server + + + dstu + ca.uhn.fhir.jpa.rp.dstu + hapi-fhir-server-resourceproviders-dstu1.xml + + + + + build_dev + + generate-jparest-server + + + dev + ca.uhn.fhir.jpa.rp.dev + hapi-fhir-server-resourceproviders-dev.xml + + + + + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu + 0.9-SNAPSHOT + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dev + 0.9-SNAPSHOT + + + org.apache.maven.plugins maven-deploy-plugin @@ -326,6 +374,17 @@ + + + ${basedir}/src/main/resources + + + ${basedir}/target/generated-sources/tinder + + + ${basedir}/target/generated-resources/tinder + + diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseFhirDao.java index df408e05394..cd3a142e583 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseFhirDao.java @@ -3,7 +3,6 @@ package ca.uhn.fhir.jpa.dao; import static org.apache.commons.lang3.StringUtils.*; import java.io.UnsupportedEncodingException; -import java.math.BigDecimal; import java.text.Normalizer; import java.util.ArrayList; import java.util.Collection; @@ -16,9 +15,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import javax.measure.quantity.Quantity; -import javax.measure.unit.NonSI; -import javax.measure.unit.Unit; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; @@ -32,7 +28,6 @@ import javax.persistence.criteria.Root; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; -import org.apache.commons.lang3.tuple.Pair; import org.hl7.fhir.instance.model.IBaseResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.PlatformTransactionManager; @@ -42,6 +37,7 @@ import org.springframework.transaction.support.TransactionTemplate; import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.jpa.entity.BaseHasResource; @@ -61,29 +57,16 @@ import ca.uhn.fhir.jpa.entity.ResourceTable; import ca.uhn.fhir.jpa.entity.ResourceTag; import ca.uhn.fhir.jpa.entity.TagDefinition; import ca.uhn.fhir.jpa.util.StopWatch; -import ca.uhn.fhir.model.api.IDatatype; -import ca.uhn.fhir.model.api.IPrimitiveDatatype; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.Tag; import ca.uhn.fhir.model.api.TagList; -import ca.uhn.fhir.model.dstu.composite.AddressDt; -import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt; -import ca.uhn.fhir.model.dstu.composite.CodingDt; -import ca.uhn.fhir.model.dstu.composite.ContactDt; -import ca.uhn.fhir.model.dstu.composite.DurationDt; -import ca.uhn.fhir.model.dstu.composite.HumanNameDt; -import ca.uhn.fhir.model.dstu.composite.IdentifierDt; -import ca.uhn.fhir.model.dstu.composite.PeriodDt; -import ca.uhn.fhir.model.dstu.composite.QuantityDt; +import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt; import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum; -import ca.uhn.fhir.model.primitive.BaseDateTimeDt; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.InstantDt; -import ca.uhn.fhir.model.primitive.IntegerDt; -import ca.uhn.fhir.model.primitive.StringDt; -import ca.uhn.fhir.model.primitive.UriDt; +import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; @@ -101,16 +84,18 @@ public abstract class BaseFhirDao implements IDao { public static final String UCUM_NS = "http://unitsofmeasure.org"; private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseFhirDao.class); + private static final Map ourRetrievalContexts = new HashMap(); @Autowired(required = true) private DaoConfig myConfig; - @Autowired(required = true) private FhirContext myContext; @PersistenceContext(name = "FHIR_UT", type = PersistenceContextType.TRANSACTION, unitName = "FHIR_UT") private EntityManager myEntityManager; + private List myListeners = new ArrayList(); + private ISearchParamExtractor mySearchParamExtractor; @Autowired private PlatformTransactionManager myPlatformTransactionManager; @@ -118,20 +103,148 @@ public abstract class BaseFhirDao implements IDao { @Autowired private List> myResourceDaos; - private Map,IFhirResourceDao> myResourceTypeToDao; + private Map, IFhirResourceDao> myResourceTypeToDao; - public FhirContext getContext() { - return myContext; + protected void createForcedIdIfNeeded(ResourceTable entity, IdDt id) { + if (id.isEmpty() == false && id.hasIdPart()) { + if (isValidPid(id)) { + return; + } + ForcedId fid = new ForcedId(); + fid.setForcedId(id.getIdPart()); + fid.setResource(entity); + entity.setForcedId(fid); + } } - @Override - public void registerDaoListener(IDaoListener theListener) { - Validate.notNull(theListener, "theListener"); - myListeners.add(theListener); + InstantDt createHistoryToTimestamp() { + // final InstantDt end = new InstantDt(DateUtils.addSeconds(DateUtils.truncate(new Date(), Calendar.SECOND), + // -1)); + return InstantDt.withCurrentTime(); } - public void setContext(FhirContext theContext) { - myContext = theContext; + protected List extractResourceLinks(ResourceTable theEntity, IResource theResource) { + ArrayList retVal = new ArrayList(); + + RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource); + for (RuntimeSearchParam nextSpDef : def.getSearchParams()) { + if (nextSpDef.getParamType() != SearchParamTypeEnum.REFERENCE) { + continue; + } + + String nextPathsUnsplit = nextSpDef.getPath(); + if (isBlank(nextPathsUnsplit)) { + continue; + } + + boolean multiType = false; + if (nextPathsUnsplit.endsWith("[x]")) { + multiType = true; + } + + for (Object nextObject : extractValues(nextPathsUnsplit, theResource)) { + if (nextObject == null) { + continue; + } + + ResourceLink nextEntity; + if (nextObject instanceof BaseResourceReferenceDt) { + BaseResourceReferenceDt nextValue = (BaseResourceReferenceDt) nextObject; + if (nextValue.isEmpty()) { + continue; + } + if (nextValue.getReference().getValue().startsWith("#")) { + // This is a contained resource reference + continue; + } + + String typeString = nextValue.getReference().getResourceType(); + if (isBlank(typeString)) { + throw new InvalidRequestException("Invalid resource reference found at path[" + nextPathsUnsplit + "] - Does not contain resource type - " + nextValue.getReference().getValue()); + } + Class type = getContext().getResourceDefinition(typeString).getImplementingClass(); + String id = nextValue.getReference().getIdPart(); + if (StringUtils.isBlank(id)) { + continue; + } + + IFhirResourceDao dao = getDao(type); + if (dao == null) { + StringBuilder b = new StringBuilder(); + b.append("This server (version "); + b.append(myContext.getVersion().getVersion()); + b.append(") is not able to handle resources of type["); + b.append(nextValue.getReference().getResourceType()); + b.append("] - Valid resource types for this server: "); + b.append(myResourceTypeToDao.keySet().toString()); + + throw new InvalidRequestException(b.toString()); + } + Long valueOf; + try { + valueOf = translateForcedIdToPid(nextValue.getReference()); + } catch (Exception e) { + String resName = getContext().getResourceDefinition(type).getName(); + throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit + " (this is an invalid ID, must be numeric on this server)"); + } + ResourceTable target = myEntityManager.find(ResourceTable.class, valueOf); + if (target == null) { + String resName = getContext().getResourceDefinition(type).getName(); + throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit); + } + nextEntity = new ResourceLink(nextPathsUnsplit, theEntity, target); + } else { + if (!multiType) { + throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass()); + } else { + continue; + } + } + if (nextEntity != null) { + retVal.add(nextEntity); + } + } + } + + theEntity.setHasLinks(retVal.size() > 0); + + return retVal; + } + + protected List extractSearchParamDates(ResourceTable theEntity, IResource theResource) { + return mySearchParamExtractor.extractSearchParamDates(theEntity, theResource); + } + + protected ArrayList extractSearchParamNumber(ResourceTable theEntity, IResource theResource) { + return mySearchParamExtractor.extractSearchParamNumber(theEntity, theResource); + } + + protected List extractSearchParamQuantity(ResourceTable theEntity, IResource theResource) { + return mySearchParamExtractor.extractSearchParamQuantity(theEntity, theResource); + } + + protected List extractSearchParamStrings(ResourceTable theEntity, IResource theResource) { + return mySearchParamExtractor.extractSearchParamStrings(theEntity, theResource); + } + + protected List extractSearchParamTokens(ResourceTable theEntity, IResource theResource) { + return mySearchParamExtractor.extractSearchParamTokens(theEntity, theResource); + } + + private List extractValues(String thePaths, IResource theResource) { + List values = new ArrayList(); + String[] nextPathsSplit = thePaths.split("\\|"); + FhirTerser t = getContext().newTerser(); + for (String nextPath : nextPathsSplit) { + String nextPathTrimmed = nextPath.trim(); + try { + values.addAll(t.getValues(theResource, nextPathTrimmed)); + } catch (Exception e) { + RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource); + ourLog.warn("Failed to index values from path[{}] in resource type[{}]: ", nextPathTrimmed, def.getName(), e.toString()); + } + } + return values; } private void findMatchingTagIds(String theResourceName, IdDt theResourceId, Set tagIds, Class entityClass) { @@ -157,6 +270,302 @@ public abstract class BaseFhirDao implements IDao { } } + protected DaoConfig getConfig() { + return myConfig; + } + + public FhirContext getContext() { + return myContext; + } + + public FhirContext getContext(FhirVersionEnum theVersion) { + FhirVersionEnum ver = theVersion != null ? theVersion : FhirVersionEnum.DSTU1; + synchronized (ourRetrievalContexts) { + FhirContext retVal = ourRetrievalContexts.get(ver); + if (retVal == null) { + retVal = new FhirContext(ver); + ourRetrievalContexts.put(ver, retVal); + } + return retVal; + } + } + + protected IFhirResourceDao getDao(Class theType) { + if (myResourceTypeToDao == null) { + myResourceTypeToDao = new HashMap, IFhirResourceDao>(); + for (IFhirResourceDao next : myResourceDaos) { + myResourceTypeToDao.put(next.getResourceType(), next); + } + + if (this instanceof IFhirResourceDao) { + IFhirResourceDao thiz = (IFhirResourceDao) this; + myResourceTypeToDao.put(thiz.getResourceType(), thiz); + } + + } + + return myResourceTypeToDao.get(theType); + } + + protected TagDefinition getTag(String theScheme, String theTerm, String theLabel) { + CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); + CriteriaQuery cq = builder.createQuery(TagDefinition.class); + Root from = cq.from(TagDefinition.class); + cq.where(builder.and(builder.equal(from.get("myScheme"), theScheme), builder.equal(from.get("myTerm"), theTerm))); + TypedQuery q = myEntityManager.createQuery(cq); + try { + return q.getSingleResult(); + } catch (NoResultException e) { + TagDefinition retVal = new TagDefinition(theTerm, theLabel, theScheme); + myEntityManager.persist(retVal); + return retVal; + } + } + + protected TagList getTags(Class theResourceType, IdDt theResourceId) { + String resourceName = null; + if (theResourceType != null) { + resourceName = toResourceName(theResourceType); + if (theResourceId != null && theResourceId.hasVersionIdPart()) { + IFhirResourceDao dao = getDao(theResourceType); + BaseHasResource entity = dao.readEntity(theResourceId); + TagList retVal = new TagList(); + for (BaseTag next : entity.getTags()) { + retVal.add(next.getTag().toTag()); + } + return retVal; + } + } + + Set tagIds = new HashSet(); + findMatchingTagIds(resourceName, theResourceId, tagIds, ResourceTag.class); + findMatchingTagIds(resourceName, theResourceId, tagIds, ResourceHistoryTag.class); + if (tagIds.isEmpty()) { + return new TagList(); + } + { + CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); + CriteriaQuery cq = builder.createQuery(TagDefinition.class); + Root from = cq.from(TagDefinition.class); + cq.where(from.get("myId").in(tagIds)); + cq.orderBy(builder.asc(from.get("myScheme")), builder.asc(from.get("myTerm"))); + TypedQuery q = myEntityManager.createQuery(cq); + q.setMaxResults(getConfig().getHardTagListLimit()); + + TagList retVal = new TagList(); + for (TagDefinition next : q.getResultList()) { + retVal.add(next.toTag()); + } + + return retVal; + } + } + + protected IBundleProvider history(String theResourceName, Long theId, Date theSince) { + final List tuples = new ArrayList(); + + final InstantDt end = createHistoryToTimestamp(); + + StopWatch timer = new StopWatch(); + + int limit = 10000; + + // Get list of IDs + searchHistoryCurrentVersion(theResourceName, theId, theSince, end.getValue(), limit, tuples); + assert tuples.size() < 2 || !tuples.get(tuples.size() - 2).getUpdated().before(tuples.get(tuples.size() - 1).getUpdated()); + ourLog.info("Retrieved {} history IDs from current versions in {} ms", tuples.size(), timer.getMillisAndRestart()); + + searchHistoryHistory(theResourceName, theId, theSince, end.getValue(), limit, tuples); + assert tuples.size() < 2 || !tuples.get(tuples.size() - 2).getUpdated().before(tuples.get(tuples.size() - 1).getUpdated()); + ourLog.info("Retrieved {} history IDs from previous versions in {} ms", tuples.size(), timer.getMillisAndRestart()); + + // Sort merged list + Collections.sort(tuples, Collections.reverseOrder()); + assert tuples.size() < 2 || !tuples.get(tuples.size() - 2).getUpdated().before(tuples.get(tuples.size() - 1).getUpdated()); + + return new IBundleProvider() { + + @Override + public InstantDt getPublished() { + return end; + } + + @Override + public List getResources(final int theFromIndex, final int theToIndex) { + final StopWatch timer = new StopWatch(); + TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager); + return template.execute(new TransactionCallback>() { + @Override + public List doInTransaction(TransactionStatus theStatus) { + List resEntities = Lists.newArrayList(); + + List tupleSubList = tuples.subList(theFromIndex, theToIndex); + searchHistoryCurrentVersion(tupleSubList, resEntities); + ourLog.info("Loaded history from current versions in {} ms", timer.getMillisAndRestart()); + + searchHistoryHistory(tupleSubList, resEntities); + ourLog.info("Loaded history from previous versions in {} ms", timer.getMillisAndRestart()); + + Collections.sort(resEntities, new Comparator() { + @Override + public int compare(BaseHasResource theO1, BaseHasResource theO2) { + return theO2.getUpdated().getValue().compareTo(theO1.getUpdated().getValue()); + } + }); + + int limit = theToIndex - theFromIndex; + if (resEntities.size() > limit) { + resEntities = resEntities.subList(0, limit); + } + + ArrayList retVal = new ArrayList(); + for (BaseHasResource next : resEntities) { + RuntimeResourceDefinition type; + try { + type = myContext.getResourceDefinition(next.getResourceType()); + } catch (DataFormatException e) { + if (next.getFhirVersion() != getContext().getVersion().getVersion()) { + ourLog.info("Ignoring history resource of type[{}] because it is not compatible with version[{}]", next.getResourceType(), getContext().getVersion().getVersion()); + continue; + } + throw e; + } + IResource resource = (IResource) toResource(type.getImplementingClass(), next); + retVal.add(resource); + } + return retVal; + } + }); + } + + @Override + public int size() { + return tuples.size(); + } + }; + } + + protected boolean isValidPid(IdDt theId) { + String idPart = theId.getIdPart(); + for (int i = 0; i < idPart.length(); i++) { + char nextChar = idPart.charAt(i); + if (nextChar < '0' || nextChar > '9') { + return false; + } + } + return true; + } + + protected List loadResourcesById(Set theIncludePids) { + Set pids = new HashSet(); + for (IdDt next : theIncludePids) { + if (next.isIdPartValidLong()) { + pids.add(next.getIdPartAsLong()); + } else { + try { + pids.add(translateForcedIdToPid(next)); + } catch (ResourceNotFoundException e) { + ourLog.warn("Failed to translate forced ID [{}] to PID", next.getValue()); + } + } + } + + CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); + CriteriaQuery cq = builder.createQuery(ResourceTable.class); + Root from = cq.from(ResourceTable.class); + // cq.where(builder.equal(from.get("myResourceType"), + // getContext().getResourceDefinition(myResourceType).getName())); + // if (theIncludePids != null) { + cq.where(from.get("myId").in(pids)); + // } + TypedQuery q = myEntityManager.createQuery(cq); + + ArrayList retVal = new ArrayList(); + for (ResourceTable next : q.getResultList()) { + IResource resource = (IResource) toResource(next); + retVal.add(resource); + } + + return retVal; + } + + protected static String normalizeString(String theString) { + char[] out = new char[theString.length()]; + theString = Normalizer.normalize(theString, Normalizer.Form.NFD); + int j = 0; + for (int i = 0, n = theString.length(); i < n; ++i) { + char c = theString.charAt(i); + if (c <= '\u007F') { + out[j++] = c; + } + } + return new String(out).toUpperCase(); + } + + protected void notifyWriteCompleted() { + for (IDaoListener next : myListeners) { + next.writeCompleted(); + } + } + + protected void populateResourceIntoEntity(IResource theResource, ResourceTable theEntity) { + + if (theEntity.getPublished().isEmpty()) { + theEntity.setPublished(new Date()); + } + theEntity.setUpdated(new Date()); + + theEntity.setResourceType(toResourceName(theResource)); + + List refs = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, ResourceReferenceDt.class); + for (ResourceReferenceDt nextRef : refs) { + if (nextRef.getReference().isEmpty() == false) { + if (nextRef.getReference().hasVersionIdPart()) { + nextRef.setReference(nextRef.getReference().toUnqualifiedVersionless()); + } + } + } + + String encoded = myConfig.getResourceEncoding().newParser(myContext).encodeResourceToString(theResource); + ResourceEncodingEnum encoding = myConfig.getResourceEncoding(); + theEntity.setEncoding(encoding); + theEntity.setFhirVersion(myContext.getVersion().getVersion()); + try { + switch (encoding) { + case JSON: + theEntity.setResource(encoded.getBytes("UTF-8")); + break; + case JSONC: + theEntity.setResource(GZipUtil.compress(encoded)); + break; + } + } catch (UnsupportedEncodingException e) { + throw new InternalErrorException(e); + } + + TagList tagList = (TagList) theResource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST); + if (tagList != null) { + for (Tag next : tagList) { + TagDefinition tag = getTag(next.getScheme(), next.getTerm(), next.getLabel()); + theEntity.addTag(tag); + theEntity.setHasTags(true); + } + } + + String title = ResourceMetadataKeyEnum.TITLE.get(theResource); + if (title != null && title.length() > BaseHasResource.MAX_TITLE_LENGTH) { + title = title.substring(0, BaseHasResource.MAX_TITLE_LENGTH); + } + theEntity.setTitle(title); + + } + + @Override + public void registerDaoListener(IDaoListener theListener) { + Validate.notNull(theListener, "theListener"); + myListeners.add(theListener); + } + private void searchHistoryCurrentVersion(List theTuples, List theRetVal) { Collection tuples = Collections2.filter(theTuples, new com.google.common.base.Predicate() { @Override @@ -293,770 +702,18 @@ public abstract class BaseFhirDao implements IDao { } } - protected void createForcedIdIfNeeded(ResourceTable entity, IdDt id) { - if (id.isEmpty() == false && id.hasIdPart()) { - if (isValidPid(id)) { - return; - } - ForcedId fid = new ForcedId(); - fid.setForcedId(id.getIdPart()); - fid.setResource(entity); - entity.setForcedId(fid); + public void setContext(FhirContext theContext) { + myContext = theContext; + switch (myContext.getVersion().getVersion()) { + case DEV: + mySearchParamExtractor = new SearchParamExtractorDev(theContext); + break; + case DSTU1: + mySearchParamExtractor = new SearchParamExtractorDstu1(theContext); + break; } } - protected List extractResourceLinks(ResourceTable theEntity, IResource theResource) { - ArrayList retVal = new ArrayList(); - - RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource); - for (RuntimeSearchParam nextSpDef : def.getSearchParams()) { - if (nextSpDef.getParamType() != SearchParamTypeEnum.REFERENCE) { - continue; - } - - String nextPathsUnsplit = nextSpDef.getPath(); - if (isBlank(nextPathsUnsplit)) { - continue; - } - - boolean multiType = false; - if (nextPathsUnsplit.endsWith("[x]")) { - multiType = true; - } - - for (Object nextObject : extractValues(nextPathsUnsplit, theResource)) { - if (nextObject == null) { - continue; - } - - ResourceLink nextEntity; - if (nextObject instanceof ResourceReferenceDt) { - ResourceReferenceDt nextValue = (ResourceReferenceDt) nextObject; - if (nextValue.isEmpty()) { - continue; - } - if (nextValue.getReference().getValue().startsWith("#")) { - // This is a contained resource reference - continue; - } - - String typeString = nextValue.getReference().getResourceType(); - if (isBlank(typeString)) { - throw new InvalidRequestException("Invalid resource reference found at path[" + nextPathsUnsplit + "] - Does not contain resource type - " + nextValue.getReference().getValue()); - } - Class type = getContext().getResourceDefinition(typeString).getImplementingClass(); - String id = nextValue.getReference().getIdPart(); - if (StringUtils.isBlank(id)) { - continue; - } - - IFhirResourceDao dao = getDao(type); - if (dao == null) { - throw new InvalidRequestException("This server is not able to handle resources of type: " + nextValue.getReference().getResourceType()); - } - Long valueOf; - try { - valueOf = translateForcedIdToPid(nextValue.getReference()); - } catch (Exception e) { - String resName = getContext().getResourceDefinition(type).getName(); - throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit + " (this is an invalid ID, must be numeric on this server)"); - } - ResourceTable target = myEntityManager.find(ResourceTable.class, valueOf); - if (target == null) { - String resName = getContext().getResourceDefinition(type).getName(); - throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit); - } - nextEntity = new ResourceLink(nextPathsUnsplit, theEntity, target); - } else { - if (!multiType) { - throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass()); - } else { - continue; - } - } - if (nextEntity != null) { - retVal.add(nextEntity); - } - } - } - - theEntity.setHasLinks(retVal.size() > 0); - - return retVal; - } - - private List extractValues(String thePaths, IResource theResource) { - List values = new ArrayList(); - String[] nextPathsSplit = thePaths.split("\\|"); - FhirTerser t = getContext().newTerser(); - for (String nextPath : nextPathsSplit) { - String nextPathTrimmed = nextPath.trim(); - try { - values.addAll(t.getValues(theResource, nextPathTrimmed)); - } catch (Exception e) { - RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource); - ourLog.warn("Failed to index values from path[{}] in resource type[{}]: ", nextPathTrimmed, def.getName(), e.toString()); - } - } - return values; - } - - protected List extractSearchParamDates(ResourceTable theEntity, IResource theResource) { - ArrayList retVal = new ArrayList(); - - RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource); - for (RuntimeSearchParam nextSpDef : def.getSearchParams()) { - if (nextSpDef.getParamType() != SearchParamTypeEnum.DATE) { - continue; - } - - String nextPath = nextSpDef.getPath(); - if (isBlank(nextPath)) { - continue; - } - - boolean multiType = false; - if (nextPath.endsWith("[x]")) { - multiType = true; - } - - for (Object nextObject : extractValues(nextPath, theResource)) { - if (nextObject == null) { - continue; - } - - ResourceIndexedSearchParamDate nextEntity; - if (nextObject instanceof BaseDateTimeDt) { - BaseDateTimeDt nextValue = (BaseDateTimeDt) nextObject; - if (nextValue.isEmpty()) { - continue; - } - nextEntity = new ResourceIndexedSearchParamDate(nextSpDef.getName(), nextValue.getValue(), nextValue.getValue()); - } else if (nextObject instanceof PeriodDt) { - PeriodDt nextValue = (PeriodDt) nextObject; - if (nextValue.isEmpty()) { - continue; - } - nextEntity = new ResourceIndexedSearchParamDate(nextSpDef.getName(), nextValue.getStart().getValue(), nextValue.getEnd().getValue()); - } else { - if (!multiType) { - throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass()); - } else { - continue; - } - } - if (nextEntity != null) { - nextEntity.setResource(theEntity); - retVal.add(nextEntity); - } - } - } - - theEntity.setParamsDatePopulated(retVal.size() > 0); - - return retVal; - } - - protected ArrayList extractSearchParamNumber(ResourceTable theEntity, IResource theResource) { - ArrayList retVal = new ArrayList(); - - RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource); - for (RuntimeSearchParam nextSpDef : def.getSearchParams()) { - if (nextSpDef.getParamType() != SearchParamTypeEnum.NUMBER) { - continue; - } - - String nextPath = nextSpDef.getPath(); - if (isBlank(nextPath)) { - continue; - } - - for (Object nextObject : extractValues(nextPath, theResource)) { - if (nextObject == null || ((IDatatype) nextObject).isEmpty()) { - continue; - } - - String resourceName = nextSpDef.getName(); - boolean multiType = false; - if (nextPath.endsWith("[x]")) { - multiType = true; - } - - if (nextObject instanceof DurationDt) { - DurationDt nextValue = (DurationDt) nextObject; - if (nextValue.getValue().isEmpty()) { - continue; - } - - if (new UriDt(UCUM_NS).equals(nextValue.getSystem())) { - if (isNotBlank(nextValue.getCode().getValue())) { - - Unit unit = Unit.valueOf(nextValue.getCode().getValue()); - javax.measure.converter.UnitConverter dayConverter = unit.getConverterTo(NonSI.DAY); - double dayValue = dayConverter.convert(nextValue.getValue().getValue().doubleValue()); - DurationDt newValue = new DurationDt(); - newValue.setSystem(UCUM_NS); - newValue.setCode(NonSI.DAY.toString()); - newValue.setValue(dayValue); - nextValue = newValue; - - /* - * @SuppressWarnings("unchecked") PhysicsUnit> unit = (PhysicsUnit>) UCUMFormat.getCaseInsensitiveInstance().parse(nextValue.getCode().getValue(), null); if (unit.isCompatible(UCUM.DAY)) { - * - * @SuppressWarnings("unchecked") PhysicsUnit timeUnit = (PhysicsUnit