/** * Gets the list of all non-retired concept names which are index terms in a given locale * * @param locale the locale for the index terms to return * @return a collection of concept names which are index terms in the given locale * @since 1.7 */ public Collection<ConceptName> getIndexTermsForLocale(Locale locale) { return getIndexTerms().stream() .filter(n -> n.getLocale().equals(locale)) .collect(Collectors.toList()); }
/** * Convenience method for determining whether this is a synonym in a given locale. * * @param locale The locale in which this synonym should belong * @return true if the concept name is marked as a synonym in the given locale, otherwise false */ public Boolean isSynonymInLocale(Locale locale) { return getConceptNameType() == null && locale.equals(getLocale()); }
/** * Returns all names available in a specific locale. <br> * <br> * This is recommended when managing the concept dictionary. * * @param locale locale for which names should be returned * @return Collection of ConceptNames with the given locale */ public Collection<ConceptName> getNames(Locale locale) { return getNames().stream() .filter(n -> n.getLocale().equals(locale)) .collect(Collectors.toSet()); }
/** * Returns all names available for locale language "or" country. <br> * <br> * * @param locale locale for which names should be returned * @return Collection of ConceptNames with the given locale language or country */ private Collection<ConceptName> getPartiallyCompatibleNames(Locale locale) { String language = locale.getLanguage(); String country = locale.getCountry(); return getNames().stream() .filter(n -> language.equals(n.getLocale().getLanguage()) || StringUtils.isNotBlank(country) && country.equals(n.getLocale().getCountry())) .collect(Collectors.toSet()); }
/** * Convenience method that returns a set of all the locales in which names have been added for * this concept. * * @return a set of all locales for names for this concept * @since 1.7 * @should return all locales for conceptNames for this concept without duplicates */ public Set<Locale> getAllConceptNameLocales() { if (getNames().isEmpty()) { if (log.isDebugEnabled()) { log.debug("The Concept with id: " + conceptId + " has no names"); } return null; } Set<Locale> locales = new HashSet<>(); for (ConceptName cn : getNames()) { locales.add(cn.getLocale()); } return locales; }
/** * Gets the explicitly specified short name for a locale. * * @param locale locale for which to find a short name * @return the short name, or null if none has been explicitly set */ public ConceptName getShortNameInLocale(Locale locale) { ConceptName bestMatch = null; if (locale != null && !getShortNames().isEmpty()) { for (ConceptName shortName : getShortNames()) { Locale nameLocale = shortName.getLocale(); if (nameLocale.equals(locale)) { return shortName; } // test for partially locale match - any language matches takes precedence over country matches. if (OpenmrsUtil.nullSafeEquals(locale.getLanguage(), nameLocale.getLanguage())) { bestMatch = shortName; } else if (bestMatch == null && StringUtils.isNotBlank(locale.getCountry()) && locale.getCountry().equals(nameLocale.getCountry())) { bestMatch = shortName; } } } return bestMatch; }
/** * Convenience method for determining whether this is an index Term for a given locale. * * @param locale The locale in which this concept name should belong as an index term * @return true if the name is marked as an index term, otherwise false */ public Boolean isIndexTermInLocale(Locale locale) { return getConceptNameType() != null && getConceptNameType().equals(ConceptNameType.INDEX_TERM) && locale.equals(getLocale()); }
/** * Gets the synonyms in the given locale. Returns a list of names from the same language with * the preferred synonym sorted first, or an empty list if none found. * * @param locale * @return Collection of ConceptNames which are synonyms for the Concept in the given locale */ public Collection<ConceptName> getSynonyms(Locale locale) { List<ConceptName> syns = new ArrayList<>(); ConceptName preferredConceptName = null; for (ConceptName possibleSynonymInLoc : getSynonyms()) { if (locale.equals(possibleSynonymInLoc.getLocale())) { if (possibleSynonymInLoc.isPreferred()) { preferredConceptName = possibleSynonymInLoc; } else { syns.add(possibleSynonymInLoc); } } } // Add preferred name first in the list. if (preferredConceptName != null) { syns.add(0, preferredConceptName); } log.debug("returning: " + syns); return syns; }
compatibleNames = new ArrayList<>(); for (ConceptName possibleName : getNames()) { if (LocaleUtility.areCompatible(possibleName.getLocale(), desiredLocale)) { compatibleNames.add(possibleName);
for (ConceptName conceptName : getPartiallyCompatibleNames(locale)) { if (ObjectUtils.nullSafeEquals(conceptName.isFullySpecifiedName(), true)) { Locale nameLocale = conceptName.getLocale(); if (locale.getLanguage().equals(nameLocale.getLanguage())) { return conceptName;
if (possibleName.getLocale().equals(locale) && ((shortestNameForLocale == null) || (possibleName.getName().length() < shortestNameForLocale .getName().length()))) {
conceptName.setConceptNameType(ConceptNameType.FULLY_SPECIFIED); } else { if (conceptName.isPreferred() && !conceptName.isIndexTerm() && conceptName.getLocale() != null) { ConceptName prefName = getPreferredName(conceptName.getLocale()); if (prefName != null) { prefName.setLocalePreferred(false); if (conceptName.isFullySpecifiedName() && conceptName.getLocale() != null) { ConceptName fullySpecName = getFullySpecifiedName(conceptName.getLocale()); if (fullySpecName != null) { fullySpecName.setConceptNameType(null); } else if (conceptName.isShort() && conceptName.getLocale() != null) { ConceptName shortName = getShortNameInLocale(conceptName.getLocale()); if (shortName != null) { shortName.setConceptNameType(null);
private void ensurePreferredNameForLocale(Concept concept) { //Ensure if there's a name for a locale that at least one suitable name is marked preferred in that locale //Order of preference is: // 1) any name that concept.getPreferredName returns // 2) fully specified name // 3) any synonym // short name and index terms are never preferred. Set<Locale> checkedLocales = new HashSet<>(); for (ConceptName n : concept.getNames()) { Locale locale = n.getLocale(); if (checkedLocales.contains(locale)) { continue; //we've already checked this locale } //getPreferredName(locale) returns any name marked preferred, //or the fullySpecifiedName even if not marked preferred ConceptName possiblePreferredName = concept.getPreferredName(locale); if (possiblePreferredName != null) { //do nothing yet, but stick around to setLocalePreferred(true) } else if (concept.getFullySpecifiedName(locale) != null) { possiblePreferredName = concept.getFullySpecifiedName(locale); } else if (!CollectionUtils.isEmpty(concept.getSynonyms(locale))) { concept.getSynonyms(locale).iterator().next().setLocalePreferred(true); } //index terms are never used as preferred name if (possiblePreferredName != null) { //there may have been none possiblePreferredName.setLocalePreferred(true); } checkedLocales.add(locale); } }
/** * Sets the specified name as the short name for the locale and the current shortName(if any) * ceases to be the short name for the locale. * * @param shortName the new shortName to set * @should set the concept name type of the specified name to short * @should convert the previous shortName if any to a synonym * @should add the name to the list of names if it not among them before * @should void old short name if new one is blank (do not save blanks!) */ public void setShortName(ConceptName shortName) { if (shortName != null) { if (shortName.getLocale() == null) { throw new APIException(CONCEPT_NAME_LOCALE_NULL, (Object[]) null); } ConceptName oldShortName = getShortNameInLocale(shortName.getLocale()); if (oldShortName != null) { oldShortName.setConceptNameType(null); } shortName.setConceptNameType(ConceptNameType.SHORT); if (StringUtils.isNotBlank(shortName.getName()) && (shortName.getConceptNameId() == null || !getNames().contains(shortName))) { //add this name, if it is new or not among this concept's names addName(shortName); } } else { throw new APIException("Concept.error.shortName.null", (Object[]) null); } }
/** * Checks if the conceptName is unique among all unvoided preferred and fully specified names * across all other un-retired concepts except the concept it is associated to. * * @param connection The datbase Connection * @param conceptName The conceptName to be validated * @return true if the conceptName is unique, otherwise false */ private boolean isNameUniqueInLocale(JdbcConnection connection, ConceptName conceptName, int conceptId) { int duplicates = getInt(connection, "SELECT count(*) FROM concept_name cn, concept c WHERE cn.concept_id = c.concept_id AND (cn.concept_name_type = '" + ConceptNameType.FULLY_SPECIFIED + "' OR cn.locale_preferred = '1') AND cn.voided = '0' AND cn.name = '" + HibernateUtil.escapeSqlWildcards(conceptName.getName(), connection.getUnderlyingConnection()) + "' AND cn.locale = '" + HibernateUtil.escapeSqlWildcards(conceptName.getLocale().toString(), connection .getUnderlyingConnection()) + "' AND c.retired = '0' AND c.concept_id != " + conceptId); return duplicates == 0; }
/** * Sets the specified name as the fully specified name for the locale and the current fully * specified (if any) ceases to be the fully specified name for the locale. * * @param fullySpecifiedName the new fully specified name to set * @should set the concept name type of the specified name to fully specified * @should convert the previous fully specified name if any to a synonym * @should add the name to the list of names if it not among them before */ public void setFullySpecifiedName(ConceptName fullySpecifiedName) { if (fullySpecifiedName == null || fullySpecifiedName.getLocale() == null) { throw new APIException(CONCEPT_NAME_LOCALE_NULL, (Object[]) null); } else if (fullySpecifiedName.getVoided()) { throw new APIException("Concept.error.fullySpecifiedName.null", (Object[]) null); } ConceptName oldFullySpecifiedName = getFullySpecifiedName(fullySpecifiedName.getLocale()); if (oldFullySpecifiedName != null) { oldFullySpecifiedName.setConceptNameType(null); } fullySpecifiedName.setConceptNameType(ConceptNameType.FULLY_SPECIFIED); //add this name, if it is new or not among this concept's names if (fullySpecifiedName.getConceptNameId() == null || !getNames().contains(fullySpecifiedName)) { addName(fullySpecifiedName); } }
/** * This test fetches all concepts in the xml test dataset and ensures that every locale for a * concept name is among those listed in the global property 'locale.allowed.list' and default * locale. NOTE that it doesn't test a particular API method directly. */ @Test public void saveConcept_shouldNotAcceptALocaleThatIsNeitherAmongTheLocaleAllowedListNorADefaultLocale() { List<Concept> concepts = Context.getConceptService().getAllConcepts(); Set<Locale> allowedLocales = LocaleUtility.getLocalesInOrder(); for (Concept concept : concepts) { if (!CollectionUtils.isEmpty(concept.getNames())) { for (ConceptName cn : concept.getNames()) { Assert.assertTrue("The locale '" + cn.getLocale() + "' of conceptName with id: " + cn.getConceptNameId() + " is not among those listed in the global property 'locale.allowed.list'", allowedLocales .contains(cn.getLocale())); } } } }
/** * @see Concept#getFullySpecifiedName(Locale) */ @Test public void getFullySpecifiedName_shouldReturnTheNameMarkedAsFullySpecifiedForTheGivenLocale() { Locale primaryLocale = Locale.US; Concept testConcept = createConcept(1, primaryLocale); ConceptName fullySpecifiedName_FR = createConceptName(3, "Docteur", new Locale("fr"), ConceptNameType.FULLY_SPECIFIED, true); testConcept.addName(fullySpecifiedName_FR); Assert.assertEquals(primaryLocale, testConcept.getFullySpecifiedName(primaryLocale).getLocale()); Assert.assertEquals(ConceptNameType.FULLY_SPECIFIED, testConcept.getFullySpecifiedName(primaryLocale).getConceptNameType()); }
@Test public void validate_shouldPassIfTheDuplicateNameInTheLocaleForTheConceptBeingValidatedIsVoided() { ConceptName otherName = conceptService.getConceptName(1439); //sanity check since names should only be unique amongst preferred and fully specified names Assert.assertTrue(otherName.isFullySpecifiedName() || otherName.isPreferred()); Assert.assertFalse(otherName.getVoided()); Assert.assertFalse(otherName.getConcept().getRetired()); //change to a duplicate name in the same locale ConceptName duplicateName = conceptService.getConceptName(2477); duplicateName.setName(otherName.getName()); Concept concept = duplicateName.getConcept(); concept.setPreferredName(duplicateName); //ensure that the name has been marked as preferred in its locale Assert.assertEquals(duplicateName, concept.getPreferredName(duplicateName.getLocale())); Assert.assertTrue(duplicateName.isPreferred()); duplicateName.setVoided(true); Errors errors = new BindException(concept, "concept"); validator.validate(concept, errors); Assert.assertFalse(errors.hasErrors()); }