merge trunk to hibernate4
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / taxon / TaxonDaoHibernateImpl.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 package eu.etaxonomy.cdm.persistence.dao.hibernate.taxon;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.Comparator;
15 import java.util.HashSet;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Set;
19 import java.util.SortedSet;
20 import java.util.TreeSet;
21 import java.util.UUID;
22
23 import org.apache.log4j.Logger;
24 import org.apache.lucene.queryParser.ParseException;
25 import org.hibernate.Criteria;
26 import org.hibernate.FetchMode;
27 import org.hibernate.Hibernate;
28 import org.hibernate.Query;
29 import org.hibernate.Session;
30 import org.hibernate.criterion.Criterion;
31 import org.hibernate.criterion.Order;
32 import org.hibernate.criterion.Projections;
33 import org.hibernate.criterion.Restrictions;
34 import org.hibernate.envers.query.AuditEntity;
35 import org.hibernate.envers.query.AuditQuery;
36 import org.hibernate.search.FullTextSession;
37 import org.hibernate.search.Search;
38 import org.springframework.beans.factory.annotation.Autowired;
39 import org.springframework.beans.factory.annotation.Qualifier;
40 import org.springframework.dao.DataAccessException;
41 import org.springframework.stereotype.Repository;
42
43 import eu.etaxonomy.cdm.model.common.CdmBase;
44 import eu.etaxonomy.cdm.model.common.LSID;
45 import eu.etaxonomy.cdm.model.common.OriginalSourceBase;
46 import eu.etaxonomy.cdm.model.common.RelationshipBase;
47 import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
48 import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;
49 import eu.etaxonomy.cdm.model.location.NamedArea;
50 import eu.etaxonomy.cdm.model.name.NonViralName;
51 import eu.etaxonomy.cdm.model.name.Rank;
52 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
53 import eu.etaxonomy.cdm.model.name.TaxonNameComparator;
54 import eu.etaxonomy.cdm.model.reference.Reference;
55 import eu.etaxonomy.cdm.model.taxon.Classification;
56 import eu.etaxonomy.cdm.model.taxon.Synonym;
57 import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
58 import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
59 import eu.etaxonomy.cdm.model.taxon.Taxon;
60 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
61 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
62 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
63 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
64 import eu.etaxonomy.cdm.model.view.AuditEvent;
65 import eu.etaxonomy.cdm.persistence.dao.QueryParseException;
66 import eu.etaxonomy.cdm.persistence.dao.hibernate.AlternativeSpellingSuggestionParser;
67 import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
68 import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;
69 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
70 import eu.etaxonomy.cdm.persistence.fetch.CdmFetch;
71 import eu.etaxonomy.cdm.persistence.query.MatchMode;
72 import eu.etaxonomy.cdm.persistence.query.OrderHint;
73
74
75 /**
76 * @author a.mueller
77 * @created 24.11.2008
78 * @version 1.0
79 */
80 @Repository
81 @Qualifier("taxonDaoHibernateImpl")
82 public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implements ITaxonDao {
83 private AlternativeSpellingSuggestionParser<TaxonBase> alternativeSpellingSuggestionParser;
84 private static final Logger logger = Logger.getLogger(TaxonDaoHibernateImpl.class);
85
86 public TaxonDaoHibernateImpl() {
87 super(TaxonBase.class);
88 indexedClasses = new Class[2];
89 indexedClasses[0] = Taxon.class;
90 indexedClasses[1] = Synonym.class;
91 super.defaultField = "name.titleCache_tokenized";
92 }
93
94 @Autowired
95 private ITaxonNameDao taxonNameDao;
96
97 // spelling support currently disabled in appcontext, see spelling.xml ... "
98 // @Autowired(required = false) //TODO switched of because it caused problems when starting CdmApplicationController
99 public void setAlternativeSpellingSuggestionParser(AlternativeSpellingSuggestionParser<TaxonBase> alternativeSpellingSuggestionParser) {
100 this.alternativeSpellingSuggestionParser = alternativeSpellingSuggestionParser;
101 }
102
103
104 /* (non-Javadoc)
105 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference)
106 */
107 public List<Taxon> getRootTaxa(Reference sec) {
108 return getRootTaxa(sec, CdmFetch.FETCH_CHILDTAXA(), true, false);
109 }
110
111 /* (non-Javadoc)
112 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.Reference, eu.etaxonomy.cdm.persistence.fetch.CdmFetch, java.lang.Boolean, java.lang.Boolean)
113 */
114 public List<Taxon> getRootTaxa(Rank rank, Reference sec, CdmFetch cdmFetch, Boolean onlyWithChildren, Boolean withMisapplications, List<String> propertyPaths) {
115 checkNotInPriorView("TaxonDaoHibernateImpl.getRootTaxa(Rank rank, Reference sec, CdmFetch cdmFetch, Boolean onlyWithChildren, Boolean withMisapplications)");
116 if (onlyWithChildren == null){
117 onlyWithChildren = true;
118 }
119 if (withMisapplications == null){
120 withMisapplications = true;
121 }
122 if (cdmFetch == null){
123 cdmFetch = CdmFetch.NO_FETCH();
124 }
125
126 Criteria crit = getSession().createCriteria(Taxon.class);
127
128 crit.setFetchMode("name", FetchMode.JOIN);
129 crit.createAlias("name", "name");
130
131 if (rank != null) {
132 crit.add(Restrictions.eq("name.rank", rank));
133 }else{
134 crit.add(Restrictions.isNull("taxonomicParentCache"));
135 }
136
137 if (sec != null){
138 crit.add(Restrictions.eq("sec", sec) );
139 }
140
141 if (! cdmFetch.includes(CdmFetch.FETCH_CHILDTAXA())){
142 logger.info("Not fetching child taxa");
143 //TODO overwrite LAZY (SELECT) does not work (bug in hibernate?)
144 crit.setFetchMode("relationsToThisTaxon.fromTaxon", FetchMode.LAZY);
145 }
146
147 List<Taxon> results = new ArrayList<Taxon>();
148 List<Taxon> taxa = crit.list();
149 for(Taxon taxon : taxa){
150
151
152 //childTaxa
153 //TODO create restriction instead
154 // (a) not using cache fields
155 /*Hibernate.initialize(taxon.getRelationsFromThisTaxon());
156 if (onlyWithChildren == false || taxon.getRelationsFromThisTaxon().size() > 0){
157 if (withMisapplications == true || ! taxon.isMisappliedName()){
158 defaultBeanInitializer.initialize(taxon, propertyPaths);
159 results.add(taxon);
160 }
161 }*/
162 // (b) using cache fields
163 if (onlyWithChildren == false || taxon.hasTaxonomicChildren()){
164 if (withMisapplications == true || ! taxon.isMisapplication()){
165 defaultBeanInitializer.initialize(taxon, propertyPaths);
166 results.add(taxon);
167 }
168 }
169 }
170 return results;
171 }
172
173 /* (non-Javadoc)
174 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, eu.etaxonomy.cdm.persistence.fetch.CdmFetch, java.lang.Boolean, java.lang.Boolean)
175 */
176 public List<Taxon> getRootTaxa(Reference sec, CdmFetch cdmFetch, Boolean onlyWithChildren, Boolean withMisapplications) {
177 return getRootTaxa(null, sec, cdmFetch, onlyWithChildren, withMisapplications, null);
178 }
179
180 /*
181 * (non-Javadoc)
182 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.String, eu.etaxonomy.cdm.model.reference.Reference)
183 */
184 public List<TaxonBase> getTaxaByName(String queryString, Reference sec) {
185
186 return getTaxaByName(queryString, true, sec);
187 }
188
189 /*
190 * (non-Javadoc)
191 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.String, java.lang.Boolean, eu.etaxonomy.cdm.model.reference.Reference)
192 */
193 public List<TaxonBase> getTaxaByName(String queryString, Boolean accepted, Reference sec) {
194 checkNotInPriorView("TaxonDaoHibernateImpl.getTaxaByName(String name, Reference sec)");
195
196 Criteria criteria = null;
197 if (accepted == true) {
198 criteria = getSession().createCriteria(Taxon.class);
199 } else {
200 criteria = getSession().createCriteria(Synonym.class);
201 }
202
203 criteria.setFetchMode( "name", FetchMode.JOIN );
204 criteria.createAlias("name", "name");
205
206 if (sec != null && sec.getId() != 0) {
207 criteria.add(Restrictions.eq("sec", sec ) );
208 }
209
210 if (queryString != null) {
211 criteria.add(Restrictions.ilike("name.nameCache", queryString));
212 }
213
214 return (List<TaxonBase>)criteria.list();
215 }
216
217 public List<TaxonBase> getTaxaByName(boolean doTaxa, boolean doSynonyms, String queryString, MatchMode matchMode,
218 Integer pageSize, Integer pageNumber) {
219
220 return getTaxaByName(doTaxa, doSynonyms, false, queryString, null, matchMode, null, pageSize, pageNumber, null);
221 }
222
223 /*
224 * (non-Javadoc)
225 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, java.lang.Boolean, java.lang.Integer, java.lang.Integer)
226 */
227 public List<TaxonBase> getTaxaByName(String queryString, MatchMode matchMode,
228 Boolean accepted, Integer pageSize, Integer pageNumber) {
229
230 boolean doTaxa = true;
231 boolean doSynonyms = true;
232
233 if (accepted == true) {
234 doSynonyms = false;
235 } else {
236 doTaxa = false;
237 }
238 return getTaxaByName(doTaxa, doSynonyms, queryString, matchMode, pageSize, pageNumber);
239 }
240
241 /*
242 * (non-Javadoc)
243 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.persistence.query.MatchMode, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)
244 */
245 public List<TaxonBase> getTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames,String queryString, Classification classification,
246 MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageSize,
247 Integer pageNumber, List<String> propertyPaths) {
248
249 boolean doCount = false;
250
251 Query query = prepareTaxaByName(doTaxa, doSynonyms, doMisappliedNames, "nameCache", queryString, classification, matchMode, namedAreas, pageSize, pageNumber, doCount);
252
253 if (query != null){
254 List<TaxonBase> results = query.list();
255
256 defaultBeanInitializer.initializeAll(results, propertyPaths);
257 //TaxonComparatorSearch comp = new TaxonComparatorSearch();
258 //Collections.sort(results, comp);
259 return results;
260 }
261
262 return new ArrayList<TaxonBase>();
263
264 }
265
266
267 /*
268 * (non-Javadoc)
269 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.persistence.query.MatchMode, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)
270 */
271 //new search for the editor, for performance issues the return values are only uuid and titleCache, to avoid the initialisation of all objects
272 @SuppressWarnings("unchecked")
273 public List<UuidAndTitleCache<TaxonBase>> getTaxaByNameForEditor(boolean doTaxa, boolean doSynonyms, String queryString, Classification classification,
274 MatchMode matchMode, Set<NamedArea> namedAreas) {
275 long zstVorher;
276 long zstNachher;
277
278 boolean doCount = false;
279 Query query = prepareTaxaByNameForEditor(doTaxa, doSynonyms, "nameCache", queryString, classification, matchMode, namedAreas, doCount);
280
281
282 if (query != null){
283 List<Object[]> results = query.list();
284
285 List<UuidAndTitleCache<TaxonBase>> resultObjects = new ArrayList<UuidAndTitleCache<TaxonBase>>();
286 Object[] result;
287 for(int i = 0; i<results.size();i++){
288 result = results.get(i);
289
290 //differentiate taxa and synonyms
291 if (doTaxa && doSynonyms){
292 if (result[2].equals("synonym")) {
293 resultObjects.add( new UuidAndTitleCache(Synonym.class, (UUID) result[0], (String)result[1], (Boolean)result[3]));
294 }
295 else {
296 resultObjects.add( new UuidAndTitleCache(Taxon.class, (UUID) result[0], (String)result[1], (Boolean)result[3]));
297 }
298 }else if (doTaxa){
299 resultObjects.add( new UuidAndTitleCache(Taxon.class, (UUID) result[0], (String)result[1], (Boolean)result[3]));
300 }else if (doSynonyms){
301 resultObjects.add( new UuidAndTitleCache(Synonym.class, (UUID) result[0], (String)result[1], (Boolean)result[3]));
302 }
303 }
304
305 return resultObjects;
306
307 }
308 return new ArrayList<UuidAndTitleCache<TaxonBase>>();
309
310 }
311
312 /*
313 * (non-Javadoc)
314 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByCommonName(java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.persistence.query.MatchMode, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)
315 */
316 public List<Object[]> getTaxaByCommonName(String queryString, Classification classification,
317 MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageSize,
318 Integer pageNumber, List<String> propertyPaths) {
319 boolean doCount = false;
320 Query query = prepareTaxaByCommonName(queryString, classification, matchMode, namedAreas, pageSize, pageNumber, doCount);
321 if (query != null){
322 List<Object[]> results = query.list();
323 defaultBeanInitializer.initializeAll(results, propertyPaths);
324 return results;
325 }
326 return new ArrayList<Object[]>();
327
328 }
329
330 /**
331 * @param clazz
332 * @param searchField the field in TaxonNameBase to be searched through usually either <code>nameCache</code> or <code>titleCache</code>
333 * @param queryString
334 * @param classification TODO
335 * @param matchMode
336 * @param namedAreas
337 * @param pageSize
338 * @param pageNumber
339 * @param doCount
340 * @return
341 *
342 *
343 */
344 private Query prepareTaxaByNameForEditor(boolean doTaxa, boolean doSynonyms, String searchField, String queryString, Classification classification,
345 MatchMode matchMode, Set<NamedArea> namedAreas, boolean doCount) {
346 return prepareQuery(doTaxa, doSynonyms, false, searchField, queryString,
347 classification, matchMode, namedAreas, doCount, true);
348 }
349
350 /**
351 * @param searchField
352 * @param queryString
353 * @param classification
354 * @param matchMode
355 * @param namedAreas
356 * @param doCount
357 * @param doNotReturnFullEntities
358 * if set true the seach method will not return synonym and taxon
359 * entities but an array containing the uuid, titleCache, and the
360 * DTYPE in lowercase letters.
361 * @param clazz
362 * @return
363 */
364 private Query prepareQuery(boolean doTaxa, boolean doSynonyms, boolean doIncludeMisappliedNames, String searchField, String queryString,
365 Classification classification, MatchMode matchMode, Set<NamedArea> namedAreas, boolean doCount, boolean doNotReturnFullEntities){
366
367 String hqlQueryString = matchMode.queryStringFrom(queryString);
368 String selectWhat;
369 if (doNotReturnFullEntities){
370 selectWhat = "t.uuid, t.titleCache ";
371 }else {
372 selectWhat = (doCount ? "count(t)": "t");
373 }
374
375 String hql = "";
376 Set<NamedArea> areasExpanded = new HashSet<NamedArea>();
377 if(namedAreas != null && namedAreas.size() > 0){
378 // expand areas and restrict by distribution area
379 Query areaQuery = getSession().createQuery("select childArea from NamedArea as childArea left join childArea.partOf as parentArea where parentArea = :area");
380 expandNamedAreas(namedAreas, areasExpanded, areaQuery);
381 }
382 boolean doAreaRestriction = areasExpanded.size() > 0;
383
384 Set<UUID> namedAreasUuids = new HashSet<UUID>();
385 for (NamedArea area:areasExpanded){
386 namedAreasUuids.add(area.getUuid());
387 }
388
389
390 String [] subSelects = createHQLString(doTaxa, doSynonyms, doIncludeMisappliedNames, classification, areasExpanded, matchMode, searchField);
391 String taxonSubselect = subSelects[1];
392 String synonymSubselect = subSelects[2];
393 String misappliedSelect = subSelects[0];
394
395
396 /*if(classification != null ){
397 if (!doIncludeMisappliedNames){
398 if(doAreaRestriction){
399
400 taxonSubselect = "select t.id from" +
401 " Distribution e" +
402 " join e.inDescription d" +
403 " join d.taxon t" +
404 " join t.name n " +
405 " join t.taxonNodes as tn "+
406 " where" +
407 " e.area.uuid in (:namedAreasUuids) AND" +
408 " tn.classification = :classification" +
409 " AND n." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
410
411
412
413 synonymSubselect = "select s.id from" +
414 " Distribution e" +
415 " join e.inDescription d" +
416 " join d.taxon t" + // the taxa
417 " join t.taxonNodes as tn "+
418 " join t.synonymRelations sr" +
419 " join sr.relatedFrom s" + // the synonyms
420 " join s.name sn"+
421 " where" +
422 " e.area.uuid in (:namedAreasUuids) AND" +
423 " tn.classification = :classification" +
424 " AND sn." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
425
426 } else {
427
428 taxonSubselect = "select t.id from" +
429 " Taxon t" +
430 " join t.name n " +
431 " join t.taxonNodes as tn "+
432 " where" +
433 " tn.classification = :classification" +
434 " AND n." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
435
436 synonymSubselect = "select s.id from" +
437 " Taxon t" + // the taxa
438 " join t.taxonNodes as tn "+
439 " join t.synonymRelations sr" +
440 " join sr.relatedFrom s" + // the synonyms
441 " join s.name sn"+
442 " where" +
443 " tn.classification = :classification" +
444 " AND sn." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
445 }
446 }else{
447 if(doAreaRestriction){
448 if (!doTaxa && !doSynonyms ){
449 misappliedSelect = "select t.id from" +
450 " Distribution e" +
451 " join e.inDescription d" +
452 " join d.taxon t" +
453 " join t.name n " +
454 " join t.taxonNodes as tn "+
455 " left join t.relationsFromThisTaxon as rft" +
456 " left join rft.relatedTo as rt" +
457 " left join rt.taxonNodes as tn2" +
458 " left join rt.name as n2" +
459 " left join rft.type as rtype"+
460 " where" +
461 " e.area.uuid in (:namedAreasUuids) AND" +
462 " (tn.classification != :classification" +
463 " AND n." + searchField + " " + matchMode.getMatchOperator() + " :queryString" +
464 " AND tn2.classification = :classification" +
465 " AND rtype = :rType )";
466
467 }else{
468 taxonSubselect = "select t.id from" +
469 " Distribution e" +
470 " join e.inDescription d" +
471 " join d.taxon t" +
472 " join t.name n " +
473 " join t.taxonNodes as tn "+
474 " left join t.relationsFromThisTaxon as rft" +
475 " left join rft.relatedTo as rt" +
476 " left join rt.taxonNodes as tn2" +
477 " left join rt.name as n2" +
478 " left join rft.type as rtype"+
479 " where" +
480 " e.area.uuid in (:namedAreasUuids) AND" +
481 " (tn.classification = :classification" +
482 " AND n." + searchField + " " + matchMode.getMatchOperator() + " :queryString )" +
483 " OR"+
484 " (tn.classification != :classification" +
485 " AND n." + searchField + " " + matchMode.getMatchOperator() + " :queryString" +
486 " AND tn2.classification = :classification" +
487 " AND rtype = :rType )";
488
489
490 synonymSubselect = "select s.id from" +
491 " Distribution e" +
492 " join e.inDescription d" +
493 " join d.taxon t" + // the taxa
494 " join t.taxonNodes as tn "+
495 " join t.synonymRelations sr" +
496 " join sr.relatedFrom s" + // the synonyms
497 " join s.name sn"+
498 " where" +
499 " e.area.uuid in (:namedAreasUuids) AND" +
500 " tn.classification != :classification" +
501 " AND sn." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
502 }
503 } else {
504 if (!doTaxa && !doSynonyms ){
505 misappliedSelect = "select t.id from" +
506 " Distribution e" +
507 " join e.inDescription d" +
508 " join d.taxon t" +
509 " join t.name n " +
510 " join t.taxonNodes as tn "+
511 " left join t.relationsFromThisTaxon as rft" +
512 " left join rft.relatedTo as rt" +
513 " left join rt.taxonNodes as tn2" +
514 " left join rt.name as n2" +
515 " left join rft.type as rtype"+
516 " where" +
517 " (tn.classification != :classification" +
518 " AND n." + searchField + " " + matchMode.getMatchOperator() + " :queryString" +
519 " AND tn2.classification = :classification" +
520 " AND rtype = :rType )";
521
522 }else{
523 taxonSubselect = "select t.id from" +
524 " Taxon t" +
525 " join t.name n " +
526 " join t.taxonNodes as tn "+
527 " left join t.relationsFromThisTaxon as rft" +
528 " left join rft.relatedTo as rt" +
529 " left join rt.taxonNodes as tn2" +
530 " left join rt.name as n2" +
531 " left join rft.type as rtype"+
532 " where " +
533 " (tn.classification = :classification" +
534 " AND n." + searchField + " " + matchMode.getMatchOperator() + " :queryString )" +
535 " OR"+
536 " (tn.classification != :classification" +
537 " AND n." + searchField + " " + matchMode.getMatchOperator() + " :queryString" +
538 " AND tn2.classification = :classification" +
539 " AND rtype = :rType )";
540
541 synonymSubselect = "select s.id from" +
542 " Taxon t" + // the taxa
543 " join t.taxonNodes as tn "+
544 " join t.synonymRelations sr" +
545 " join sr.relatedFrom s" + // the synonyms
546 " join s.name sn"+
547 " where" +
548 " tn.classification != :classification" +
549 " AND sn." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
550 }
551 }
552 }
553 } else {
554
555 if (!doIncludeMisappliedNames){
556 if(doAreaRestriction){
557 taxonSubselect = "select t.id from " +
558 " Distribution e" +
559 " join e.inDescription d" +
560 " join d.taxon t" +
561 " join t.name n "+
562 " where" +
563 (doAreaRestriction ? " e.area.uuid in (:namedAreasUuids) AND" : "") +
564 " n." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
565
566 synonymSubselect = "select s.id from" +
567 " Distribution e" +
568 " join e.inDescription d" +
569 " join d.taxon t" + // the taxa
570 " join t.synonymRelations sr" +
571 " join sr.relatedFrom s" + // the synonyms
572 " join s.name sn"+
573 " where" +
574 (doAreaRestriction ? " e.area.uuid in (:namedAreasUuids) AND" : "") +
575 " sn." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
576
577 } else {
578
579 taxonSubselect = "select t.id from " +
580 " Taxon t" +
581 " join t.name n "+
582 " where" +
583 " n." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
584
585 synonymSubselect = "select s.id from" +
586 " Taxon t" + // the taxa
587 " join t.synonymRelations sr" +
588 " join sr.relatedFrom s" + // the synonyms
589 " join s.name sn"+
590 " where" +
591 " sn." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
592 }
593 }else{
594
595 }
596
597 }*/
598
599 logger.debug("taxonSubselect: " + taxonSubselect != null ? taxonSubselect: "NULL");
600 logger.debug("synonymSubselect: " + synonymSubselect != null ? synonymSubselect: "NULL");
601
602 Query subTaxon = null;
603 Query subSynonym = null;
604 Query subMisappliedNames = null;
605 if(doTaxa){
606 // find Taxa
607 subTaxon = getSession().createQuery(taxonSubselect).setParameter("queryString", hqlQueryString);
608
609 if(doAreaRestriction){
610 subTaxon.setParameterList("namedAreasUuids", namedAreasUuids);
611 }
612 if(classification != null){
613 subTaxon.setParameter("classification", classification);
614
615 }
616
617
618 }
619
620 if(doSynonyms){
621 // find synonyms
622 subSynonym = getSession().createQuery(synonymSubselect).setParameter("queryString", hqlQueryString);
623
624 if(doAreaRestriction){
625 subSynonym.setParameterList("namedAreasUuids", namedAreasUuids);
626 }
627 if(classification != null){
628 subSynonym.setParameter("classification", classification);
629 }
630 }
631 if (doIncludeMisappliedNames ){
632 subMisappliedNames = getSession().createQuery(misappliedSelect).setParameter("queryString", hqlQueryString);
633 subMisappliedNames.setParameter("rType", TaxonRelationshipType.MISAPPLIED_NAME_FOR());
634 if(doAreaRestriction){
635 subMisappliedNames.setParameterList("namedAreasUuids", namedAreasUuids);
636 }
637 if(classification != null){
638 subMisappliedNames.setParameter("classification", classification);
639 }
640 }
641
642 List<Integer> taxa = new ArrayList<Integer>();
643 List<Integer> synonyms = new ArrayList<Integer>();
644 if (doSynonyms){
645 synonyms = subSynonym.list();
646 }
647 if(doTaxa){
648 taxa = subTaxon.list();
649 }
650 if (doIncludeMisappliedNames){
651 taxa.addAll(subMisappliedNames.list());
652 }
653
654 if (doTaxa && doSynonyms){
655 if(synonyms.size()>0 && taxa.size()>0){
656 hql = "select " + selectWhat;
657 // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:
658 // also return the computed isOrphaned flag
659 if (doNotReturnFullEntities && !doCount ){
660 hql += ", case when t.id in (:taxa) then 'taxon' else 'synonym' end, " +
661 " case when t.id in (:taxa) and t.taxonNodes is empty and t.relationsFromThisTaxon is empty and t.relationsToThisTaxon is empty then true else false end ";
662 }
663 hql += " from %s t " +
664 " where (t.id in (:taxa) OR t.id in (:synonyms)) ";
665 }else if (synonyms.size()>0 ){
666 hql = "select " + selectWhat;
667 // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:
668 // also return the computed isOrphaned flag
669 if (doNotReturnFullEntities && !doCount ){
670 hql += ", 'synonym', " +
671 " false ";
672 }
673 hql += " from %s t " +
674 " where t.id in (:synonyms) ";
675
676 } else if (taxa.size()>0 ){
677 hql = "select " + selectWhat;
678 // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:
679 // also return the computed isOrphaned flag
680 if (doNotReturnFullEntities && !doCount ){
681 hql += ", 'taxon', " +
682 " case when t.taxonNodes is empty and t.relationsFromThisTaxon is empty and t.relationsToThisTaxon is empty then true else false end ";
683 }
684 hql += " from %s t " +
685 " where t.id in (:taxa) ";
686
687 } else{
688 hql = "select " + selectWhat + " from %s t";
689 }
690 } else if(doTaxa){
691 if (taxa.size()>0){
692 hql = "select " + selectWhat;
693 // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:
694 // also return the computed isOrphaned flag
695 if (doNotReturnFullEntities){
696 hql += ", 'taxon', " +
697 " case when t.taxonNodes is empty and t.relationsFromThisTaxon is empty and t.relationsToThisTaxon is empty then true else false end ";
698 }
699 hql += " from %s t " +
700 " where t.id in (:taxa) ";
701
702 }else{
703 hql = "select " + selectWhat + " from %s t";
704 }
705 } else if(doSynonyms){
706 if (synonyms.size()>0){
707
708 hql = "select " + selectWhat;
709 // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:
710 // also return the computed isOrphaned flag
711 if (doNotReturnFullEntities){
712 hql += ", 'synonym', " +
713 " false ";
714 }
715 hql += " from %s t " +
716 " where t.id in (:synonyms) ";
717 }else{
718 hql = "select " + selectWhat + " from %s t";
719 }
720 } else if (doIncludeMisappliedNames){
721 hql = "select " + selectWhat;
722 // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:
723 // also return the computed isOrphaned flag
724 if (doNotReturnFullEntities){
725 hql += ", 'taxon', " +
726 " case when t.taxonNodes is empty and t.relationsFromThisTaxon is empty and t.relationsToThisTaxon is empty then true else false end ";
727 }
728 hql += " from %s t " +
729 " where t.id in (:taxa) ";
730
731 }
732
733 String classString;
734 if (doTaxa && doSynonyms){
735 classString = "TaxonBase";
736 } else if (doTaxa){
737 classString = "Taxon";
738 } else if (doSynonyms){
739 classString = "Synonym";
740 } else{//only misappliedNames
741 classString = "Taxon";
742 }
743
744 hql = String.format(hql, classString);
745
746
747 if (hql == "") return null;
748 if(!doCount){
749 hql += " order by t.name.genusOrUninomial, case when t.name.specificEpithet like '\"%\"' then 1 else 0 end, t.name.specificEpithet, t.name.rank desc, t.name.nameCache";
750 }
751
752 logger.debug("hql: " + hql);
753 Query query = getSession().createQuery(hql);
754
755
756 if (doTaxa && doSynonyms){
757 // find taxa and synonyms
758 if (taxa.size()>0){
759 query.setParameterList("taxa", taxa);
760 }
761 if (synonyms.size()>0){
762 query.setParameterList("synonyms",synonyms);
763 }
764 if (taxa.size()== 0 && synonyms.size() == 0){
765 return null;
766 }
767 }else if(doTaxa){
768 //find taxa
769 if (taxa.size()>0){
770 query.setParameterList("taxa", taxa );
771 }else{
772 return null;
773 }
774 } else if(doSynonyms){
775 // find synonyms
776 if (synonyms.size()>0){
777 query.setParameterList("synonyms", synonyms);
778 }else{
779 return null;
780 }
781 } else{
782 //only misappliedNames
783 if (taxa.size()>0){
784 query.setParameterList("taxa", taxa );
785 }else{
786 return null;
787 }
788 }
789
790
791 return query;
792
793
794 }
795
796
797 /**
798 * @param searchField the field in TaxonNameBase to be searched through usually either <code>nameCache</code> or <code>titleCache</code>
799 * @param queryString
800 * @param classification TODO
801 * @param matchMode
802 * @param namedAreas
803 * @param pageSize
804 * @param pageNumber
805 * @param doCount
806 * @param clazz
807 * @return
808 *
809 * FIXME implement classification restriction & implement test: see {@link TaxonDaoHibernateImplTest#testCountTaxaByName()}
810 */
811 private Query prepareTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames, String searchField, String queryString,
812 Classification classification, MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageSize, Integer pageNumber, boolean doCount) {
813
814 Query query = prepareQuery(doTaxa, doSynonyms, doMisappliedNames, searchField, queryString, classification, matchMode, namedAreas, doCount, false);
815
816 if(pageSize != null && !doCount) {
817 query.setMaxResults(pageSize);
818 if(pageNumber != null) {
819 query.setFirstResult(pageNumber * pageSize);
820 }
821 }
822
823 return query;
824 }
825
826 private Query prepareTaxaByCommonName(String queryString, Classification classification,
827 MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageSize, Integer pageNumber, boolean doCount){
828
829 String hql= "from Taxon t " +
830 "join t.descriptions d "+
831 "join d.descriptionElements e " +
832 "join e.feature f " +
833 "where f.supportsCommonTaxonName = true and e.name "+matchMode.getMatchOperator()+" :queryString";//and ls.text like 'common%'";
834
835 Query query = getSession().createQuery(hql);
836
837 query.setParameter("queryString", queryString);
838
839 if(pageSize != null && !doCount) {
840 query.setMaxResults(pageSize);
841 if(pageNumber != null) {
842 query.setFirstResult(pageNumber * pageSize);
843 }
844 }
845 return query;
846 }
847
848 /* (non-Javadoc)
849 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxaByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, eu.etaxonomy.cdm.persistence.query.SelectMode, eu.etaxonomy.cdm.model.reference.Reference, java.util.Set)
850 */
851 public long countTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames, String queryString, Classification classification,
852 MatchMode matchMode, Set<NamedArea> namedAreas) {
853
854 boolean doCount = true;
855 /*
856 boolean doTaxa = true;
857 boolean doSynonyms = true;
858 if (clazz.equals(Taxon.class)){
859 doSynonyms = false;
860 } else if (clazz.equals(Synonym.class)){
861 doTaxa = false;
862 }
863 */
864
865
866 Query query = prepareTaxaByName(doTaxa, doSynonyms, doMisappliedNames, "nameCache", queryString, classification, matchMode, namedAreas, null, null, doCount);
867 if (query != null) {
868 return (Long)query.uniqueResult();
869 }else{
870 return 0;
871 }
872 }
873
874 /**
875 * @param namedAreas
876 * @param areasExpanded
877 * @param areaQuery
878 */
879 private void expandNamedAreas(Collection<NamedArea> namedAreas, Set<NamedArea> areasExpanded, Query areaQuery) {
880 List<NamedArea> childAreas;
881 for(NamedArea a : namedAreas){
882 areasExpanded.add(a);
883 areaQuery.setParameter("area", a);
884 childAreas = areaQuery.list();
885 if(childAreas.size() > 0){
886 areasExpanded.addAll(childAreas);
887 expandNamedAreas(childAreas, areasExpanded, areaQuery);
888 }
889 }
890 }
891
892 // /* (non-Javadoc)
893 // * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxaByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, eu.etaxonomy.cdm.persistence.query.SelectMode)
894 // */
895 // public Integer countTaxaByName(String queryString, MatchMode matchMode, SelectMode selectMode) {
896 // return countTaxaByName(queryString, matchMode, selectMode, null);
897 // }
898
899 // /* (non-Javadoc)
900 // * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxaByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, eu.etaxonomy.cdm.persistence.query.SelectMode, eu.etaxonomy.cdm.model.reference.Reference)
901 // */
902 // public Integer countTaxaByName(String queryString,
903 // MatchMode matchMode, SelectMode selectMode, Reference sec) {
904 //
905 // Long count = countTaxaByName(queryString, matchMode, selectMode, sec, null);
906 // return count.intValue();
907 //
908 // }
909
910 // public Integer countTaxaByName(String queryString, MatchMode matchMode, Boolean accepted) {
911 //
912 // SelectMode selectMode = (accepted ? SelectMode.TAXA : SelectMode.SYNONYMS);
913 // Long count = countTaxaByName(queryString, matchMode, selectMode, null, null);
914 // return count.intValue();
915 // }
916
917 public List<TaxonBase> getAllTaxonBases(Integer pagesize, Integer page) {
918 return super.list(pagesize, page);
919 }
920
921 /*
922 * (non-Javadoc)
923 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getAllSynonyms(java.lang.Integer, java.lang.Integer)
924 */
925 public List<Synonym> getAllSynonyms(Integer limit, Integer start) {
926 Criteria criteria = getSession().createCriteria(Synonym.class);
927
928 if(limit != null) {
929 criteria.setFirstResult(start);
930 criteria.setMaxResults(limit);
931 }
932
933 return criteria.list();
934 }
935
936 /*
937 * (non-Javadoc)
938 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getAllTaxa(java.lang.Integer, java.lang.Integer)
939 */
940 public List<Taxon> getAllTaxa(Integer limit, Integer start) {
941 Criteria criteria = getSession().createCriteria(Taxon.class);
942
943 if(limit != null) {
944 criteria.setFirstResult(start);
945 criteria.setMaxResults(limit);
946 }
947
948 return criteria.list();
949 }
950
951 /*
952 * (non-Javadoc)
953 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getAllRelationships(java.lang.Integer, java.lang.Integer)
954 */
955 @Override
956 public List<RelationshipBase> getAllRelationships(/*Class<? extends RelationshipBase> clazz,*/ Integer limit, Integer start) {
957 Class<? extends RelationshipBase> clazz = RelationshipBase.class; //preliminary, see #2653
958 AuditEvent auditEvent = getAuditEventFromContext();
959 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
960 // for some reason the HQL .class discriminator didn't work here so I created this preliminary
961 // implementation for now. Should be cleaned in future.
962
963 List<RelationshipBase> result = new ArrayList<RelationshipBase>();
964
965 int taxRelSize = countAllRelationships(TaxonRelationship.class);
966
967 if (taxRelSize > start){
968
969 String hql = " FROM TaxonRelationship as rb ORDER BY rb.id ";
970 Query query = getSession().createQuery(hql);
971 query.setFirstResult(start);
972 if (limit != null){
973 query.setMaxResults(limit);
974 }
975 result = query.list();
976 }
977 limit = limit - result.size();
978 if (limit > 0){
979 String hql = " FROM SynonymRelationship as rb ORDER BY rb.id ";
980 Query query = getSession().createQuery(hql);
981 start = (taxRelSize > start) ? 0 : (start - taxRelSize);
982 query.setFirstResult(start);
983 if (limit != null){
984 query.setMaxResults(limit);
985 }
986 result.addAll(query.list());
987 }
988 return result;
989
990 } else {
991 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(clazz,auditEvent.getRevisionNumber());
992 return (List<RelationshipBase>)query.getResultList();
993 }
994 }
995
996 /** Sets the taxonomic parent to null. Does not handle taxonomic relationships. */
997 // private boolean nullifyTaxonomicParent(Taxon taxon) {
998 //
999 // try {
1000 // Method nullifyTaxonomicParent = taxon.getClass().getMethod("nullifyTaxonomicParent");
1001 // nullifyTaxonomicParent.invoke(taxon);
1002 // } catch (NoSuchMethodException ex) {
1003 // logger.error("NoSuchMethod: " + ex.getMessage());
1004 // return false;
1005 // } catch (IllegalArgumentException ex) {
1006 // logger.error("IllegalArgumentException: " + ex.getMessage());
1007 // return false;
1008 // } catch (IllegalAccessException ex) {
1009 // logger.error("IllegalAccessException: " + ex.getMessage());
1010 // return false;
1011 // } catch (InvocationTargetException ex) {
1012 // logger.error("IllegalAccessException: " + ex.getMessage());
1013 // return false;
1014 // }
1015 // return true;
1016 // }
1017
1018 @Override
1019 public UUID delete(TaxonBase taxonBase) throws DataAccessException{
1020 if (taxonBase == null){
1021 logger.warn("TaxonBase was 'null'");
1022 return null;
1023 }
1024
1025 // Merge the object in if it is detached
1026 //
1027 // I think this is preferable to catching lazy initialization errors
1028 // as that solution only swallows and hides the exception, but doesn't
1029 // actually solve it.
1030 getSession().merge(taxonBase);
1031
1032 if (taxonBase instanceof Taxon){ // is Taxon
1033 for (Iterator<TaxonRelationship> iterator = ((Taxon)taxonBase).getRelationsFromThisTaxon().iterator(); iterator.hasNext();){
1034 TaxonRelationship relationFromThisTaxon = iterator.next();
1035
1036 // decrease children count of taxonomic parent by one
1037 if (relationFromThisTaxon.getType().equals(TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN())) {
1038 Taxon toTaxon = relationFromThisTaxon.getToTaxon(); // parent
1039 if (toTaxon != null) {
1040 toTaxon.setTaxonomicChildrenCount(toTaxon.getTaxonomicChildrenCount() - 1);
1041 }
1042 }
1043 }
1044 }
1045
1046 return super.delete(taxonBase);
1047 }
1048
1049
1050 /* (non-Javadoc)
1051 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#findByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, int, int, boolean)
1052 */
1053 public List<TaxonBase> findByNameTitleCache(boolean doTaxa, boolean doSynonyms, String queryString, Classification classification, MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageNumber, Integer pageSize, List<String> propertyPaths) {
1054
1055 boolean doCount = false;
1056 Query query = prepareTaxaByName(doTaxa, doSynonyms, false, "titleCache", queryString, classification, matchMode, namedAreas, pageSize, pageNumber, doCount);
1057 if (query != null){
1058 List<TaxonBase> results = query.list();
1059 defaultBeanInitializer.initializeAll(results, propertyPaths);
1060 return results;
1061 }
1062 return new ArrayList<TaxonBase>();
1063
1064 }
1065
1066 /* (non-Javadoc)
1067 < * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#findByUuid(java.util.UUID, java.util.List<org.hibernate.criterion.Criterion>, java.util.List<java.lang.String>)
1068 */
1069 public TaxonBase findByUuid(UUID uuid, List<Criterion> criteria, List<String> propertyPaths) {
1070
1071 Criteria crit = getSession().createCriteria(type);
1072
1073 if (uuid != null) {
1074 crit.add(Restrictions.eq("uuid", uuid));
1075 } else {
1076 logger.warn("UUID is NULL");
1077 return null;
1078 }
1079 if(criteria != null){
1080 for (Criterion criterion : criteria) {
1081 crit.add(criterion);
1082 }
1083 }
1084 crit.addOrder(Order.asc("uuid"));
1085
1086 List<? extends TaxonBase> results = crit.list();
1087 if (results.size() == 1) {
1088 defaultBeanInitializer.initializeAll(results, propertyPaths);
1089 TaxonBase taxon = results.iterator().next();
1090 return taxon;
1091 } else if (results.size() > 1) {
1092 logger.error("Multiple results for UUID: " + uuid);
1093 } else if (results.size() == 0) {
1094 logger.info("No results for UUID: " + uuid);
1095 }
1096
1097 return null;
1098 }
1099
1100 public List<? extends TaxonBase> findByUuids(List<UUID> uuids, List<Criterion> criteria, List<String> propertyPaths) {
1101
1102 Criteria crit = getSession().createCriteria(type);
1103
1104 if (uuids != null) {
1105 crit.add(Restrictions.in("uuid", uuids));
1106 } else {
1107 logger.warn("List<UUID> uuids is NULL");
1108 return null;
1109 }
1110 if(criteria != null){
1111 for (Criterion criterion : criteria) {
1112 crit.add(criterion);
1113 }
1114 }
1115 crit.addOrder(Order.asc("uuid"));
1116
1117 List<? extends TaxonBase> results = crit.list();
1118
1119 defaultBeanInitializer.initializeAll(results, propertyPaths);
1120 return results;
1121 }
1122
1123 /*
1124 * (non-Javadoc)
1125 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countMatchesByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, boolean)
1126 */
1127 public int countMatchesByName(String queryString, MatchMode matchMode, boolean onlyAcccepted) {
1128 checkNotInPriorView("TaxonDaoHibernateImpl.countMatchesByName(String queryString, ITitledDao.MATCH_MODE matchMode, boolean onlyAcccepted)");
1129 Criteria crit = getSession().createCriteria(type);
1130 crit.add(Restrictions.ilike("titleCache", matchMode.queryStringFrom(queryString)));
1131 crit.setProjection(Projections.rowCount());
1132 int result = ((Number)crit.list().get(0)).intValue();
1133 return result;
1134 }
1135
1136 /*
1137 * (non-Javadoc)
1138 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countMatchesByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, boolean, java.util.List)
1139 */
1140 public int countMatchesByName(String queryString, MatchMode matchMode, boolean onlyAcccepted, List<Criterion> criteria) {
1141 checkNotInPriorView("TaxonDaoHibernateImpl.countMatchesByName(String queryString, ITitledDao.MATCH_MODE matchMode, boolean onlyAcccepted, List<Criterion> criteria)");
1142 Criteria crit = getSession().createCriteria(type);
1143 crit.add(Restrictions.ilike("titleCache", matchMode.queryStringFrom(queryString)));
1144 if(criteria != null){
1145 for (Criterion criterion : criteria) {
1146 crit.add(criterion);
1147 }
1148 }
1149 crit.setProjection(Projections.rowCount());
1150 int result = ((Number)crit.list().get(0)).intValue();
1151 return result;
1152 }
1153
1154 /*
1155 * (non-Javadoc)
1156 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, eu.etaxonomy.cdm.model.common.RelationshipBase.Direction)
1157 */
1158 public int countTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Direction direction) {
1159 AuditEvent auditEvent = getAuditEventFromContext();
1160 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
1161 Query query = null;
1162
1163 if(type == null) {
1164 query = getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship."+direction+" = :relatedTaxon");
1165 } else {
1166 query = getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship."+direction+" = :relatedTaxon and taxonRelationship.type = :type");
1167 query.setParameter("type",type);
1168 }
1169 query.setParameter("relatedTaxon", taxon);
1170
1171 return ((Long)query.uniqueResult()).intValue();
1172 } else {
1173 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonRelationship.class,auditEvent.getRevisionNumber());
1174 query.add(AuditEntity.relatedId(direction.toString()).eq(taxon.getId()));
1175 query.addProjection(AuditEntity.id().count("id"));
1176
1177 if(type != null) {
1178 query.add(AuditEntity.relatedId("type").eq(type.getId()));
1179 }
1180
1181 return ((Long)query.getSingleResult()).intValue();
1182 }
1183 }
1184
1185 /*
1186 * (non-Javadoc)
1187 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countSynonyms(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType)
1188 */
1189 public int countSynonyms(Taxon taxon, SynonymRelationshipType type) {
1190 AuditEvent auditEvent = getAuditEventFromContext();
1191 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
1192 Criteria criteria = getSession().createCriteria(SynonymRelationship.class);
1193
1194 criteria.add(Restrictions.eq("relatedTo", taxon));
1195 if(type != null) {
1196 criteria.add(Restrictions.eq("type", type));
1197 }
1198 criteria.setProjection(Projections.rowCount());
1199 return ((Number)criteria.uniqueResult()).intValue();
1200 } else {
1201 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(SynonymRelationship.class,auditEvent.getRevisionNumber());
1202 query.add(AuditEntity.relatedId("relatedTo").eq(taxon.getId()));
1203 query.addProjection(AuditEntity.id().count("id"));
1204
1205 if(type != null) {
1206 query.add(AuditEntity.relatedId("type").eq(type.getId()));
1207 }
1208
1209 return ((Long)query.getSingleResult()).intValue();
1210 }
1211 }
1212
1213 /*
1214 * (non-Javadoc)
1215 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countSynonyms(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType)
1216 */
1217 public int countSynonyms(Synonym synonym, SynonymRelationshipType type) {
1218 AuditEvent auditEvent = getAuditEventFromContext();
1219 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
1220 Criteria criteria = getSession().createCriteria(SynonymRelationship.class);
1221
1222 criteria.add(Restrictions.eq("relatedFrom", synonym));
1223 if(type != null) {
1224 criteria.add(Restrictions.eq("type", type));
1225 }
1226
1227 criteria.setProjection(Projections.rowCount());
1228 return ((Number)criteria.uniqueResult()).intValue();
1229 } else {
1230 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(SynonymRelationship.class,auditEvent.getRevisionNumber());
1231 query.add(AuditEntity.relatedId("relatedFrom").eq(synonym.getId()));
1232 query.addProjection(AuditEntity.id().count("id"));
1233
1234 if(type != null) {
1235 query.add(AuditEntity.relatedId("type").eq(type.getId()));
1236 }
1237
1238 return ((Long)query.getSingleResult()).intValue();
1239 }
1240 }
1241
1242 /*
1243 * (non-Javadoc)
1244 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxaByName(java.lang.Class, java.lang.String, java.lang.String, java.lang.String, java.lang.String, eu.etaxonomy.cdm.model.name.Rank)
1245 */
1246 public int countTaxaByName(Class<? extends TaxonBase> clazz, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, Rank rank) {
1247 checkNotInPriorView("TaxonDaoHibernateImpl.countTaxaByName(Boolean accepted, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, Rank rank)");
1248 Criteria criteria = null;
1249
1250 criteria = getSession().createCriteria(clazz);
1251
1252 criteria.setFetchMode( "name", FetchMode.JOIN );
1253 criteria.createAlias("name", "name");
1254
1255 if(genusOrUninomial == null) {
1256 criteria.add(Restrictions.isNull("name.genusOrUninomial"));
1257 } else if(!genusOrUninomial.equals("*")) {
1258 criteria.add(Restrictions.eq("name.genusOrUninomial", genusOrUninomial));
1259 }
1260
1261 if(infraGenericEpithet == null) {
1262 criteria.add(Restrictions.isNull("name.infraGenericEpithet"));
1263 } else if(!infraGenericEpithet.equals("*")) {
1264 criteria.add(Restrictions.eq("name.infraGenericEpithet", infraGenericEpithet));
1265 }
1266
1267 if(specificEpithet == null) {
1268 criteria.add(Restrictions.isNull("name.specificEpithet"));
1269 } else if(!specificEpithet.equals("*")) {
1270 criteria.add(Restrictions.eq("name.specificEpithet", specificEpithet));
1271
1272 }
1273
1274 if(infraSpecificEpithet == null) {
1275 criteria.add(Restrictions.isNull("name.infraSpecificEpithet"));
1276 } else if(!infraSpecificEpithet.equals("*")) {
1277 criteria.add(Restrictions.eq("name.infraSpecificEpithet", infraSpecificEpithet));
1278 }
1279
1280 if(rank != null) {
1281 criteria.add(Restrictions.eq("name.rank", rank));
1282 }
1283
1284 criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
1285
1286 return ((Number)criteria.uniqueResult()).intValue();
1287 }
1288
1289 /*
1290 * (non-Javadoc)
1291 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#findTaxaByName(java.lang.Class, java.lang.String, java.lang.String, java.lang.String, java.lang.String, eu.etaxonomy.cdm.model.name.Rank, java.lang.Integer, java.lang.Integer)
1292 */
1293 public List<TaxonBase> findTaxaByName(Class<? extends TaxonBase> clazz, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, Rank rank, Integer pageSize, Integer pageNumber) {
1294 checkNotInPriorView("TaxonDaoHibernateImpl.findTaxaByName(Boolean accepted, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, Rank rank, Integer pageSize, Integer pageNumber)");
1295 Criteria criteria = null;
1296 if (clazz == null){
1297 criteria = getSession().createCriteria(TaxonBase.class);
1298 } else{
1299 criteria = getSession().createCriteria(clazz);
1300 }
1301 criteria.setFetchMode( "name", FetchMode.JOIN );
1302 criteria.createAlias("name", "name");
1303
1304 if(genusOrUninomial == null) {
1305 criteria.add(Restrictions.isNull("name.genusOrUninomial"));
1306 } else if(!genusOrUninomial.equals("*")) {
1307 criteria.add(Restrictions.eq("name.genusOrUninomial", genusOrUninomial));
1308 }
1309
1310 if(infraGenericEpithet == null) {
1311 criteria.add(Restrictions.isNull("name.infraGenericEpithet"));
1312 } else if(!infraGenericEpithet.equals("*")) {
1313 criteria.add(Restrictions.eq("name.infraGenericEpithet", infraGenericEpithet));
1314 }
1315
1316 if(specificEpithet == null) {
1317 criteria.add(Restrictions.isNull("name.specificEpithet"));
1318 } else if(!specificEpithet.equals("*")) {
1319 criteria.add(Restrictions.eq("name.specificEpithet", specificEpithet));
1320
1321 }
1322
1323 if(infraSpecificEpithet == null) {
1324 criteria.add(Restrictions.isNull("name.infraSpecificEpithet"));
1325 } else if(!infraSpecificEpithet.equals("*")) {
1326 criteria.add(Restrictions.eq("name.infraSpecificEpithet", infraSpecificEpithet));
1327 }
1328
1329 if(rank != null) {
1330 criteria.add(Restrictions.eq("name.rank", rank));
1331 }
1332
1333 if(pageSize != null) {
1334 criteria.setMaxResults(pageSize);
1335 if(pageNumber != null) {
1336 criteria.setFirstResult(pageNumber * pageSize);
1337 } else {
1338 criteria.setFirstResult(0);
1339 }
1340 }
1341
1342 return (List<TaxonBase>)criteria.list();
1343 }
1344
1345 /*
1346 * (non-Javadoc)
1347 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List, eu.etaxonomy.cdm.model.common.RelationshipBase.Direction)
1348 */
1349 public List<TaxonRelationship> getTaxonRelationships(Taxon taxon, TaxonRelationshipType type,
1350 Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths, Direction direction) {
1351
1352 AuditEvent auditEvent = getAuditEventFromContext();
1353 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
1354
1355 Criteria criteria = getSession().createCriteria(TaxonRelationship.class);
1356
1357 if(direction != null) {
1358 criteria.add(Restrictions.eq(direction.name(), taxon));
1359 } else {
1360 criteria.add(Restrictions.or(
1361 Restrictions.eq(Direction.relatedFrom.name(), taxon),
1362 Restrictions.eq(Direction.relatedTo.name(), taxon))
1363 );
1364 }
1365
1366 if(type != null) {
1367 criteria.add(Restrictions.eq("type", type));
1368 }
1369
1370 addOrder(criteria,orderHints);
1371
1372 if(pageSize != null) {
1373 criteria.setMaxResults(pageSize);
1374 if(pageNumber != null) {
1375 criteria.setFirstResult(pageNumber * pageSize);
1376 } else {
1377 criteria.setFirstResult(0);
1378 }
1379 }
1380
1381 List<TaxonRelationship> result = (List<TaxonRelationship>)criteria.list();
1382 defaultBeanInitializer.initializeAll(result, propertyPaths);
1383
1384 return result;
1385 } else {
1386 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonRelationship.class,auditEvent.getRevisionNumber());
1387 query.add(AuditEntity.relatedId("relatedTo").eq(taxon.getId()));
1388
1389 if(type != null) {
1390 query.add(AuditEntity.relatedId("type").eq(type.getId()));
1391 }
1392
1393 if(pageSize != null) {
1394 query.setMaxResults(pageSize);
1395 if(pageNumber != null) {
1396 query.setFirstResult(pageNumber * pageSize);
1397 } else {
1398 query.setFirstResult(0);
1399 }
1400 }
1401
1402 List<TaxonRelationship> result = (List<TaxonRelationship>)query.getResultList();
1403 defaultBeanInitializer.initializeAll(result, propertyPaths);
1404
1405 // Ugly, but for now, there is no way to sort on a related entity property in Envers,
1406 // and we can't live without this functionality in CATE as it screws up the whole
1407 // taxon tree thing
1408 if(orderHints != null && !orderHints.isEmpty()) {
1409 SortedSet<TaxonRelationship> sortedList = new TreeSet<TaxonRelationship>(new TaxonRelationshipFromTaxonComparator());
1410 sortedList.addAll(result);
1411 return new ArrayList<TaxonRelationship>(sortedList);
1412 }
1413
1414 return result;
1415 }
1416 }
1417
1418 class TaxonRelationshipFromTaxonComparator implements Comparator<TaxonRelationship> {
1419
1420 public int compare(TaxonRelationship o1, TaxonRelationship o2) {
1421 return o1.getFromTaxon().getTitleCache().compareTo(o2.getFromTaxon().getTitleCache());
1422 }
1423
1424 }
1425
1426 class SynonymRelationshipFromTaxonComparator implements Comparator<SynonymRelationship> {
1427
1428 public int compare(SynonymRelationship o1, SynonymRelationship o2) {
1429 return o1.getSynonym().getTitleCache().compareTo(o2.getSynonym().getTitleCache());
1430 }
1431
1432 }
1433
1434 /*
1435 * (non-Javadoc)
1436 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getSynonyms(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
1437 */
1438 public List<SynonymRelationship> getSynonyms(Taxon taxon, SynonymRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
1439 AuditEvent auditEvent = getAuditEventFromContext();
1440 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
1441 Criteria criteria = getSession().createCriteria(SynonymRelationship.class);
1442
1443 criteria.add(Restrictions.eq("relatedTo", taxon));
1444 if(type != null) {
1445 criteria.add(Restrictions.eq("type", type));
1446 }
1447
1448 addOrder(criteria,orderHints);
1449
1450 if(pageSize != null) {
1451 criteria.setMaxResults(pageSize);
1452 if(pageNumber != null) {
1453 criteria.setFirstResult(pageNumber * pageSize);
1454 } else {
1455 criteria.setFirstResult(0);
1456 }
1457 }
1458
1459 List<SynonymRelationship> result = (List<SynonymRelationship>)criteria.list();
1460 defaultBeanInitializer.initializeAll(result, propertyPaths);
1461
1462 return result;
1463 } else {
1464 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(SynonymRelationship.class,auditEvent.getRevisionNumber());
1465 query.add(AuditEntity.relatedId("relatedTo").eq(taxon.getId()));
1466
1467 if(type != null) {
1468 query.add(AuditEntity.relatedId("type").eq(type.getId()));
1469 }
1470
1471 if(pageSize != null) {
1472 query.setMaxResults(pageSize);
1473 if(pageNumber != null) {
1474 query.setFirstResult(pageNumber * pageSize);
1475 } else {
1476 query.setFirstResult(0);
1477 }
1478 }
1479
1480 List<SynonymRelationship> result = (List<SynonymRelationship>)query.getResultList();
1481 defaultBeanInitializer.initializeAll(result, propertyPaths);
1482
1483 return result;
1484 }
1485 }
1486
1487 /*
1488 * (non-Javadoc)
1489 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getSynonyms(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
1490 */
1491 public List<SynonymRelationship> getSynonyms(Synonym synonym, SynonymRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
1492 AuditEvent auditEvent = getAuditEventFromContext();
1493 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
1494 Criteria criteria = getSession().createCriteria(SynonymRelationship.class);
1495
1496 criteria.add(Restrictions.eq("relatedFrom", synonym));
1497 if(type != null) {
1498 criteria.add(Restrictions.eq("type", type));
1499 }
1500
1501 addOrder(criteria,orderHints);
1502
1503 if(pageSize != null) {
1504 criteria.setMaxResults(pageSize);
1505 if(pageNumber != null) {
1506 criteria.setFirstResult(pageNumber * pageSize);
1507 } else {
1508 criteria.setFirstResult(0);
1509 }
1510 }
1511
1512 List<SynonymRelationship> result = (List<SynonymRelationship>)criteria.list();
1513 defaultBeanInitializer.initializeAll(result, propertyPaths);
1514
1515 return result;
1516 } else {
1517 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(SynonymRelationship.class,auditEvent.getRevisionNumber());
1518 query.add(AuditEntity.relatedId("relatedFrom").eq(synonym.getId()));
1519
1520 if(type != null) {
1521 query.add(AuditEntity.relatedId("type").eq(type.getId()));
1522 }
1523
1524 if(pageSize != null) {
1525 query.setMaxResults(pageSize);
1526 if(pageNumber != null) {
1527 query.setFirstResult(pageNumber * pageSize);
1528 } else {
1529 query.setFirstResult(0);
1530 }
1531 }
1532
1533 List<SynonymRelationship> result = (List<SynonymRelationship>)query.getResultList();
1534 defaultBeanInitializer.initializeAll(result, propertyPaths);
1535
1536 return result;
1537 }
1538 }
1539
1540 @Override
1541 public void rebuildIndex() {
1542 FullTextSession fullTextSession = Search.getFullTextSession(getSession());
1543
1544 for(TaxonBase taxonBase : list(null,null)) { // re-index all taxon base
1545 Hibernate.initialize(taxonBase.getName());
1546 fullTextSession.index(taxonBase);
1547 }
1548 fullTextSession.flushToIndexes();
1549 }
1550
1551 @Override
1552 public String suggestQuery(String queryString) {
1553 checkNotInPriorView("TaxonDaoHibernateImpl.suggestQuery(String queryString)");
1554 String alternativeQueryString = null;
1555 if (alternativeSpellingSuggestionParser != null) {
1556 try {
1557
1558 alternativeSpellingSuggestionParser.parse(queryString);
1559 org.apache.lucene.search.Query alternativeQuery = alternativeSpellingSuggestionParser.suggest(queryString);
1560 if (alternativeQuery != null) {
1561 alternativeQueryString = alternativeQuery
1562 .toString("name.titleCache");
1563 }
1564
1565 } catch (ParseException e) {
1566 throw new QueryParseException(e, queryString);
1567 }
1568 }
1569 return alternativeQueryString;
1570 }
1571
1572 /*
1573 * (non-Javadoc)
1574 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheOfAcceptedTaxa(eu.etaxonomy.cdm.model.taxon.Classification)
1575 */
1576 public List<UuidAndTitleCache<TaxonNode>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(Classification classification) {
1577
1578 int classificationId = classification.getId();
1579
1580 String queryString = "SELECT nodes.uuid, taxa.titleCache FROM TaxonNode AS nodes LEFT JOIN TaxonBase AS taxa ON nodes.taxon_id = taxa.id WHERE taxa.DTYPE = 'Taxon' AND nodes.classification_id = " + classificationId;
1581
1582 List<Object[]> result = getSession().createSQLQuery(queryString).list();
1583
1584 if(result.size() == 0){
1585 return null;
1586 }else{
1587 List<UuidAndTitleCache<TaxonNode>> list = new ArrayList<UuidAndTitleCache<TaxonNode>>(result.size());
1588
1589 for (Object object : result){
1590
1591 Object[] objectArray = (Object[]) object;
1592
1593 UUID uuid = UUID.fromString((String) objectArray[0]);
1594 String titleCache = (String) objectArray[1];
1595
1596 list.add(new UuidAndTitleCache(TaxonNode.class, uuid, titleCache));
1597 }
1598
1599 return list;
1600 }
1601 }
1602
1603
1604 public class UuidAndTitleCacheOfAcceptedTaxon{
1605 UUID uuid;
1606
1607 String titleCache;
1608
1609 public UuidAndTitleCacheOfAcceptedTaxon(UUID uuid, String titleCache){
1610 this.uuid = uuid;
1611 this.titleCache = titleCache;
1612 }
1613
1614 public UUID getUuid() {
1615 return uuid;
1616 }
1617
1618 public void setUuid(UUID uuid) {
1619 this.uuid = uuid;
1620 }
1621
1622 public String getTitleCache() {
1623 return titleCache;
1624 }
1625
1626 public void setTitleCache(String titleCache) {
1627 this.titleCache = titleCache;
1628 }
1629 }
1630
1631 @Override
1632 public TaxonBase find(LSID lsid) {
1633 TaxonBase<?> taxonBase = super.find(lsid);
1634 if(taxonBase != null) {
1635 List<String> propertyPaths = new ArrayList<String>();
1636 propertyPaths.add("createdBy");
1637 propertyPaths.add("updatedBy");
1638 propertyPaths.add("name");
1639 propertyPaths.add("sec");
1640 propertyPaths.add("relationsToThisTaxon");
1641 propertyPaths.add("relationsToThisTaxon.fromTaxon");
1642 propertyPaths.add("relationsToThisTaxon.toTaxon");
1643 propertyPaths.add("relationsFromThisTaxon");
1644 propertyPaths.add("relationsFromThisTaxon.toTaxon");
1645 propertyPaths.add("relationsToThisTaxon.type");
1646 propertyPaths.add("synonymRelations");
1647 propertyPaths.add("synonymRelations.synonym");
1648 propertyPaths.add("synonymRelations.type");
1649 propertyPaths.add("descriptions");
1650
1651 defaultBeanInitializer.initialize(taxonBase, propertyPaths);
1652 }
1653 return taxonBase;
1654 }
1655
1656 public List<TaxonBase> getTaxaByCommonName(String queryString,
1657 Classification classification, MatchMode matchMode,
1658 Set<NamedArea> namedAreas, Integer pageSize, Integer pageNumber) {
1659 logger.warn("getTaxaByCommonName not yet implemented.");
1660 return null;
1661 }
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671 /* private void xxx(List<SynonymRelationship> synonymRelationships, HashMap <UUID, ZoologicalName> zooHashMap, SynonymRelationshipType type, String addString){
1672
1673 for (SynonymRelationship synonymRelation:synonymRelationships){
1674 TaxonNameBase synName;
1675 NonViralName inferredSynName;
1676 Synonym syn = synonymRelation.getSynonym();
1677 HibernateProxyHelper.deproxy(syn);
1678
1679 synName = syn.getName();
1680 ZoologicalName zooName = zooHashMap.get(synName.getUuid());
1681 String synGenusName = zooName.getGenusOrUninomial();
1682
1683 switch(type.getId()){
1684 case SynonymRelationshipType.INFERRED_EPITHET_OF().getId():
1685 inferredSynName.setSpecificEpithet(addString);
1686 break;
1687 case SynonymRelationshipType.INFERRED_GENUS_OF().getId():
1688 break;
1689 case SynonymRelationshipType.POTENTIAL_COMBINATION_OF().getId():
1690 break;
1691 default:
1692 }
1693 if (!synonymsGenus.contains(synGenusName)){
1694 synonymsGenus.add(synGenusName);
1695 }
1696 inferredSynName = NonViralName.NewInstance(Rank.SPECIES());
1697 inferredSynName.setSpecificEpithet(epithetOfTaxon);
1698 inferredSynName.setGenusOrUninomial(synGenusName);
1699 inferredEpithet = Synonym.NewInstance(inferredSynName, null);
1700 taxon.addSynonym(inferredEpithet, SynonymRelationshipType.INFERRED_GENUS_OF());
1701 inferredSynonyms.add(inferredEpithet);
1702 inferredSynName.generateTitle();
1703 taxonNames.add(inferredSynName.getNameCache());
1704 }
1705
1706
1707 if (!taxonNames.isEmpty()){
1708 List<String> synNotInCDM = this.taxaByNameNotInDB(taxonNames);
1709 ZoologicalName name;
1710 if (!synNotInCDM.isEmpty()){
1711 for (Synonym syn :inferredSynonyms){
1712 name =zooHashMap.get(syn.getName().getUuid());
1713 if (!synNotInCDM.contains(name.getNameCache())){
1714 inferredSynonyms.remove(syn);
1715 }
1716 }
1717 }
1718 }
1719 }*/
1720
1721 /*
1722 * (non-Javadoc)
1723 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countAllRelationships()
1724 */
1725 public int countAllRelationships() {
1726 return countAllRelationships(null);
1727 }
1728
1729 /*
1730 * (non-Javadoc)
1731 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countAllRelationships()
1732 */
1733 public int countAllRelationships(Class<? extends RelationshipBase> clazz) {
1734 if (clazz != null && ! TaxonRelationship.class.isAssignableFrom(clazz) && ! SynonymRelationship.class.isAssignableFrom(clazz) ){
1735 throw new RuntimeException("Class must be assignable by a taxon or snonym relation");
1736 }
1737 int size = 0;
1738
1739 if (clazz == null || TaxonRelationship.class.isAssignableFrom(clazz)){
1740 String hql = " SELECT count(rel) FROM TaxonRelationship rel";
1741 size += (Long)getSession().createQuery(hql).list().get(0);
1742 }
1743 if (clazz == null || SynonymRelationship.class.isAssignableFrom(clazz)){
1744 String hql = " SELECT count(rel) FROM SynonymRelationship rel";
1745 size += (Long)getSession().createQuery(hql).list().get(0);
1746 }
1747 return size;
1748 }
1749
1750
1751 public List<String> taxaByNameNotInDB(List<String> taxonNames){
1752 List<TaxonBase> notInDB = new ArrayList<TaxonBase>();
1753 //get all taxa, already in db
1754 Query query = getSession().createQuery("from TaxonNameBase t where t.nameCache IN (:taxonList)");
1755 query.setParameterList("taxonList", taxonNames);
1756 List<TaxonNameBase> taxaInDB = query.list();
1757 //compare the original list with the result of the query
1758 for (TaxonNameBase taxonName: taxaInDB){
1759 if (taxonName.isInstanceOf(NonViralName.class)) {
1760 NonViralName nonViralName = CdmBase.deproxy(taxonName, NonViralName.class);
1761 String nameCache = nonViralName.getNameCache();
1762 if (taxonNames.contains(nameCache)){
1763 taxonNames.remove(nameCache);
1764 }
1765 }
1766 }
1767
1768 return taxonNames;
1769 }
1770
1771 //TODO: mal nur mit UUID probieren (ohne fetch all properties), vielleicht geht das schneller?
1772 public List<UUID> findIdenticalTaxonNameIds(List<String> propertyPaths){
1773 Query query=getSession().createQuery("select tmb2 from ZoologicalName tmb, ZoologicalName tmb2 fetch all properties where tmb.id != tmb2.id and tmb.nameCache = tmb2.nameCache");
1774 List<UUID> zooNames = query.list();
1775
1776 return zooNames;
1777
1778 }
1779
1780 public List<TaxonNameBase> findIdenticalTaxonNames(List<String> propertyPaths) {
1781
1782 Query query=getSession().createQuery("select tmb2 from ZoologicalName tmb, ZoologicalName tmb2 fetch all properties where tmb.id != tmb2.id and tmb.nameCache = tmb2.nameCache");
1783
1784 List<TaxonNameBase> zooNames = query.list();
1785
1786 TaxonNameComparator taxComp = new TaxonNameComparator();
1787 Collections.sort(zooNames, taxComp);
1788
1789 for (TaxonNameBase taxonNameBase: zooNames){
1790 defaultBeanInitializer.initialize(taxonNameBase, propertyPaths);
1791 }
1792
1793 return zooNames;
1794 }
1795
1796 public List<TaxonNameBase> findIdenticalNamesNew(List<String> propertyPaths){
1797
1798 //Hole die beiden Source_ids von "Fauna Europaea" und "Erms" und in sources der names darf jeweils nur das entgegengesetzte auftreten (i member of tmb.taxonBases)
1799 Query query = getSession().createQuery("Select id from Reference where titleCache like 'Fauna Europaea database'");
1800 List<String> secRefFauna = query.list();
1801 query = getSession().createQuery("Select id from Reference where titleCache like 'ERMS'");
1802 List<String> secRefErms = query.list();
1803 //Query query = getSession().createQuery("select tmb2.nameCache from ZoologicalName tmb, TaxonBase tb1, ZoologicalName tmb2, TaxonBase tb2 where tmb.id != tmb2.id and tb1.name = tmb and tb2.name = tmb2 and tmb.nameCache = tmb2.nameCache and tb1.sec != tb2.sec");
1804 //Get all names of fauna europaea
1805 query = getSession().createQuery("select zn.nameCache from ZoologicalName zn, TaxonBase tb where tb.name = zn and tb.sec.id = :secRefFauna");
1806 query.setParameter("secRefFauna", secRefFauna.get(0));
1807 List<String> namesFauna= query.list();
1808
1809 //Get all names of erms
1810
1811 query = getSession().createQuery("select zn.nameCache from ZoologicalName zn, TaxonBase tb where tb.name = zn and tb.sec.id = :secRefErms");
1812 query.setParameter("secRefErms", secRefErms.get(0));
1813
1814 List<String> namesErms = query.list();
1815 /*TaxonNameComparator comp = new TaxonNameComparator();
1816 Collections.sort(namesFauna);
1817 Collections.sort(namesErms);
1818 */
1819 List <String> identicalNames = new ArrayList<String>();
1820 String predecessor = "";
1821
1822 for (String nameFauna: namesFauna){
1823 if (namesErms.contains(nameFauna)){
1824 identicalNames.add(nameFauna);
1825 }
1826 }
1827
1828
1829 query = getSession().createQuery("from ZoologicalName zn where zn.nameCache IN (:identicalNames)");
1830 query.setParameterList("identicalNames", identicalNames);
1831 List<TaxonNameBase> result = query.list();
1832 TaxonNameBase temp = result.get(0);
1833
1834 Iterator<OriginalSourceBase> sources = temp.getSources().iterator();
1835
1836 TaxonNameComparator taxComp = new TaxonNameComparator();
1837 Collections.sort(result, taxComp);
1838 defaultBeanInitializer.initializeAll(result, propertyPaths);
1839 return result;
1840
1841 }
1842
1843
1844
1845 public String getPhylumName(TaxonNameBase name){
1846 List results = new ArrayList();
1847 try{
1848 Query query = getSession().createSQLQuery("select getPhylum("+ name.getId()+");");
1849 results = query.list();
1850 }catch(Exception e){
1851 System.err.println(name.getUuid());
1852 return null;
1853 }
1854 System.err.println("phylum of "+ name.getTitleCache() );
1855 return (String)results.get(0);
1856 }
1857
1858
1859 public long countTaxaByCommonName(String searchString,
1860 Classification classification, MatchMode matchMode,
1861 Set<NamedArea> namedAreas) {
1862 boolean doCount = true;
1863 Query query = prepareTaxaByCommonName(searchString, classification, matchMode, namedAreas, null, null, doCount);
1864 if (query != null && !query.list().isEmpty()) {
1865 Object o = query.uniqueResult();
1866 if(o != null) {
1867 return (Long)o;
1868 }
1869 }
1870 return 0;
1871 }
1872
1873
1874 /* (non-Javadoc)
1875 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
1876 */
1877 public long deleteSynonymRelationships(Synonym synonym, Taxon taxon) {
1878
1879 String hql = "delete SynonymRelationship sr where sr.relatedFrom = :syn ";
1880 if (taxon != null){
1881 hql += " and sr.relatedTo = :taxon";
1882 }
1883 Session session = this.getSession();
1884 Query q = session.createQuery(hql);
1885
1886 q.setParameter("syn", synonym);
1887 if (taxon != null){
1888 q.setParameter("taxon", taxon);
1889 }
1890 long result = q.executeUpdate();
1891
1892 return result;
1893 }
1894
1895
1896 @Override
1897 public Integer countSynonymRelationships(TaxonBase taxonBase,
1898 SynonymRelationshipType type, Direction relatedfrom) {
1899 AuditEvent auditEvent = getAuditEventFromContext();
1900 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
1901 Query query = null;
1902
1903 if(type == null) {
1904 query = getSession().createQuery("select count(synonymRelationship) from SynonymRelationship synonymRelationship where synonymRelationship."+relatedfrom+" = :relatedSynonym");
1905 } else {
1906 query = getSession().createQuery("select count(synonymRelationship) from SynonymRelationship synonymRelationship where synonymRelationship."+relatedfrom+" = :relatedSynonym and synonymRelationship.type = :type");
1907 query.setParameter("type",type);
1908 }
1909 query.setParameter("relatedTaxon", taxonBase);
1910
1911 return ((Long)query.uniqueResult()).intValue();
1912 } else {
1913 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonRelationship.class,auditEvent.getRevisionNumber());
1914 query.add(AuditEntity.relatedId(relatedfrom.toString()).eq(taxonBase.getId()));
1915 query.addProjection(AuditEntity.id().count("id"));
1916
1917 if(type != null) {
1918 query.add(AuditEntity.relatedId("type").eq(type.getId()));
1919 }
1920
1921 return ((Long)query.getSingleResult()).intValue();
1922 }
1923 }
1924
1925
1926 @Override
1927 public List<SynonymRelationship> getSynonymRelationships(TaxonBase taxonBase,
1928 SynonymRelationshipType type, Integer pageSize, Integer pageNumber,
1929 List<OrderHint> orderHints, List<String> propertyPaths,
1930 Direction direction) {
1931
1932 AuditEvent auditEvent = getAuditEventFromContext();
1933 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
1934 Criteria criteria = getSession().createCriteria(SynonymRelationship.class);
1935
1936 if (direction.equals(Direction.relatedTo)){
1937 criteria.add(Restrictions.eq("relatedTo", taxonBase));
1938 }else{
1939 criteria.add(Restrictions.eq("relatedFrom", taxonBase));
1940 }
1941 if(type != null) {
1942 criteria.add(Restrictions.eq("type", type));
1943 }
1944
1945 addOrder(criteria,orderHints);
1946
1947 if(pageSize != null) {
1948 criteria.setMaxResults(pageSize);
1949 if(pageNumber != null) {
1950 criteria.setFirstResult(pageNumber * pageSize);
1951 } else {
1952 criteria.setFirstResult(0);
1953 }
1954 }
1955
1956 List<SynonymRelationship> result = (List<SynonymRelationship>)criteria.list();
1957 defaultBeanInitializer.initializeAll(result, propertyPaths);
1958
1959 return result;
1960 } else {
1961 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonRelationship.class,auditEvent.getRevisionNumber());
1962
1963 if (direction.equals(Direction.relatedTo)){
1964 query.add(AuditEntity.relatedId("relatedTo").eq(taxonBase.getId()));
1965 }else{
1966 query.add(AuditEntity.relatedId("relatedFrom").eq(taxonBase.getId()));
1967 }
1968
1969 if(type != null) {
1970 query.add(AuditEntity.relatedId("type").eq(type.getId()));
1971 }
1972
1973 if(pageSize != null) {
1974 query.setMaxResults(pageSize);
1975 if(pageNumber != null) {
1976 query.setFirstResult(pageNumber * pageSize);
1977 } else {
1978 query.setFirstResult(0);
1979 }
1980 }
1981
1982 List<SynonymRelationship> result = (List<SynonymRelationship>)query.getResultList();
1983 defaultBeanInitializer.initializeAll(result, propertyPaths);
1984
1985 // Ugly, but for now, there is no way to sort on a related entity property in Envers,
1986 // and we can't live without this functionality in CATE as it screws up the whole
1987 // taxon tree thing
1988 if(orderHints != null && !orderHints.isEmpty()) {
1989 SortedSet<SynonymRelationship> sortedList = new TreeSet<SynonymRelationship>(new SynonymRelationshipFromTaxonComparator());
1990 sortedList.addAll(result);
1991 return new ArrayList<SynonymRelationship>(sortedList);
1992 }
1993
1994 return result;
1995 }
1996 }
1997
1998
1999 /* (non-Javadoc)
2000 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getUuidAndTitleCacheTaxon()
2001 */
2002 @Override
2003 public List<UuidAndTitleCache<TaxonBase>> getUuidAndTitleCacheTaxon() {
2004 String queryString = String.format("select uuid, titleCache from %s where DTYPE = '%s'", type.getSimpleName(), Taxon.class.getSimpleName());
2005 Query query = getSession().createQuery(queryString);
2006
2007 List<UuidAndTitleCache<TaxonBase>> result = getUuidAndTitleCache(query);
2008
2009 return result;
2010 }
2011
2012
2013 /* (non-Javadoc)
2014 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getUuidAndTitleCacheSynonym()
2015 */
2016 @Override
2017 public List<UuidAndTitleCache<TaxonBase>> getUuidAndTitleCacheSynonym() {
2018 String queryString = String.format("select uuid, titleCache from %s where DTYPE = '%s'", type.getSimpleName(), Synonym.class.getSimpleName());
2019 Query query = getSession().createQuery(queryString);
2020
2021 List<UuidAndTitleCache<TaxonBase>> result = getUuidAndTitleCache(query);
2022
2023 return result;
2024 }
2025
2026
2027 private String[] createHQLString(boolean doTaxa, boolean doSynonyms, boolean doIncludeMisappliedNames, Classification classification, Set<NamedArea> areasExpanded, MatchMode matchMode, String searchField){
2028
2029 boolean doAreaRestriction = areasExpanded.size() > 0;
2030 String doAreaRestrictionSubSelect = "select %s.id from" +
2031 " Distribution e" +
2032 " join e.inDescription d" +
2033 " join d.taxon t" +
2034 (classification != null ? " join t.taxonNodes as tn " : " ");
2035
2036 String doAreaRestrictionMisappliedNameSubSelect = "select %s.id from" +
2037 " Distribution e" +
2038 " join e.inDescription d" +
2039 " join d.taxon t";
2040
2041 String doTaxonSubSelect = "select %s.id from Taxon t " + (classification != null ? " join t.taxonNodes as tn " : " ");
2042 String doTaxonMisappliedNameSubSelect = "select %s.id from Taxon t ";
2043
2044 String doTaxonNameJoin = " join t.name n ";
2045
2046 String doSynonymNameJoin = " join t.synonymRelations sr join sr.relatedFrom s join s.name sn";
2047
2048 String doMisappliedNamesJoin = " left join t.relationsFromThisTaxon as rft" +
2049 " left join rft.relatedTo as rt" +
2050 (classification != null ? " left join rt.taxonNodes as tn2" : " ") +
2051 " left join rt.name as n2" +
2052 " left join rft.type as rtype";
2053
2054 String doClassificationWhere = " tn.classification = :classification";
2055 String doClassificationForMisappliedNamesWhere = " tn2 .classification = :classification";
2056
2057 String doAreaRestrictionWhere = " e.area.uuid in (:namedAreasUuids)";
2058
2059 String doSearchFieldWhere = "%s." + searchField + " " + matchMode.getMatchOperator() + " :queryString";
2060
2061 String doRelationshipTypeComparison = " rtype = :rType ";
2062
2063 String taxonSubselect = null;
2064 String synonymSubselect = null;
2065 String misappliedSelect = null;
2066
2067 if(classification != null ){
2068 if (!doIncludeMisappliedNames){
2069 if(doAreaRestriction){
2070 taxonSubselect = String.format(doAreaRestrictionSubSelect, "t") + doTaxonNameJoin +
2071 " WHERE " + doAreaRestrictionWhere +
2072 " AND " + doClassificationWhere +
2073 " AND " + String.format(doSearchFieldWhere, "n");
2074 synonymSubselect = String.format(doAreaRestrictionSubSelect, "s") + doSynonymNameJoin +
2075 " WHERE " + doAreaRestrictionWhere +
2076 " AND " + doClassificationWhere +
2077 " AND " + String.format(doSearchFieldWhere, "sn");
2078 } else {
2079 taxonSubselect = String.format(doTaxonSubSelect, "t" )+ doTaxonNameJoin +
2080 " WHERE " + doClassificationWhere +
2081 " AND " + String.format(doSearchFieldWhere, "n");
2082 synonymSubselect = String.format(doTaxonSubSelect, "s" ) + doSynonymNameJoin +
2083 " WHERE " + doClassificationWhere +
2084 " AND " + String.format(doSearchFieldWhere, "sn");
2085 }
2086 }else{ //misappliedNames included
2087 if(doAreaRestriction){
2088 misappliedSelect = String.format(doAreaRestrictionMisappliedNameSubSelect, "t") + doTaxonNameJoin + doMisappliedNamesJoin +
2089 " WHERE " + doAreaRestrictionWhere +
2090 " AND " + String.format(doSearchFieldWhere, "n") +
2091 " AND " + doClassificationForMisappliedNamesWhere +
2092 " AND " + doRelationshipTypeComparison;
2093
2094 taxonSubselect = String.format(doAreaRestrictionSubSelect, "t") + doTaxonNameJoin +
2095 " WHERE " + doAreaRestrictionWhere +
2096 " AND "+ String.format(doSearchFieldWhere, "n") + " AND "+ doClassificationWhere;
2097
2098 synonymSubselect = String.format(doAreaRestrictionSubSelect, "s") + doSynonymNameJoin +
2099 " WHERE " + doAreaRestrictionWhere +
2100 " AND " + doClassificationWhere + " AND " + String.format(doSearchFieldWhere, "sn");;
2101
2102 } else {
2103 misappliedSelect = String.format(doTaxonMisappliedNameSubSelect, "t" ) + doTaxonNameJoin + doMisappliedNamesJoin +
2104 " WHERE " + String.format(doSearchFieldWhere, "n") +
2105 " AND " + doClassificationForMisappliedNamesWhere +
2106 " AND " + doRelationshipTypeComparison;
2107
2108 taxonSubselect = String.format(doTaxonSubSelect, "t" ) + doTaxonNameJoin +
2109 " WHERE " + String.format(doSearchFieldWhere, "n") +
2110 " AND "+ doClassificationWhere;
2111
2112 synonymSubselect = String.format(doTaxonSubSelect, "s" ) + doSynonymNameJoin +
2113 " WHERE " + doClassificationWhere +
2114 " AND " + String.format(doSearchFieldWhere, "sn");
2115
2116 }
2117 }
2118 } else {
2119 if(doAreaRestriction){
2120 misappliedSelect = String.format(doAreaRestrictionMisappliedNameSubSelect, "t") + doTaxonNameJoin + doMisappliedNamesJoin +
2121 " WHERE " + doAreaRestrictionWhere +
2122 " AND " + String.format(doSearchFieldWhere, "n")+
2123 " AND " + doRelationshipTypeComparison;
2124
2125 taxonSubselect = String.format(doAreaRestrictionSubSelect, "t") + doTaxonNameJoin +
2126 " WHERE " + doAreaRestrictionWhere +
2127 " AND " + String.format(doSearchFieldWhere, "n");
2128
2129 synonymSubselect = String.format(doAreaRestrictionSubSelect, "s") + doSynonymNameJoin +
2130 " WHERE " + doAreaRestrictionWhere +
2131 " AND " + String.format(doSearchFieldWhere, "sn");
2132
2133
2134 } else {
2135 misappliedSelect = String.format(doTaxonMisappliedNameSubSelect, "t" ) + doTaxonNameJoin + doMisappliedNamesJoin + " WHERE " + String.format(doSearchFieldWhere, "n") + " AND " + doRelationshipTypeComparison;
2136 taxonSubselect = String.format(doTaxonSubSelect, "t" ) + doTaxonNameJoin + " WHERE " + String.format(doSearchFieldWhere, "n");
2137 synonymSubselect = String.format(doTaxonSubSelect, "s" ) + doSynonymNameJoin + " WHERE " + String.format(doSearchFieldWhere, "sn");
2138
2139 }
2140 }
2141 String[] result = {misappliedSelect, taxonSubselect, synonymSubselect};
2142
2143 return result;
2144 }
2145
2146
2147 }