org.openehealth.coala.beans.ConsentBean.java Source code

Java tutorial

Introduction

Here is the source code for org.openehealth.coala.beans.ConsentBean.java

Source

/*
 * 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.beans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UIOutput;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.persistence.Transient;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.richfaces.component.UIExtendedDataTable;
import org.richfaces.component.UIPopupPanel;
import org.richfaces.component.UIRegion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import org.openehealth.coala.domain.CoalaAuthor;
import org.openehealth.coala.domain.ConsentSortParameter;
import org.openehealth.coala.domain.FindPatientConsentResult;
import org.openehealth.coala.domain.Patient;
import org.openehealth.coala.domain.PatientConsent;
import org.openehealth.coala.domain.PatientConsentPolicy;
import org.openehealth.coala.exception.CdaXmlTransformerException;
import org.openehealth.coala.interfacing.CDATransformationService;
import org.openehealth.coala.interfacing.ConsentCreationService;

/**
 * Represents a patients privacy consent. It will be used if a new consent is
 * created, or an existing gets deleted.
 * 
 * @author astiefer, mkuballa
 */
@Component
@Scope("session")
public class ConsentBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Log LOG = LogFactory.getLog(ConsentBean.class);

    private PatientConsentPolicy policy = PatientConsentPolicy.ONE; // default value
    private Date validFrom;
    private Date validUntil;
    private CoalaAuthor author;
    @Transient
    private DataModel<PatientConsent> consents = new ListDataModel<PatientConsent>();
    private List<PatientConsent> consentList;

    private Collection<Object> selectionConsent;
    private PatientConsent selectedConsent;

    private Patient selectedPatient;
    private String patientString = "";
    // SORTING
    private ConsentSortParameter sortParameter = ConsentSortParameter.CREATION_DATE_NEWEST_FIRST;

    // SELECTING POLICIES VIA SELECT-MENU.
    private static Map<String, PatientConsentPolicy> selectablePolicies;
    private String selectedPolicy = policy.getShortName();

    private boolean successfulRegistration;
    private boolean errorfulRegistration;
    private boolean validationSuccessful;

    /*
     * Handle on the coala-communication layer
     */
    @Transient
    @Autowired
    private ConsentCreationService consentCreationService;

    /*
     * Handle on the CDA/Consent service layer
     */
    @Transient
    @Autowired
    private CDATransformationService cdaService;

    /*
     * Managed bean injection to get current locale which is needed for I18n
     * e.g. error messages/warnings.
     */
    @Transient
    @Autowired
    private LocaleHandler localeHandler;

    /**
     * @return the ConsentCreationService
     */
    public ConsentCreationService getConsentCreationService() {
        return consentCreationService;
    }

    /**
     * @param sets the ConsentCreationService
     */
    public void setConsentCreationService(ConsentCreationService consentCreationService) {
        this.consentCreationService = consentCreationService;
        LOG.info("ConsentCreationService configured and ready... [OK]");
    }

    /**
     * @return the policy
     */
    public PatientConsentPolicy getPolicy() {
        return policy;
    }

    /**
     * @param policy the policy to set
     */
    public void setPolicy(PatientConsentPolicy policy) {
        this.policy = policy;
    }

    /**
     * @return the validFrom
     */
    public Date getValidFrom() {
        return validFrom;
    }

    /**
     * @param validFrom the validFrom to set
     */
    public void setValidFrom(Date validFrom) {
        /*
         *  HACK HERE! we get invalid Date object from RichFaces Calendar component which is exactly 1 Day in the past! so we fix it to have the proper date instance that is shown/selected by the user!
         */
        if (validFrom != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTime(validFrom);
            cal.add(Calendar.DAY_OF_MONTH, 1);
            this.validFrom = cal.getTime();
        } else {
            this.validFrom = validFrom;
        }
    }

    /**
     * @return the validUntil
     */
    public Date getValidUntil() {
        return validUntil;
    }

    /**
     * @param validUntil the validUntil to set
     */
    public void setValidUntil(Date validUntil) {
        /*
         *  HACK HERE! we get invalid Date object from RichFaces Calendar component which is exactly 1 Day in the past! so we fix it to have the proper date instance that is shown/selected by the user!
         */
        if (validUntil != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTime(validUntil);
            cal.add(Calendar.DAY_OF_MONTH, 1);
            this.validUntil = cal.getTime();
        } else {
            this.validUntil = validUntil;
        }
    }

    /**
     * Selections-Listener for data table displaying {@link PatientConsent}
     * instances.
     * 
     * @param event
     *            Provided by UI context.
     */
    public void selectionListenerConsent(AjaxBehaviorEvent event) {
        FacesContext fc = FacesContext.getCurrentInstance();
        String messages = fc.getApplication().getMessageBundle();
        Locale locale = new Locale(localeHandler.getLocale());
        ResourceBundle bundle = ResourceBundle.getBundle(messages, locale);

        UIExtendedDataTable dataTable = (UIExtendedDataTable) event.getComponent();
        Object originalKey = dataTable.getRowKey();
        for (Object selectionKey : selectionConsent) {
            dataTable.setRowKey(selectionKey);
            if (dataTable.isRowAvailable()) {
                selectedConsent = (PatientConsent) dataTable.getRowData();
                LOG.info("[CONSENT SELECTED]  by " + selectedConsent.getAuthor());
                LOG.info("[CONSENT SELECTED] Patient" + selectedPatient.getLastName());

                UIRegion consentResultPanel = (UIRegion) dataTable.getParent();

                UIOutput renderedConsentText = (UIOutput) consentResultPanel.findComponent("renderedConsentText");
                String consentAsHTML = "";
                try {
                    consentAsHTML = cdaService.transformToHTML(selectedPatient, selectedConsent.getValidFrom(),
                            selectedConsent.getValidUntil(), selectedConsent.getPolicyType(),
                            selectedConsent.getAuthor());
                } catch (IllegalArgumentException e) {
                    consentAsHTML = bundle.getString("errors.htmlTransformationFailed");
                    LOG.warn(e.getMessage());
                } catch (CdaXmlTransformerException e) {
                    consentAsHTML = bundle.getString("errors.htmlTransformationFailed");
                    LOG.warn(e.getMessage());
                }
                renderedConsentText.setValue(consentAsHTML);
                UIPopupPanel consentDisplayPanel = (UIPopupPanel) consentResultPanel
                        .findComponent("consentDisplayPanel");
                LOG.info("[CONSENT SELECTED] setShow");
                consentDisplayPanel.setShow(true);
            } else {
                LOG.warn("ROW NOT AVAILABLE");
            }
        }
        dataTable.setRowKey(originalKey);
    }

    /**
     * Searches the {@link PatientConsent} of the {@link Patient} currently
     * selected in the patient data table (see
     * {@link ConsentBean#selectionListener(AjaxBehaviorEvent)}) and sets them
     * in the consent data table of the UI.
     * 
     * @return Always returns "patientSeach"
     */
    public String search() {
        consentList = null;
        consentList = new ArrayList<PatientConsent>();

        long start = System.currentTimeMillis();

        // perform query against PXS finally
        FindPatientConsentResult findPatientConsentResult = consentCreationService
                .getPatientConsents(selectedPatient, sortParameter);
        long end = System.currentTimeMillis();

        LOG.info("PXS iti-18-43 query took " + (end - start) + " ms.");

        if (findPatientConsentResult != null) {
            consentList = findPatientConsentResult.getPatientConsents();
            setConsents(new ListDataModel<PatientConsent>(consentList));

        }
        buildPatientFullName();
        return "patientSearch";
    }

    /**
     * Builds the fullname of the patient for displaying in the UI
     */
    private void buildPatientFullName() {
        setPatientString(selectedPatient.getLastName() + ", " + selectedPatient.getGivenName() + " ("
                + selectedPatient.getPatientID() + ")");
    }

    /**
     * @param consents the consents to set
     */
    public void setConsents(DataModel<PatientConsent> consents) {
        this.consents = consents;
    }

    /**
     * @return the consents
     */
    public DataModel<PatientConsent> getConsents() {
        return consents;
    }

    /**
     * @param selection sets the selectionConset
     */
    public void setConsentSelection(Collection<Object> selection) {
        this.selectionConsent = selection;
    }

    /**
     * @return the selectionConsent
     */
    public Collection<Object> getConsentSelection() {
        return selectionConsent;
    }

    /**
     * @return the sortParameter
     */
    public ConsentSortParameter getSortParameter() {
        return sortParameter;
    }

    /**
     * @param sortParameter the sortParameter to set
     */
    public void setSortParameter(ConsentSortParameter sortParameter) {
        this.sortParameter = sortParameter;
    }

    /**
     * Sorts the table of consents by start date
     */
    public void sortByStartDate() {
        if (sortParameter.equals(ConsentSortParameter.START_DATE_NEWEST_FIRST)) {
            setSortParameter(ConsentSortParameter.START_DATE_OLDEST_FIRST);
        } else {
            setSortParameter(ConsentSortParameter.START_DATE_NEWEST_FIRST);
        }
        search();
    }

    /**
     * Sorts the table of consents by end date
     */
    public void sortByEndDate() {
        if (sortParameter.equals(ConsentSortParameter.END_DATE_NEWEST_FIRST)) {
            setSortParameter(ConsentSortParameter.END_DATE_OLDEST_FIRST);
        } else {
            setSortParameter(ConsentSortParameter.END_DATE_NEWEST_FIRST);
        }
        search();
    }

    /**
     * Sorts the table of consents by policy
     */
    public void sortByPolicy() {
        if (sortParameter.equals(ConsentSortParameter.POLICY_TYPE_ASCENDING)) {
            setSortParameter(ConsentSortParameter.POLICY_TYPE_DESCENDING);
        } else {
            setSortParameter(ConsentSortParameter.POLICY_TYPE_ASCENDING);
        }
        search();
    }

    /**
     * Sorts the table of consents by creation date
     */
    public void sortByCreationDate() {
        if (sortParameter.equals(ConsentSortParameter.CREATION_DATE_NEWEST_FIRST)) {
            setSortParameter(ConsentSortParameter.CREATION_DATE_OLDEST_FIRST);
        } else {
            setSortParameter(ConsentSortParameter.CREATION_DATE_NEWEST_FIRST);
        }
        search();
    }

    /**
     * Sorts the table of consents by author
     */
    public void sortByAuthor() {
        if (sortParameter.equals(ConsentSortParameter.AUTHOR_ASCENDING)) {
            setSortParameter(ConsentSortParameter.AUTHOR_DESCENDING);
        } else {
            setSortParameter(ConsentSortParameter.AUTHOR_ASCENDING);
        }
        search();
    }

    /**
     * Sorts the table of consents by activ
     */
    public void sortByActive() {
        if (sortParameter.equals(ConsentSortParameter.EFFECTIVE_TRUE_FIRST)) {
            setSortParameter(ConsentSortParameter.EFFECTIVE_FALSE_FIRST);
        } else {
            setSortParameter(ConsentSortParameter.EFFECTIVE_TRUE_FIRST);
        }
        search();
    }

    /**
     * @param patientString the patientString to set
     */
    public void setPatientString(String patientString) {
        this.patientString = patientString;
    }

    /**
     * @return the patientString
     */
    public String getPatientString() {
        return patientString;
    }

    static {
        selectablePolicies = new LinkedHashMap<String, PatientConsentPolicy>();
        selectablePolicies.put(PatientConsentPolicy.ONE.getShortName(), PatientConsentPolicy.ONE);
        selectablePolicies.put(PatientConsentPolicy.TWO.getShortName(), PatientConsentPolicy.TWO);
        selectablePolicies.put(PatientConsentPolicy.THREE.getShortName(), PatientConsentPolicy.THREE);
        selectablePolicies.put(PatientConsentPolicy.FOUR.getShortName(), PatientConsentPolicy.FOUR);
        selectablePolicies.put(PatientConsentPolicy.FIVE.getShortName(), PatientConsentPolicy.FIVE);
    }

    /**
     * Method gets called when the user selects a policy via the select-menu. It
     * is needed to view the current policy in the draft view.
     * 
     * @param e
     */
    public void policyChanged(ValueChangeEvent e) {
        // assign new policy
        policy = getPolicyByNr(e.getNewValue().toString());
        selectedPolicy = policy.getShortName();
    }

    /**
     * @return the selectablePolicies
     */
    public Map<String, PatientConsentPolicy> getSelectablePolicyInMap() {
        return ConsentBean.selectablePolicies;
    }

    /**
     * @return the selectedPolicy
     */
    public String getSelectablePolicy() {
        return selectedPolicy;
    }

    /**
     * @param policy the policy to set
     */
    public void setSelectablePolicy(String policy) {
        selectedPolicy = getPolicyByNr(policy).getShortName();
    }

    /**
     * Cleans the outdated view state
     */
    public void cleanOutdatedViewState() {
        this.selectionConsent = new ArrayList<Object>();
        this.selectedConsent = null;
        this.selectedPatient = null;
    }

    /**
     * Cleans the ConsentBean for a new PatientSearch
     */
    public void cleanForNewPatientSearch() {
        this.consentList = new ArrayList<PatientConsent>();
        this.consents = new ListDataModel<PatientConsent>();
        this.patientString = "";
        this.selectedConsent = null;
        this.selectionConsent = new ArrayList<Object>();

    }

    /**
     * Cleans the current selection
     * @param event 
     */
    public void cleanCurrentSelection(AjaxBehaviorEvent event) {
        this.selectionConsent = new ArrayList<Object>();
        this.selectedConsent = null;
        LOG.info("[BAEBAEMMMM!]: " + event.getComponent().getClientId());
    }

    /**
     * @param selectedPatient the selectedPatient to set
     */
    public void setSelectedPatient(Patient selectedPatient) {
        this.selectedPatient = selectedPatient;
    }

    /**
     * Method to validate input parameters (validFrom and validUntil) of consent
     * creation. This is needed to have proper error notification on missing
     * date input at consent creation view.
     * 
     * @param event
     */
    public void validateCreateConsentParameters(ComponentSystemEvent event) {
        FacesContext fc = FacesContext.getCurrentInstance();
        String messages = fc.getApplication().getMessageBundle();
        Locale locale = new Locale(localeHandler.getLocale());
        ResourceBundle bundle = ResourceBundle.getBundle(messages, locale);

        UIComponent components = event.getComponent();

        UIInput validFromDateInput = (UIInput) components.findComponent("validFromInput");
        UIInput validUntilDateInput = (UIInput) components.findComponent("validUntilInput");

        boolean validFromDateEmpty = false;
        boolean validUntilDateEmpty = false;

        if (validFromDateInput.getLocalValue() == null
                || validFromDateInput.getLocalValue().toString().trim().isEmpty()) {
            validFromDateEmpty = true;
        }
        if (validUntilDateInput.getLocalValue() == null
                || validUntilDateInput.getLocalValue().toString().trim().isEmpty()) {
            validUntilDateEmpty = true;
        }

        if (validFromDateEmpty || validUntilDateEmpty) {
            validationSuccessful = false;
            FacesMessage msg = new FacesMessage(bundle.getString("errors.nonEmptyValidationDates"), "");
            msg.setSeverity(FacesMessage.SEVERITY_WARN);
            fc.addMessage(components.getClientId(), msg);
            // passed to the Render Response phase
            fc.renderResponse();
        }

        //validates if validFrom is after or equals validUntil
        Date from = (Date) validFromDateInput.getValue();
        Date until = (Date) validUntilDateInput.getValue();
        if (from == null || until == null) {
            validationSuccessful = false;
            FacesMessage msg = new FacesMessage("Please provide valid date input values for From AND Until.", "");
            msg.setSeverity(FacesMessage.SEVERITY_WARN);
            fc.addMessage(components.getClientId(), msg);
            // passed to the Render Response phase
            fc.renderResponse();
        } else if (from != null && until != null) {
            if (from.after(until) || from.equals(until)) {
                validationSuccessful = false;
                FacesMessage msg = new FacesMessage(bundle.getString("errors.fromBeforeUntil"), "");
                msg.setSeverity(FacesMessage.SEVERITY_WARN);
                fc.addMessage(components.getClientId(), msg);
                // passed to the Render Response phase
                fc.renderResponse();
            }
            // all checks passed now, set validationSuccessful to true, which causes the "Register" button to become active!
            else {
                LOG.info("Consent creation validation has passed now.");
                validationSuccessful = true;
            }
        } else {
            validationSuccessful = false;
            FacesMessage msg = new FacesMessage("Please provide valid date input values for From AND Until.", "");
            msg.setSeverity(FacesMessage.SEVERITY_WARN);
            fc.addMessage(components.getClientId(), msg);
            // passed to the Render Response phase
            fc.renderResponse();
        }
    }

    /**
     * Overriding this method ensures that rich:calender validation is not done
     * by standard validation procedure but by our own
     * {@link ConsentBean#validateCreateConsentParameters(ComponentSystemEvent)}
     * method.
     */
    public void validator(javax.faces.context.FacesContext fc, javax.faces.component.UIComponent component,
            java.lang.Object object) {
        // JUST DO NOT VALIDATE ANYTHING HERE -> all done in
        // validateCreateConsentParameters...
    }

    /**
     * Gets the logged-in user and sets him as an author.
     * Then takes the 5 parameters(patient, validFrom, validUntil, policy, author) which are
     * given by the user and puts them into a patient consent and tries to send it to pxsQuery.
     * 
     * @return
     */
    public String registerConsent() {
        FacesContext fc = FacesContext.getCurrentInstance();

        // Replaced dependency to eHF with fixed mocks for the time being.
        author = new CoalaAuthor("testTitle", "testFirstName", "testLastName");

        UIViewRoot uiRoot = FacesContext.getCurrentInstance().getViewRoot();

        try {
            // try to register now, as we have all relevant data for it
            consentCreationService.createPatientConsent(selectedPatient, validFrom, validUntil, policy, author);
            setSuccessfulRegistration(true);
            setErrorfulRegistration(false);
            // show successful creation panel to the user
            UIPopupPanel consentCreationSuccessDialog = (UIPopupPanel) uiRoot
                    .findComponent("consentCreationSuccessDialog");
            if (consentCreationSuccessDialog != null) {
                consentCreationSuccessDialog.setShow(true);
                LOG.info("[CONSENT CREATION] ok, showing success PopUpPanel");
            }
            // cleanup selected values here, as they are outdated now.
            setValidFrom(null);
            setValidUntil(null);
            setPolicy(PatientConsentPolicy.ONE);
            setValidationSuccessful(false);
            return "patientSearch";

        } catch (Throwable t) {
            setErrorfulRegistration(true);
            setSuccessfulRegistration(false);
            UIPopupPanel consentCreationErrorDialog = (UIPopupPanel) uiRoot
                    .findComponent("consentCreationErrorDialog");
            if (consentCreationErrorDialog != null) {
                consentCreationErrorDialog.setShow(true);
                LOG.warn("[CONSENT CREATION] failed, showing error PopUpPanel");
            }
            setValidationSuccessful(false);

            FacesMessage msg = new FacesMessage("Could not create consent.");
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            fc.addMessage(null, msg);

            LOG.error(t.getLocalizedMessage(), t);
            // TODO Maybe add Facesmessage for display in ErrorPanelDialog
        }
        return "createConsent";
    }

    /**
     * Returns the selected policy by the number.
     * @param nr number of the selected policy (ONE, TWO, THREE, FOUR or FIVE)
     * @return selected policy
     */
    public PatientConsentPolicy getPolicyByNr(String nr) {
        if (nr.equals("ONE")) {
            return PatientConsentPolicy.ONE;
        } else if (nr.equals("TWO")) {
            return PatientConsentPolicy.TWO;
        } else if (nr.equals("THREE")) {
            return PatientConsentPolicy.THREE;
        } else if (nr.equals("FOUR")) {
            return PatientConsentPolicy.FOUR;
        } else {
            return PatientConsentPolicy.FIVE;
        }

    }

    /**
     * @return the selectedConsent
     */
    public PatientConsent getSelectedConsent() {
        return selectedConsent;
    }

    /**
     * @param selectedConsent the selectedConsent to set
     */
    public void setSelectedConsent(PatientConsent selectedConsent) {
        this.selectedConsent = selectedConsent;
    }

    public boolean isSuccessfulRegistration() {
        return successfulRegistration;
    }

    public void setSuccessfulRegistration(boolean successfulRegistration) {
        this.successfulRegistration = successfulRegistration;
    }

    public boolean isErrorfulRegistration() {
        return errorfulRegistration;
    }

    public void setErrorfulRegistration(boolean errorfulRegistration) {
        this.errorfulRegistration = errorfulRegistration;
    }

    public void setValidationSuccessful(boolean validationSuccessful) {
        this.validationSuccessful = validationSuccessful;
    }

    public boolean isValidationSuccessful() {
        return validationSuccessful;
    }

}