/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.coala.service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.activation.DataHandler;
import org.openehealth.coala.builder.DocumentEntryBuilder;
import org.openehealth.coala.communication.PdqMessageBuilder;
import org.openehealth.coala.converter.ConsentConverter;
import org.openehealth.coala.converter.PdqHL7Converter;
import org.openehealth.coala.converter.PdqHL7ConverterImpl;
import org.openehealth.coala.domain.CoalaAuthor;
import org.openehealth.coala.domain.ConsentSortParameter;
import org.openehealth.coala.domain.FindPatientConsentResult;
import org.openehealth.coala.domain.FindPatientQuery;
import org.openehealth.coala.domain.FindPatientResult;
import org.openehealth.coala.domain.Patient;
import org.openehealth.coala.domain.PatientConsent;
import org.openehealth.coala.domain.PatientConsentPolicy;
import org.openehealth.coala.domain.PatientSortParameter;
import org.openehealth.coala.exception.PDQRequestFailedException;
import org.openehealth.coala.exception.ServiceParameterException;
import org.openehealth.coala.exception.XDSRequestFailedException;
import org.openehealth.coala.interfacing.CDATransformationService;
import org.openehealth.coala.interfacing.ConsentCreationService;
import org.openehealth.coala.interfacing.PatientService;
import org.openehealth.coala.pdq.PDQGate;
import org.openehealth.coala.util.CdaDataSourceImpl;
import org.openehealth.coala.xds.XDSGate;
import org.openehealth.ipf.commons.ihe.xds.core.metadata.AvailabilityStatus;
import org.openehealth.ipf.commons.ihe.xds.core.metadata.Document;
import org.openehealth.ipf.commons.ihe.xds.core.metadata.DocumentEntry;
import org.openehealth.ipf.commons.ihe.xds.core.responses.RetrievedDocument;
import org.slf4j.Logger;
/**
* Provides an implementation for CoALA's communication layer to work with ICW
* AG's PXS communication server.
*
* @author kmaerz, mwiesner
*
* @FIXME This class apparently does more than one thing. Its responsibility is not clearly defined.
* Code smell! A refactoring is needed here.
*/
public class PXSQueryServiceImpl implements PatientService, ConsentCreationService {
private static final Logger LOG = org.slf4j.LoggerFactory
.getLogger(PXSQueryServiceImpl.class);
/*
* Provides links into the IPF layer
*/
private PDQGate pdqGate;
private XDSGate xdsGate;
private List<AvailabilityStatus> stati;
private PdqHL7Converter pdqConverter;
private CDATransformationService cdaTransformationService;
private ConsentConverter consentConverter;
private DocumentEntryBuilder documentEntryBuilder;
private PdqMessageBuilder pdqMessageBuilder;
public void setPdqMessageBuilder(PdqMessageBuilder pdqMessageBuilder) {
this.pdqMessageBuilder = pdqMessageBuilder;
}
public void setDocumentEntryBuilder(DocumentEntryBuilder documentEntryBuilder) {
this.documentEntryBuilder = documentEntryBuilder;
}
public void setConsentConverter(ConsentConverter consentConverter) {
this.consentConverter = consentConverter;
}
public void setPdqConverter(PdqHL7Converter pdqConverter) {
this.pdqConverter = pdqConverter;
}
/*
* This default constructor is needed for Spring bean instantiation don't
* remove me!
*/
public PXSQueryServiceImpl() {
stati = new ArrayList<AvailabilityStatus>();
stati.add(AvailabilityStatus.APPROVED);
stati.add(AvailabilityStatus.SUBMITTED);
stati.add(AvailabilityStatus.DEPRECATED);
pdqConverter = new PdqHL7ConverterImpl();
}
/*
* (non-Javadoc)
*
* @see
* org.openehealth.coala.interfacing.QueryInterface#findPatients(org.openehealth.coala
* .domain.FindPatientQuery, org.openehealth.coala.domain.PatientSortParameter)
*/
@Override
public FindPatientResult findPatients(FindPatientQuery query,
PatientSortParameter sortBy) throws PDQRequestFailedException {
if (query == null)
throw new ServiceParameterException(
"Tried to call findPatients, but did not provide an argument (query is null).");
// Transform Query to String request to package for PDQ Layer
String request = pdqMessageBuilder.buildPdqRequest(
query.getPatientID(), query.getGivenName(),
query.getLastName(), query.getBirthdate());
String hl7response = pdqGate.requestPatients(request);
FindPatientResult result = new FindPatientResult(query, sortBy);
result.addAll(pdqConverter.convertPdqToPatients(hl7response));
result.lock();
return result;
}
/*
* (non-Javadoc)
*
* @see
* org.openehealth.coala.interfacing.QueryInterface#getPatientConsents(de.hhn.
* mi.coala.domain.Patient, org.openehealth.coala.domain.ConsentSortParameter)
*/
@Override
public FindPatientConsentResult getPatientConsents(Patient patient,
ConsentSortParameter sortBy) throws XDSRequestFailedException {
if (patient == null)
throw new IllegalArgumentException("patient cannot be null.");
// The code here may not be intuitively understandable due to it being
// an interwoven sets of ITI 18 and 43 requests. First, a metadata set
// of all consents is retrieved for a given patient using ITI-18. After
// that, for each metadata set,we retrieve the actual document, and pass
// it to the converter, which converts it to a PatientConsent of our
// Coala-Domain.
// Sorting happens automagically in the FindPatientConsentResult object.
// 1) get List of documents
List<DocumentEntry> metadataList = xdsGate.requestConsents(
patient.getPatientID(), stati, sortBy);
FindPatientConsentResult result = new FindPatientConsentResult(patient,
sortBy);
// 2) For each metadataSet, query appropriate Document
for (DocumentEntry entry : metadataList) {
List<RetrievedDocument> consentList = xdsGate
.retrieveDocumentSet(entry);
LOG.debug(consentList.get(0).getRequestData().toString());
// Check if there is only exactly one object in the list.
if (consentList.size() != 1)
throw new RuntimeException(
"Fatal Error during conversion of consent: Assuming a retrieved document list of size 1, but list was of size "
+ consentList.size());
// 3) convert data to PatientConsents
PatientConsent consent = consentConverter.transformToCoalaConsent(
entry, consentList.get(0), patient);
result.addPatientConsent(consent);
}
result.lock();
return result;
}
//TODO Javadoc @see...
@Override
public void createPatientConsent(Patient patient, Date validFrom,
Date validUntil, PatientConsentPolicy policy, CoalaAuthor author)
throws XDSRequestFailedException {
//forward, indicate that no other consents be overwritten
this.createConsent(patient, validFrom, validUntil, policy, author, false);
}
//TODO Javadoc @see...
@Override
public void replacePatientConsent(Patient patient, Date validFrom,
Date validUntil, PatientConsentPolicy policy, CoalaAuthor author,
PatientConsent oldConsent) throws XDSRequestFailedException {
throw new UnsupportedOperationException(
"This call is not yet supported. Lazy Programmers, get to work!");
}
//TODO Javadoc @see...
@Override
public void replaceAllPatientConsents(Patient patient, Date validFrom,
Date validUntil, PatientConsentPolicy policy, CoalaAuthor author)
throws XDSRequestFailedException {
//forward, indicate that all other consents be overwritten
this.createConsent(patient, validFrom, validUntil, policy, author, true);
}
/**
* Basic Method to create a consent
* @param patient Patient for consent
* @param validFrom validity duration start
* @param validUntil validity duration end
* @param policy the type of policy for this consent
* @param author the author of this consent
* @param replaceAllOther whether other consents should be replaced or not
* @throws XDSRequestFailedException if something goes wrong
*/
private void createConsent(Patient patient, Date validFrom,
Date validUntil, PatientConsentPolicy policy, CoalaAuthor author, boolean replaceAllOther)
throws XDSRequestFailedException {
// Basic checks
if (patient == null)
throw new IllegalArgumentException("Patient cannot be null.");
if (validFrom == null)
throw new IllegalArgumentException("startDate cannot be null.");
if (validUntil == null)
throw new IllegalArgumentException("endDate cannot be null.");
if (policy == null)
throw new IllegalArgumentException("policy cannot be null.");
// Create metadata
DocumentEntry entry = documentEntryBuilder.createDocumentEntry(author, patient, policy, validFrom, validUntil);
//Create a cda
String cda = cdaTransformationService.transformToValidPatientConsent(patient, policy, author, entry);
// Create a DataHandler for the document
DataHandler handler = new DataHandler(new CdaDataSourceImpl(
cda));
// Register the Consent
xdsGate.registerNewConsent(new Document(entry, handler), replaceAllOther);
}
public void setPdqGate(PDQGate pdqGate) {
this.pdqGate = pdqGate;
}
public void setXdsGate(XDSGate xdsGate) {
this.xdsGate = xdsGate;
}
public void setCdaService(CDATransformationService cdaService) {
this.cdaTransformationService = cdaService;
}
}