Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
James 2017-10-17 16:43:46 -04:00
commit fd4efd638f
8 changed files with 279 additions and 239 deletions

View File

@ -24,6 +24,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -47,7 +48,7 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProviderDstu2Plus<Bundl
@Qualifier("mySystemDaoDstu2") @Qualifier("mySystemDaoDstu2")
private IFhirSystemDao<Bundle, MetaDt> mySystemDao; private IFhirSystemDao<Bundle, MetaDt> mySystemDao;
@Autowired @Autowired(required = false)
private IFulltextSearchSvc mySearchDao; private IFulltextSearchSvc mySearchDao;
//@formatter:off //@formatter:off
@ -178,7 +179,8 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProviderDstu2Plus<Bundl
@OperationParam(name="searchParam", min=1, max=1) String theSearchParam, @OperationParam(name="searchParam", min=1, max=1) String theSearchParam,
@OperationParam(name="text", min=1, max=1) String theText @OperationParam(name="text", min=1, max=1) String theText
) { ) {
JpaSystemProviderDstu3.validateFulltextSearchEnabled(mySearchDao);
if (isBlank(theContext)) { if (isBlank(theContext)) {
throw new InvalidRequestException("Parameter 'context' must be provided"); throw new InvalidRequestException("Parameter 'context' must be provided");
} }
@ -188,16 +190,14 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProviderDstu2Plus<Bundl
if (isBlank(theText)) { if (isBlank(theText)) {
throw new InvalidRequestException("Parameter 'text' must be provided"); throw new InvalidRequestException("Parameter 'text' must be provided");
} }
List<Suggestion> keywords = mySearchDao.suggestKeywords(theContext, theSearchParam, theText); List<Suggestion> keywords = mySearchDao.suggestKeywords(theContext, theSearchParam, theText);
Parameters retVal = new Parameters(); Parameters retVal = new Parameters();
for (Suggestion next : keywords) { for (Suggestion next : keywords) {
//@formatter:off
retVal.addParameter() retVal.addParameter()
.addPart(new Parameter().setName("keyword").setValue(new StringDt(next.getTerm()))) .addPart(new Parameter().setName("keyword").setValue(new StringDt(next.getTerm())))
.addPart(new Parameter().setName("score").setValue(new DecimalDt(next.getScore()))); .addPart(new Parameter().setName("score").setValue(new DecimalDt(next.getScore())));
//@formatter:on
} }
return retVal; return retVal;

View File

@ -1,5 +1,27 @@
package ca.uhn.fhir.jpa.provider.dstu3; package ca.uhn.fhir.jpa.provider.dstu3;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl.Suggestion;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProviderDstu2Plus;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.annotation.Transaction;
import ca.uhn.fhir.rest.annotation.TransactionParam;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
/* /*
@ -11,9 +33,9 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -21,23 +43,6 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
* limitations under the License. * limitations under the License.
* #L% * #L%
*/ */
import java.util.*;
import java.util.Map.Entry;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl.Suggestion;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProviderDstu2Plus;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus<Bundle, Meta> { public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus<Bundle, Meta> {
@ -45,122 +50,122 @@ public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus<Bundl
@Qualifier("mySystemDaoDstu3") @Qualifier("mySystemDaoDstu3")
private IFhirSystemDao<Bundle, Meta> mySystemDao; private IFhirSystemDao<Bundle, Meta> mySystemDao;
@Autowired @Autowired(required = false)
private IFulltextSearchSvc mySearchDao; private IFulltextSearchSvc mySearchDao;
//@formatter:off //@formatter:off
// This is generated by hand: // This is generated by hand:
// ls hapi-fhir-structures-dstu2/target/generated-sources/tinder/ca/uhn/fhir/model/dstu2/resource/ | sort | sed "s/.java//" | sed "s/^/@OperationParam(name=\"/" | sed "s/$/\", type=IntegerType.class, min=0, max=1),/" // ls hapi-fhir-structures-dstu2/target/generated-sources/tinder/ca/uhn/fhir/model/dstu2/resource/ | sort | sed "s/.java//" | sed "s/^/@OperationParam(name=\"/" | sed "s/$/\", type=IntegerType.class, min=0, max=1),/"
@Operation(name="$get-resource-counts", idempotent=true, returnParameters= { @Operation(name = "$get-resource-counts", idempotent = true, returnParameters = {
@OperationParam(name="AllergyIntolerance", type=IntegerType.class, min=0, max=1), @OperationParam(name = "AllergyIntolerance", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Appointment", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Appointment", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="AppointmentResponse", type=IntegerType.class, min=0, max=1), @OperationParam(name = "AppointmentResponse", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="AuditEvent", type=IntegerType.class, min=0, max=1), @OperationParam(name = "AuditEvent", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Basic", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Basic", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Binary", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Binary", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="BodySite", type=IntegerType.class, min=0, max=1), @OperationParam(name = "BodySite", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Bundle", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Bundle", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="CarePlan", type=IntegerType.class, min=0, max=1), @OperationParam(name = "CarePlan", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="CarePlan2", type=IntegerType.class, min=0, max=1), @OperationParam(name = "CarePlan2", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Claim", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Claim", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ClaimResponse", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ClaimResponse", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ClinicalImpression", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ClinicalImpression", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Communication", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Communication", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="CommunicationRequest", type=IntegerType.class, min=0, max=1), @OperationParam(name = "CommunicationRequest", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Composition", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Composition", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ConceptMap", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ConceptMap", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Condition", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Condition", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Conformance", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Conformance", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Contract", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Contract", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Contraindication", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Contraindication", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Coverage", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Coverage", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="DataElement", type=IntegerType.class, min=0, max=1), @OperationParam(name = "DataElement", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Device", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Device", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="DeviceComponent", type=IntegerType.class, min=0, max=1), @OperationParam(name = "DeviceComponent", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="DeviceMetric", type=IntegerType.class, min=0, max=1), @OperationParam(name = "DeviceMetric", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="DeviceUseRequest", type=IntegerType.class, min=0, max=1), @OperationParam(name = "DeviceUseRequest", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="DeviceUseStatement", type=IntegerType.class, min=0, max=1), @OperationParam(name = "DeviceUseStatement", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="DiagnosticOrder", type=IntegerType.class, min=0, max=1), @OperationParam(name = "DiagnosticOrder", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="DiagnosticReport", type=IntegerType.class, min=0, max=1), @OperationParam(name = "DiagnosticReport", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="DocumentManifest", type=IntegerType.class, min=0, max=1), @OperationParam(name = "DocumentManifest", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="DocumentReference", type=IntegerType.class, min=0, max=1), @OperationParam(name = "DocumentReference", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="EligibilityRequest", type=IntegerType.class, min=0, max=1), @OperationParam(name = "EligibilityRequest", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="EligibilityResponse", type=IntegerType.class, min=0, max=1), @OperationParam(name = "EligibilityResponse", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Encounter", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Encounter", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="EnrollmentRequest", type=IntegerType.class, min=0, max=1), @OperationParam(name = "EnrollmentRequest", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="EnrollmentResponse", type=IntegerType.class, min=0, max=1), @OperationParam(name = "EnrollmentResponse", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="EpisodeOfCare", type=IntegerType.class, min=0, max=1), @OperationParam(name = "EpisodeOfCare", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ExplanationOfBenefit", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ExplanationOfBenefit", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="FamilyMemberHistory", type=IntegerType.class, min=0, max=1), @OperationParam(name = "FamilyMemberHistory", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Flag", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Flag", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Goal", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Goal", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Group", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Group", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="HealthcareService", type=IntegerType.class, min=0, max=1), @OperationParam(name = "HealthcareService", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ImagingObjectSelection", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ImagingObjectSelection", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ImagingStudy", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ImagingStudy", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Immunization", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Immunization", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ImmunizationRecommendation", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ImmunizationRecommendation", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ListResource", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ListResource", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Location", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Location", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Media", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Media", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Medication", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Medication", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="MedicationAdministration", type=IntegerType.class, min=0, max=1), @OperationParam(name = "MedicationAdministration", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="MedicationDispense", type=IntegerType.class, min=0, max=1), @OperationParam(name = "MedicationDispense", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="MedicationPrescription", type=IntegerType.class, min=0, max=1), @OperationParam(name = "MedicationPrescription", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="MedicationStatement", type=IntegerType.class, min=0, max=1), @OperationParam(name = "MedicationStatement", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="MessageHeader", type=IntegerType.class, min=0, max=1), @OperationParam(name = "MessageHeader", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="NamingSystem", type=IntegerType.class, min=0, max=1), @OperationParam(name = "NamingSystem", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="NutritionOrder", type=IntegerType.class, min=0, max=1), @OperationParam(name = "NutritionOrder", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Observation", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Observation", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="OperationDefinition", type=IntegerType.class, min=0, max=1), @OperationParam(name = "OperationDefinition", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="OperationOutcome", type=IntegerType.class, min=0, max=1), @OperationParam(name = "OperationOutcome", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Order", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Order", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="OrderResponse", type=IntegerType.class, min=0, max=1), @OperationParam(name = "OrderResponse", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Organization", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Organization", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Parameters", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Parameters", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Patient", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Patient", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="PaymentNotice", type=IntegerType.class, min=0, max=1), @OperationParam(name = "PaymentNotice", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="PaymentReconciliation", type=IntegerType.class, min=0, max=1), @OperationParam(name = "PaymentReconciliation", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Person", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Person", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Practitioner", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Practitioner", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Procedure", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Procedure", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ProcedureRequest", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ProcedureRequest", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ProcessRequest", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ProcessRequest", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ProcessResponse", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ProcessResponse", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Provenance", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Provenance", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Questionnaire", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Questionnaire", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="QuestionnaireAnswers", type=IntegerType.class, min=0, max=1), @OperationParam(name = "QuestionnaireAnswers", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ReferralRequest", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ReferralRequest", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="RelatedPerson", type=IntegerType.class, min=0, max=1), @OperationParam(name = "RelatedPerson", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="RiskAssessment", type=IntegerType.class, min=0, max=1), @OperationParam(name = "RiskAssessment", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Schedule", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Schedule", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="SearchParameter", type=IntegerType.class, min=0, max=1), @OperationParam(name = "SearchParameter", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Slot", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Slot", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Specimen", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Specimen", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="StructureDefinition", type=IntegerType.class, min=0, max=1), @OperationParam(name = "StructureDefinition", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Subscription", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Subscription", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Substance", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Substance", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="Supply", type=IntegerType.class, min=0, max=1), @OperationParam(name = "Supply", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="ValueSet", type=IntegerType.class, min=0, max=1), @OperationParam(name = "ValueSet", type = IntegerType.class, min = 0, max = 1),
@OperationParam(name="VisionPrescription", type=IntegerType.class, min=0, max=1) @OperationParam(name = "VisionPrescription", type = IntegerType.class, min = 0, max = 1)
}) })
@Description(shortDefinition="Provides the number of resources currently stored on the server, broken down by resource type") @Description(shortDefinition = "Provides the number of resources currently stored on the server, broken down by resource type")
//@formatter:on //@formatter:on
public Parameters getResourceCounts() { public Parameters getResourceCounts() {
Parameters retVal = new Parameters(); Parameters retVal = new Parameters();
Map<String, Long> counts = mySystemDao.getResourceCounts(); Map<String, Long> counts = mySystemDao.getResourceCounts();
counts = new TreeMap<String, Long>(counts); counts = new TreeMap<String, Long>(counts);
for (Entry<String, Long> nextEntry : counts.entrySet()) { for (Entry<String, Long> nextEntry : counts.entrySet()) {
retVal.addParameter().setName((nextEntry.getKey())).setValue(new IntegerType(nextEntry.getValue().intValue())); retVal.addParameter().setName((nextEntry.getKey())).setValue(new IntegerType(nextEntry.getValue().intValue()));
} }
return retVal; return retVal;
} }
//@formatter:off //@formatter:off
@Operation(name="$meta", idempotent=true, returnParameters= { @Operation(name = "$meta", idempotent = true, returnParameters = {
@OperationParam(name="return", type=Meta.class) @OperationParam(name = "return", type = Meta.class)
}) })
//@formatter:on //@formatter:on
public Parameters meta(RequestDetails theRequestDetails) { public Parameters meta(RequestDetails theRequestDetails) {
@ -168,14 +173,15 @@ public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus<Bundl
parameters.addParameter().setName("return").setValue(getDao().metaGetOperation(theRequestDetails)); parameters.addParameter().setName("return").setValue(getDao().metaGetOperation(theRequestDetails));
return parameters; return parameters;
} }
@Operation(name="$suggest-keywords", idempotent=true) @Operation(name = "$suggest-keywords", idempotent = true)
public Parameters suggestKeywords( public Parameters suggestKeywords(
@OperationParam(name="context", min=1, max=1) String theContext, @OperationParam(name = "context", min = 1, max = 1) String theContext,
@OperationParam(name="searchParam", min=1, max=1) String theSearchParam, @OperationParam(name = "searchParam", min = 1, max = 1) String theSearchParam,
@OperationParam(name="text", min=1, max=1) String theText @OperationParam(name = "text", min = 1, max = 1) String theText
) { ) {
JpaSystemProviderDstu3.validateFulltextSearchEnabled(mySearchDao);
if (isBlank(theContext)) { if (isBlank(theContext)) {
throw new InvalidRequestException("Parameter 'context' must be provided"); throw new InvalidRequestException("Parameter 'context' must be provided");
} }
@ -185,21 +191,21 @@ public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus<Bundl
if (isBlank(theText)) { if (isBlank(theText)) {
throw new InvalidRequestException("Parameter 'text' must be provided"); throw new InvalidRequestException("Parameter 'text' must be provided");
} }
List<Suggestion> keywords = mySearchDao.suggestKeywords(theContext, theSearchParam, theText); List<Suggestion> keywords = mySearchDao.suggestKeywords(theContext, theSearchParam, theText);
Parameters retVal = new Parameters(); Parameters retVal = new Parameters();
for (Suggestion next : keywords) { for (Suggestion next : keywords) {
//@formatter:off //@formatter:off
retVal.addParameter() retVal.addParameter()
.addPart(new ParametersParameterComponent().setName("keyword").setValue(new StringType(next.getTerm()))) .addPart(new ParametersParameterComponent().setName("keyword").setValue(new StringType(next.getTerm())))
.addPart(new ParametersParameterComponent().setName("score").setValue(new DecimalType(next.getScore()))); .addPart(new ParametersParameterComponent().setName("score").setValue(new DecimalType(next.getScore())));
//@formatter:on //@formatter:on
} }
return retVal; return retVal;
} }
@Transaction @Transaction
public Bundle transaction(RequestDetails theRequestDetails, @TransactionParam Bundle theResources) { public Bundle transaction(RequestDetails theRequestDetails, @TransactionParam Bundle theResources) {
startRequest(((ServletRequestDetails) theRequestDetails).getServletRequest()); startRequest(((ServletRequestDetails) theRequestDetails).getServletRequest());
@ -210,4 +216,10 @@ public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus<Bundl
} }
} }
public static void validateFulltextSearchEnabled(IFulltextSearchSvc theSearchDao) {
if (theSearchDao == null || theSearchDao.isDisabled()) {
throw new InvalidRequestException("Fulltext searching is disabled on this server");
}
}
} }

View File

@ -120,7 +120,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
protected Object myResourceProviders; protected Object myResourceProviders;
@Autowired @Autowired
protected ISearchCoordinatorSvc mySearchCoordinatorSvc; protected ISearchCoordinatorSvc mySearchCoordinatorSvc;
@Autowired @Autowired(required = false)
protected IFulltextSearchSvc mySearchDao; protected IFulltextSearchSvc mySearchDao;
@Autowired @Autowired
protected ISearchParamPresenceSvc mySearchParamPresenceSvc; protected ISearchParamPresenceSvc mySearchParamPresenceSvc;

View File

@ -172,7 +172,7 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
protected IResourceTagDao myResourceTagDao; protected IResourceTagDao myResourceTagDao;
@Autowired @Autowired
protected ISearchCoordinatorSvc mySearchCoordinatorSvc; protected ISearchCoordinatorSvc mySearchCoordinatorSvc;
@Autowired @Autowired(required = false)
protected IFulltextSearchSvc mySearchDao; protected IFulltextSearchSvc mySearchDao;
@Autowired @Autowired
protected ISearchDao mySearchEntityDao; protected ISearchDao mySearchEntityDao;

View File

@ -181,7 +181,7 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
protected IResourceTagDao myResourceTagDao; protected IResourceTagDao myResourceTagDao;
@Autowired @Autowired
protected ISearchCoordinatorSvc mySearchCoordinatorSvc; protected ISearchCoordinatorSvc mySearchCoordinatorSvc;
@Autowired @Autowired(required = false)
protected IFulltextSearchSvc mySearchDao; protected IFulltextSearchSvc mySearchDao;
@Autowired @Autowired
protected ISearchDao mySearchEntityDao; protected ISearchDao mySearchEntityDao;

View File

@ -1646,7 +1646,6 @@
<artifactId>maven-scm-api</artifactId> <artifactId>maven-scm-api</artifactId>
<version>1.9.5</version> <version>1.9.5</version>
</dependency> </dependency>
<!-- <dependency> <groupId>org.apache.maven.doxia</groupId> <artifactId>doxia-core</artifactId> <version>1.7</version> </dependency> -->
<dependency> <dependency>
<groupId>org.apache.maven.doxia</groupId> <groupId>org.apache.maven.doxia</groupId>
<artifactId>doxia-module-markdown</artifactId> <artifactId>doxia-module-markdown</artifactId>
@ -1686,17 +1685,11 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- <plugin> <groupId>com.github.github</groupId> <artifactId>site-maven-plugin</artifactId> <version>0.12</version> <configuration> <message>Building site for ${project.version}</message> <server>github</server>
</configuration> <executions> <execution> <goals> <goal>site</goal> </goals> <phase>site-deploy</phase> </execution> </executions> </plugin> -->
</plugins> </plugins>
</build> </build>
<reporting> <reporting>
<plugins> <plugins>
<!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-checkstyle-plugin</artifactId> <reportSets> <reportSet> <reports><report>checkstyle-aggregate</report></reports> </reportSet>
</reportSets> <configuration> <configLocation>config/sun_checks.xml</configLocation> <includes> hapi-fhir-base/src/main/java/**/*.java </includes> </configuration> </plugin> -->
<!-- <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.7.7.201606060606</version> <reportSets> <reportSet> <reports> <report>report</report> </reports> <configuration>
<dataFileIncludes>${baseDir}/hapi-fhir-base/target/jacoco.exec</dataFileIncludes> </configuration> </reportSet> </reportSets> </plugin> -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-changes-plugin</artifactId> <artifactId>maven-changes-plugin</artifactId>

View File

@ -7,6 +7,17 @@
</properties> </properties>
<body> <body>
<release version="3.1.0" date="TBD"> <release version="3.1.0" date="TBD">
<action type="fix">
The Android client module has been restored to working order, and no longer
requires a special classifier or an XML parser to be present in order to
work. This means that the hapi-fhir-android library is much less likely
to cause conflicts with other libraries imported into an Android application
via Gradle.
<![CDATA[<br/><br/>]]>
See the
<![CDATA[<a href="http://hapifhir.io/doc_android.html">HAPI FHIR Android Documentation</a>]]>
for more information.
</action>
<action type="add"> <action type="add">
A performance to the JPA server has been made which reduces the number A performance to the JPA server has been made which reduces the number
of writes to index tables when updating a resource with contents that of writes to index tables when updating a resource with contents that
@ -102,7 +113,7 @@
classes (which are Java Enums for the various FHIR codesystems). classes (which are Java Enums for the various FHIR codesystems).
These were accidentally removed in HAPI FHIR 3.0.0. Thanks to These were accidentally removed in HAPI FHIR 3.0.0. Thanks to
GitHub user @CarthageKing for reporting! GitHub user @CarthageKing for reporting!
</action> </action>
</release> </release>
<release version="3.0.0" date="2017-09-27"> <release version="3.0.0" date="2017-09-27">
<action type="add"> <action type="add">

View File

@ -1,93 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"> <document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties> <properties>
<title>Android Support</title> <title>Android Support</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author> <author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties> </properties>
<body> <body>
<section name="Android Client Development"> <section name="Android Client Development">
<p> <p>
HAPI now has a specially built binary (JAR) which can be used on Android. Android developers HAPI now has a specially built module for use on Android. Android developers
may use this JAR to take advantage of the FHIR model classes, and the FHIR client (running a FHIR server may use this JAR to take advantage of the FHIR model classes, and the FHIR client (running a FHIR server
on Android is not yet supported. Help wanted!) on Android is not yet supported. Get in touch if this is something you are interested in working on!)
</p> </p>
<p> <p>
The Android JAR ships as a "shade JAR", meaning it is a single JAR containing all of the As of HAPI FHIR 3.1.0, the <code>hapi-fhir-android</code> module has been streamlined in order
dependencies required in order to use HAPI FHIR. You should not need to include any other to reduce its footprint. Previous versions of the library included both an XML and a JSON parser
libraries. but this has been streamlined to only include JSON support in order to reduce the number of
</p> libraries required in an Android build.
<p> </p>
Note that the Android JAR is still new and hasn't received as much testing as other
parts of the library. We would greatly appreciate feedback, testing, etc. Also note that <p>
because mobile apps run on less powerful hardware compared to desktop and server applications, When using the HAPI FHIR Android client, the client will request only JSON responses
it is all the more important to keep a single instance of the <code>FhirContext</code> (via the HTTP <code>Accept</code> header) and will not be able to communicate
around for good performance, since this object is expensive to create. We are hoping to with FHIR servers that support only XML encoding (few, if any, servers actually exist
improve performance of the creation of this object in a future release. If you are an with this limitation that we are aware of).
Android developer and would like to help with this, please get in touch! </p>
</p>
<p>
<subsection name="Get the Android JAR"> The Android client also uses the <code>hapi-fhir-client-okhttp</code> module,
which is an HTTP client based on the OkHttp library. This library has proven to be
<p> more powerful and less likely to cause issues on Android than the Apache HttpClient
To add the HAPI library via Gradle, use the following implementation which is bundled by default.
dependency. Note the following things: </p>
</p>
<ul> <p>
<li>The classifier should be set to the version of FHIR you want to support.</li> Note that the Android JAR is still new and hasn't received as much testing as other
<li> parts of the library. We would greatly appreciate feedback, testing, etc. Also note that
You need to excluded a few things in order to get this to work. This is because mobile apps run on less powerful hardware compared to desktop and server applications,
a quirk because the way HAPI is built and will hopefully be resolved in a future it is all the more important to keep a single instance of the <code>FhirContext</code>
release. around for good performance, since this object is expensive to create. We are hoping to
</li> improve performance of the creation of this object in a future release. If you are an
</ul> Android developer and would like to help with this, please get in touch!
<source><![CDATA[dependencies { </p>
compile "ca.uhn.hapi.fhir:hapi-fhir-android:2.2:dstu2@jar"
}]]></source> <subsection name="Get the Android JAR">
<p> <p>
You may also download a copy from the GitHub To add the HAPI library via Gradle, you should add the
<a href="https://github.com/jamesagnew/hapi-fhir/releases">Releases</a> page. <a href="http://search.maven.org/#search%7Cga%7C1%7Chapi-fhir-android">hapi-fhir-android</a>
</p> library to your Gradle file, as well as a structures library for the appropriate
</subsection> version of FHIR that you want to support, e.g.
</section> <a href="http://search.maven.org/#search%7Cga%7C1%7Chapi-fhir-structures">hapi-fhir-structures-dstu3</a>.
</p>
<section name="Performance"> <source><![CDATA[dependencies {
<p> compile "ca.uhn.hapi.fhir:hapi-fhir-android:3.1.0-SNAPSHOT"
On mobile devices, performance problems are particularly noticeable. This compile "ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2:3.1.0-SNAPSHOT"
is made worse by the fact that some Android devices have much slower performance }]]></source>
than modern desktop computers. See the
<a href="./doc_rest_client_http_config.html#performance">Client Configuration Performance</a> <p>
page for some tips on how to improve client performance. Uou will also need to manually exclude the Woodstox StAX library from
</p> inclusion, as this library uses namespaces which are prohibited on Android. You should also
</section> exclude
</p>
<section name="Examples"> <source><![CDATA[configurations {
all*.exclude group: 'org.codehaus.woodstox'
<p> all*.exclude group: 'org.apache.httpcomponents'
The following is intended to be a selection of publicly available open source }</source>
Android applications which use HAPI FHIR and might be useful as a reference.
</p> <p>
<p> To see a sample Gradle file for a working Android project
If you know of others, please let us know! using HAPI FHIR, see the
</p> <a href="https://github.com/hapifhir/hapi-fhir-android-integration-test">Android Integration Test</a>
<ul> project.
<li> </p>
<a href="https://github.com/hapifhir/hapi-fhir-android-integration-test">https://github.com/hapifhir/hapi-fhir-android-integration-test</a> </subsection>
- hapi-fhir-android Integration Test and Reference Application is our test platform for validating new releases. Created by Thomas Andersen. </section>
</li>
<li> <section name="Performance">
<a href="https://github.com/SynappzMA/FHIR-Android">https://github.com/SynappzMA/FHIR-Android</a> <p>
- Nice FHIR DSTU2 search app On mobile devices, performance problems are particularly noticeable. This
</li> is made worse by the fact that some economy Android devices have much slower performance
</ul> than modern desktop computers. See the
<a href="./doc_rest_client_http_config.html#performance">Client Configuration Performance</a>
</section> page for some tips on how to improve client performance.
</p>
</body> </section>
</document> <section name="Examples">
<p>
The following is intended to be a selection of publicly available open source
Android applications which use HAPI FHIR and might be useful as a reference.
</p>
<p>
If you know of others, please let us know!
</p>
<ul>
<li>
<a href="https://github.com/hapifhir/hapi-fhir-android-integration-test">https://github.com/hapifhir/hapi-fhir-android-integration-test</a>
- hapi-fhir-android Integration Test and Reference Application is our test platform for validating new releases. Created by Thomas Andersen.
</li>
<li>
<a href="https://github.com/SynappzMA/FHIR-Android">https://github.com/SynappzMA/FHIR-Android</a>
- Nice FHIR DSTU2 search app
</li>
</ul>
</section>
</body>
</document>