remove exception when comparing terms from 2 different vocabularies
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / term / OrderedTermBase.java
index 965638dba684b5dfa7c0b956aa00839a4cd93914..372065ed3e567e3bb1afe4ef00bc623e7c3035ef 100644 (file)
@@ -6,9 +6,10 @@
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * See LICENSE.TXT at the top of this package for the full license terms.
 */
-
 package eu.etaxonomy.cdm.model.term;
 
+import java.util.UUID;
+
 import javax.persistence.Entity;
 import javax.persistence.Transient;
 import javax.xml.bind.annotation.XmlAccessType;
@@ -17,9 +18,11 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlType;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.hibernate.envers.Audited;
 
+import eu.etaxonomy.cdm.common.CdmUtils;
 import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.RelationshipTermBase;
 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
@@ -48,12 +51,12 @@ import eu.etaxonomy.cdm.model.name.Rank;
 })
 @Entity
 @Audited
-public abstract class OrderedTermBase<T extends OrderedTermBase<?>>
+public abstract class OrderedTermBase<T extends OrderedTermBase<T>>
         extends DefinedTermBase<T> {
 
     private static final long serialVersionUID = 8000797926720467399L;
     @SuppressWarnings("unused")
-    private static final Logger logger = Logger.getLogger(OrderedTermBase.class);
+    private static final Logger logger = LogManager.getLogger(OrderedTermBase.class);
 
     //Order index, value < 1 means that this Term is not in order yet
     @XmlElement(name = "OrderIndex")
@@ -72,7 +75,7 @@ public abstract class OrderedTermBase<T extends OrderedTermBase<?>>
 
 // *********************** CONSTRUCTOR *************************/
 
-    //for JAXB only, TODO needed?
+  //for hibernate use only, protected required by bytebuddy and subclasses outside package
     @Deprecated
     protected OrderedTermBase(){}
 
@@ -108,8 +111,8 @@ public abstract class OrderedTermBase<T extends OrderedTermBase<?>>
     }
 
     /**
-     * Compares this OrderedTermBase with the specified OrderedTermBase for
-     * order. Returns a -1, 0, or +1 if the orderId of this object is greater
+     * Compares this {@link OrderedTermBase ordered term} with the given {@link OrderedTermBase thatTerm} for
+     * order.  Returns a -1, 0, or +1 if the orderId of this object is greater
      * than, equal to, or less than the specified object.
      * <p>
      * <b>Note:</b> The compare logic of this method is the <b>inverse logic</b>
@@ -124,23 +127,25 @@ public abstract class OrderedTermBase<T extends OrderedTermBase<?>>
      * @throws NullPointerException
      *             if the specified object is null
      */
-    protected int performCompareTo(T orderedTerm, boolean skipVocabularyCheck) {
+    protected int performCompareTo(T thatTerm , boolean skipVocabularyCheck ) {
 
-       OrderedTermBase<?> orderedTermLocal = CdmBase.deproxy(orderedTerm, OrderedTermBase.class);
+       T thatTermLocal = CdmBase.deproxy(thatTerm);
        if(!skipVocabularyCheck){
-            if (this.vocabulary == null || orderedTermLocal.vocabulary == null){
-                throw new IllegalStateException("An ordered term (" + this.toString() + " or " + orderedTermLocal.toString() + ") of class " + this.getClass() + " or " + orderedTermLocal.getClass() + " does not belong to a vocabulary and therefore can not be compared");
-            }
-            if (! this.getVocabulary().getUuid().equals(orderedTermLocal.vocabulary.getUuid())){
-               throw new IllegalStateException("2 terms do not belong to the same vocabulary and therefore can not be compared: " + this.getTitleCache() + " and " + orderedTermLocal.getTitleCache());
+            if (this.vocabulary == null || thatTermLocal.vocabulary == null){
+                throw new IllegalStateException("An ordered term (" + this.toString() + " or " + thatTermLocal.toString() + ") of class " + this.getClass() + " or " + thatTermLocal.getClass() + " does not belong to a vocabulary and therefore can not be compared");
             }
         }
 
+       int vocCompare = compareVocabularies(thatTermLocal);
+        if (vocCompare != 0){
+            return vocCompare;
+        }
+
         int orderThat;
         int orderThis;
         try {
-            orderThat = orderedTermLocal.orderIndex;//OLD: this.getVocabulary().getTerms().indexOf(orderedTerm);
-            orderThis = orderIndex; //OLD: this.getVocabulary().getTerms().indexOf(this);
+            orderThat = thatTermLocal.orderIndex;
+            orderThis = orderIndex;
         } catch (RuntimeException e) {
             throw e;
         }
@@ -152,18 +157,24 @@ public abstract class OrderedTermBase<T extends OrderedTermBase<?>>
             if (skipVocabularyCheck){
                 String errorStr = "The term %s (ID: %s) is not attached to any vocabulary. This should not happen. "
                         + "Please add the term to an vocabulary";
-                if (this.getVocabulary() == null){
+                if (this.vocabulary == null){
                     throw new IllegalStateException(String.format(errorStr, this.getLabel(), String.valueOf(this.getId())));
-                }else if (orderedTermLocal.vocabulary == null){
-                    throw new IllegalStateException(String.format(errorStr, orderedTermLocal.getLabel(), String.valueOf(orderedTermLocal.getId())));
+                }else if (thatTermLocal.vocabulary == null){
+                    throw new IllegalStateException(String.format(errorStr, thatTermLocal.getLabel(), String.valueOf(thatTermLocal.getId())));
                 }
-                return this.getVocabulary().getUuid().compareTo(orderedTermLocal.vocabulary.getUuid());
-            }else{
-                return 0;
             }
+            return 0;
         }
     }
 
+    protected int compareVocabularies(T thatTerm) {
+        //if vocabularies are not equal order by voc.uuid to get a defined behavior
+        //ordering terms from 2 different vocabularies is generally not recommended
+        UUID thisVocUuid = this.vocabulary == null? null:this.vocabulary.getUuid();
+        UUID thatVocUuid = thatTerm.getVocabulary() == null? null:thatTerm.getVocabulary().getUuid();
+        int vocCompare = CdmUtils.nullSafeCompareTo(thisVocUuid, thatVocUuid);
+        return vocCompare;
+    }
 
     /**
      * If this term is lower than the parameter term, true is returned, else false.
@@ -175,7 +186,6 @@ public abstract class OrderedTermBase<T extends OrderedTermBase<?>>
         return (this.compareTo(orderedTerm) < 0 );
     }
 
-
     /**
      * If this term is higher than the parameter term, true is returned, else false.
      * If the parameter term is null, an Exception is thrown.
@@ -186,7 +196,6 @@ public abstract class OrderedTermBase<T extends OrderedTermBase<?>>
         return (this.compareTo(orderedTerm) > 0 );
     }
 
-
     /**
      * @deprecated To be used only by OrderedTermVocabulary
      **/
@@ -246,8 +255,8 @@ public abstract class OrderedTermBase<T extends OrderedTermBase<?>>
      * @see java.lang.Object#clone()
      */
     @Override
-    public Object clone() {
-        OrderedTermBase<?> result = (OrderedTermBase<?>) super.clone();
+    public OrderedTermBase<T> clone() {
+        OrderedTermBase<T> result = (OrderedTermBase<T>) super.clone();
         //no changes to orderIndex
         return result;
     }