Java tutorial
/** * This Source Code Form is subject to the terms of the Mozilla Public License, * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. * * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS * graphic logo is a trademark of OpenMRS Inc. */ package org.openmrs.web.controller; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.collections.FactoryUtils; import org.apache.commons.collections.ListUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.Concept; import org.openmrs.ConceptAnswer; import org.openmrs.ConceptComplex; import org.openmrs.ConceptDescription; import org.openmrs.ConceptMap; import org.openmrs.ConceptMapType; import org.openmrs.ConceptName; import org.openmrs.ConceptNumeric; import org.openmrs.ConceptReferenceTerm; import org.openmrs.ConceptSet; import org.openmrs.Drug; import org.openmrs.Form; import org.openmrs.PersonAttributeType; import org.openmrs.Program; import org.openmrs.ProgramWorkflow; import org.openmrs.ProgramWorkflowState; import org.openmrs.api.APIException; import org.openmrs.api.ConceptNameType; import org.openmrs.api.ConceptService; import org.openmrs.api.ConceptsLockedException; import org.openmrs.api.DuplicateConceptNameException; import org.openmrs.api.context.Context; import org.openmrs.module.web.extension.ConceptUsageExtension; import org.openmrs.module.web.extension.provider.Link; import org.openmrs.propertyeditor.ConceptAnswersEditor; import org.openmrs.propertyeditor.ConceptClassEditor; import org.openmrs.propertyeditor.ConceptDatatypeEditor; import org.openmrs.propertyeditor.ConceptMapTypeEditor; import org.openmrs.propertyeditor.ConceptReferenceTermEditor; import org.openmrs.propertyeditor.ConceptSetsEditor; import org.openmrs.propertyeditor.ConceptSourceEditor; import org.openmrs.util.OpenmrsConstants; import org.openmrs.util.OpenmrsUtil; import org.openmrs.util.PrivilegeConstants; import org.openmrs.validator.ValidateUtil; import org.openmrs.web.WebConstants; import org.openmrs.web.controller.concept.ConceptReferenceTermWebValidator; import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.beans.propertyeditors.CustomNumberEditor; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.util.StringUtils; import org.springframework.validation.BindException; import org.springframework.validation.Errors; import org.springframework.web.bind.ServletRequestDataBinder; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.SimpleFormController; import org.springframework.web.servlet.view.RedirectView; /** * This is the controlling class for the conceptForm.jsp page. It initBinder and formBackingObject * are called before page load. After submission, formBackingObject (because we're not a session * form), processFormSubmission, and onSubmit methods are called * * @see org.openmrs.Concept */ public class ConceptFormController extends SimpleFormController { /** Logger for this class and subclasses */ private static final Log log = LogFactory.getLog(ConceptFormController.class); /** * Allows for other Objects to be used as values in input tags. Normally, only strings and lists * are expected * * @see org.springframework.web.servlet.mvc.BaseCommandController#initBinder(javax.servlet.http.HttpServletRequest, * org.springframework.web.bind.ServletRequestDataBinder) */ @Override protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception { super.initBinder(request, binder); ConceptFormBackingObject commandObject = (ConceptFormBackingObject) binder.getTarget(); NumberFormat nf = NumberFormat.getInstance(Context.getLocale()); binder.registerCustomEditor(java.lang.Integer.class, new CustomNumberEditor(java.lang.Integer.class, nf, true)); binder.registerCustomEditor(java.lang.Double.class, new CustomNumberEditor(java.lang.Double.class, nf, true)); binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor( SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT, Context.getLocale()), true)); binder.registerCustomEditor(org.openmrs.ConceptClass.class, new ConceptClassEditor()); binder.registerCustomEditor(org.openmrs.ConceptDatatype.class, new ConceptDatatypeEditor()); binder.registerCustomEditor(java.util.Collection.class, "concept.conceptSets", new ConceptSetsEditor(commandObject.getConcept().getConceptSets())); binder.registerCustomEditor(java.util.Collection.class, "concept.answers", new ConceptAnswersEditor(commandObject.getConcept().getAnswers(true))); binder.registerCustomEditor(org.openmrs.ConceptSource.class, new ConceptSourceEditor()); binder.registerCustomEditor(ConceptMapType.class, new ConceptMapTypeEditor()); binder.registerCustomEditor(ConceptReferenceTerm.class, new ConceptReferenceTermEditor()); } /** * @see org.springframework.web.servlet.mvc.AbstractFormController#processFormSubmission(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse, java.lang.Object, * org.springframework.validation.BindException) */ @Override protected ModelAndView processFormSubmission(HttpServletRequest request, HttpServletResponse response, Object object, BindException errors) throws Exception { if (getMessageSourceAccessor().getMessage("Concept.cancel").equals(request.getParameter("action"))) { return new ModelAndView(new RedirectView("index.htm")); } Concept concept = ((ConceptFormBackingObject) object).getConcept(); ConceptService cs = Context.getConceptService(); // check to see if they clicked next/previous concept: String jumpAction = request.getParameter("jumpAction"); if (jumpAction != null) { Concept newConcept = null; if ("previous".equals(jumpAction)) { newConcept = cs.getPrevConcept(concept); } else if ("next".equals(jumpAction)) { newConcept = cs.getNextConcept(concept); } if (newConcept != null) { return new ModelAndView( new RedirectView(getSuccessView() + "?conceptId=" + newConcept.getConceptId())); } else { return new ModelAndView(new RedirectView(getSuccessView())); } } return super.processFormSubmission(request, response, object, errors); } /** * The onSubmit function receives the form/command object that was modified by the input form * and saves it to the db * * @see org.springframework.web.servlet.mvc.SimpleFormController#onSubmit(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse, java.lang.Object, * org.springframework.validation.BindException) * @should display numeric values from table * @should copy numeric values into numeric concepts * @should return a concept with a null id if no match is found * @should void a synonym marked as preferred when it is removed * @should set the local preferred name * @should add a new Concept map to an existing concept * @should remove a concept map from an existing concept * @should ignore new concept map row if the user did not select a term * @should add a new Concept map when creating a concept * @should not save changes if there are validation errors */ @Override protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object obj, BindException errors) throws Exception { HttpSession httpSession = request.getSession(); ConceptService cs = Context.getConceptService(); if (Context.isAuthenticated()) { ConceptFormBackingObject conceptBackingObject = (ConceptFormBackingObject) obj; MessageSourceAccessor msa = getMessageSourceAccessor(); String action = request.getParameter("action"); if (action.equals(msa.getMessage("general.retire"))) { Concept concept = conceptBackingObject.getConcept(); try { String reason = request.getParameter("retiredReason"); if (!StringUtils.hasText(reason)) { reason = msa.getMessage("general.default.retireReason"); } cs.retireConcept(concept, reason); httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Concept.concept.retired.successFully"); return new ModelAndView( new RedirectView(getSuccessView() + "?conceptId=" + concept.getConceptId())); } catch (APIException e) { log.error("Unable to Retire concept because an error occurred: " + concept, e); httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "general.cannot.retire"); } // return to the edit screen because an error was thrown return new ModelAndView( new RedirectView(getSuccessView() + "?conceptId=" + concept.getConceptId())); } else if (action.equals(msa.getMessage("general.unretire"))) { Concept concept = conceptBackingObject.getConcept(); try { concept.setRetired(false); cs.saveConcept(concept); httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Concept.concept.unRetired.successFully"); return new ModelAndView( new RedirectView(getSuccessView() + "?conceptId=" + concept.getConceptId())); } catch (ConceptsLockedException cle) { log.error("Tried to unretire concept while concepts were locked", cle); httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "Concept.concepts.locked.unRetire"); } catch (DuplicateConceptNameException e) { log.error("Tried to unretire concept with a duplicate name", e); httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "general.cannot.unretire"); } catch (APIException e) { log.error("Error while trying to unretire concept", e); httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "general.cannot.unretire"); } // return to the edit screen because an error was thrown return new ModelAndView( new RedirectView(getSuccessView() + "?conceptId=" + concept.getConceptId())); } else if (action.equals(msa.getMessage("Concept.delete", "Delete Concept"))) { Concept concept = conceptBackingObject.getConcept(); try { cs.purgeConcept(concept); httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Concept.deleted"); return new ModelAndView(new RedirectView("index.htm")); } catch (ConceptsLockedException cle) { log.error("Tried to delete concept while concepts were locked", cle); httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "Concept.concepts.locked"); } catch (DataIntegrityViolationException e) { log.error("Unable to delete a concept because it is in use: " + concept, e); httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "Concept.cannot.delete"); } catch (Exception e) { log.error("Unable to delete concept because an error occurred: " + concept, e); httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "Concept.cannot.delete"); } // return to the edit screen because an error was thrown return new ModelAndView( new RedirectView(getSuccessView() + "?conceptId=" + concept.getConceptId())); } else { Concept concept = conceptBackingObject.getConceptFromFormData(); //if the user is editing a concept, initialise the associated creator property //this is aimed at avoiding a lazy initialisation exception when rendering //the jsp after validation has failed if (concept.getConceptId() != null) { concept.getCreator().getPersonName(); } try { errors.pushNestedPath("concept"); ValidateUtil.validate(concept, errors); errors.popNestedPath(); validateConceptUsesPersistedObjects(concept, errors); if (!errors.hasErrors()) { if (action.equals(msa.getMessage("Concept.cancel"))) { return new ModelAndView(new RedirectView("index.htm")); } cs.saveConcept(concept); httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Concept.saved"); if (action.equals(msa.getMessage("Concept.save"))) { return new ModelAndView( new RedirectView("concept.htm" + "?conceptId=" + concept.getConceptId())); } return new ModelAndView( new RedirectView(getSuccessView() + "?conceptId=" + concept.getConceptId())); } httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "Concept.cannot.save"); } catch (ConceptsLockedException cle) { errors.popNestedPath(); log.error("Tried to save concept while concepts were locked", cle); httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "Concept.concepts.locked"); errors.reject("concept", "Concept.concepts.locked"); } catch (DuplicateConceptNameException e) { errors.popNestedPath(); log.error("Tried to save concept with a duplicate name", e); httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "Concept.cannot.save"); errors.rejectValue("concept", "Concept.name.duplicate"); } catch (APIException e) { errors.popNestedPath(); log.error("Error while trying to save concept", e); httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "Concept.cannot.save"); errors.reject("concept", "Concept.cannot.save"); } } // return to the edit form because an error was thrown return showForm(request, response, errors); } return new ModelAndView(new RedirectView(getFormView())); } /** * @param concept * @param errors * @should add error if source is not saved * @should add error if map type is not saved * @should add error if term b is not saved */ void validateConceptUsesPersistedObjects(Concept concept, Errors errors) { if (concept.getConceptMappings() != null) { int index = 0; for (ConceptMap conceptMap : concept.getConceptMappings()) { errors.pushNestedPath("conceptMappings[" + index + "].conceptReferenceTerm"); new ConceptReferenceTermWebValidator().validate(conceptMap.getConceptReferenceTerm(), errors); errors.popNestedPath(); } } } /** * This is called prior to displaying a form for the first time. It tells Spring the * form/command object to load into the request * * @see org.springframework.web.servlet.mvc.AbstractFormController#formBackingObject(javax.servlet.http.HttpServletRequest) */ @Override protected ConceptFormBackingObject formBackingObject(HttpServletRequest request) throws ServletException { String conceptId = request.getParameter("conceptId"); try { Concept concept = null; if (StringUtils.hasText(conceptId)) { concept = Context.getConceptService().getConcept(Integer.valueOf(conceptId)); } if (concept == null) { return new ConceptFormBackingObject(new Concept()); } else { return new ConceptFormBackingObject(concept); } } catch (NumberFormatException ex) { return new ConceptFormBackingObject(new Concept()); } } /** * Called prior to form display. Allows for data to be put in the request to be used in the view * * @see org.springframework.web.servlet.mvc.SimpleFormController#referenceData(javax.servlet.http.HttpServletRequest) */ @Override protected Map<String, Object> referenceData(HttpServletRequest request) throws Exception { Map<String, Object> map = new HashMap<String, Object>(); ConceptService cs = Context.getConceptService(); String defaultVerbose = "false"; if (Context.isAuthenticated()) { defaultVerbose = Context.getAuthenticatedUser() .getUserProperty(OpenmrsConstants.USER_PROPERTY_SHOW_VERBOSE); } map.put("defaultVerbose", defaultVerbose.equals("true") ? true : false); map.put("tags", cs.getAllConceptNameTags()); //get complete class and datatype lists if (Context.hasPrivilege(PrivilegeConstants.GET_CONCEPT_CLASSES)) { map.put("classes", cs.getAllConceptClasses()); } if (Context.hasPrivilege(PrivilegeConstants.GET_CONCEPT_DATATYPES)) { map.put("datatypes", cs.getAllConceptDatatypes()); } String conceptId = request.getParameter("conceptId"); boolean dataTypeReadOnly = false; if (Context.hasPrivilege(PrivilegeConstants.GET_OBS)) { try { Concept concept = cs.getConcept(Integer.valueOf(conceptId)); dataTypeReadOnly = cs.hasAnyObservation(concept); if (concept != null && concept.getDatatype().isBoolean()) { map.put("isBoolean", true); } } catch (NumberFormatException ex) { // nothing to do } } map.put("dataTypeReadOnly", dataTypeReadOnly); //get complex handlers map.put("handlers", Context.getObsService().getHandlers()); // make spring locale available to jsp map.put("locale", Context.getLocale()); // should be same string format as conceptNamesByLocale map keys return map; } /** * Class that represents all data on this form */ public class ConceptFormBackingObject { public Concept concept = null; public List<Locale> locales = null; public Map<Locale, ConceptName> namesByLocale = new HashMap<Locale, ConceptName>(); public Map<Locale, ConceptName> shortNamesByLocale = new HashMap<Locale, ConceptName>(); public Map<Locale, List<ConceptName>> synonymsByLocale = new HashMap<Locale, List<ConceptName>>(); public Map<Locale, ConceptDescription> descriptionsByLocale = new HashMap<Locale, ConceptDescription>(); public Map<Locale, List<ConceptName>> indexTermsByLocale = new HashMap<Locale, List<ConceptName>>(); public Map<Locale, Map<String, String>> conceptAnswersByLocale = new HashMap<Locale, Map<String, String>>(); public List<ConceptMap> conceptMappings; // a "lazy list" version of the concept.getMappings() list /** The list of drugs for its concept object */ public List<Drug> conceptDrugList = new ArrayList<Drug>(); public Double hiAbsolute; public Double lowAbsolute; public Double lowCritical; public Double hiCritical; public Double lowNormal; public Double hiNormal; public boolean allowDecimal = false; public Integer displayPrecision; public String units; public String handlerKey; public Map<Locale, String> preferredNamesByLocale = new HashMap<Locale, String>(); /** * Default constructor must take in a Concept object to create itself * * @param concept The concept for this page */ @SuppressWarnings("unchecked") public ConceptFormBackingObject(Concept concept) { this.concept = concept; this.locales = Context.getAdministrationService().getAllowedLocales(); for (Locale locale : locales) { ConceptName preferredName = concept.getPreferredName(locale); preferredNamesByLocale.put(locale, (preferredName != null ? preferredName.getName() : null)); namesByLocale.put(locale, concept.getFullySpecifiedName(locale)); shortNamesByLocale.put(locale, concept.getShortNameInLocale(locale)); synonymsByLocale.put(locale, (List<ConceptName>) concept.getSynonyms(locale)); descriptionsByLocale.put(locale, concept.getDescription(locale, true)); indexTermsByLocale.put(locale, (List<ConceptName>) concept.getIndexTermsForLocale(locale)); conceptAnswersByLocale.put(locale, (Map<String, String>) getConceptAnswers(locale)); // put in default values so the binding doesn't fail if (namesByLocale.get(locale) == null) { namesByLocale.put(locale, new ConceptName(null, locale)); } if (shortNamesByLocale.get(locale) == null) { shortNamesByLocale.put(locale, new ConceptName(null, locale)); } if (descriptionsByLocale.get(locale) == null) { descriptionsByLocale.put(locale, new ConceptDescription(null, locale)); } synonymsByLocale.put(locale, ListUtils.lazyList(synonymsByLocale.get(locale), FactoryUtils.instantiateFactory(ConceptName.class))); indexTermsByLocale.put(locale, ListUtils.lazyList(indexTermsByLocale.get(locale), FactoryUtils.instantiateFactory(ConceptName.class))); } // turn the list objects into lazy lists conceptMappings = ListUtils.lazyList(new ArrayList<ConceptMap>(concept.getConceptMappings()), FactoryUtils.instantiateFactory(ConceptMap.class)); if (concept instanceof ConceptNumeric) { ConceptNumeric cn = (ConceptNumeric) concept; this.hiAbsolute = cn.getHiAbsolute(); this.lowAbsolute = cn.getLowAbsolute(); this.lowCritical = cn.getLowCritical(); this.hiCritical = cn.getHiCritical(); this.lowNormal = cn.getLowNormal(); this.hiNormal = cn.getHiNormal(); this.allowDecimal = cn.getAllowDecimal(); this.displayPrecision = cn.getDisplayPrecision(); this.units = cn.getUnits(); } else if (concept instanceof ConceptComplex) { ConceptComplex complex = (ConceptComplex) concept; this.handlerKey = complex.getHandler(); } if (concept.getConceptClass() != null && OpenmrsUtil.nullSafeEquals(concept.getConceptClass().getName(), "Drug")) { this.conceptDrugList.addAll(Context.getConceptService().getDrugsByConcept(concept)); } } /** * This method takes all the form data from the input boxes and puts it onto the concept * object so that it can be saved to the database * * @return the concept to be saved to the database * @should set concept on concept answers */ public Concept getConceptFromFormData() { // add all the new names/descriptions to the concept for (Locale locale : locales) { ConceptName fullySpecifiedNameInLocale = namesByLocale.get(locale); if (StringUtils.hasText(fullySpecifiedNameInLocale.getName())) { concept.setFullySpecifiedName(fullySpecifiedNameInLocale); if (fullySpecifiedNameInLocale.getName().equalsIgnoreCase(preferredNamesByLocale.get(locale))) { concept.setPreferredName(fullySpecifiedNameInLocale); } } ConceptName shortNameInLocale = shortNamesByLocale.get(locale); concept.setShortName(shortNameInLocale); for (ConceptName synonym : synonymsByLocale.get(locale)) { if (synonym != null && StringUtils.hasText(synonym.getName())) { synonym.setLocale(locale); //donot set voided names otherwise setPreferredname() will throw an exception if (synonym.getName().equalsIgnoreCase(preferredNamesByLocale.get(locale)) && !synonym.isVoided()) { concept.setPreferredName(synonym); } else if (!concept.getNames().contains(synonym) && !concept.hasName(synonym.getName(), locale)) { //we leave systemTag field as null to indicate that it is a synonym concept.addName(synonym); } //if the user removed this synonym with a void reason, returned to the page due validation errors, //then they chose to cancel the removal of the synonym but forgot to clear the void reason text box, //clear the text if (!synonym.isVoided()) { synonym.setVoidReason(null); } else { // always set the default void/retire reason synonym.setVoidReason( Context.getMessageSourceService().getMessage("general.default.voidReason")); } } } for (ConceptName indexTerm : indexTermsByLocale.get(locale)) { if (indexTerm != null && StringUtils.hasText(indexTerm.getName())) { if (!concept.getNames().contains(indexTerm) && !concept.hasName(indexTerm.getName(), locale)) { indexTerm.setConceptNameType(ConceptNameType.INDEX_TERM); indexTerm.setLocale(locale); concept.addName(indexTerm); } if (!indexTerm.isVoided()) { indexTerm.setVoidReason(null); } else if (indexTerm.isVoided() && !StringUtils.hasText(indexTerm.getVoidReason())) { indexTerm.setVoidReason(Context.getMessageSourceService() .getMessage("Concept.name.default.voidReason")); } } } ConceptDescription descInLocale = descriptionsByLocale.get(locale); if (!StringUtils.hasText(descInLocale.getDescription())) { concept.removeDescription(descInLocale); } else if (!concept.getDescriptions().contains(descInLocale)) { concept.addDescription(descInLocale); } } // add in all the mappings //store ids of already mapped terms so that we don't map a term multiple times Set<Integer> mappedTermIds = null; for (ConceptMap map : conceptMappings) { if (mappedTermIds == null) { mappedTermIds = new HashSet<Integer>(); } if (map.getConceptReferenceTerm().getConceptReferenceTermId() == null) { //if the user didn't select an existing term via the reference term autocomplete // OR the user added a new row but entered nothing, ignore if (map.getConceptMapId() == null) { continue; } // because of the _mappings[x].conceptReferenceTerm input name in the jsp, the ids for // terms will be empty for deleted mappings, remove those from the concept object now. concept.removeConceptMapping(map); } else if (!mappedTermIds.add(map.getConceptReferenceTerm().getConceptReferenceTermId())) { //skip past this mapping because its term is already in use by another mapping for this concept continue; } else if (!concept.getConceptMappings().contains(map)) { // assumes null sources also don't get here concept.addConceptMapping(map); } } // if the user unchecked the concept sets box, erase past saved sets if (!concept.isSet() && concept.getConceptSets() != null) { concept.getConceptSets().clear(); } // if the user changed the datatype to be non "Coded", erase past saved datatypes if (!concept.getDatatype().isCoded() && concept.getAnswers(true) != null) { concept.getAnswers(true).clear(); } else { for (ConceptAnswer ca : concept.getAnswers(true)) { ca.setConcept(concept); } } // add in subobject specific code if (concept.getDatatype().getName().equals("Numeric")) { ConceptNumeric cn; if (concept instanceof ConceptNumeric) { cn = (ConceptNumeric) concept; } else { cn = new ConceptNumeric(concept); } cn.setHiAbsolute(hiAbsolute); cn.setLowAbsolute(lowAbsolute); cn.setHiCritical(hiCritical); cn.setLowCritical(lowCritical); cn.setHiNormal(hiNormal); cn.setLowNormal(lowNormal); cn.setAllowDecimal(allowDecimal); cn.setDisplayPrecision(displayPrecision); cn.setUnits(units); concept = cn; } else if (concept.getDatatype().getName().equals("Complex")) { ConceptComplex complexConcept; if (concept instanceof ConceptComplex) { complexConcept = (ConceptComplex) concept; } else { complexConcept = new ConceptComplex(concept); } complexConcept.setHandler(handlerKey); concept = complexConcept; } return concept; } /** * Builds a white-space separated list of concept ids belonging to a concept set * @return white-space separated list */ public String getSetElements() { StringBuilder result = new StringBuilder(); for (ConceptSet set : concept.getConceptSets()) { result.append(set.getConcept().getConceptId()).append(" "); } return result.toString(); } /** * @return the concept */ public Concept getConcept() { return concept; } /** * @param concept the concept to set */ public void setConcept(Concept concept) { this.concept = concept; } /** * @return the locales */ public List<Locale> getLocales() { return locales; } /** * @param locales the locales to set */ public void setLocales(List<Locale> locales) { this.locales = locales; } /** * @return the namesByLocale */ public Map<Locale, ConceptName> getNamesByLocale() { return namesByLocale; } /** * @param namesByLocale the namesByLocale to set */ public void setNamesByLocale(Map<Locale, ConceptName> namesByLocale) { this.namesByLocale = namesByLocale; } /** * @return the shortNamesByLocale */ public Map<Locale, ConceptName> getShortNamesByLocale() { return shortNamesByLocale; } /** * @param shortNamesByLocale the shortNamesByLocale to set */ public void setShortNamesByLocale(Map<Locale, ConceptName> shortNamesByLocale) { this.shortNamesByLocale = shortNamesByLocale; } /** * @return the descriptionsByLocale */ public Map<Locale, ConceptDescription> getDescriptionsByLocale() { return descriptionsByLocale; } /** * @param descriptionsByLocale the descriptionsByLocale to set */ public void setDescriptionsByLocale(Map<Locale, ConceptDescription> descriptionsByLocale) { this.descriptionsByLocale = descriptionsByLocale; } /** * @return the conceptMappings */ public List<ConceptMap> getConceptMappings() { return conceptMappings; } /** * @param conceptMappings the conceptMappings to set */ public void setConceptMappings(List<ConceptMap> conceptMappings) { this.conceptMappings = conceptMappings; } /** * @return the synonymsByLocale */ public Map<Locale, List<ConceptName>> getSynonymsByLocale() { return synonymsByLocale; } /** * @param synonymsByLocale the synonymsByLocale to set */ public void setSynonymsByLocale(Map<Locale, List<ConceptName>> synonymsByLocale) { this.synonymsByLocale = synonymsByLocale; } /** * @return the hiAbsolute */ public Double getHiAbsolute() { return hiAbsolute; } /** * @param hiAbsolute the hiAbsolute to set */ public void setHiAbsolute(Double hiAbsolute) { this.hiAbsolute = hiAbsolute; } /** * @return the lowAbsolute */ public Double getLowAbsolute() { return lowAbsolute; } /** * @param lowAbsolute the lowAbsolute to set */ public void setLowAbsolute(Double lowAbsolute) { this.lowAbsolute = lowAbsolute; } /** * @return the lowCritical */ public Double getLowCritical() { return lowCritical; } /** * @param lowCritical the lowCritical to set */ public void setLowCritical(Double lowCritical) { this.lowCritical = lowCritical; } /** * @return the hiCritical */ public Double getHiCritical() { return hiCritical; } /** * @param hiCritical the hiCritical to set */ public void setHiCritical(Double hiCritical) { this.hiCritical = hiCritical; } /** * @return the lowNormal */ public Double getLowNormal() { return lowNormal; } /** * @param lowNormal the lowNormal to set */ public void setLowNormal(Double lowNormal) { this.lowNormal = lowNormal; } /** * @return the hiNormal */ public Double getHiNormal() { return hiNormal; } /** * @param hiNormal the hiNormal to set */ public void setHiNormal(Double hiNormal) { this.hiNormal = hiNormal; } /** * @return the allowDecimal */ public boolean isAllowDecimal() { return allowDecimal; } /** * @param allowDecimal the allowDecimal to set */ public void setAllowDecimal(boolean allowDecimal) { this.allowDecimal = allowDecimal; } /** * @return the units */ public String getUnits() { return units; } /** * @param units the units to set */ public void setUnits(String units) { this.units = units; } /** * @return the handlerKey */ public String getHandlerKey() { return handlerKey; } /** * @param handlerKey the handlerKey to set */ public void setHandlerKey(String handlerKey) { this.handlerKey = handlerKey; } /** * @return the indexTermsByLocale */ public Map<Locale, List<ConceptName>> getIndexTermsByLocale() { return indexTermsByLocale; } /** * @param indexTermsByLocale the indexTermsByLocale to set */ public void setIndexTermsByLocale(Map<Locale, List<ConceptName>> indexTermsByLocale) { this.indexTermsByLocale = indexTermsByLocale; } /** * Get the forms that this concept is declared to be used in * * @return list of forms */ public List<Form> getFormsInUse() { return Context.getFormService().getFormsContainingConcept(concept); } /** * * Get the list of extensions/metadata and the specific instances of them that use this * concept. * * @return list of {@link ConceptUsageExtension} */ public List<ConceptUsageExtension> getConceptUsage() { List<ConceptUsageExtension> togo = new ArrayList<ConceptUsageExtension>(); // Forms List<Link> forms = new ArrayList<Link>(); for (Form form : Context.getFormService().getFormsContainingConcept(concept)) { Link link = new Link(form.getName(), "/admin/forms/formEdit.form?formId=" + form.getFormId()); link.setStrike(form.getRetired()); forms.add(link); } togo.add(new ConceptUsageExtension("dictionary.forms", forms, PrivilegeConstants.GET_FORMS)); // Drugs List<Link> drugs = new ArrayList<Link>(); for (Drug drug : Context.getConceptService().getDrugsByConcept(concept)) { drugs.add(new Link(drug.getName(), "/admin/concepts/conceptDrug.form?drugId=" + drug.getId())); } togo.add(new ConceptUsageExtension("dictionary.drugs", drugs, PrivilegeConstants.GET_CONCEPTS)); // Programs List<Link> programs = new ArrayList<Link>(); for (Program program : Context.getProgramWorkflowService().getProgramsByConcept(concept)) { programs.add( new Link(program.getName(), "/admin/programs/program.form?programId=" + program.getId())); } togo.add(new ConceptUsageExtension("dictionary.programs", programs, PrivilegeConstants.GET_PROGRAMS)); // ProgramWorkflows List<Link> programWorkflows = new ArrayList<Link>(); for (ProgramWorkflow programWorkflow : Context.getProgramWorkflowService() .getProgramWorkflowsByConcept(concept)) { programWorkflows.add(new Link(programWorkflow.getProgram().getName(), "/admin/programs/workflow.form?programWorkflowId=" + programWorkflow.getId())); } togo.add(new ConceptUsageExtension("dictionary.programworkflows", programWorkflows, PrivilegeConstants.GET_PROGRAMS)); // ProgramWorkflowStates List<Link> programWorkflowStates = new ArrayList<Link>(); for (ProgramWorkflowState programWorkflowState : Context.getProgramWorkflowService() .getProgramWorkflowStatesByConcept(concept)) { programWorkflowStates .add(new Link(programWorkflowState.getProgramWorkflow().getProgram().getName(), "")); } togo.add(new ConceptUsageExtension("dictionary.programworkflowstates", programWorkflowStates, PrivilegeConstants.GET_PROGRAMS)); // PersonAttributeTypes List<Link> personAttributeTypes = new ArrayList<Link>(); for (PersonAttributeType pat : Context.getPersonService().getPersonAttributeTypes(null, Concept.class.getName(), concept.getId(), null)) { personAttributeTypes.add(new Link(pat.getName(), "/admin/person/personAttributeType.form?personAttributeTypeId=" + pat.getId())); } togo.add(new ConceptUsageExtension("dictionary.personattributetypes", personAttributeTypes, PrivilegeConstants.GET_PERSON_ATTRIBUTE_TYPES)); return togo; } /** * Get the number of observations that use this concept. * * @return number of obs using this concept */ public int getNumberOfObsUsingThisConcept() { List<Concept> searchConcepts = Arrays.asList(concept); return Context.getObsService().getObservationCount(null, null, searchConcepts, null, null, null, null, null, null, true); } /** * Get the other concept questions that this concept is declared as an answer for * * @return list of concepts */ public List<Concept> getQuestionsAnswered() { return Context.getConceptService().getConceptsByAnswer(concept); } /** * Get the sets that this concept is declared to be a child member of * * @return list of concept sets */ public List<ConceptSet> getContainedInSets() { return Context.getConceptService().getSetsContainingConcept(concept); } /** * Get the answers for this concept with decoded names. The keys to this map are the * conceptIds or the conceptIds^drugId if applicable * * @return a map with localized concept answers */ private Map<String, String> getConceptAnswers(Locale locale) { Map<String, String> conceptAnswers = new LinkedHashMap<String, String>(); // get concept answers with locale decoded names for (ConceptAnswer answer : concept.getAnswers(true)) { log.debug("getting answers"); String key = answer.getAnswerConcept().getConceptId().toString(); ConceptName cn = answer.getAnswerConcept().getName(locale); String name = ""; if (cn != null) { name = cn.toString(); } if (answer.getAnswerDrug() != null) { // if this answer is a drug, append the drug id information key = key + "^" + answer.getAnswerDrug().getDrugId(); name = answer.getAnswerDrug().getFullName(locale); } if (answer.getAnswerConcept().isRetired()) { name = "<span class='retired'>" + name + "</span>"; } conceptAnswers.put(key, name); } return conceptAnswers; } /** * @see #getConceptAnswers(java.util.Locale) * @return a map with localized concept answers */ public Map<String, String> getConceptAnswers() { return getConceptAnswers(Context.getLocale()); } /** * @return the preferredNamesByLocale */ public Map<Locale, String> getPreferredNamesByLocale() { return preferredNamesByLocale; } /** * @param preferredNamesByLocale the preferredNamesByLocale to set */ public void setPreferredNamesByLocale(Map<Locale, String> preferredNamesByLocale) { this.preferredNamesByLocale = preferredNamesByLocale; } /** * @return the not-null list of its concept drugs */ public List<Drug> getConceptDrugList() { return conceptDrugList; } /** * Sets the list of drugs for its concept object * * @param conceptDrugList the value to be set */ public void setConceptDrugList(List<Drug> conceptDrugList) { this.conceptDrugList = conceptDrugList; } public Integer getDisplayPrecision() { return displayPrecision; } public void setDisplayPrecision(Integer displayPrecision) { this.displayPrecision = displayPrecision; } /** * @return the conceptAnswersByLocale */ public Map<Locale, Map<String, String>> getConceptAnswersByLocale() { return conceptAnswersByLocale; } /** * @param conceptAnswersByLocale the conceptAnswersByLocale to set */ public void setConceptAnswersByLocale(Map<Locale, Map<String, String>> conceptAnswersByLocale) { this.conceptAnswersByLocale = conceptAnswersByLocale; } } }