org.openmrs.module.kenyaemr.regimen.RegimenManager.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.kenyaemr.regimen.RegimenManager.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.kenyaemr.regimen;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.openmrs.Concept;
import org.openmrs.DrugOrder;
import org.openmrs.api.context.Context;
import org.openmrs.module.kenyacore.ContentManager;
import org.openmrs.module.metadatadeploy.MetadataUtils;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Manager for regimens
 */
@Component
public class RegimenManager implements ContentManager {

    private Map<String, Integer> masterSetConcepts = new LinkedHashMap<String, Integer>();

    private Map<String, Map<String, DrugReference>> drugs = new LinkedHashMap<String, Map<String, DrugReference>>();

    private Map<String, List<RegimenDefinitionGroup>> regimenGroups = new LinkedHashMap<String, List<RegimenDefinitionGroup>>();

    /**
     * @see org.openmrs.module.kenyacore.ContentManager#getPriority()
     */
    @Override
    public int getPriority() {
        return 30;
    }

    /**
     * @see org.openmrs.module.kenyacore.ContentManager#refresh()
     */
    @Override
    public synchronized void refresh() {
        masterSetConcepts.clear();
        drugs.clear();
        regimenGroups.clear();

        for (RegimenConfiguration configuration : Context.getRegisteredComponents(RegimenConfiguration.class)) {
            try {
                ClassLoader loader = configuration.getClassLoader();
                InputStream stream = loader.getResourceAsStream(configuration.getDefinitionsPath());

                loadDefinitionsFromXML(stream);
            } catch (Exception ex) {
                ex.printStackTrace();
                throw new RuntimeException(
                        "Unable to load " + configuration.getModuleId() + ":" + configuration.getDefinitionsPath(),
                        ex);
            }
        }
    }

    /**
     * Gets the category codes
     * @return the category codes
     */
    public Set<String> getCategoryCodes() {
        return masterSetConcepts.keySet();
    }

    /**
     * Gets the master set concept for the given category
     * @param category the category, e.g. "ARV"
     * @return the concept
     */
    public Concept getMasterSetConcept(String category) {
        Integer conceptId = masterSetConcepts.get(category);
        return conceptId != null ? Context.getConceptService().getConcept(conceptId) : null;
    }

    /**
     * Gets the individual drugs for the given category
     * @param category the category, e.g. "ARV"
     * @return the concept ids or null if category isn't defined
     */
    public Collection<DrugReference> getDrugs(String category) {
        Map<String, DrugReference> drugsForCategory = drugs.get(category);
        return (drugsForCategory != null) ? drugsForCategory.values() : null;
    }

    /**
     * Gets the regimen groups for the given category
     * @param category the category, e.g. "ARV"
     * @return the regimen groups
     */
    public List<RegimenDefinitionGroup> getRegimenGroups(String category) {
        return regimenGroups.get(category);
    }

    /**
     * Finds definitions that match the given regimen
     * @param category the category, e.g. "ARV"
     * @param regimenOrder the regimen
     * @param exact whether matches must be exact (includes dose, units and frequency)
     * @return the definitions
     */
    public List<RegimenDefinition> findDefinitions(String category, RegimenOrder regimenOrder, boolean exact) {
        List<RegimenDefinitionGroup> groups = regimenGroups.get(category);
        if (groups == null) {
            throw new IllegalArgumentException("No such category: " + category);
        }

        List<RegimenDefinition> matches = new ArrayList<RegimenDefinition>();

        for (RegimenDefinitionGroup group : groups) {
            outer: for (RegimenDefinition definition : group.getRegimens()) {
                List<RegimenComponent> regimen = definition.getComponents();
                Set<DrugOrder> orders = regimenOrder.getDrugOrders();

                // Skip if regimen doesn't have same number of orders
                if (regimen.size() != orders.size()) {
                    continue;
                }

                // Check each component has an equivalent drug order
                for (RegimenComponent component : regimen) {

                    // Does regimen have a drug order for this component?
                    boolean regimenHasComponent = false;
                    for (DrugOrder order : orders) {
                        DrugReference componentDrugRef = component.getDrugRef();
                        DrugReference orderDrugRef = DrugReference.fromDrugOrder(order);

                        if (componentDrugRef.equals(orderDrugRef)) {

                            if (!exact || (ObjectUtils.equals(order.getDose(), component.getDose())
                                    && StringUtils.equals(order.getUnits(), component.getUnits())
                                    && StringUtils.equals(order.getFrequency(), component.getFrequency()))) {
                                regimenHasComponent = true;
                                break;
                            }
                        }
                    }

                    if (!regimenHasComponent) {
                        continue outer;
                    }
                }

                // Regimen has all components of the definition
                matches.add(definition);
            }
        }

        return matches;
    }

    /**
     * Loads definitions from an input stream containing XML
     * @param stream the path to XML resource
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws SAXException
     */
    public void loadDefinitionsFromXML(InputStream stream)
            throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = dbFactory.newDocumentBuilder();

        Document document = builder.parse(stream);

        Element root = document.getDocumentElement();

        // Parse each category
        NodeList categoryNodes = root.getElementsByTagName("category");
        for (int c = 0; c < categoryNodes.getLength(); c++) {
            Element categoryElement = (Element) categoryNodes.item(c);
            String categoryCode = categoryElement.getAttribute("code");
            String masterSetUuid = categoryElement.getAttribute("masterSetUuid");

            Concept masterSetConcept = MetadataUtils.existing(Concept.class, masterSetUuid);
            masterSetConcepts.put(categoryCode, masterSetConcept.getConceptId());

            Map<String, DrugReference> categoryDrugs = new HashMap<String, DrugReference>();
            List<RegimenDefinitionGroup> categoryGroups = new ArrayList<RegimenDefinitionGroup>();

            // Parse all drug concepts for this category
            NodeList drugNodes = categoryElement.getElementsByTagName("drug");
            for (int d = 0; d < drugNodes.getLength(); d++) {
                Element drugElement = (Element) drugNodes.item(d);
                String drugCode = drugElement.getAttribute("code");
                String drugConceptUuid = drugElement.hasAttribute("conceptUuid")
                        ? drugElement.getAttribute("conceptUuid")
                        : null;
                String drugDrugUuid = drugElement.hasAttribute("drugUuid") ? drugElement.getAttribute("drugUuid")
                        : null;

                DrugReference drug = (drugDrugUuid != null) ? DrugReference.fromDrugUuid(drugDrugUuid)
                        : DrugReference.fromConceptUuid(drugConceptUuid);
                if (drug != null) {
                    categoryDrugs.put(drugCode, drug);
                }
            }

            // Parse all groups for this category
            NodeList groupNodes = categoryElement.getElementsByTagName("group");
            for (int g = 0; g < groupNodes.getLength(); g++) {
                Element groupElement = (Element) groupNodes.item(g);
                String groupCode = groupElement.getAttribute("code");
                String groupName = groupElement.getAttribute("name");

                RegimenDefinitionGroup group = new RegimenDefinitionGroup(groupCode, groupName);
                categoryGroups.add(group);

                // Parse all regimen definitions for this group
                NodeList regimenNodes = groupElement.getElementsByTagName("regimen");
                for (int r = 0; r < regimenNodes.getLength(); r++) {
                    Element regimenElement = (Element) regimenNodes.item(r);
                    String name = regimenElement.getAttribute("name");

                    RegimenDefinition regimenDefinition = new RegimenDefinition(name, group);

                    // Parse all components for this regimen
                    NodeList componentNodes = regimenElement.getElementsByTagName("component");
                    for (int p = 0; p < componentNodes.getLength(); p++) {
                        Element componentElement = (Element) componentNodes.item(p);
                        String drugCode = componentElement.getAttribute("drugCode");
                        Double dose = componentElement.hasAttribute("dose")
                                ? Double.parseDouble(componentElement.getAttribute("dose"))
                                : null;
                        String units = componentElement.hasAttribute("units")
                                ? componentElement.getAttribute("units")
                                : null;
                        String frequency = componentElement.hasAttribute("frequency")
                                ? componentElement.getAttribute("frequency")
                                : null;

                        DrugReference drug = categoryDrugs.get(drugCode);
                        if (drug == null)
                            throw new RuntimeException("Regimen component references invalid drug: " + drugCode);

                        regimenDefinition.addComponent(drug, dose, units, frequency);
                    }

                    group.addRegimen(regimenDefinition);
                }
            }

            drugs.put(categoryCode, categoryDrugs);
            regimenGroups.put(categoryCode, categoryGroups);
        }
    }
}