import org.apache.log4j.Logger;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.hibernate.collection.AbstractPersistentCollection;
+import org.hibernate.search.annotations.Indexed;
import au.com.bytecode.opencsv.CSVWriter;
-import eu.etaxonomy.cdm.model.common.init.TermLoader;
+import eu.etaxonomy.cdm.model.common.init.ITermInitializer;
+import eu.etaxonomy.cdm.model.media.Media;
+import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
+import java.lang.reflect.Field;
import java.util.*;
import javax.persistence.*;
+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.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
/**
- * workaround for enumerations, base type according to TDWG. For linear ordering
+ * walkaround for enumerations, base type according to TDWG. For linear ordering
* use partOf relation and BreadthFirst. Default iterator order should therefore
* be BreadthFirst (not DepthFirst)
* @author m.doering
* @version 1.0
* @created 08-Nov-2007 13:06:19
*/
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "DefinedTermBase", propOrder = {
+ "kindOf",
+ "generalizationOf",
+ "partOf",
+ "includes",
+ "media",
+ "vocabulary"
+})
+@XmlRootElement(name = "DefinedTermBase")
@Entity
+//@Audited
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
-public abstract class DefinedTermBase<T extends DefinedTermBase> extends TermBase implements IDefTerm{
- static Logger logger = Logger.getLogger(DefinedTermBase.class);
- //public static IDefinedTermDao dao;
- //public static ITermService termService;
- //Map for preloading all DefinedTerms
- static protected Map<UUID, DefinedTermBase> definedTermsMap = null;
-
- private DefinedTermBase kindOf;
- private Set<DefinedTermBase> generalizationOf = new HashSet<DefinedTermBase>();
- private DefinedTermBase partOf;
- private Set<DefinedTermBase> includes = new HashSet<DefinedTermBase>();
- private Set<Media> media = new HashSet<Media>();
- protected TermVocabulary<T> vocabulary;
-
-// protected TermVocabulary<DefinedTermBase> getNewVocabulary(){
-// }
+@Indexed
+public abstract class DefinedTermBase<T extends DefinedTermBase> extends TermBase implements ILoadableTerm<T>, IDefinedTerm<T> {
+ private static final long serialVersionUID = 2931811562248571531L;
+ private static final Logger logger = Logger.getLogger(DefinedTermBase.class);
+
+ @XmlElement(name = "KindOf")
+ @XmlIDREF
+ @XmlSchemaType(name = "IDREF")
+ private T kindOf;
+ /**
+ * FIXME - Hibernate retuns this as a collection of CGLibProxy$$DefinedTermBase objects
+ * which can't be cast to instances of T - can we explicitly initialize these terms using
+ * Hibernate.initialize(), does this imply a distinct load, and find methods in the dao?
+ */
+ @XmlElement(name = "GeneralizationOf")
+ @XmlIDREF
+ @XmlSchemaType(name = "IDREF")
+ private Set<T> generalizationOf = new HashSet<T>();
- public static void initTermList(ITermLister termLister){
- logger.debug("initTermList");
- if (definedTermsMap == null){
- if (termLister == null){ //e.g. when used in tests with no database connection
- definedTermsMap = new HashMap<UUID, DefinedTermBase>();
- try {
- String strUuidEnglish = "e9f8cdb7-6819-44e8-95d3-e2d0690c3523";
- UUID uuidEnglish = UUID.fromString(strUuidEnglish);
- Language english = new Language(uuidEnglish);
- definedTermsMap.put(english.getUuid(), english);
- TermLoader.setDefinedTermsMap(definedTermsMap);
- new TermLoader().loadAllDefaultTerms();
- } catch (Exception e) {
- logger.error("Error ocurred when loading terms");
- }
-
- }else{
- List<DefinedTermBase> list = termLister.listTerms();
- definedTermsMap = new HashMap<UUID, DefinedTermBase>();
- for (DefinedTermBase dtb: list){
- definedTermsMap.put(dtb.getUuid(), dtb);
- }
- }
- }
- logger.debug("initTermList - end");
- }
+ @XmlElement(name = "PartOf")
+ @XmlIDREF
+ @XmlSchemaType(name = "IDREF")
+ private T partOf;
- public static DefinedTermBase findByUuid(UUID uuid){
- //in tests tems may no be initialised by database access
- if (!isInitialized()){
- initTermList(null);
- }
- return definedTermsMap.get(uuid);
- }
+ /**
+ * FIXME - Hibernate retuns this as a collection of CGLibProxy$$DefinedTermBase objects
+ * which can't be cast to instances of T - can we explicitly initialize these terms using
+ * Hibernate.initialize(), does this imply a distinct load, and find methods in the dao?
+ */
+ @XmlElementWrapper(name = "Includes")
+ @XmlElement(name = "Include")
+ private Set<T> includes = new HashSet<T>();
- public static boolean isInitialized(){
- return (definedTermsMap != null);
- }
+ @XmlElementWrapper(name = "Media")
+ @XmlElement(name = "Medium")
+ @XmlIDREF
+ @XmlSchemaType(name = "IDREF")
+ private Set<Media> media = new HashSet<Media>();
- public static Map<UUID, DefinedTermBase> getDefinedTerms(){
- return definedTermsMap;
- }
+ @XmlElement(name = "TermVocabulary")
+ @XmlIDREF
+ @XmlSchemaType(name = "IDREF")
+ protected TermVocabulary<T> vocabulary;
+// ************** Constructor ******************************************/
public DefinedTermBase() {
super();
}
- public DefinedTermBase(String term, String label) {
- super(term, label);
+ public DefinedTermBase(String term, String label, String labelAbbrev) {
+ super(term, label, labelAbbrev);
}
+ protected abstract void setDefaultTerms(TermVocabulary<T> termVocabulary);
/* (non-Javadoc)
- * @see eu.etaxonomy.cdm.model.common.IDefTerm#readCsvLine(java.util.List)
+ * @see eu.etaxonomy.cdm.model.common.ILoadableTerm#readCsvLine(java.util.List)
+ */
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#readCsvLine(java.lang.Class, java.util.List, java.util.Map)
*/
- public void readCsvLine(List<String> csvLine) {
- readCsvLine(csvLine, Language.ENGLISH());
+ public T readCsvLine(Class<T> termClass, List<String> csvLine, Map<UUID,DefinedTermBase> terms) {
+ try {
+ T newInstance = termClass.newInstance();
+ return readCsvLine(newInstance, csvLine, Language.ENGLISH());
+ } catch (Exception e) {
+ logger.error(e);
+ for(StackTraceElement ste : e.getStackTrace()) {
+ logger.error(ste);
+ }
+ }
+
+ return null;
}
- public void readCsvLine(List<String> csvLine, Language lang) {
- this.setUuid(UUID.fromString(csvLine.get(0)));
- this.setUri(csvLine.get(1));
- this.addRepresentation(new Representation(csvLine.get(3), csvLine.get(2).trim(), lang) );
+
+ protected static <TERM extends DefinedTermBase> TERM readCsvLine(TERM newInstance, List<String> csvLine, Language lang) {
+ newInstance.setUuid(UUID.fromString(csvLine.get(0)));
+ newInstance.setUri(csvLine.get(1));
+ String label = csvLine.get(2).trim();
+ String text = csvLine.get(3);
+ String abbreviatedLabel = csvLine.get(4);
+ newInstance.addRepresentation(Representation.NewInstance(text, label, abbreviatedLabel, lang) );
+ return newInstance;
}
/* (non-Javadoc)
- * @see eu.etaxonomy.cdm.model.common.IDefTerm#writeCsvLine(au.com.bytecode.opencsv.CSVWriter)
+ * @see eu.etaxonomy.cdm.model.common.ILoadableTerm#writeCsvLine(au.com.bytecode.opencsv.CSVWriter)
*/
- public void writeCsvLine(CSVWriter writer) {
+ public void writeCsvLine(CSVWriter writer, T term) {
String [] line = new String[4];
- line[0] = getUuid().toString();
- line[1] = getUri();
- line[2] = getLabel();
- line[3] = getDescription();
+ line[0] = term.getUuid().toString();
+ line[1] = term.getUri();
+ line[2] = term.getLabel();
+ line[3] = term.getDescription();
writer.writeNext(line);
}
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getByUuid(java.util.UUID)
+ */
@Transient
- //@ManyToOne
- //@Cascade({CascadeType.SAVE_UPDATE})
- public DefinedTermBase getKindOf(){
+ public T getByUuid(UUID uuid){
+ return this.vocabulary.findTermByUuid(uuid);
+ }
+
+
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getKindOf()
+ */
+ @ManyToOne(fetch = FetchType.LAZY, targetEntity = DefinedTermBase.class)
+ @Cascade({CascadeType.SAVE_UPDATE})
+ public T getKindOf(){
return this.kindOf;
}
- public void setKindOf(DefinedTermBase kindOf){
+
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setKindOf(T)
+ */
+ public void setKindOf(T kindOf){
this.kindOf = kindOf;
}
- @Transient
- //@OneToMany(fetch=FetchType.LAZY)
- //@Cascade({CascadeType.SAVE_UPDATE})
- public Set<DefinedTermBase> getGeneralizationOf(){
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getGeneralizationOf()
+ */
+ @OneToMany(fetch=FetchType.LAZY, mappedBy = "kindOf", targetEntity = DefinedTermBase.class)
+ @Cascade({CascadeType.SAVE_UPDATE})
+ public Set<T> getGeneralizationOf(){
return this.generalizationOf;
}
- public void setGeneralizationOf(Set<DefinedTermBase> generalizationOf) {
+
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setGeneralizationOf(java.util.Set)
+ */
+ public void setGeneralizationOf(Set<T> generalizationOf) {
this.generalizationOf = generalizationOf;
}
+
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#addGeneralizationOf(T)
+ */
+ public void addGeneralizationOf(T generalization) {
+ generalization.setKindOf(this);
+ this.generalizationOf.add(generalization);
+ }
+
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#removeGeneralization(T)
+ */
+ public void removeGeneralization(T generalization) {
+ if(generalizationOf.contains(generalization)){
+ generalization.setKindOf(null);
+ this.generalizationOf.remove(generalization);
+ }
+ }
- @Transient
- //@ManyToOne
- //@Cascade({CascadeType.SAVE_UPDATE})
- public DefinedTermBase getPartOf(){
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getPartOf()
+ */
+ @ManyToOne(fetch = FetchType.LAZY, targetEntity = DefinedTermBase.class)
+ @Cascade({CascadeType.SAVE_UPDATE})
+ public T getPartOf(){
return this.partOf;
}
- public void setPartOf(DefinedTermBase partOf){
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setPartOf(T)
+ */
+ public void setPartOf(T partOf){
this.partOf = partOf;
}
- @Transient
- //@OneToMany(fetch=FetchType.LAZY)
- //@Cascade({CascadeType.SAVE_UPDATE})
- public Set<DefinedTermBase> getIncludes(){
+
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getIncludes()
+ */
+ @OneToMany(fetch=FetchType.LAZY, mappedBy = "partOf", targetEntity = DefinedTermBase.class)
+ @Cascade({CascadeType.SAVE_UPDATE})
+ public Set<T> getIncludes(){
return this.includes;
}
- public void setIncludes(Set<DefinedTermBase> includes) {
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setIncludes(java.util.Set)
+ */
+ public void setIncludes(Set<T> includes) {
this.includes = includes;
}
- public void addIncludes(DefinedTermBase includes) {
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#addIncludes(T)
+ */
+ public void addIncludes(T includes) {
+ includes.setPartOf(this);
this.includes.add(includes);
}
- public void removeIncludes(TermBase includes) {
- this.includes.remove(includes);
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#removeIncludes(T)
+ */
+ public void removeIncludes(T includes) {
+ if(this.includes.contains(includes)) {
+ includes.setPartOf(null);
+ this.includes.remove(includes);
+ }
}
- @OneToMany
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getMedia()
+ */
+ @ManyToMany(fetch = FetchType.LAZY)
@Cascade({CascadeType.SAVE_UPDATE})
public Set<Media> getMedia(){
return this.media;
}
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setMedia(java.util.Set)
+ */
public void setMedia(Set<Media> media) {
this.media = media;
}
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#addMedia(eu.etaxonomy.cdm.model.media.Media)
+ */
public void addMedia(Media media) {
this.media.add(media);
}
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#removeMedia(eu.etaxonomy.cdm.model.media.Media)
+ */
public void removeMedia(Media media) {
this.media.remove(media);
}
-
/* (non-Javadoc)
* @see eu.etaxonomy.cdm.model.common.IDefTerm#getVocabulary()
*/
- @ManyToOne(fetch=FetchType.EAGER)
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getVocabulary()
+ */
+ @XmlTransient
+ @ManyToOne(fetch=FetchType.LAZY)
@Cascade( { CascadeType.SAVE_UPDATE })
- public TermVocabulary getVocabulary() {
+ public TermVocabulary<T> getVocabulary() {
return this.vocabulary;
}
/* (non-Javadoc)
* @see eu.etaxonomy.cdm.model.common.IDefTerm#setVocabulary(eu.etaxonomy.cdm.model.common.TermVocabulary)
*/
- public void setVocabulary(TermVocabulary newVocabulary) {
- // Hibernate bidirectional cascade hack:
- // http://opensource.atlassian.com/projects/hibernate/browse/HHH-1054
- if(this.vocabulary == newVocabulary){ return;}
- if (this.vocabulary != null) {
- this.vocabulary.terms.remove(this);
- }
- if (newVocabulary!= null) {
- newVocabulary.terms.add(this);
- }
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setVocabulary(eu.etaxonomy.cdm.model.common.TermVocabulary)
+ */
+ public void setVocabulary(TermVocabulary<T> newVocabulary) {
this.vocabulary = newVocabulary;
- }
-
+ }
}
\ No newline at end of file