Merge branch 'release/3.12.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / store / TermStore.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.taxeditor.store;
12
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Collections;
16 import java.util.Comparator;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Set;
20
21 import eu.etaxonomy.cdm.api.service.ITermService;
22 import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
23 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
24 import eu.etaxonomy.cdm.model.common.MarkerType;
25 import eu.etaxonomy.cdm.model.common.TermType;
26 import eu.etaxonomy.cdm.model.common.TermVocabulary;
27 import eu.etaxonomy.cdm.model.description.Feature;
28 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
29 import eu.etaxonomy.cdm.model.name.Rank;
30 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
31 import eu.etaxonomy.taxeditor.model.DefaultTermComparator;
32 import eu.etaxonomy.taxeditor.model.TaxonRelationshipTypeInverseContainer;
33 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
34
35 /**
36 * All terms may be accessed through this store.
37 * Note: This is for internal use. When using vocabularies in the UI, try to use the preferred terms from
38 * PreferenceUtil
39 *
40 * @author n.hoffmann
41 * @created 25.06.2009
42 * @version 1.0
43 */
44 public class TermStore {
45
46 /**
47 * Returns an alphabetically sorted list of terms (anything that extends {@link DefinedTermBase}) of the given type currently available in the system.
48 *
49 * @param clazz a class that inherits from {@link DefinedTermBase}
50 * @return an alphabetically sorted list of terms
51 */
52 public static <TERM extends DefinedTermBase> List<TERM> getTerms(Class<TERM> clazz){
53 return getTerms(clazz, null, true);
54 }
55
56 /**
57 * Returns an alphabetically sorted list of terms (anything that extends {@link DefinedTermBase}) of the given {@link TermType})
58 * currently available in the system.
59 *
60 * @param termType the term type
61 * @return an alphabetically sorted list of terms
62 */
63 public static <TERM extends DefinedTermBase> List<TERM> getTerms(TermType termType, Comparator<TERM> comparator){
64 return getTermsFromService(termType, comparator);
65 }
66
67 /**
68 * Returns an alphabetically sorted list of terms (anything that extends {@link DefinedTermBase}) of the given {@link TermType})
69 * currently available in the system.
70 *
71 * @param termType the term type
72 * @return an alphabetically sorted list of terms
73 */
74 public static <TERM extends DefinedTermBase> Set<TERM> getTerms(TermVocabulary<TERM> termVocabulary, Comparator<DefinedTermBase<?>> comparator){
75 return termVocabulary.getTerms();
76 }
77
78 /**
79 * Returns a list of terms of the given type currently available in the system.
80 * If <code>filtered</code> is set to <code>true</code>, all terms for certain types will be
81 * gathered from edge cases.
82 *
83 * @param clazz a class that inherits from {@link DefinedTermBase}
84 * @param comparator a {@link Comparator} that defines the sorting algorithm. If set to null, {@link DefaultTermComparator} will be used
85 * @param filtered if set to true, some terms are filtered from the result (according to definition in {@link ITermStoreEdgeCase}s)
86 * @return a sorted list of terms
87 */
88 public static <TERM extends DefinedTermBase> List<TERM> getTerms(Class<TERM> clazz, Comparator<TERM> comparator, boolean filtered){
89 List<TERM> terms = new ArrayList<TERM>();
90
91 ITermStoreEdgeCase<TERM> edgeCase = getEdgeCase(clazz);
92 if(filtered && edgeCase != null){
93 terms = edgeCase.getTerms();
94 }else{
95 terms = getTermsFromService(clazz, comparator);
96 }
97
98 return terms;
99
100 }
101
102 /**
103 *
104 * @param termClass
105 * @param comparator
106 * @return
107 */
108 private static <T extends DefinedTermBase> List<T> getTermsFromService(TermType termType, Comparator<T> comparator){
109 if (comparator == null){
110 comparator = new DefaultTermComparator<T>();
111 }
112
113 List<T> terms = CdmStore.getService(ITermService.class).listByTermType(termType, null, null, null, null);
114 Collections.sort(terms, comparator);
115 return terms;
116 }
117
118 /**
119 *
120 * @param termClass
121 * @param comparator
122 * @return
123 */
124 private static <T extends DefinedTermBase> List<T> getTermsFromService(Class<T> termClass, Comparator<T> comparator){
125 if (comparator == null){
126 comparator = new DefaultTermComparator<T>();
127 }
128
129 List<T> terms = CdmStore.getService(ITermService.class).list(termClass, null, null, null, null);
130 Collections.sort(terms, comparator);
131 return terms;
132 }
133
134 /**
135 * @param term a {@link eu.etaxonomy.cdm.model.common.DefinedTermBase} object.
136 */
137 public static void saveTerm(DefinedTermBase term){
138 CdmStore.getService(ITermService.class).saveOrUpdate(term);
139 }
140
141 /**
142 * <p>delete</p>
143 *
144 * @param selected a {@link eu.etaxonomy.cdm.model.common.DefinedTermBase} object.
145 * @throws ReferencedObjectUndeletableException
146 */
147 public static void delete(DefinedTermBase selected) throws ReferencedObjectUndeletableException {
148 CdmStore.getService(ITermService.class).delete(selected);
149 }
150
151 /**
152 * Save a vacabulary to data store
153 *
154 * @param term a {@link eu.etaxonomy.cdm.model.common.DefinedTermBase} object.
155 */
156 public static void updateVocabulary(DefinedTermBase term) {
157 CdmStore.getService(ITermService.class).saveOrUpdate(term);
158 }
159
160 /**
161 * Handingling of special cases
162 */
163
164 private static Set<ITermStoreEdgeCase<? extends DefinedTermBase>> termStoreEdgeCases = new HashSet<ITermStoreEdgeCase<? extends DefinedTermBase>>();
165
166 static {
167 termStoreEdgeCases.add(new ITermStoreEdgeCase<Feature>() {
168
169 @Override
170 public Class<Feature> getTermClass() {
171 return Feature.class;
172 }
173
174 @Override
175 public List<Feature> getTerms() {
176 List<Feature> features = TermStore.getTermsFromService(Feature.class, null);
177 features.remove(Feature.IMAGE());
178 return features;
179 }
180 });
181 termStoreEdgeCases.add(new ITermStoreEdgeCase<MarkerType>(){
182
183 @Override
184 public Class<MarkerType> getTermClass() {
185 return MarkerType.class;
186 }
187
188 @Override
189 public List<MarkerType> getTerms() {
190 // filter out non technical markers
191 List<MarkerType> nonTechnicalMarkerTypes = new ArrayList<MarkerType>();
192 List<MarkerType> markerTypes = TermStore.getTermsFromService(MarkerType.class, null);
193
194 for (Object type : markerTypes) {
195 if (((MarkerType) type).isTechnical() == false) {
196 nonTechnicalMarkerTypes.add((MarkerType) type);
197 }
198 }
199
200 return nonTechnicalMarkerTypes;
201 }
202
203 });
204 termStoreEdgeCases.add(new ITermStoreEdgeCase<Rank>() {
205
206 @Override
207 public Class<Rank> getTermClass() {
208 return Rank.class;
209 }
210
211 @Override
212 public List<Rank> getTerms() {
213 if(PreferencesUtil.getSortRanksHierarchichally()){
214 return TermStore.getTermsFromService(Rank.class, new Comparator<Rank>(){
215
216 @Override
217 public int compare(Rank o1, Rank o2) {
218 return o1.compareTo(o2);
219 }
220
221 });
222 }else{
223 return TermStore.getTermsFromService(Rank.class, null);
224 }
225 }
226
227 });
228 termStoreEdgeCases.add(new ITermStoreEdgeCase<PresenceAbsenceTerm>() {
229
230 @Override
231 public Class<PresenceAbsenceTerm> getTermClass() {
232 return PresenceAbsenceTerm.class;
233 }
234
235 @Override
236 public List<PresenceAbsenceTerm> getTerms() {
237 List<PresenceAbsenceTerm> presenceAbsenceTerms = TermStore.getTermsFromService(PresenceAbsenceTerm.class, null);
238
239 return presenceAbsenceTerms;
240 }
241 });
242 termStoreEdgeCases.add(new ITermStoreEdgeCase<TaxonRelationshipTypeInverseContainer>() {
243
244 @Override
245 public Class<TaxonRelationshipTypeInverseContainer> getTermClass() {
246 return TaxonRelationshipTypeInverseContainer.class;
247 }
248
249 @Override
250 public List<TaxonRelationshipTypeInverseContainer> getTerms() {
251 List<TaxonRelationshipType> excludeTaxonRelationshipTypes = Arrays.asList(new TaxonRelationshipType[]{
252 TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN(),
253 TaxonRelationshipType.MISAPPLIED_NAME_FOR(),
254 TaxonRelationshipType.ALL_RELATIONSHIPS()
255 });
256
257 List<TaxonRelationshipTypeInverseContainer> relationshipTypeInverseContainers = new ArrayList<TaxonRelationshipTypeInverseContainer>();
258
259 List<TaxonRelationshipType> relationshipTypes = TermStore.getTerms(TaxonRelationshipType.class);
260
261 relationshipTypes.removeAll(excludeTaxonRelationshipTypes);
262
263 for (TaxonRelationshipType relationshipType : relationshipTypes){
264 if(!relationshipType.isSymmetric()){
265 TaxonRelationshipTypeInverseContainer inverseContainer = new TaxonRelationshipTypeInverseContainer(relationshipType, true);
266 relationshipTypeInverseContainers.add(inverseContainer);
267 }
268 TaxonRelationshipTypeInverseContainer container = new TaxonRelationshipTypeInverseContainer(relationshipType, false);
269 relationshipTypeInverseContainers.add(container);
270 }
271
272 return relationshipTypeInverseContainers;
273 }
274 });
275 }
276
277 private static <T extends DefinedTermBase> ITermStoreEdgeCase<T> getEdgeCase(Class<T> termClass) {
278
279 for (ITermStoreEdgeCase termStoreEdgeCase : termStoreEdgeCases){
280 if (termStoreEdgeCase.getTermClass().equals(termClass)){
281 return termStoreEdgeCase;
282 }
283 }
284
285 return null;
286 }
287
288 private interface ITermStoreEdgeCase<TERM> {
289
290 public abstract Class<TERM> getTermClass();
291
292 public abstract List<TERM> getTerms();
293
294 }
295 }