package eu.etaxonomy.cdm.model.common;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.OneToMany;
+import javax.persistence.Transient;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlIDREF;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+
import org.apache.log4j.Logger;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Type;
-import java.util.*;
-
-import javax.persistence.*;
+import org.hibernate.envers.Audited;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.annotations.IndexedEmbedded;
/**
* A single enumeration must only contain DefinedTerm instances of one kind
- * (=class)
+ * (this means a subclass of DefinedTerm).
* @author m.doering
* @version 1.0
* @created 08-Nov-2007 13:06:23
*/
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "TermVocabulary", propOrder = {
+ "termSourceUri",
+ "terms"
+})
+@XmlRootElement(name = "TermVocabulary")
@Entity
+@Indexed(index = "eu.etaxonomy.cdm.model.common.TermVocabulary")
+@Audited
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class TermVocabulary<T extends DefinedTermBase> extends TermBase implements Iterable<T> {
- static Logger logger = Logger.getLogger(TermVocabulary.class);
-
- private static final UUID uuidLanguage = UUID.fromString("17ba1c02-256d-47cf-bed0-2964ec1108ba");
- private static final UUID uuidRank = UUID.fromString("b17451eb-4278-4179-af68-44f27aa3d151");
- private static final UUID uuidContinent = UUID.fromString("ed4e5948-172a-424c-83d6-6fc7c7da70ed");
-
-
- public static TermVocabulary findByUuid(UUID uuid){
- //in tests tems may no be initialised by database access
-// if (!isInitialized()){
-// initTermList(null);
-// }
-// return termVocabularyMap.get(uuid);
- //TODO
- logger.error("Not yet implemented");
- return null;
- }
- public static final TermVocabulary getUUID(UUID uuid){
- return (TermVocabulary)findByUuid(uuid);
- }
- public static final TermVocabulary LANGUAGE(){
- return getUUID(uuidLanguage);
- }
+ private static final long serialVersionUID = 1925052321596648672L;
+ @SuppressWarnings("unused")
+ private static final Logger logger = Logger.getLogger(TermVocabulary.class);
//The vocabulary source (e.g. ontology) defining the terms to be loaded when a database is created for the first time.
// Software can go and grap these terms incl labels and description.
// UUID needed? Further vocs can be setup through our own ontology.
+ @XmlElement(name = "TermSourceURI")
+ @Field(index=org.hibernate.search.annotations.Index.UN_TOKENIZED)
private String termSourceUri;
- protected Class termClass;
+
+ //TODO Changed
+ @XmlElementWrapper(name = "Terms")
+ @XmlElement(name = "Term")
+ @XmlIDREF
+ @XmlSchemaType(name = "IDREF")
+ @OneToMany(mappedBy="vocabulary", fetch=FetchType.LAZY, targetEntity = DefinedTermBase.class)
+ @Type(type="DefinedTermBase")
+ @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
+ @IndexedEmbedded(depth = 2)
protected Set<T> terms = getNewTermSet();
- //to be overriden by subclasses, e.g. OrderedTermVocabulary
- @Transient
- protected Set<T> getNewTermSet(){
- return new HashSet<T>();
+// ********************************* FACTORY METHODS *****************************************/
+
+ public static TermVocabulary NewInstance(String description, String label, String abbrev, String termSourceUri){
+ return new TermVocabulary(description, label, abbrev, termSourceUri);
}
- public TermVocabulary() {
- super();
+// ************************* CONSTRUCTOR *************************************************
+
+ protected TermVocabulary() {
}
- public TermVocabulary(String term, String label, String termSourceUri) {
- super(term, label);
+
+ protected TermVocabulary(String term, String label, String labelAbbrev, String termSourceUri) {
+ super(term, label, labelAbbrev);
setTermSourceUri(termSourceUri);
}
- @OneToMany(mappedBy="vocabulary")
- @Type(type="DefinedTermBase")
- @Cascade({CascadeType.SAVE_UPDATE})
- public Set<T> getTerms() {
- Set<T> result = getNewTermSet();
- result.addAll(terms);
- return result;
+
+// ******************* METHODS *************************************************/
+
+ public T findTermByUuid(UUID uuid){
+ for(T t : terms) {
+ if(t.getUuid().equals(uuid)) {
+ return t;
+ }
+ }
+ return null;
}
- protected void setTerms(Set<T> terms) {
- this.terms = terms;
+
+ @Transient
+ Set<T> getNewTermSet() {
+ return new HashSet<T>();
}
- public void addTerm(T term) throws WrongTermTypeException {
- if (terms.size()<1){
- // no term yet in the list. First term defines the vocabulary kind
- termClass=term.getClass();
- }else if (term.getClass()!=termClass){
- // check if new term in this vocabulary matches the previous ones
- throw new WrongTermTypeException(term.getClass().getCanonicalName());
- }
+
+ public Set<T> getTerms() {
+ return terms;
+ }
+
+ public void addTerm(T term) {
term.setVocabulary(this);
+ this.terms.add(term);
}
public void removeTerm(T term) {
+ this.terms.remove(term);
term.setVocabulary(null);
}
}
- public Class getTermClass() {
- return termClass;
- }
- private void setTermClass(Class termClass) {
- this.termClass = termClass;
- }
-
-
-// // inner iterator class for the iterable interface
-// private class TermIterator<T> implements Iterator<T> {
-// // FIXME: using a list here is probably not safe. Sth passed by value, an array, would be better
-// // but arrays cause generics problems: http://forum.java.sun.com/thread.jspa?threadID=651276&messageID=3832182
-// // hack for now ;(
-// private Set<T> array;
-// private int i= 0;
-// // ctor
-// public TermIterator(Set<T> array) {
-// // check for null being passed in etc.
-// this.array= array;
-// }
-// // interface implementation
-// public boolean hasNext() { return i < array.size(); }
-// public T next() { return array.get(i++); }
-// public void remove() { throw new UnsupportedOperationException(); }
-// }
-
public Iterator<T> iterator() {
return terms.iterator(); // OLD: new TermIterator<T>(this.terms);
}
public int size(){
return terms.size();
}
+
+
+ /**
+ * Returns all terms of this vocabulary sorted by their representation defined by the given language.
+ * If such an representation does not exist, the representation of the default language is testing instead for ordering.
+ * @param language
+ * @return
+ */
+ public SortedSet<T> getTermsOrderedByLabels(Language language){
+ TermLanguageComparator<T> comp = new TermLanguageComparator<T>();
+ comp.setCompareLanguage(language);
+
+ SortedSet<T> result = new TreeSet<T>(comp);
+ result.addAll(getTerms());
+ return result;
+ }
+
+
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.ILoadableTerm#readCsvLine(java.util.List)
+ */
+ public TermVocabulary<T> readCsvLine(List<String> csvLine) {
+ return readCsvLine(csvLine, Language.CSV_LANGUAGE());
+ }
+
+ public TermVocabulary<T> readCsvLine(List<String> csvLine, Language lang) {
+ this.setUuid(UUID.fromString(csvLine.get(0)));
+ this.setUri(csvLine.get(1));
+ //this.addRepresentation(Representation.NewInstance(csvLine.get(3), csvLine.get(2).trim(), lang) );
+ return this;
+ }
}
\ No newline at end of file