95e68a2cd26d9a196e803a7f21725def4011f24d
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / common / OrderedTermBase.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.model.common;
11
12 import javax.persistence.Entity;
13 import javax.persistence.Transient;
14 import javax.xml.bind.annotation.XmlAccessType;
15 import javax.xml.bind.annotation.XmlAccessorType;
16 import javax.xml.bind.annotation.XmlElement;
17 import javax.xml.bind.annotation.XmlSeeAlso;
18 import javax.xml.bind.annotation.XmlType;
19
20 import org.apache.log4j.Logger;
21 import org.hibernate.envers.Audited;
22 import org.hibernate.search.annotations.Indexed;
23
24 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
25 import eu.etaxonomy.cdm.model.description.State;
26 import eu.etaxonomy.cdm.model.location.NamedArea;
27 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
28 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
29 import eu.etaxonomy.cdm.model.name.Rank;
30
31 /**
32 * @author m.doering
33 * @created 08-Nov-2007 13:06:23
34 */
35 @XmlAccessorType(XmlAccessType.FIELD)
36 @XmlType(name = "OrderedTermBase", propOrder = {
37 "orderIndex"
38 })
39 @XmlSeeAlso({
40 RelationshipTermBase.class,
41 PresenceAbsenceTermBase.class,
42 State.class,
43 NamedArea.class,
44 NamedAreaLevel.class,
45 NomenclaturalStatusType.class,
46 Rank.class
47 })
48 @Entity
49 @Indexed(index = "eu.etaxonomy.cdm.model.common.DefinedTermBase")
50 @Audited
51 public abstract class OrderedTermBase<T extends OrderedTermBase<?>> extends DefinedTermBase<T> implements Comparable<T> {
52 private static final long serialVersionUID = 8000797926720467399L;
53 @SuppressWarnings("unused")
54 private static final Logger logger = Logger.getLogger(OrderedTermBase.class);
55
56 //Order index, value < 1 means that this Term is not in order yet
57 @XmlElement(name = "OrderIndex")
58 protected int orderIndex;
59
60 /**
61 * Higher ordered terms have a lower order index,
62 * lower ordered terms have a higher order index:
63 * <p>
64 * <b>a.oderIndex &lt; b.oderIndex : a &gt; b</b>
65 * @return the order index of a term
66 */
67 public int getOrderIndex() {
68 return orderIndex;
69 }
70
71 // *********************** CONSTRUCTOR *************************/
72
73 //for JAXB only, TODO needed?
74 @Deprecated
75 protected OrderedTermBase(){}
76
77 protected OrderedTermBase(TermType type) {
78 super(type);
79 }
80 public OrderedTermBase(TermType type, String term, String label, String labelAbbrev) {
81 super(type, term, label, labelAbbrev);
82 }
83
84 // **************************** METHODS ******************************/
85
86 /**
87 * Compares this OrderedTermBase with the specified OrderedTermBase for
88 * order. Returns a -1, 0, or +1 if the orderId of this object is greater
89 * than, equal to, or less than the specified object. In case the parameter
90 * is <code>null</code> the
91 * <p>
92 * <b>Note:</b> The compare logic of this method is the <b>inverse logic</b>
93 * of the the one implemented in
94 * {@link java.lang.Comparable#compareTo(java.lang.Object)}
95 *
96 * @param orderedTerm
97 * the OrderedTermBase to be compared
98 * @throws NullPointerException
99 * if the specified object is null
100 */
101 @Override
102 public int compareTo(T orderedTerm) {
103 return performCompareTo(orderedTerm, false);
104 }
105
106 /**
107 * Compares this OrderedTermBase with the specified OrderedTermBase for
108 * order. Returns a -1, 0, or +1 if the orderId of this object is greater
109 * than, equal to, or less than the specified object.
110 * <p>
111 * <b>Note:</b> The compare logic of this method is the <b>inverse logic</b>
112 * of the the one implemented in
113 * {@link java.lang.Comparable#compareTo(java.lang.Object)}
114 *
115 * @param orderedTerm
116 * the OrderedTermBase to be compared
117 * @param skipVocabularyCheck
118 * whether to skip checking if both terms to compare are in the
119 * same vocabulary
120 * @throws NullPointerException
121 * if the specified object is null
122 */
123 protected int performCompareTo(T orderedTerm, boolean skipVocabularyCheck) {
124
125 OrderedTermBase<?> orderedTermLocal = CdmBase.deproxy(orderedTerm, OrderedTermBase.class);
126 if(!skipVocabularyCheck){
127 if (this.vocabulary == null || orderedTermLocal.vocabulary == null){
128 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");
129 }
130 if (! this.getVocabulary().getUuid().equals(orderedTermLocal.vocabulary.getUuid())){
131 throw new IllegalStateException("2 terms do not belong to the same vocabulary and therefore can not be compared");
132 }
133 }
134
135 int orderThat;
136 int orderThis;
137 try {
138 orderThat = orderedTermLocal.orderIndex;//OLD: this.getVocabulary().getTerms().indexOf(orderedTerm);
139 orderThis = orderIndex; //OLD: this.getVocabulary().getTerms().indexOf(this);
140 } catch (RuntimeException e) {
141 throw e;
142 }
143 if (orderThis > orderThat){
144 return -1;
145 }else if (orderThis < orderThat){
146 return 1;
147 }else {
148 return 0;
149 }
150 }
151
152 // public int compareTo(IdentifiableEntity o) {
153 // if (o instanceof OrderedTermBase){
154 // return compareTo((OrderedTermBase)o);
155 // }else{
156 // return super.compareTo(o);
157 // }
158 // }
159
160 /**
161 * If this term is lower than the parameter term, true is returned, else false.
162 * If the parameter term is null, an Exception is thrown.
163 * @param orderedTerm
164 * @return boolean result of the comparison
165 */
166 public boolean isLower(T orderedTerm){
167 return (this.compareTo(orderedTerm) < 0 );
168 }
169
170
171 /**
172 * If this term is higher than the parameter term, true is returned, else false.
173 * If the parameter term is null, an Exception is thrown.
174 * @param orderedTerm
175 * @return boolean result of the comparison
176 */
177 public boolean isHigher(T orderedTerm){
178 return (this.compareTo(orderedTerm) > 0 );
179 }
180
181
182 /**
183 * @deprecated To be used only by OrderedTermVocabulary
184 **/
185 @Deprecated
186 protected boolean decreaseIndex(OrderedTermVocabulary<T> vocabulary){
187 if (vocabulary.indexChangeAllowed(this) == true){
188 orderIndex--;
189 return true;
190 }else{
191 return false;
192 }
193 }
194
195 /**
196 * @deprecated To be used only by OrderedTermVocabulary
197 **/
198 @Deprecated
199 protected boolean incrementIndex(OrderedTermVocabulary<T> vocabulary){
200 if (vocabulary.indexChangeAllowed(this) == true){
201 orderIndex++;
202 return true;
203 }else{
204 return false;
205 }
206 }
207
208 @Override
209 public boolean equals(Object object){
210 if(this == object) {
211 return true;
212 }
213 if((object == null) || (!OrderedTermBase.class.isAssignableFrom(object.getClass()))) {
214 return false;
215 }else{
216 OrderedTermBase<?> orderedTermBase = (OrderedTermBase<?>)object;
217 if (orderedTermBase.getUuid().equals(this.getUuid())){
218 return true;
219 }else{
220 return false;
221 }
222 }
223 }
224
225 @Transient
226 public T getNextHigherTerm(){ //#3327
227 if (getVocabulary() == null){
228 return null;
229 }else{
230 @SuppressWarnings("unchecked")
231 OrderedTermBase<T> result = CdmBase.deproxy(getVocabulary(), OrderedTermVocabulary.class).getNextHigherTerm(this);
232 return (T)result;
233 }
234 }
235
236 @Transient
237 public T getNextLowerTerm(){ //#3327
238 if (getVocabulary() == null){
239 return null;
240 }else{
241 @SuppressWarnings("unchecked")
242 OrderedTermBase<T> result = CdmBase.deproxy(getVocabulary(), OrderedTermVocabulary.class).getNextLowerTerm(this);
243 return (T)result;
244 }
245 }
246
247 //*********************** CLONE ********************************************************/
248
249 /**
250 * Clones <i>this</i> OrderedTermBase. This is a shortcut that enables to create
251 * a new instance that differs only slightly from <i>this</i> OrderedTermBase.
252 *
253 * @see eu.etaxonomy.cdm.model.common.DefinedTermBase#clone()
254 * @see java.lang.Object#clone()
255 */
256 @Override
257 public Object clone() {
258 OrderedTermBase<?> result = (OrderedTermBase<?>) super.clone();
259 //no changes to orderIndex
260 return result;
261 }
262 }