Merge trunk into CDM 3.3
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / common / OrderedTermVocabulary.java
1 /**
2 * Copyright (C) 2009 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 java.net.URI;
13 import java.util.Iterator;
14 import java.util.NoSuchElementException;
15 import java.util.Set;
16 import java.util.SortedSet;
17 import java.util.TreeSet;
18
19 import javax.persistence.Entity;
20 import javax.persistence.Transient;
21 import javax.xml.bind.annotation.XmlAccessType;
22 import javax.xml.bind.annotation.XmlAccessorType;
23 import javax.xml.bind.annotation.XmlRootElement;
24 import javax.xml.bind.annotation.XmlType;
25
26 import org.apache.log4j.Logger;
27 import org.hibernate.envers.Audited;
28 import org.hibernate.search.annotations.Indexed;
29
30 /**
31 * @author a.mueller
32 *
33 */
34 @XmlAccessorType(XmlAccessType.FIELD)
35 @XmlType(name = "OrderedTermVocabulary")
36 @XmlRootElement(name = "OrderedTermVocabulary")
37 @Entity
38 @Indexed(index = "eu.etaxonomy.cdm.model.common.TermVocabulary")
39 @Audited
40 public class OrderedTermVocabulary<T extends OrderedTermBase> extends TermVocabulary<T> {
41 private static final long serialVersionUID = 7871741306306371242L;
42 @SuppressWarnings("unused")
43 private static final Logger logger = Logger.getLogger(OrderedTermVocabulary.class);
44
45 // ************************* FACTORY METHODS ***********************************************/
46
47 public static OrderedTermVocabulary NewInstance(String term, String label, String labelAbbrev, URI termSourceUri){
48 return new OrderedTermVocabulary(term, label, labelAbbrev, termSourceUri);
49 }
50
51
52 //************************ CONSTRUCTOR *****************************************************/
53
54 protected OrderedTermVocabulary() {
55 super();
56 }
57
58 /**
59 * @param term
60 * @param label
61 * @param termSourceUri
62 */
63 protected OrderedTermVocabulary(String term, String label, String labelAbbrev, URI termSourceUri) {
64 super(term, label, labelAbbrev, termSourceUri);
65 }
66
67
68 //************************* METHODS **************************************/
69
70 @Transient
71 @Override
72 public Set<T> getNewTermSet() {
73 return new TreeSet<T>();
74 }
75
76 @Transient
77 public SortedSet<T> getOrderedTerms() {
78 SortedSet<T> result = getSortedSetOfTerms();
79 return result;
80 }
81
82 public SortedSet<T> getHigherAndEqualTerms(T otb) {
83 SortedSet<T> result = new TreeSet<T>();
84 SortedSet<T> sortedSet = getSortedSetOfTerms();
85 result.addAll( sortedSet.tailSet(otb));
86 return result;
87 }
88
89 public SortedSet<T> getHigherTerms(T otb) {
90 SortedSet<T> result = getHigherAndEqualTerms(otb);
91 for (T setObject : terms){
92 if (setObject.compareTo(otb) == 0){
93 result.remove(setObject);
94 }
95 }
96 return result;
97 }
98
99 public SortedSet<T> getLowerAndEqualTerms(T otb) {
100 SortedSet<T> result = new TreeSet<T>();
101 SortedSet<T> sortedSet = getSortedSetOfTerms();
102
103 result.addAll( sortedSet.headSet(otb));
104 //headSet Returns a view of the portion of this set whose elements are STRICTLY less than toElement
105 for (T setObject : terms){
106 if (setObject.compareTo(otb) == 0){
107 result.add(setObject);
108 }
109 }
110 return result;
111 }
112
113 public SortedSet<T> getLowerTerms(T otb) {
114 SortedSet<T> result = getLowerAndEqualTerms(otb);
115 for (T setObject : terms){
116 if (setObject.compareTo(otb) == 0){
117 result.remove(setObject);
118 }
119 }
120 return result;
121 }
122
123 public SortedSet<T> getEqualTerms(T otb) {
124 SortedSet<T> result = new TreeSet<T>();
125 for (T setObject : terms){
126 if (setObject.compareTo(otb) == 0){
127 result.add(setObject);
128 }
129 }
130 return result;
131 }
132
133 public T getNextHigherTerm(T otb) {
134 try {
135 return getHigherTerms(otb).first();
136 } catch (NoSuchElementException e) {
137 return null;
138 }
139 }
140
141 public T getNextLowerTerm(T otb) {
142 try {
143 return getLowerTerms(otb).last();
144 } catch (NoSuchElementException e) {
145 return null;
146 }
147 }
148
149 @Transient
150 public T getLowestTerm() {
151 try {
152 SortedSet<T> sortedSet = getSortedSetOfTerms();
153 return sortedSet.first();
154 //return ((SortedSet<T>)terms).first();
155 } catch (NoSuchElementException e) {
156 return null;
157 }
158 }
159
160 @Transient
161 public T getHighestTerm() {
162 try {
163 SortedSet<T> sortedSet = getSortedSetOfTerms();
164 return sortedSet.last();
165 } catch (NoSuchElementException e) {
166 return null;
167 }
168 }
169
170 /**
171 * Adds a term to the the end / lowest
172 * @see eu.etaxonomy.cdm.model.common.TermVocabulary#addTerm(eu.etaxonomy.cdm.model.common.DefinedTermBase)
173 */
174 public void addTerm(T term) {
175 SortedSet<T> sortedTerms = getSortedSetOfTerms();
176 int lowestOrderIndex;
177 if (sortedTerms.isEmpty()){
178 lowestOrderIndex = 0;
179 }else{
180 T first = sortedTerms.first();
181 lowestOrderIndex = first.orderIndex;
182 }
183 term.orderIndex = lowestOrderIndex + 1;
184 super.addTerm(term);
185 }
186
187 public void addTermAbove(T termToBeAdded, T lowerTerm) {
188 int orderInd = lowerTerm.orderIndex;
189 termToBeAdded.orderIndex = orderInd;
190 //increment all orderIndexes of terms below
191 Iterator<T> iterator = terms.iterator();
192 while(iterator.hasNext()){
193 T term = iterator.next();
194 if (term.orderIndex >= orderInd){ //should always be true
195 term.orderIndex++;
196 }
197 }
198 super.addTerm(termToBeAdded);
199 }
200
201 public void addTermBelow(T termToBeAdded, T higherTerm) {
202 int orderInd = higherTerm.orderIndex;
203 termToBeAdded.orderIndex = orderInd + 1;
204 //increment all orderIndexes of terms below
205 Iterator<T> iterator = getLowerTerms(higherTerm).iterator();
206 while(iterator.hasNext()){
207 T term = iterator.next();
208 if (term.orderIndex > orderInd){
209 term.orderIndex++;
210 }
211 }
212 super.addTerm(termToBeAdded);
213 }
214
215 public void addTermEqualLevel(T termToBeAdded, T equalLevelTerm) throws WrongTermTypeException {
216 int orderInd = equalLevelTerm.orderIndex;
217 termToBeAdded.orderIndex = orderInd;
218 super.addTerm(termToBeAdded);
219 }
220
221 @Override
222 public void removeTerm(T term) {
223 if (term == null){
224 return;
225 }
226 if (this.getEqualTerms(term).size() == 0){
227 Iterator<T> iterator = getLowerTerms(term).iterator();
228 while (iterator.hasNext()){
229 T otb = iterator.next();
230 toBeChangedByObject = otb;
231 otb.decreaseIndex(this);
232 toBeChangedByObject = null;
233 }
234 }
235 super.removeTerm(term);
236 }
237
238 @Transient
239 private T toBeChangedByObject;
240
241 public boolean indexChangeAllowed(OrderedTermBase<T> orderedTermBase){
242 return orderedTermBase == toBeChangedByObject ;
243 }
244
245
246 @Transient
247 private SortedSet<T> getSortedSetOfTerms(){
248 SortedSet<T> sortedSet = new TreeSet<T>();
249 sortedSet.addAll(terms);
250 return sortedSet;
251 }
252
253 }