/** * Copyright 2010 Society for Health Information Systems Programmes, India (HISP India) * * This file is part of Hospital-core module. * * Hospital-core module is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * Hospital-core module is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Hospital-core module. If not, see <http://www.gnu.org/licenses/>. * **/ package org.openmrs.module.hospitalcore.impl; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.TreeSet; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathExpressionException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.Concept; import org.openmrs.ConceptAnswer; import org.openmrs.ConceptClass; import org.openmrs.ConceptDatatype; import org.openmrs.ConceptDescription; import org.openmrs.ConceptMap; import org.openmrs.ConceptName; import org.openmrs.ConceptNameTag; import org.openmrs.ConceptSource; import org.openmrs.Encounter; import org.openmrs.EncounterType; import org.openmrs.GlobalProperty; import org.openmrs.Location; import org.openmrs.Obs; import org.openmrs.Patient; import org.openmrs.PersonAttribute; import org.openmrs.User; import org.openmrs.api.APIException; import org.openmrs.api.ConceptService; import org.openmrs.api.context.Context; import org.openmrs.api.impl.BaseOpenmrsService; import org.openmrs.module.hospitalcore.HospitalCoreService; import org.openmrs.module.hospitalcore.concept.ConceptModel; import org.openmrs.module.hospitalcore.concept.Mapping; import org.openmrs.module.hospitalcore.concept.Synonym; import org.openmrs.module.hospitalcore.db.HospitalCoreDAO; import org.openmrs.module.hospitalcore.model.CoreForm; import org.openmrs.module.hospitalcore.model.PatientSearch; import org.openmrs.module.hospitalcore.util.HospitalCoreConstants; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class HospitalCoreServiceImpl extends BaseOpenmrsService implements HospitalCoreService { private Log log = LogFactory.getLog(this.getClass()); public HospitalCoreServiceImpl() { } protected HospitalCoreDAO dao; public List<Obs> listObsGroup(Integer personId, Integer conceptId, Integer min, Integer max) throws APIException { return dao.listObsGroup(personId, conceptId, min, max); } private Concept insertConcept(ConceptService conceptService, String dataTypeName, String conceptClassName, String concept) { try { ConceptDatatype datatype = Context.getConceptService() .getConceptDatatypeByName(dataTypeName); ConceptClass conceptClass = conceptService .getConceptClassByName(conceptClassName); Concept con = conceptService.getConcept(concept); if (con == null) { con = new Concept(); ConceptName name = new ConceptName(concept, Context.getLocale()); con.addName(name); con.setDatatype(datatype); con.setConceptClass(conceptClass); return conceptService.saveConcept(con); } } catch (Exception e) { e.printStackTrace(); } return null; } public void creatConceptQuestionAndAnswer(ConceptService conceptService, User user, String conceptParent, String... conceptChild) { Concept concept = conceptService.getConcept(conceptParent); if (concept == null) { insertConcept(conceptService, "Coded", "Question", conceptParent); } if (concept != null) { for (String hn : conceptChild) { insertHospital(conceptService, hn); } addConceptAnswers(concept, conceptChild, user); } } private void addConceptAnswers(Concept concept, String[] answerNames, User creator) { Set<Integer> currentAnswerIds = new HashSet<Integer>(); for (ConceptAnswer answer : concept.getAnswers()) { currentAnswerIds.add(answer.getAnswerConcept().getConceptId()); } boolean changed = false; for (String answerName : answerNames) { Concept answer = Context.getConceptService().getConcept(answerName); if (!currentAnswerIds.contains(answer.getConceptId())) { changed = true; ConceptAnswer conceptAnswer = new ConceptAnswer(answer); conceptAnswer.setCreator(creator); concept.addAnswer(conceptAnswer); } } if (changed) { Context.getConceptService().saveConcept(concept); } } private Concept insertHospital(ConceptService conceptService, String hospitalName) { try { ConceptDatatype datatype = Context.getConceptService() .getConceptDatatypeByName("N/A"); ConceptClass conceptClass = conceptService .getConceptClassByName("Misc"); Concept con = conceptService.getConceptByName(hospitalName); // System.out.println(con); if (con == null) { con = new Concept(); ConceptName name = new ConceptName(hospitalName, Context.getLocale()); con.addName(name); con.setDatatype(datatype); con.setConceptClass(conceptClass); return conceptService.saveConcept(con); } return con; } catch (Exception e) { e.printStackTrace(); } return null; } public EncounterType insertEncounterTypeByKey(String type) throws APIException { EncounterType encounterType = null; try { GlobalProperty gp = Context.getAdministrationService() .getGlobalPropertyObject(type); encounterType = Context.getEncounterService().getEncounterType( gp.getPropertyValue()); if (encounterType == null) { encounterType = new EncounterType(gp.getPropertyValue(), ""); encounterType = Context.getEncounterService() .saveEncounterType(encounterType); } } catch (Exception e) { e.printStackTrace(); } return encounterType; } /** * * @param type * @throws APIException */ /* * public EncounterType insertEncounterTypeByKey(String type) throws * APIException { EncounterType encounterType = null; try { GlobalProperty * gp = Context.getAdministrationService().getGlobalPropertyObject(type); * encounterType = * Context.getEncounterService().getEncounterType(gp.getPropertyValue()); if * (encounterType == null) { encounterType = new * EncounterType(gp.getPropertyValue(), ""); * encounterType=Context.getEncounterService * ().saveEncounterType(encounterType); } } catch (Exception e) { * e.printStackTrace(); } return encounterType; } * * public void addConceptAnswers(ConceptService conceptService, Concept * concept, String[] answerNames, User creator) throws APIException { * Set<Integer> currentAnswerIds = new HashSet<Integer>(); for * (ConceptAnswer answer : concept.getAnswers()) { * currentAnswerIds.add(answer.getAnswerConcept().getConceptId()); } boolean * changed = false; * * for (String answerName : answerNames) { * System.out.println("======================== CJUE: "+answerName); * insertAnswerConcept(Context.getConceptService(), answerName); * System.out.println("========OUT================ CJUE "+answerName); } * * for (String answerName : answerNames) { * System.out.println("answerName in== : "+answerName); Concept answer = * Context.getConceptService().getConcept(answerName); if * (!currentAnswerIds.contains(answer.getConceptId())) { changed = true; * System.out.println("co nhay vao day khong "+answer); ConceptAnswer * conceptAnswer = new ConceptAnswer(answer); * conceptAnswer.setCreator(creator); concept.addAnswer(conceptAnswer); } } * if (changed) { System.out.println("nhay vao tao cai concept: "); * Context.getConceptService().saveConcept(concept); } } * * private Concept insertAnswerConcept(ConceptService conceptService, String * hospitalName) { try { ConceptDatatype datatype = * Context.getConceptService() .getConceptDatatypeByName("N/A"); * ConceptClass conceptClass = conceptService * .getConceptClassByName("Misc"); Concept con = * conceptService.getConceptByName(hospitalName); // * System.out.println(con); if (con == null) { con = new Concept(); * ConceptName name = new ConceptName(hospitalName, Context.getLocale()); * con.addName(name); con.setDatatype(datatype); * con.setConceptClass(conceptClass); return * conceptService.saveConcept(con); } return con; } catch (Exception e) { * e.printStackTrace(); } return null; } * * public HospitalCoreDAO getDao() { return dao; } * * public void setDao(HospitalCoreDAO dao) { this.dao = dao; } *//** * Insert a concept unless it exists * * @param dataTypeName * @param conceptClassName * @param conceptName * @return found concept or created */ /* * public Concept insertConceptUnlessExist(String dataTypeName, String * conceptClassName, String conceptName) { Concept con = null; try { * ConceptService conceptService = Context.getConceptService(); * ConceptDatatype datatype = * Context.getConceptService().getConceptDatatypeByName(dataTypeName); * System.out.println("me datatype: "+datatype); ConceptClass conceptClass = * conceptService .getConceptClassByName(conceptClassName); * System.out.println("me conceptclass: "+conceptClass); con = * conceptService.getConceptByName(conceptName); * System.out.println("be4 con: "+con); if (con == null) { con = new * Concept(); ConceptName name = new * ConceptName(conceptName,Context.getLocale()); con.addName(name); * con.setDatatype(datatype); con.setConceptClass(conceptClass); * System.out.println("con after: datatype: "+con.getDatatype()); * System.out.println("con after: conceptClass: "+conceptClass); * //con.setDateCreated(new Date()); Concept ccccc * =conceptService.saveConcept(con); System.out.println("cccccc; "+ccccc); * return ccccc; } } catch (Exception e) { e.printStackTrace(); } return * con; } */ /** * Create the global obs for a patient * * @param patient */ public Concept insertConceptUnlessExist(String dataTypeName, String conceptClassName, String conceptName) throws APIException { Concept con = null; try { ConceptService conceptService = Context.getConceptService(); ConceptDatatype datatype = Context.getConceptService() .getConceptDatatypeByName(dataTypeName); // System.out.println("me datatype: "+datatype); ConceptClass conceptClass = conceptService .getConceptClassByName(conceptClassName); // System.out.println("me conceptclass: "+conceptClass); con = conceptService.getConceptByName(conceptName); // System.out.println("be4 con: "+con); if (con == null) { con = new Concept(); ConceptName name = new ConceptName(conceptName, Context.getLocale()); con.addName(name); con.setDatatype(datatype); con.setConceptClass(conceptClass); // System.out.println("con after: datatype: "+con.getDatatype()); // System.out.println("con after: conceptClass: "+conceptClass); // con.setDateCreated(new Date()); Concept ccccc = conceptService.saveConcept(con); // System.out.println("cccccc; "+ccccc); return ccccc; } } catch (Exception e) { e.printStackTrace(); } return con; } public Obs createObsGroup(Patient patient, String properyKey) { String opdVisitConceptName = Context.getAdministrationService() .getGlobalProperty(properyKey); if (!StringUtils.isBlank(opdVisitConceptName)) { Concept concept = insertConceptUnlessExist("N/A", "Misc", opdVisitConceptName); Obs obs = new Obs(); obs.setPatient(patient); obs.setConcept(concept); obs.setDateCreated(new Date()); obs.setObsDatetime(new Date()); obs.setLocation(new Location(1)); return Context.getObsService().saveObs(obs, "Global obs for " + patient.getPersonName().getGivenName()); } return null; } /** * Get global obs for a patient * * @param patient * @return */ public Obs getObsGroup(Patient patient) { String name = Context.getAdministrationService().getGlobalProperty( HospitalCoreConstants.PROPERTY_OBSGROUP); Obs obs = null; try { Concept concept = Context.getConceptService() .getConceptByName(name); List<Obs> obses = listObsGroup(patient.getPersonId(), concept.getConceptId(), 0, 1); obs = CollectionUtils.isEmpty(obses) ? null : obses.get(0); } catch (Exception e) { e.printStackTrace(); } return obs; } public Obs getObsGroupCurrentDate(Integer personId) throws APIException { String name = Context.getAdministrationService().getGlobalProperty( HospitalCoreConstants.PROPERTY_OBSGROUP); Concept concept = Context.getConceptService().getConceptByName(name); // TODO Auto-generated method stub return dao.getObsGroupCurrentDate(personId, concept.getConceptId()); } public HospitalCoreDAO getDao() { return dao; } public void setDao(HospitalCoreDAO dao) { this.dao = dao; } /** * Insert a synonym to an existing concept. * * @param concept * @param name */ public void insertSynonym(Concept concept, String name) { Locale loc = new Locale("en"); ConceptName conceptName = new ConceptName(name, loc); ConceptNameTag tag = Context.getConceptService() .getConceptNameTagByName("synonym"); conceptName.addTag(tag); conceptName.setDateCreated(new Date()); conceptName.setCreator(Context.getAuthenticatedUser()); concept.addName(conceptName); Context.getConceptService().saveConcept(concept); } /** * Insert a synonym to an existing concept. * * @param concept * @param name */ public void insertMapping(Concept concept, String sourceName, String sourceCode) { ConceptSource conceptSource = Context.getConceptService() .getConceptSourceByName(sourceName); List<ConceptMap> conceptMaps = new ArrayList<ConceptMap>(); conceptMaps.addAll(concept.getConceptMappings()); boolean found = false; for (ConceptMap cm : concept.getConceptMappings()) { if (cm.getSource().equals(conceptSource)) if (cm.getSourceCode().equalsIgnoreCase(sourceCode)) { found = true; break; } } if (!found) { ConceptMap conceptMap = new ConceptMap(); conceptMap.setConcept(concept); conceptMap.setSource(conceptSource); conceptMap.setSourceCode(sourceCode); conceptMap.setDateCreated(new Date()); conceptMap.setCreator(Context.getAuthenticatedUser()); concept.addConceptMapping(conceptMap); Context.getConceptService().saveConcept(concept); } } public Concept insertConcept(String dataTypeName, String conceptClassName, String name, String shortname, String description) throws APIException { Concept con = null; try { ConceptService conceptService = Context.getConceptService(); con = conceptService.getConceptByName(name); if (con == null) { con = new Concept(); Locale loc = new Locale("en"); // Add concept name con = addName(con, name.toUpperCase(), loc); // Add concept shortname con = addName(con, shortname.toUpperCase(), loc); // Add description ConceptDescription conceptDescription = new ConceptDescription( description, loc); con.addDescription(conceptDescription); // Add datatype ConceptDatatype conceptDatatype = Context.getConceptService() .getConceptDatatypeByName(dataTypeName); con.setDatatype(conceptDatatype); // add conceptClass ConceptClass conceptClass = conceptService .getConceptClassByName(conceptClassName); con.setConceptClass(conceptClass); return conceptService.saveConcept(con); } } catch (Exception e) { e.printStackTrace(); } return con; } private Concept addName(Concept concept, String name, Locale loc) { if (!StringUtils.isBlank(name)) { ConceptName conceptName = new ConceptName(name, loc); // ConceptNameTag tag = Context.getConceptService() // .getConceptNameTagByName(type); // conceptName.addTag(tag); conceptName.setDateCreated(new Date()); conceptName.setCreator(Context.getAuthenticatedUser()); concept.addName(conceptName); } return concept; } public Integer importConcepts(InputStream diagnosisStream, InputStream mappingStream, InputStream synonymStream) throws XPathExpressionException, ParserConfigurationException, SAXException, IOException { Integer diagnosisNo = 0; Set<ConceptModel> concepts = new HashSet<ConceptModel>(); Set<Mapping> mapping = new HashSet<Mapping>(); Set<Synonym> synonym = new HashSet<Synonym>(); if (diagnosisStream != null) { concepts = parseDiagnosis(diagnosisStream); } if (mappingStream != null) { mapping = parseMapping(mappingStream); } if (synonymStream != null) { synonym = parseSynonym(synonymStream); } List<ConceptModel> conceptModels = merge(concepts, mapping, synonym); System.out.println("NUMBER OF CONCEPTS + " + conceptModels.size()); diagnosisNo = dao.buildConcepts(conceptModels); return diagnosisNo; } private Set<ConceptModel> parseDiagnosis(InputStream stream) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException { Set<ConceptModel> concepts = new TreeSet<ConceptModel>(); DocumentBuilderFactory domFactory = DocumentBuilderFactory .newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse(stream); NodeList rows = doc.getFirstChild().getChildNodes(); for (int i = 0; i < rows.getLength(); i++) { Node row = rows.item(i); if (row.getNodeName().equalsIgnoreCase("row")) { ConceptModel cm = new ConceptModel(); NodeList fields = row.getChildNodes(); for (int j = 0; j < fields.getLength(); j++) { Node field = fields.item(j); NamedNodeMap attributes = field.getAttributes(); if (field.getNodeName().equalsIgnoreCase("field")) { String type = attributes.getNamedItem("name") .getTextContent(); String value = field.getTextContent(); if ("name".equalsIgnoreCase(type)) { cm.setName(value); } if ("description".equalsIgnoreCase(type)) { cm.setDescription(value); } } } concepts.add(cm); } } return concepts; } private Set<Mapping> parseMapping(InputStream stream) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException { Set<Mapping> mappings = new TreeSet<Mapping>(); DocumentBuilderFactory domFactory = DocumentBuilderFactory .newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse(stream); NodeList rows = doc.getFirstChild().getChildNodes(); for (int i = 0; i < rows.getLength(); i++) { Node row = rows.item(i); if (row.getNodeName().equalsIgnoreCase("row")) { Mapping cm = new Mapping(); NodeList fields = row.getChildNodes(); for (int j = 0; j < fields.getLength(); j++) { Node field = fields.item(j); NamedNodeMap attributes = field.getAttributes(); if (field.getNodeName().equalsIgnoreCase("field")) { String type = attributes.getNamedItem("name") .getTextContent(); String value = field.getTextContent(); if ("name".equalsIgnoreCase(type)) { cm.setName(value); } if ("source_code".equalsIgnoreCase(type)) { cm.setSourceCode(value); } if ("source_name".equalsIgnoreCase(type)) { cm.setSource(value); } } } mappings.add(cm); } } return mappings; } private Set<Synonym> parseSynonym(InputStream stream) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException { Set<Synonym> synnonyms = new TreeSet<Synonym>(); DocumentBuilderFactory domFactory = DocumentBuilderFactory .newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse(stream); NodeList rows = doc.getFirstChild().getChildNodes(); for (int i = 0; i < rows.getLength(); i++) { Node row = rows.item(i); if (row.getNodeName().equalsIgnoreCase("row")) { Synonym cm = new Synonym(); NodeList fields = row.getChildNodes(); for (int j = 0; j < fields.getLength(); j++) { Node field = fields.item(j); NamedNodeMap attributes = field.getAttributes(); if (field.getNodeName().equalsIgnoreCase("field")) { String type = attributes.getNamedItem("name") .getTextContent(); String value = field.getTextContent(); if ("concept".equalsIgnoreCase(type)) { cm.setName(value); } if ("synonym".equalsIgnoreCase(type)) { cm.setSynonym(value); } } } synnonyms.add(cm); } } return synnonyms; } private List<ConceptModel> merge(Set<ConceptModel> conceptSet, Set<Mapping> mappingSet, Set<Synonym> synonymSet) { List<ConceptModel> conceptList = new ArrayList<ConceptModel>(); conceptList.addAll(conceptSet); for (Mapping mapping : mappingSet) { int index = indexOf(conceptList, mapping.getName()); if (index >= 0) { ConceptModel concept = conceptList.get(index); concept.getMappings().add(mapping); } } for (Synonym synonym : synonymSet) { int index = indexOf(conceptList, synonym.getName()); if (index >= 0) { ConceptModel concept = conceptList.get(index); concept.getSynonyms().add(synonym.getSynonym()); } } return conceptList; } private int indexOf(List<ConceptModel> conceptList, String name) { ConceptModel concept = new ConceptModel(); concept.setName(name); return Collections.binarySearch(conceptList, concept); } public List<Patient> searchPatient(String nameOrIdentifier, String gender, int age, int rangeAge, String date, int rangeDay, String relativeName) throws APIException { return dao.searchPatient(nameOrIdentifier, gender, age, rangeAge, date, rangeDay, relativeName); } public List<Patient> searchPatient(String hql) { return dao.searchPatient(hql); } public BigInteger getPatientSearchResultCount(String hql) { return dao.getPatientSearchResultCount(hql); } public List<PersonAttribute> getPersonAttributes(Integer patientId) { return dao.getPersonAttributes(patientId); } public Encounter getLastVisitEncounter(Patient patient, List<EncounterType> types) { return dao.getLastVisitEncounter(patient, types); } /** * Save core form * * @param form * @return */ public CoreForm saveCoreForm(CoreForm form) { return dao.saveCoreForm(form); } /** * Get core form by id * * @param id * @return */ public CoreForm getCoreForm(Integer id) { return dao.getCoreForm(id); } /** * Get core forms by name * * @param conceptName * @return */ public List<CoreForm> getCoreForms(String conceptName) { return dao.getCoreForms(conceptName); } /** * Get all core forms * * @return */ public List<CoreForm> getCoreForms(){ return dao.getCoreForms(); } /** * Delete core form * * @param form */ public void deleteCoreForm(CoreForm form){ dao.deleteCoreForm(form); } /** * Save patientSearch */ public PatientSearch savePatientSearch(PatientSearch patientSearch){ return dao.savePatientSearch(patientSearch); } /** * * @see org.openmrs.module.hospitalcore.HospitalCoreService#getLastVisitTime(int) */ public java.util.Date getLastVisitTime(int patientID) { return dao.getLastVisitTime(patientID); } //ghanshyam,22-oct-2013,New Requirement #2940 Dealing with dead patient public PatientSearch getPatient(int patientID){ return dao.getPatient(patientID); } /*public List<Patient> getAllEncounterCurrentDate(String date,Set<EncounterType> encounterTypes) { // TODO Auto-generated method stub return dao.getAllEncounterCurrentDate(date,encounterTypes); }*/ public Set<Encounter> getEncountersByPatientAndDate(String date,Set<EncounterType> encounterTypes){ return dao.getEncountersByPatientAndDate(date,encounterTypes); } public Set<Encounter> getEncountersByPatientAndDateFromObs(String date){ return dao.getEncountersByPatientAndDateFromObs(date); } public List<Obs> getObsInstanceForDiagnosis(Encounter encounter,Concept concept){ return dao.getObsInstanceForDiagnosis(encounter,concept); } }