/**
* 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;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.Vector;
import org.openmrs.util.OpenmrsConstants;
/**
* ConceptWord Concept words are the individual terms of which a concept name is composed. They are
* case-preserving but compare case insensitively.
*/
public class ConceptWord implements java.io.Serializable, Comparable<ConceptWord> {
public static final long serialVersionUID = 888677L;
// Fields
/**
* @since 1.5
*/
private Integer conceptWordId;
private Concept concept;
private ConceptName conceptName;
private String word;
@Deprecated
private String synonym;
private Locale locale;
private Double weight = 0.0;
/**
* Get the unique internal database identifier for this concept word
* @since 1.5
*/
public Integer getConceptWordId() {
return conceptWordId;
}
/**
* Set the unique identifier for this concept word
* @since 1.5
*/
public void setConceptWordId(Integer conceptWordId) {
this.conceptWordId = conceptWordId;
}
// Constructors
/** default constructor */
public ConceptWord() {
}
/**
* Convenience constructor
*
* @param word the single word that will be matched to search terms
* @param concept the concept that is being matched to
* @param conceptName the specific name that will be matched
* @param locale the locale that is being pulled from
*/
public ConceptWord(String word, Concept concept, ConceptName conceptName, Locale locale) {
this.concept = concept;
this.conceptName = conceptName;
this.word = word;
this.locale = locale;
}
/**
* @deprecated see {@link #ConceptWord(String, Concept, ConceptName, Locale)}
*/
@Deprecated
public ConceptWord(String word, Concept concept, ConceptName conceptName, Locale locale, String synonym) {
this.concept = concept;
this.conceptName = conceptName;
this.word = word;
this.locale = locale;
this.synonym = synonym;
}
public ConceptWord(Concept c, ConceptName conceptName) {
this.concept = c;
this.conceptName = conceptName;
this.word = null;
this.locale = null;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (obj instanceof ConceptWord) {
ConceptWord c = (ConceptWord) obj;
boolean matches = true;
if (getConcept() != null && c.getConcept() != null)
matches = matches && concept.equals(c.getConcept());
if (getWord() != null && c.getWord() != null)
matches = matches && word.equalsIgnoreCase(c.getWord());
if (getLocale() != null && c.getLocale() != null)
matches = matches && locale.equals(c.getLocale());
if (getConceptName() != null && c.getConceptName() != null)
matches = matches && conceptName.equals(c.getConceptName());
return (matches);
}
return false;
}
/**
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
int hash = 3;
if (concept != null)
hash = 37 * hash + this.getConcept().hashCode();
if (word != null)
hash = 37 * hash + this.getWord().toLowerCase().hashCode(); // ABKTODO: MySQL searches are case insensitive
if (locale != null)
hash = 37 * hash + this.getLocale().hashCode();
if (conceptName != null)
hash = 37 * hash + this.getConceptName().hashCode();
return hash;
}
/**
* @return Returns the locale.
*/
public Locale getLocale() {
return locale;
}
/**
* @param locale The locale to set.
*/
public void setLocale(Locale locale) {
this.locale = locale;
}
/**
* @return Returns the synonym.
* @deprecated this value is not stored anymore
*/
@Deprecated
public String getSynonym() {
return synonym;
}
/**
* @param synonym The synonym to set.
* @deprecated this value is not stored anymore
*/
@Deprecated
public void setSynonym(String synonym) {
this.synonym = synonym;
}
/**
* @return Returns the word.
*/
public String getWord() {
return word;
}
/**
* @param word The word to set.
*/
public void setWord(String word) {
this.word = word;
}
/**
* @return Returns the concept.
*/
public Concept getConcept() {
return concept;
}
/**
* @param concept The concept to set.
*/
public void setConcept(Concept concept) {
this.concept = concept;
}
/**
* Sets the concept name associated with this word.
*
* @param conceptName
*/
public void setConceptName(ConceptName conceptName) {
this.conceptName = conceptName;
}
/**
* @return Returns the concept name from which this word was derived.
*/
public ConceptName getConceptName() {
return conceptName;
}
/**
* @return Returns the weight.
*/
public Double getWeight() {
return weight;
}
/**
* @param weight The weight to set.
*/
public void setWeight(Double weight) {
this.weight = weight;
}
/**
* Increment the weight by i
*
* @param i
*/
public void increaseWeight(Double i) {
this.weight += i;
}
/**
* @param concept The concept from which to make the list of concept words.
* @return Returns a list of unique concept words based on the specified concept.
* @should return separate ConceptWord objects for the same word in different ConceptNames
* @should not include voided names
*/
public static Set<ConceptWord> makeConceptWords(Concept concept) {
Set<ConceptWord> words = new HashSet<ConceptWord>();
for (ConceptName name : concept.getNames()) {
if (!name.isVoided()) {
List<String> uniqueParts = getUniqueWords(name.getName());
for (String part : uniqueParts) {
words.add(new ConceptWord(part, concept, name, name.getLocale()));
}
}
}
return words;
}
/**
* Split the given phrase on words and remove unique and stop words
*
* @param phrase
* @return Returns a list of the unique parts of the phrase, in all upper case.
*/
public static List<String> getUniqueWords(String phrase) {
String[] parts = splitPhrase(phrase);
List<String> uniqueParts = new Vector<String>();
for (String part : parts) {
String p = part.trim();
String upper = p.toUpperCase();
if (!p.equals("") && !OpenmrsConstants.STOP_WORDS().contains(upper) && !uniqueParts.contains(upper))
uniqueParts.add(upper);
}
return uniqueParts;
}
/**
* Split words according to OpenmrsConstants.REGEXes, newlines, and spaces
*
* @param phrase
* @return String[] array of words
*/
public static String[] splitPhrase(String phrase) {
if (phrase.length() > 2) {
phrase = phrase.replaceAll(OpenmrsConstants.REGEX_LARGE, " ");
} else {
phrase = phrase.replaceAll(OpenmrsConstants.REGEX_SMALL, " ");
}
String[] words = phrase.trim().replace('\n', ' ').split(" ");
return words;
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
String s = "";
if (concept != null)
s += concept.getConceptId() + "|";
if (word != null)
s += word + "|";
if (locale != null)
s += locale;
return s;
}
/**
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(ConceptWord word) {
return Double.compare(word.getWeight(), weight);
}
}