-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#369: additions for ITI-65 and 66 for MHD 4.2.1
- Loading branch information
Christian Ohr
committed
Dec 13, 2023
1 parent
0ccc6bc
commit 2a6f06d
Showing
61 changed files
with
64,414 additions
and
0 deletions.
There are no files selected for viewing
117 changes: 117 additions & 0 deletions
117
...d/src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti66/Iti66ListResourceProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* | ||
* Copyright 2023 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.openehealth.ipf.commons.ihe.fhir.iti66; | ||
|
||
import ca.uhn.fhir.model.api.Include; | ||
import ca.uhn.fhir.rest.annotation.*; | ||
import ca.uhn.fhir.rest.api.SortSpec; | ||
import ca.uhn.fhir.rest.api.server.IBundleProvider; | ||
import ca.uhn.fhir.rest.api.server.RequestDetails; | ||
import ca.uhn.fhir.rest.param.*; | ||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; | ||
import org.hl7.fhir.instance.model.api.IAnyResource; | ||
import org.hl7.fhir.r4.model.*; | ||
import org.openehealth.ipf.commons.ihe.fhir.AbstractPlainProvider; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.util.Set; | ||
|
||
/** | ||
* Resource Provider for MHD (ITI-66 List) | ||
* | ||
* @author Christian Ohr | ||
* @since 4.8 | ||
*/ | ||
public class Iti66ListResourceProvider extends Iti66ResourceProvider { | ||
|
||
// Supported as of MHD 4.2.1 | ||
|
||
private static final String SP_DESIGNATION_TYPE = "designationType"; | ||
private static final String SP_SOURCE_ID = "sourceId"; | ||
|
||
@SuppressWarnings("unused") | ||
@Search(type = ListResource.class) | ||
public IBundleProvider listSearch( | ||
@RequiredParam(name = ListResource.SP_PATIENT, chainWhitelist = {"", Patient.SP_IDENTIFIER}) ReferenceParam patient, | ||
@OptionalParam(name = ListResource.SP_DATE) DateRangeParam date, | ||
@OptionalParam(name = ListResource.SP_SOURCE, chainWhitelist = { Practitioner.SP_FAMILY, Practitioner.SP_GIVEN }) ReferenceAndListParam author, | ||
@OptionalParam(name = ListResource.SP_IDENTIFIER) TokenParam identifier, | ||
@OptionalParam(name = ListResource.SP_CODE) TokenOrListParam code, | ||
@OptionalParam(name = ListResource.SP_STATUS) TokenOrListParam status, | ||
@OptionalParam(name = SP_SOURCE_ID) TokenOrListParam sourceId, | ||
@OptionalParam(name = SP_DESIGNATION_TYPE) TokenOrListParam designationType, | ||
// Extension to ITI-66 | ||
@OptionalParam(name = IAnyResource.SP_RES_ID) TokenParam resourceId, | ||
@Sort SortSpec sortSpec, | ||
@IncludeParam Set<Include> includeSpec, | ||
RequestDetails requestDetails, | ||
HttpServletRequest httpServletRequest, | ||
HttpServletResponse httpServletResponse) { | ||
|
||
|
||
var searchParameters = Iti66ListSearchParameters.builder() | ||
.date(date) | ||
.code(code) | ||
.designationType(designationType) | ||
.sourceId(sourceId) | ||
.status(status) | ||
.identifier(identifier) | ||
._id(resourceId) | ||
.sortSpec(sortSpec) | ||
.includeSpec(includeSpec) | ||
.fhirContext(getFhirContext()) | ||
.build(); | ||
|
||
searchParameters.setAuthor(author); | ||
|
||
var chain = patient.getChain(); | ||
if (Patient.SP_IDENTIFIER.equals(chain)) { | ||
searchParameters.setPatientIdentifier(patient.toTokenParam(getFhirContext())); | ||
} else if (chain == null || chain.isEmpty()) { | ||
searchParameters.setPatientReference(patient); | ||
} | ||
|
||
// Run down the route | ||
return requestBundleProvider(null, searchParameters, ResourceType.List.name(), | ||
httpServletRequest, httpServletResponse, requestDetails); | ||
} | ||
|
||
/** | ||
* Handles List Retrieve. This is not an actual part of the ITI-66 specification, but in the | ||
* context of restful FHIR IHE transaction it makes sense to be able to retrieve a ListResource by | ||
* its resource ID. | ||
* | ||
* @param id resource ID | ||
* @param httpServletRequest servlet request | ||
* @param httpServletResponse servlet response | ||
* @param requestDetails request details | ||
* @return {@link ListResource} resource | ||
*/ | ||
@SuppressWarnings("unused") | ||
@Read(version = true, type = ListResource.class) | ||
public ListResource listRetrieve( | ||
@IdParam IdType id, | ||
RequestDetails requestDetails, | ||
HttpServletRequest httpServletRequest, | ||
HttpServletResponse httpServletResponse) { | ||
if (id == null) throw new InvalidRequestException("Must provide ID with READ request"); | ||
// Run down the route | ||
return requestResource(id, null, ListResource.class, httpServletRequest, httpServletResponse, requestDetails); | ||
} | ||
|
||
} |
114 changes: 114 additions & 0 deletions
114
...d/src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti66/Iti66ListSearchParameters.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Copyright 2016 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.openehealth.ipf.commons.ihe.fhir.iti66; | ||
|
||
import ca.uhn.fhir.context.FhirContext; | ||
import ca.uhn.fhir.model.api.Include; | ||
import ca.uhn.fhir.rest.api.SortSpec; | ||
import ca.uhn.fhir.rest.param.*; | ||
import lombok.*; | ||
import org.hl7.fhir.r4.model.DocumentManifest; | ||
import org.hl7.fhir.r4.model.Practitioner; | ||
import org.hl7.fhir.r4.model.PractitionerRole; | ||
import org.openehealth.ipf.commons.ihe.fhir.FhirSearchAndSortParameters; | ||
|
||
import java.util.*; | ||
|
||
import static java.util.Comparator.comparing; | ||
import static java.util.Comparator.nullsLast; | ||
|
||
/** | ||
* @since 3.6 | ||
*/ | ||
@Builder | ||
@ToString | ||
@AllArgsConstructor | ||
public class Iti66ListSearchParameters extends FhirSearchAndSortParameters<DocumentManifest> { | ||
|
||
@Getter @Setter private DateRangeParam date; | ||
@Getter @Setter private StringParam authorFamilyName; | ||
@Getter @Setter private StringParam authorGivenName; | ||
@Getter @Setter private TokenOrListParam code; | ||
@Getter @Setter private TokenOrListParam designationType; | ||
@Getter @Setter private TokenOrListParam sourceId; | ||
@Getter @Setter private TokenOrListParam status; | ||
@Getter @Setter private TokenParam identifier; | ||
@Getter @Setter private ReferenceParam patientReference; | ||
@Getter @Setter private TokenParam patientIdentifier; | ||
@Getter @Setter private TokenParam _id; | ||
|
||
@Getter @Setter private SortSpec sortSpec; | ||
@Getter @Setter private Set<Include> includeSpec; | ||
|
||
@Getter | ||
private final FhirContext fhirContext; | ||
|
||
@Override | ||
public List<TokenParam> getPatientIdParam() { | ||
if (_id != null) | ||
return Collections.singletonList(_id); | ||
if (patientReference != null) | ||
return Collections.singletonList(patientReference.toTokenParam(fhirContext)); | ||
|
||
return Collections.singletonList(patientIdentifier); | ||
} | ||
|
||
public Iti66ListSearchParameters setAuthor(ReferenceAndListParam author) { | ||
if (author != null) { | ||
author.getValuesAsQueryTokens().forEach(param -> { | ||
var ref = param.getValuesAsQueryTokens().get(0); | ||
var authorChain = ref.getChain(); | ||
if (Practitioner.SP_FAMILY.equals(authorChain)) { | ||
setAuthorFamilyName(ref.toStringParam(getFhirContext())); | ||
} else if (Practitioner.SP_GIVEN.equals(authorChain)) { | ||
setAuthorGivenName(ref.toStringParam(getFhirContext())); | ||
} | ||
}); | ||
} | ||
return this; | ||
} | ||
|
||
@Override | ||
public Optional<Comparator<DocumentManifest>> comparatorFor(String paramName) { | ||
if (DocumentManifest.SP_CREATED.equals(paramName)) { | ||
return Optional.of(CP_CREATED); | ||
} else if (DocumentManifest.SP_AUTHOR.equals(paramName)) { | ||
return Optional.of(CP_AUTHOR); | ||
} | ||
return Optional.empty(); | ||
} | ||
|
||
private static final Comparator<DocumentManifest> CP_CREATED = nullsLast(comparing(DocumentManifest::getCreated)); | ||
|
||
private static final Comparator<DocumentManifest> CP_AUTHOR = nullsLast(comparing(documentManifest -> { | ||
if (!documentManifest.hasAuthor()) return null; | ||
var author = documentManifest.getAuthorFirstRep(); | ||
if (author.getResource() instanceof PractitionerRole) { | ||
var practitionerRole = (PractitionerRole) author.getResource(); | ||
if (!practitionerRole.hasPractitioner()) return null; | ||
author = practitionerRole.getPractitioner(); | ||
} | ||
if (author.getResource() == null) return null; | ||
if (author.getResource() instanceof Practitioner) { | ||
var practitioner = (Practitioner) author.getResource(); | ||
if (!practitioner.hasName()) return null; | ||
var name = practitioner.getNameFirstRep(); | ||
return name.getFamilyElement().getValueNotNull() + name.getGivenAsSingleString(); | ||
} | ||
return null; | ||
})); | ||
} |
51 changes: 51 additions & 0 deletions
51
.../ihe/fhir/r4/mhd/src/main/java/org/openehealth/ipf/commons/ihe/fhir/mhd/MhdConstants.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright 2023 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.openehealth.ipf.commons.ihe.fhir.mhd; | ||
|
||
import org.hl7.fhir.r4.model.Coding; | ||
|
||
interface MhdConstants { | ||
|
||
// Bundle Profiles V4 | ||
|
||
String ITI65_MINIMAL_BUNDLE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Minimal.ProvideBundle"; | ||
String ITI65_COMPREHENSIVE_BUNDLE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Comprehensive.ProvideBundle"; | ||
String ITI65_UNCONTAINED_COMPREHENSIVE_BUNDLE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.UnContained.Comprehensive.ProvideBundle"; | ||
String ITI65_PROVIDE_DOCUMENT_BUNDLE_RESPONSE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.ProvideDocumentBundleResponse"; | ||
String ITI66_FIND_DOCUMENT_LISTS_RESPONSE_BUNDLE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.FindDocumentListsResponseMessage"; | ||
String ITI67_FIND_DOCUMENT_REFERENCES_RESPONSE_BUNDLE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.FindDocumentReferencesResponseMessage"; | ||
String ITI67_FIND_DOCUMENT_REFERENCES_COMPREHENSIVE_RESPONSE_BUNDLE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.FindDocumentReferencesComprehensiveResponseMessage"; | ||
|
||
// DocumentManifest/List profiles | ||
|
||
String MHD_LIST_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.List"; | ||
String COMPREHENSIVE_SUBMISSIONSET_TYPE_LIST_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Comprehensive.SubmissionSet"; | ||
String UNCONTAINED_COMPREHENSIVE_SUBMISSIONSET_TYPE_LIST_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.UnContained.Comprehensive.SubmissionSet"; | ||
String MINIMAL_SUBMISSIONSET_TYPE_LIST_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Minimal.SubmissionSet"; | ||
|
||
// List Profile | ||
|
||
String MINIMAL_FOLDER_TYPE_LIST_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Minimal.Folder"; | ||
String COMPREHENSIVE_FOLDER_TYPE_LIST_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Comprehensive.Folder"; | ||
|
||
// DocumentReference profiles | ||
|
||
String COMPREHENSIVE_DOCUMENT_REFERENCE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Comprehensive.DocumentReference"; | ||
String UNCONTAINED_COMPREHENSIVE_DOCUMENT_REFERENCE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.UnContained.Comprehensive.DocumentReference"; | ||
String MINIMAL_DOCUMENT_REFERENCE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Minimal.DocumentReference"; | ||
String SIMPLIFIED_PUBLISH_DOCUMENT_REFERENCE_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.SimplifiedPublish.DocumentReference"; | ||
|
||
} |
98 changes: 98 additions & 0 deletions
98
...s/ihe/fhir/r4/mhd/src/main/java/org/openehealth/ipf/commons/ihe/fhir/mhd/MhdProfiles.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
* Copyright 2023 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.openehealth.ipf.commons.ihe.fhir.mhd; | ||
|
||
import ca.uhn.fhir.context.FhirContext; | ||
import lombok.Getter; | ||
import org.hl7.fhir.instance.model.api.IBaseResource; | ||
import org.hl7.fhir.r4.model.CanonicalType; | ||
import org.hl7.fhir.r4.model.Resource; | ||
import org.openehealth.ipf.commons.ihe.fhir.mhd.model.*; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
@Getter | ||
public enum MhdProfiles implements MhdConstants { | ||
|
||
|
||
// Bundle Profiles V4 | ||
|
||
ITI65_MINIMAL_BUNDLE( | ||
ITI65_MINIMAL_BUNDLE_PROFILE, MinimalProvideDocumentBundle.class), | ||
ITI65_COMPREHENSIVE_BUNDLE( | ||
ITI65_COMPREHENSIVE_BUNDLE_PROFILE, ComprehensiveProvideDocumentBundle.class), | ||
ITI65_UNCONTAINED_COMPREHENSIVE_BUNDLE( | ||
ITI65_UNCONTAINED_COMPREHENSIVE_BUNDLE_PROFILE, UncontainedComprehensiveProvideDocumentBundle.class), | ||
ITI65_PROVIDE_DOCUMENT_BUNDLE_RESPONSE( | ||
ITI65_PROVIDE_DOCUMENT_BUNDLE_RESPONSE_PROFILE, ProvideDocumentBundleResponse.class), | ||
ITI66_FIND_DOCUMENT_LISTS_RESPONSE_BUNDLE( | ||
ITI66_FIND_DOCUMENT_LISTS_RESPONSE_BUNDLE_PROFILE, FindDocumentListsResponseBundle.class), | ||
ITI67_FIND_DOCUMENT_REFERENCES_RESPONSE_BUNDLE( | ||
ITI67_FIND_DOCUMENT_REFERENCES_RESPONSE_BUNDLE_PROFILE, FindMinimalDocumentReferencesResponseBundle.class), | ||
ITI67_FIND_DOCUMENT_REFERENCES_COMPREHENSIVE_RESPONSE_BUNDLE( | ||
ITI67_FIND_DOCUMENT_REFERENCES_COMPREHENSIVE_RESPONSE_BUNDLE_PROFILE, FindComprehensiveDocumentReferencesResponseBundle.class), | ||
|
||
// List profiles | ||
|
||
MHD_LIST(MHD_LIST_PROFILE, MhdList.class), | ||
COMPREHENSIVE_SUBMISSIONSET_TYPE_LIST(COMPREHENSIVE_SUBMISSIONSET_TYPE_LIST_PROFILE, ComprehensiveSubmissionSetList.class), | ||
UNCONTAINED_COMPREHENSIVE_SUBMISSIONSET_TYPE_LIST(UNCONTAINED_COMPREHENSIVE_SUBMISSIONSET_TYPE_LIST_PROFILE, UncontainedComprehensiveProvideDocumentBundle.class), | ||
MINIMAL_SUBMISSIONSET_TYPE_LIST(MINIMAL_SUBMISSIONSET_TYPE_LIST_PROFILE, MinimalSubmissionSetList.class), | ||
|
||
// List Profile | ||
|
||
MINIMAL_FOLDER_TYPE_LIST(MINIMAL_FOLDER_TYPE_LIST_PROFILE, MinimalFolderList.class), | ||
COMPREHENSIVE_FOLDER_TYPE_LIST(COMPREHENSIVE_FOLDER_TYPE_LIST_PROFILE, ComprehensiveFolderList.class), | ||
|
||
// DocumentReference profiles | ||
|
||
COMPREHENSIVE_DOCUMENT_REFERENCE(COMPREHENSIVE_DOCUMENT_REFERENCE_PROFILE, ComprehensiveDocumentReference.class), | ||
UNCONTAINED_COMPREHENSIVE_DOCUMENT_REFERENCE(UNCONTAINED_COMPREHENSIVE_DOCUMENT_REFERENCE_PROFILE, UncontainedComprehensiveDocumentReference.class), | ||
MINIMAL_DOCUMENT_REFERENCE(MINIMAL_DOCUMENT_REFERENCE_PROFILE, MinimalDocumentReference.class), | ||
SIMPLIFIED_PUBLISH_DOCUMENT_REFERENCE(SIMPLIFIED_PUBLISH_DOCUMENT_REFERENCE_PROFILE, SimplifiedPublishDocumentReference.class); | ||
|
||
|
||
private final String url; | ||
|
||
private final Class<? extends IBaseResource> resourceClass; | ||
|
||
|
||
MhdProfiles(String url, Class<? extends IBaseResource> resourceClass) { | ||
this.url = url; | ||
this.resourceClass = resourceClass; | ||
} | ||
|
||
/** | ||
* Set the Meta/Profile of the resource | ||
* | ||
* @param resource FHIR resource | ||
*/ | ||
public void setProfile(Resource resource) { | ||
resource.getMeta().setProfile(List.of(new CanonicalType(url))); | ||
} | ||
|
||
/** | ||
* Registers all the profiles and implementing classes in the {@link FhirContext} | ||
* | ||
* @param fhirContext FhirContext | ||
*/ | ||
public static void registerDefaultTypes(FhirContext fhirContext) { | ||
Arrays.stream(MhdProfiles.values()).forEach(profile -> | ||
fhirContext.setDefaultTypeForProfile(profile.getUrl(), profile.resourceClass)); | ||
} | ||
|
||
} |
Oops, something went wrong.