org.openmrs.module.personalhr.web.controller.PortletController.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.personalhr.web.controller.PortletController.java

Source

/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.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://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.personalhr.web.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.Cohort;
import org.openmrs.Concept;
import org.openmrs.ConceptNumeric;
import org.openmrs.DrugOrder;
import org.openmrs.Encounter;
import org.openmrs.Obs;
import org.openmrs.Patient;
import org.openmrs.Person;
import org.openmrs.Relationship;
import org.openmrs.RelationshipType;
import org.openmrs.User;
import org.openmrs.api.AdministrationService;
import org.openmrs.api.ConceptService;
import org.openmrs.api.context.Context;
import org.openmrs.order.RegimenSuggestion;
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.web.WebConstants;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class PortletController implements Controller {

    protected Log log = LogFactory.getLog(this.getClass());

    /**
     * This method produces a model containing the following mappings:
     * 
     * <pre>
     *     (always)
     *          (java.util.Date) now
     *          (String) size
     *          (Locale) locale
     *          (String) portletUUID // unique for each instance of any portlet
     *          (other parameters)
     *     (if there's currently an authenticated user)
     *          (User) authenticatedUser
     *     (if the request has a patientId attribute)
     *          (Integer) patientId
     *          (Patient) patient
     *          (List<Obs>) patientObs
     *          (List<Encounter>) patientEncounters
     *          (List<DrugOrder>) patientDrugOrders
     *          (List<DrugOrder>) currentDrugOrders
     *          (List<DrugOrder>) completedDrugOrders
     *          (Obs) patientWeight // most recent weight obs
     *          (Obs) patientHeight // most recent height obs
     *          (Double) patientBmi // BMI derived from most recent weight and most recent height
     *          (String) patientBmiAsString // BMI rounded to one decimal place, or "?" if unknown
     *          (Integer) personId
     *          (if the patient has any obs for the concept in the global property 'concept.reasonExitedCare')
     *              (Obs) patientReasonForExit
     *     (if the request has a personId or patientId attribute)
     *          (Person) person
     *          (List<Relationship>) personRelationships
     *          (Map<RelationshipType, List<Relationship>>) personRelationshipsByType
     *     (if the request has an encounterId attribute)
     *          (Integer) encounterId
     *          (Encounter) encounter
     *          (Set<Obs>) encounterObs
     *     (if the request has a userId attribute)
     *          (Integer) userId
     *          (User) user
     *     (if the request has a patientIds attribute, which should be a (String) comma-separated list of patientIds)
     *          (PatientSet) patientSet
     *          (String) patientIds
     *     (if the request has a conceptIds attribute, which should be a (String) commas-separated list of conceptIds)
     *          (Map<Integer, Concept>) conceptMap
     *          (Map<String, Concept>) conceptMapByStringIds
     * </pre>
     * 
     * @should calculate bmi into patientBmiAsString
     * @should not fail with empty height and weight properties
     */
    @Override
    @SuppressWarnings("unchecked")
    public ModelAndView handleRequest(final HttpServletRequest request, final HttpServletResponse response)
            throws ServletException, IOException {
        this.log.warn("Entering PortletController.handleRequest");
        String portletPath = "";
        Map<String, Object> model = null;
        Integer personId = null;

        try {
            //Add temporary privilege
            //PersonalhrUtil.addTemporayPrivileges();

            final AdministrationService as = Context.getAdministrationService();
            final ConceptService cs = Context.getConceptService();

            // find the portlet that was identified in the openmrs:portlet taglib
            final Object uri = request.getAttribute("javax.servlet.include.servlet_path");

            {
                final HttpSession session = request.getSession();
                final String uniqueRequestId = (String) request.getAttribute(WebConstants.INIT_REQ_UNIQUE_ID);
                final String lastRequestId = (String) session
                        .getAttribute(WebConstants.OPENMRS_PORTLET_LAST_REQ_ID);
                if (uniqueRequestId.equals(lastRequestId)) {
                    model = (Map<String, Object>) session.getAttribute(WebConstants.OPENMRS_PORTLET_CACHED_MODEL);

                    // remove cached parameters 
                    final List<String> parameterKeys = (List<String>) model.get("parameterKeys");
                    for (final String key : parameterKeys) {
                        model.remove(key);
                    }
                }
                if (model == null) {
                    this.log.warn("creating new portlet model");
                    model = new HashMap<String, Object>();
                    session.setAttribute(WebConstants.OPENMRS_PORTLET_LAST_REQ_ID, uniqueRequestId);
                    session.setAttribute(WebConstants.OPENMRS_PORTLET_CACHED_MODEL, model);
                }
            }

            this.log.warn("PortletController.handleRequest: uri=" + uri);
            if (uri != null) {
                final long timeAtStart = System.currentTimeMillis();
                portletPath = uri.toString();

                // Allowable extensions are '' (no extension) and '.portlet'
                if (portletPath.endsWith("portlet")) {
                    portletPath = portletPath.replace(".portlet", "");
                } else if (portletPath.endsWith("jsp")) {
                    throw new ServletException(
                            "Illegal extension used for portlet: '.jsp'. Allowable extensions are '' (no extension) and '.portlet'");
                }

                this.log.warn("Loading portlet: " + portletPath);

                final String id = (String) request.getAttribute("org.openmrs.portlet.id");
                final String size = (String) request.getAttribute("org.openmrs.portlet.size");
                final Map<String, Object> params = (Map<String, Object>) request
                        .getAttribute("org.openmrs.portlet.parameters");
                final Map<String, Object> moreParams = (Map<String, Object>) request
                        .getAttribute("org.openmrs.portlet.parameterMap");

                model.put("now", new Date());
                model.put("id", id);
                model.put("size", size);
                model.put("locale", Context.getLocale());
                model.put("portletUUID", UUID.randomUUID().toString().replace("-", ""));
                final List<String> parameterKeys = new ArrayList<String>(params.keySet());
                model.putAll(params);
                if (moreParams != null) {
                    model.putAll(moreParams);
                    parameterKeys.addAll(moreParams.keySet());
                }
                model.put("parameterKeys", parameterKeys); // so we can clean these up in the next request

                // if there's an authenticated user, put them, and their patient set, in the model
                if (Context.getAuthenticatedUser() != null) {
                    model.put("authenticatedUser", Context.getAuthenticatedUser());
                }

                // if a patient id is available, put patient data documented above in the model
                Object o = request.getAttribute("org.openmrs.portlet.patientId");
                if (o != null) {
                    request.getSession().setAttribute("org.openmrs.portlet.patientId", o);

                    String patientVariation = "";
                    final Integer patientId = (Integer) o;
                    if (!model.containsKey("patient")) {
                        // we can't continue if the user can't view patients
                        if (Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_PATIENTS)) {
                            final Patient p = Context.getPatientService().getPatient(patientId);
                            model.put("patient", p);

                            // add encounters if this user can view them
                            if (Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_ENCOUNTERS)) {
                                model.put("patientEncounters",
                                        Context.getEncounterService().getEncountersByPatient(p));
                            }

                            if (Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_OBS)) {
                                final List<Obs> patientObs = Context.getObsService().getObservationsByPerson(p);
                                model.put("patientObs", patientObs);
                                Obs latestWeight = null;
                                Obs latestHeight = null;
                                String bmiAsString = "?";
                                try {
                                    final String weightString = as.getGlobalProperty("concept.weight");
                                    ConceptNumeric weightConcept = null;
                                    if (StringUtils.hasLength(weightString)) {
                                        weightConcept = cs.getConceptNumeric(
                                                cs.getConcept(Integer.valueOf(weightString)).getConceptId());
                                    }
                                    final String heightString = as.getGlobalProperty("concept.height");
                                    ConceptNumeric heightConcept = null;
                                    if (StringUtils.hasLength(heightString)) {
                                        heightConcept = cs.getConceptNumeric(
                                                cs.getConcept(Integer.valueOf(heightString)).getConceptId());
                                    }
                                    for (final Obs obs : patientObs) {
                                        if (obs.getConcept().equals(weightConcept)) {
                                            if ((latestWeight == null) || (obs.getObsDatetime()
                                                    .compareTo(latestWeight.getObsDatetime()) > 0)) {
                                                latestWeight = obs;
                                            }
                                        } else if (obs.getConcept().equals(heightConcept)) {
                                            if ((latestHeight == null) || (obs.getObsDatetime()
                                                    .compareTo(latestHeight.getObsDatetime()) > 0)) {
                                                latestHeight = obs;
                                            }
                                        }
                                    }
                                    if (latestWeight != null) {
                                        model.put("patientWeight", latestWeight);
                                    }
                                    if (latestHeight != null) {
                                        model.put("patientHeight", latestHeight);
                                    }
                                    if ((latestWeight != null) && (latestHeight != null)) {
                                        double weightInKg;
                                        double heightInM;
                                        if (weightConcept.getUnits().equals("kg")) {
                                            weightInKg = latestWeight.getValueNumeric();
                                        } else if (weightConcept.getUnits().equals("lb")) {
                                            weightInKg = latestWeight.getValueNumeric() * 0.45359237;
                                        } else {
                                            throw new IllegalArgumentException(
                                                    "Can't handle units of weight concept: "
                                                            + weightConcept.getUnits());
                                        }
                                        if (heightConcept.getUnits().equals("cm")) {
                                            heightInM = latestHeight.getValueNumeric() / 100;
                                        } else if (heightConcept.getUnits().equals("m")) {
                                            heightInM = latestHeight.getValueNumeric();
                                        } else if (heightConcept.getUnits().equals("in")) {
                                            heightInM = latestHeight.getValueNumeric() * 0.0254;
                                        } else {
                                            throw new IllegalArgumentException(
                                                    "Can't handle units of height concept: "
                                                            + heightConcept.getUnits());
                                        }
                                        final double bmi = weightInKg / (heightInM * heightInM);
                                        model.put("patientBmi", bmi);
                                        final String temp = "" + bmi;
                                        bmiAsString = temp.substring(0, temp.indexOf('.') + 2);
                                    }
                                } catch (final Exception ex) {
                                    if ((latestWeight != null) && (latestHeight != null)) {
                                        this.log.error(
                                                "Failed to calculate BMI even though a weight and height were found",
                                                ex);
                                    }
                                }
                                model.put("patientBmiAsString", bmiAsString);
                            } else {
                                model.put("patientObs", new HashSet<Obs>());
                            }

                            // information about whether or not the patient has exited care
                            Obs reasonForExitObs = null;
                            final String reasonForExitConceptString = as
                                    .getGlobalProperty("concept.reasonExitedCare");
                            if (StringUtils.hasLength(reasonForExitConceptString)) {
                                final Concept reasonForExitConcept = cs.getConcept(reasonForExitConceptString);
                                if (reasonForExitConcept != null) {
                                    final List<Obs> patientExitObs = Context.getObsService()
                                            .getObservationsByPersonAndConcept(p, reasonForExitConcept);
                                    if (patientExitObs != null) {
                                        this.log.debug("Exit obs is size " + patientExitObs.size());
                                        if (patientExitObs.size() == 1) {
                                            reasonForExitObs = patientExitObs.iterator().next();
                                            final Concept exitReason = reasonForExitObs.getValueCoded();
                                            final Date exitDate = reasonForExitObs.getObsDatetime();
                                            if ((exitReason != null) && (exitDate != null)) {
                                                patientVariation = "Exited";
                                            }
                                        } else {
                                            if (patientExitObs.size() == 0) {
                                                this.log.debug("Patient has no reason for exit");
                                            } else {
                                                this.log.error(
                                                        "Too many reasons for exit - not putting data into model");
                                            }
                                        }
                                    }
                                }
                            }
                            model.put("patientReasonForExit", reasonForExitObs);

                            if (Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_ORDERS)) {
                                final List<DrugOrder> drugOrderList = Context.getOrderService()
                                        .getDrugOrdersByPatient(p);
                                model.put("patientDrugOrders", drugOrderList);
                                final List<DrugOrder> currentDrugOrders = new ArrayList<DrugOrder>();
                                final List<DrugOrder> discontinuedDrugOrders = new ArrayList<DrugOrder>();
                                final Date rightNow = new Date();
                                for (final DrugOrder next : drugOrderList) {
                                    if (next.isCurrent() || next.isFuture()) {
                                        currentDrugOrders.add(next);
                                    }
                                    if (next.isDiscontinued(rightNow)) {
                                        discontinuedDrugOrders.add(next);
                                    }
                                }
                                model.put("currentDrugOrders", currentDrugOrders);
                                model.put("completedDrugOrders", discontinuedDrugOrders);

                                final List<RegimenSuggestion> standardRegimens = Context.getOrderService()
                                        .getStandardRegimens();
                                if (standardRegimens != null) {
                                    model.put("standardRegimens", standardRegimens);
                                }
                            }

                            if (Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_PROGRAMS)
                                    && Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_PATIENT_PROGRAMS)) {
                                model.put("patientPrograms", Context.getProgramWorkflowService()
                                        .getPatientPrograms(p, null, null, null, null, null, false));
                                model.put("patientCurrentPrograms", Context.getProgramWorkflowService()
                                        .getPatientPrograms(p, null, null, new Date(), new Date(), null, false));
                            }

                            model.put("patientId", patientId);
                            if (p != null) {
                                personId = p.getPatientId();
                                model.put("personId", personId);
                            }

                            model.put("patientVariation", patientVariation);
                        }
                    }
                }

                // if a person id is available, put person and relationships in the model
                if (personId == null) {
                    o = request.getAttribute("org.openmrs.portlet.personId");
                    if (o != null) {
                        personId = (Integer) o;
                        model.put("personId", personId);
                    }
                }
                if (personId != null) {
                    if (!model.containsKey("person")) {
                        Person p = (Person) model.get("patient");
                        if (p == null) {
                            p = Context.getPersonService().getPerson(personId);
                        }
                        model.put("person", p);

                        if (Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_RELATIONSHIPS)) {
                            final List<Relationship> relationships = new ArrayList<Relationship>();
                            relationships.addAll(Context.getPersonService().getRelationshipsByPerson(p));
                            final Map<RelationshipType, List<Relationship>> relationshipsByType = new HashMap<RelationshipType, List<Relationship>>();
                            for (final Relationship rel : relationships) {
                                List<Relationship> list = relationshipsByType.get(rel.getRelationshipType());
                                if (list == null) {
                                    list = new ArrayList<Relationship>();
                                    relationshipsByType.put(rel.getRelationshipType(), list);
                                }
                                list.add(rel);
                            }

                            model.put("personRelationships", relationships);
                            model.put("personRelationshipsByType", relationshipsByType);
                        }
                    }
                }

                // if an encounter id is available, put "encounter" and "encounterObs" in the model
                o = request.getAttribute("org.openmrs.portlet.encounterId");
                if ((o != null) && !model.containsKey("encounterId")) {
                    if (!model.containsKey("encounter")) {
                        if (Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_ENCOUNTERS)) {
                            final Encounter e = Context.getEncounterService().getEncounter((Integer) o);
                            model.put("encounter", e);
                            if (Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_OBS)) {
                                model.put("encounterObs", e.getObs());
                            }
                        }
                        model.put("encounterId", o);
                    }
                }

                // if a user id is available, put "user" in the model
                o = request.getAttribute("org.openmrs.portlet.userId");
                if (o != null) {
                    if (!model.containsKey("user")) {
                        if (Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_USERS)) {
                            final User u = Context.getUserService().getUser((Integer) o);
                            model.put("user", u);
                        }
                        model.put("userId", o);
                    }
                }

                // if a list of patient ids is available, make a patientset out of it
                o = request.getAttribute("org.openmrs.portlet.patientIds");
                if ((o != null) && !"".equals(o) && !model.containsKey("patientIds")) {
                    if (!model.containsKey("patientSet")) {
                        final Cohort ps = new Cohort((String) o);
                        model.put("patientSet", ps);
                        model.put("patientIds", (String) o);
                    }
                }

                o = model.get("conceptIds");
                if ((o != null) && !"".equals(o)) {
                    if (!model.containsKey("conceptMap")) {
                        this.log.debug("Found conceptIds parameter: " + o);
                        final Map<Integer, Concept> concepts = new HashMap<Integer, Concept>();
                        final Map<String, Concept> conceptsByStringIds = new HashMap<String, Concept>();
                        final String conceptIds = (String) o;
                        final String[] ids = conceptIds.split(",");
                        for (final String cId : ids) {
                            try {
                                final Integer i = Integer.valueOf(cId);
                                final Concept c = cs.getConcept(i);
                                concepts.put(i, c);
                                conceptsByStringIds.put(i.toString(), c);
                            } catch (final Exception ex) {
                            }
                        }
                        model.put("conceptMap", concepts);
                        model.put("conceptMapByStringIds", conceptsByStringIds);
                    }
                }

                populateModel(request, model);
                this.log.warn(portletPath + " took " + (System.currentTimeMillis() - timeAtStart) + " ms");
            }
        } finally {
            //PersonalhrUtil.removeTemporayPrivileges();
        }
        return new ModelAndView(portletPath, "model", model);
    }

    /**
     * Subclasses should override this to put more data into the model. This will be called AFTER
     * handleRequest has put mappings in the model as described in its javadoc. Note that context
     * could be null when this method is called.
     */
    protected void populateModel(final HttpServletRequest request, final Map<String, Object> model) {
        this.log.debug("Entering PortletController.populateModel");
    }

}