Fix specimen retrieval by assignment status
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / DescriptionServiceImpl.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.cdm.api.service;
12
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.UUID;
20
21 import org.apache.commons.lang.StringUtils;
22 import org.apache.log4j.Logger;
23 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.stereotype.Service;
25 import org.springframework.transaction.annotation.Transactional;
26
27 import eu.etaxonomy.cdm.api.service.pager.Pager;
28 import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
29 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
30 import eu.etaxonomy.cdm.api.utility.DescriptionUtility;
31 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
32 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
33 import eu.etaxonomy.cdm.model.common.Annotation;
34 import eu.etaxonomy.cdm.model.common.AnnotationType;
35 import eu.etaxonomy.cdm.model.common.CdmBase;
36 import eu.etaxonomy.cdm.model.common.DefinedTerm;
37 import eu.etaxonomy.cdm.model.common.Language;
38 import eu.etaxonomy.cdm.model.common.Marker;
39 import eu.etaxonomy.cdm.model.common.MarkerType;
40 import eu.etaxonomy.cdm.model.common.TermVocabulary;
41 import eu.etaxonomy.cdm.model.description.DescriptionBase;
42 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
43 import eu.etaxonomy.cdm.model.description.Distribution;
44 import eu.etaxonomy.cdm.model.description.Feature;
45 import eu.etaxonomy.cdm.model.description.FeatureTree;
46 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
47 import eu.etaxonomy.cdm.model.description.TaxonDescription;
48 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
49 import eu.etaxonomy.cdm.model.description.TextData;
50 import eu.etaxonomy.cdm.model.location.NamedArea;
51 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
52 import eu.etaxonomy.cdm.model.media.Media;
53 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
54 import eu.etaxonomy.cdm.model.taxon.Taxon;
55 import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
56 import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
57 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
58 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionElementDao;
59 import eu.etaxonomy.cdm.persistence.dao.description.IFeatureDao;
60 import eu.etaxonomy.cdm.persistence.dao.description.IFeatureNodeDao;
61 import eu.etaxonomy.cdm.persistence.dao.description.IFeatureTreeDao;
62 import eu.etaxonomy.cdm.persistence.dao.description.IStatisticalMeasurementValueDao;
63 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
64 import eu.etaxonomy.cdm.persistence.dto.TermDto;
65 import eu.etaxonomy.cdm.persistence.query.OrderHint;
66 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
67
68 /**
69 * @author a.mueller
70 * @created 24.06.2008
71 * @version 1.0
72 */
73 /**
74 * @author a.kohlbecker
75 * @date Dec 5, 2013
76 *
77 */
78 @Service
79 @Transactional(readOnly = true)
80 public class DescriptionServiceImpl extends IdentifiableServiceBase<DescriptionBase,IDescriptionDao> implements IDescriptionService {
81
82 private static final Logger logger = Logger.getLogger(DescriptionServiceImpl.class);
83
84 protected IDescriptionElementDao descriptionElementDao;
85 protected IFeatureTreeDao featureTreeDao;
86 protected IFeatureNodeDao featureNodeDao;
87 protected IFeatureDao featureDao;
88 protected ITermVocabularyDao vocabularyDao;
89 protected IDefinedTermDao definedTermDao;
90 protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao;
91 protected ITaxonDao taxonDao;
92
93 //TODO change to Interface
94 private NaturalLanguageGenerator naturalLanguageGenerator;
95
96 @Autowired
97 protected void setFeatureTreeDao(IFeatureTreeDao featureTreeDao) {
98 this.featureTreeDao = featureTreeDao;
99 }
100
101 @Autowired
102 protected void setFeatureNodeDao(IFeatureNodeDao featureNodeDao) {
103 this.featureNodeDao = featureNodeDao;
104 }
105
106 @Autowired
107 protected void setFeatureDao(IFeatureDao featureDao) {
108 this.featureDao = featureDao;
109 }
110
111 @Autowired
112 protected void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
113 this.vocabularyDao = vocabularyDao;
114 }
115
116 @Autowired
117 protected void setDefinedTermDao(IDefinedTermDao definedTermDao) {
118 this.definedTermDao = definedTermDao;
119 }
120
121 @Autowired
122 protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao) {
123 this.statisticalMeasurementValueDao = statisticalMeasurementValueDao;
124 }
125
126 @Autowired
127 protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao) {
128 this.descriptionElementDao = descriptionElementDao;
129 }
130
131 @Autowired
132 protected void setNaturalLanguageGenerator(NaturalLanguageGenerator naturalLanguageGenerator) {
133 this.naturalLanguageGenerator = naturalLanguageGenerator;
134 }
135
136 @Autowired
137 protected void setTaxonDao(ITaxonDao taxonDao) {
138 this.taxonDao = taxonDao;
139 }
140
141 /**
142 *
143 */
144 public DescriptionServiceImpl() {
145 logger.debug("Load DescriptionService Bean");
146 }
147
148
149 @Override
150 @Transactional(readOnly = false)
151 public void updateTitleCache(Class<? extends DescriptionBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<DescriptionBase> cacheStrategy, IProgressMonitor monitor) {
152 if (clazz == null){
153 clazz = DescriptionBase.class;
154 }
155 super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
156 }
157
158
159 @Override
160 public TermVocabulary<Feature> getDefaultFeatureVocabulary(){
161 String uuidFeature = "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
162 UUID featureUuid = UUID.fromString(uuidFeature);
163 return vocabularyDao.findByUuid(featureUuid);
164 }
165
166 @Override
167 @Autowired
168 protected void setDao(IDescriptionDao dao) {
169 this.dao = dao;
170 }
171
172 @Override
173 public int count(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText,Set<Feature> feature) {
174 return dao.countDescriptions(type, hasImages, hasText, feature);
175 }
176
177 @Override
178 public <T extends DescriptionElementBase> Pager<T> pageDescriptionElements(DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
179 Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
180
181 List<T> results = listDescriptionElements(description, descriptionType, features, type, pageSize, pageNumber, propertyPaths);
182 return new DefaultPagerImpl<T>(pageNumber, results.size(), pageSize, results);
183 }
184
185 @Override
186 @Deprecated
187 public <T extends DescriptionElementBase> Pager<T> getDescriptionElements(DescriptionBase description,
188 Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
189 return pageDescriptionElements(description, null, features, type, pageSize, pageNumber, propertyPaths);
190 }
191
192
193
194 @Override
195 public <T extends DescriptionElementBase> List<T> listDescriptionElements(DescriptionBase description,
196 Class<? extends DescriptionBase> descriptionType, Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber,
197 List<String> propertyPaths) {
198
199 Integer numberOfResults = dao.countDescriptionElements(description, descriptionType, features, type);
200 List<T> results = new ArrayList<T>();
201 if(AbstractPagerImpl.hasResultsInRange(numberOfResults.longValue(), pageNumber, pageSize)) {
202 results = dao.getDescriptionElements(description, descriptionType, features, type, pageSize, pageNumber, propertyPaths);
203 }
204 return results;
205
206 }
207
208
209 @Override
210 @Deprecated
211 public <T extends DescriptionElementBase> List<T> listDescriptionElements(DescriptionBase description,
212 Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
213
214 return listDescriptionElements(description, null, features, type, pageSize, pageNumber, propertyPaths);
215 }
216
217 @Override
218 public Pager<Annotation> getDescriptionElementAnnotations(DescriptionElementBase annotatedObj, MarkerType status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
219 Integer numberOfResults = descriptionElementDao.countAnnotations(annotatedObj, status);
220
221 List<Annotation> results = new ArrayList<Annotation>();
222 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
223 results = descriptionElementDao.getAnnotations(annotatedObj, status, pageSize, pageNumber, orderHints, propertyPaths);
224 }
225
226 return new DefaultPagerImpl<Annotation>(pageNumber, numberOfResults, pageSize, results);
227 }
228
229
230
231 @Override
232 public Pager<Media> getMedia(DescriptionElementBase descriptionElement, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
233 Integer numberOfResults = descriptionElementDao.countMedia(descriptionElement);
234
235 List<Media> results = new ArrayList<Media>();
236 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
237 results = descriptionElementDao.getMedia(descriptionElement, pageSize, pageNumber, propertyPaths);
238 }
239
240 return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
241 }
242
243 @Override
244 public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
245 Set<MarkerType> markerTypes = null;
246 return pageTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
247 }
248
249 @Override
250 public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
251 Set<MarkerType> markerTypes = null;
252 return listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
253 }
254
255
256 /* (non-Javadoc)
257 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#pageMarkedTaxonDescriptions(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.Set, java.util.Set, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)
258 */
259 @Override
260 public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
261 Integer numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes);
262
263 List<TaxonDescription> results = new ArrayList<TaxonDescription>();
264 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
265 results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
266 }
267
268 return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
269 }
270
271 @Override
272 public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
273 List<TaxonDescription> results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
274 return results;
275 }
276
277
278 /* (non-Javadoc)
279 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#listTaxonDescriptionMedia(UUID, boolean, Set, Integer, Integer, List)
280 */
281 @Override
282 public List<Media> listTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths){
283 return this.dao.listTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes, pageSize, pageNumber, propertyPaths);
284 }
285
286 /*
287 * @see IDescriptionService#countTaxonDescriptionMedia(UUID, boolean, Set)
288 */
289 @Override
290 public int countTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes){
291 return this.dao.countTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes);
292 }
293
294
295 /* (non-Javadoc)
296 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#getOrderedDistributions(java.util.Set, boolean, boolean, java.util.Set, java.util.List)
297 */
298 @Override
299 @Deprecated
300 public DistributionTree getOrderedDistributions(
301 Set<TaxonDescription> taxonDescriptions,
302 boolean subAreaPreference,
303 boolean statusOrderPreference,
304 Set<MarkerType> hiddenAreaMarkerTypes,
305 Set<NamedAreaLevel> omitLevels, List<String> propertyPaths){
306
307 List<Distribution> distList = new ArrayList<Distribution>();
308
309 List<UUID> uuids = new ArrayList<UUID>();
310 for (TaxonDescription taxonDescription : taxonDescriptions) {
311 if (! taxonDescription.isImageGallery()){ //image galleries should not have descriptions, but better filter fully on DTYPE of description element
312 uuids.add(taxonDescription.getUuid());
313 }
314 }
315
316 List<DescriptionBase> desclist = dao.list(uuids, null, null, null, propertyPaths);
317 for (DescriptionBase desc : desclist) {
318 if (desc.isInstanceOf(TaxonDescription.class)){
319 Set<DescriptionElementBase> elements = desc.getElements();
320 for (DescriptionElementBase element : elements) {
321 if (element.isInstanceOf(Distribution.class)) {
322 Distribution distribution = (Distribution) element;
323 if(distribution.getArea() != null){
324 distList.add(distribution);
325 }
326 }
327 }
328 }
329 }
330
331 //old
332 // for (TaxonDescription taxonDescription : taxonDescriptions) {
333 // if (logger.isDebugEnabled()){ logger.debug("load taxon description " + taxonDescription.getUuid());}
334 // //TODO why not loading all description via .list ? This may improve performance
335 // taxonDescription = (TaxonDescription) dao.load(taxonDescription.getUuid(), propertyPaths);
336 // Set<DescriptionElementBase> elements = taxonDescription.getElements();
337 // for (DescriptionElementBase element : elements) {
338 // if (element.isInstanceOf(Distribution.class)) {
339 // Distribution distribution = (Distribution) element;
340 // if(distribution.getArea() != null){
341 // distList.add(distribution);
342 // }
343 // }
344 // }
345 // }
346
347 if (logger.isDebugEnabled()){logger.debug("filter tree for " + distList.size() + " distributions ...");}
348
349 // filter distributions
350 Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(distList, hiddenAreaMarkerTypes, true, statusOrderPreference, false);
351 distList.clear();
352 distList.addAll(filteredDistributions);
353
354 return DescriptionUtility.orderDistributions(definedTermDao, omitLevels, distList, hiddenAreaMarkerTypes);
355 }
356
357
358 @Override
359 public Pager<TaxonNameDescription> getTaxonNameDescriptions(TaxonNameBase name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
360 Integer numberOfResults = dao.countTaxonNameDescriptions(name);
361
362 List<TaxonNameDescription> results = new ArrayList<TaxonNameDescription>();
363 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
364 results = dao.getTaxonNameDescriptions(name, pageSize, pageNumber,propertyPaths);
365 }
366
367 return new DefaultPagerImpl<TaxonNameDescription>(pageNumber, numberOfResults, pageSize, results);
368 }
369
370
371 @Override
372 public Pager<DescriptionBase> page(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText, Set<Feature> feature, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
373 Integer numberOfResults = dao.countDescriptions(type, hasImages, hasText, feature);
374
375 List<DescriptionBase> results = new ArrayList<DescriptionBase>();
376 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
377 results = dao.listDescriptions(type, hasImages, hasText, feature, pageSize, pageNumber,orderHints,propertyPaths);
378 }
379
380 return new DefaultPagerImpl<DescriptionBase>(pageNumber, numberOfResults, pageSize, results);
381 }
382
383 /**
384 * FIXME Candidate for harmonization
385 * Rename: searchByDistribution
386 */
387 @Override
388 public Pager<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTerm presence, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
389 Integer numberOfResults = dao.countDescriptionByDistribution(namedAreas, presence);
390
391 List<TaxonDescription> results = new ArrayList<TaxonDescription>();
392 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
393 results = dao.searchDescriptionByDistribution(namedAreas, presence, pageSize, pageNumber,orderHints,propertyPaths);
394 }
395
396 return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
397 }
398
399 /**
400 * FIXME Candidate for harmonization
401 * move: descriptionElementService.search
402 */
403 @Override
404 public Pager<DescriptionElementBase> searchElements(Class<? extends DescriptionElementBase> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
405 Integer numberOfResults = descriptionElementDao.count(clazz, queryString);
406
407 List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
408 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
409 results = descriptionElementDao.search(clazz, queryString, pageSize, pageNumber, orderHints, propertyPaths);
410 }
411
412 return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, numberOfResults, pageSize, results);
413 }
414
415 /**
416 * FIXME Candidate for harmonization
417 * descriptionElementService.find
418 */
419 @Override
420 public DescriptionElementBase getDescriptionElementByUuid(UUID uuid) {
421 return descriptionElementDao.findByUuid(uuid);
422 }
423
424 /**
425 * FIXME Candidate for harmonization
426 * descriptionElementService.load
427 */
428 @Override
429 public DescriptionElementBase loadDescriptionElement(UUID uuid, List<String> propertyPaths) {
430 return descriptionElementDao.load(uuid, propertyPaths);
431 }
432
433 /**
434 * FIXME Candidate for harmonization
435 * descriptionElementService.save
436 */
437 @Override
438 @Transactional(readOnly = false)
439 public UUID saveDescriptionElement(DescriptionElementBase descriptionElement) {
440 return descriptionElementDao.save(descriptionElement).getUuid();
441 }
442
443 /**
444 * FIXME Candidate for harmonization
445 * descriptionElementService.save
446 */
447 @Override
448 @Transactional(readOnly = false)
449 public Map<UUID, DescriptionElementBase> saveDescriptionElement(Collection<DescriptionElementBase> descriptionElements) {
450 return descriptionElementDao.saveAll(descriptionElements);
451 }
452
453 /**
454 * FIXME Candidate for harmonization
455 * descriptionElementService.delete
456 */
457 @Override
458 public UUID deleteDescriptionElement(DescriptionElementBase descriptionElement) {
459 return descriptionElementDao.delete(descriptionElement);
460 }
461
462
463 /* (non-Javadoc)
464 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#deleteDescriptionElement(java.util.UUID)
465 */
466 @Override
467 public UUID deleteDescriptionElement(UUID descriptionElementUuid) {
468 return deleteDescriptionElement(descriptionElementDao.load(descriptionElementUuid));
469 }
470
471 @Override
472 @Transactional(readOnly = false)
473 public DeleteResult deleteDescription(DescriptionBase description) {
474 DeleteResult deleteResult = new DeleteResult();
475
476 if (description instanceof TaxonDescription){
477 TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
478 Taxon tax = taxDescription.getTaxon();
479 tax.removeDescription(taxDescription, true);
480 dao.delete(description);
481
482 deleteResult.addUpdatedObject(tax);
483 deleteResult.setCdmEntity(tax);
484 }
485
486
487 return deleteResult;
488 }
489
490
491 /* (non-Javadoc)
492 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#deleteDescription(java.util.UUID)
493 */
494 @Override
495 @Transactional(readOnly = false)
496 public DeleteResult deleteDescription(UUID descriptionUuid) {
497 return deleteDescription(dao.load(descriptionUuid));
498 }
499
500
501 @Override
502 public TermVocabulary<Feature> getFeatureVocabulary(UUID uuid) {
503 return vocabularyDao.findByUuid(uuid);
504 }
505
506 @Override
507 @Deprecated
508 public <T extends DescriptionElementBase> List<T> getDescriptionElementsForTaxon(
509 Taxon taxon, Set<Feature> features,
510 Class<T> type, Integer pageSize,
511 Integer pageNumber, List<String> propertyPaths) {
512 return listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
513 }
514
515 @Override
516 public <T extends DescriptionElementBase> List<T> listDescriptionElementsForTaxon(
517 Taxon taxon, Set<Feature> features,
518 Class<T> type, Integer pageSize,
519 Integer pageNumber, List<String> propertyPaths) {
520 return dao.getDescriptionElementForTaxon(taxon.getUuid(), features, type, pageSize, pageNumber, propertyPaths);
521 }
522
523 @Override
524 public <T extends DescriptionElementBase> Pager<T> pageDescriptionElementsForTaxon(
525 Taxon taxon, Set<Feature> features,
526 Class<T> type, Integer pageSize,
527 Integer pageNumber, List<String> propertyPaths) {
528 if (logger.isDebugEnabled()){logger.debug(" get count ...");}
529 Long count = dao.countDescriptionElementForTaxon(taxon.getUuid(), features, type);
530 List<T> descriptionElements;
531 if(AbstractPagerImpl.hasResultsInRange(count, pageNumber, pageSize)){ // no point checking again
532 if (logger.isDebugEnabled()){logger.debug(" get list ...");}
533 descriptionElements = listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
534 } else {
535 descriptionElements = new ArrayList<T>(0);
536 }
537 if (logger.isDebugEnabled()){logger.debug(" service - DONE ...");}
538 return new DefaultPagerImpl<T>(pageNumber, count.intValue(), pageSize, descriptionElements);
539 }
540
541
542 /* (non-Javadoc)
543 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#generateNaturalLanguageDescription(eu.etaxonomy.cdm.model.description.FeatureTree, eu.etaxonomy.cdm.model.description.TaxonDescription, eu.etaxonomy.cdm.model.common.Language, java.util.List)
544 */
545 @Override
546 public String generateNaturalLanguageDescription(FeatureTree featureTree,
547 TaxonDescription description, List<Language> preferredLanguages, String separator) {
548
549 Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
550
551 description = (TaxonDescription)load(description.getUuid());
552 featureTree = featureTreeDao.load(featureTree.getUuid());
553
554 StringBuilder naturalLanguageDescription = new StringBuilder();
555
556 MarkerType useMarkerType = (MarkerType) definedTermDao.load(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
557 boolean isUseDescription = false;
558 if(!description.getMarkers().isEmpty()) {
559 for (Marker marker: description.getMarkers()) {
560 MarkerType markerType = marker.getMarkerType();
561 if (markerType.equals(useMarkerType)) {
562 isUseDescription = true;
563 }
564
565 }
566 }
567
568 if(description.hasStructuredData() && !isUseDescription){
569
570
571 String lastCategory = null;
572 String categorySeparator = ". ";
573
574 List<TextData> textDataList;
575 TextData naturalLanguageDescriptionText = null;
576
577 boolean useMicroFormatQuantitativeDescriptionBuilder = false;
578
579 if(useMicroFormatQuantitativeDescriptionBuilder){
580
581 MicroFormatQuantitativeDescriptionBuilder micro = new MicroFormatQuantitativeDescriptionBuilder();
582 naturalLanguageGenerator.setQuantitativeDescriptionBuilder(micro);
583 naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(featureTree, (description), lang);
584
585 } else {
586
587 naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(
588 featureTree,
589 (description),
590 lang);
591 }
592
593 return naturalLanguageDescriptionText.getText(lang);
594
595 //
596 // boolean doItBetter = false;
597 //
598 // for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
599 // if(textData.getMultilanguageText().size() > 0){
600 //
601 // if (!textData.getFeature().equals(Feature.UNKNOWN())) {
602 // String featureLabel = textData.getFeature().getLabel(lang);
603 //
604 // if(doItBetter){
605 // /*
606 // * WARNING
607 // * The code lines below are desinged to handle
608 // * a special case where as the feature label contains
609 // * hierarchical information on the features. This code
610 // * exist only as a base for discussion, and is not
611 // * intendet to be used in production.
612 // */
613 // featureLabel = StringUtils.remove(featureLabel, '>');
614 //
615 // String[] labelTokens = StringUtils.split(featureLabel, '<');
616 // if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
617 // if(naturalLanguageDescription.length() > 0){
618 // naturalLanguageDescription.append(separator);
619 // }
620 // naturalLanguageDescription.append(labelTokens[1]);
621 // } else {
622 // if(naturalLanguageDescription.length() > 0){
623 // naturalLanguageDescription.append(categorySeparator);
624 // }
625 // naturalLanguageDescription.append(StringUtils.join(labelTokens));
626 // }
627 // lastCategory = labelTokens[0];
628 // // end of demo code
629 // } else {
630 // if(naturalLanguageDescription.length() > 0){
631 // naturalLanguageDescription.append(separator);
632 // }
633 // naturalLanguageDescription.append(textData.getFeature().getLabel(lang));
634 // }
635 // } else {
636 // if(naturalLanguageDescription.length() > 0){
637 // naturalLanguageDescription.append(separator);
638 // }
639 // }
640 // String text = textData.getMultilanguageText().values().iterator().next().getText();
641 // naturalLanguageDescription.append(text);
642 //
643 // }
644 // }
645
646 }
647 else if (isUseDescription) {
648 //AT: Left Blank in case we need to generate a Natural language text string.
649 }
650 return naturalLanguageDescription.toString();
651 }
652
653
654 @Override
655 public boolean hasStructuredData(DescriptionBase<?> description) {
656 return load(description.getUuid()).hasStructuredData();
657 }
658
659
660 @Override
661 @Transactional(readOnly = false)
662 public UpdateResult moveDescriptionElementsToDescription(
663 Collection<DescriptionElementBase> descriptionElements,
664 DescriptionBase targetDescription,
665 boolean isCopy) {
666
667 UpdateResult result = new UpdateResult();
668 if (descriptionElements.isEmpty() ){
669 return result;
670 }
671
672 if (! isCopy && descriptionElements == descriptionElements.iterator().next().getInDescription().getElements()){
673 //if the descriptionElements collection is the elements set of a description, put it in a separate set before to avoid concurrent modification exceptions
674 descriptionElements = new HashSet<DescriptionElementBase>(descriptionElements);
675 // descriptionElementsTmp.addAll(descriptionElements);
676 // descriptionElements = descriptionElementsTmp;
677 }
678 for (DescriptionElementBase element : descriptionElements){
679 DescriptionBase<?> description = element.getInDescription();
680 try {
681 DescriptionElementBase newElement = (DescriptionElementBase)element.clone();
682 targetDescription.addElement(newElement);
683 } catch (CloneNotSupportedException e) {
684 throw new RuntimeException ("Clone not yet implemented for class " + element.getClass().getName(), e);
685 }
686 if (! isCopy){
687 description.removeElement(element);
688 if (description.getElements().isEmpty()){
689 if (description instanceof TaxonDescription){
690 TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
691 if (taxDescription.getTaxon() != null){
692 taxDescription.getTaxon().removeDescription((TaxonDescription)description);
693 }
694 }
695 dao.delete(description);
696 }else{
697 dao.saveOrUpdate(description);
698 result.addUpdatedObject(description);
699 }
700 }
701
702
703 }
704 dao.saveOrUpdate(targetDescription);
705 result.addUpdatedObject(targetDescription);
706 if (targetDescription instanceof TaxonDescription){
707 result.addUpdatedObject(((TaxonDescription)targetDescription).getTaxon());
708 }
709 return result;
710 }
711
712 @Override
713 @Transactional(readOnly = false)
714 public UpdateResult moveDescriptionElementsToDescription(
715 Set<UUID> descriptionElementUUIDs,
716 UUID targetDescriptionUuid,
717 boolean isCopy) {
718 Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
719 for(UUID deUuid : descriptionElementUUIDs) {
720 descriptionElements.add(descriptionElementDao.load(deUuid));
721 }
722 DescriptionBase targetDescription = dao.load(targetDescriptionUuid);
723
724 return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy);
725 }
726
727 @Override
728 @Transactional(readOnly = false)
729 public UpdateResult moveDescriptionElementsToDescription(
730 Set<UUID> descriptionElementUUIDs,
731 UUID targetTaxonUuid,
732 String moveMessage,
733 boolean isCopy) {
734 Taxon targetTaxon = CdmBase.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
735 DescriptionBase targetDescription = TaxonDescription.NewInstance(targetTaxon);
736 targetDescription.setTitleCache(moveMessage, true);
737 Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
738 annotation.setAnnotationType(AnnotationType.TECHNICAL());
739 targetDescription.addAnnotation(annotation);
740
741 targetDescription = dao.save(targetDescription);
742 Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
743 for(UUID deUuid : descriptionElementUUIDs) {
744 descriptionElements.add(descriptionElementDao.load(deUuid));
745 }
746
747 return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy);
748 }
749
750 @Override
751 public Pager<TermDto> pageNamedAreasInUse(boolean includeAllParents, Integer pageSize,
752 Integer pageNumber){
753 List<TermDto> results = dao.listNamedAreasInUse(includeAllParents, null, null);
754 int startIndex= pageNumber * pageSize;
755 int toIndex = Math.min(startIndex + pageSize, results.size());
756 List<TermDto> page = results.subList(startIndex, toIndex);
757 return new DefaultPagerImpl<TermDto>(pageNumber, results.size(), pageSize, page);
758 }
759
760
761 @Override
762 @Transactional(readOnly = false)
763 public UpdateResult moveTaxonDescriptions(Taxon sourceTaxon, Taxon targetTaxon) {
764 List<TaxonDescription> descriptions = new ArrayList(sourceTaxon.getDescriptions());
765 UpdateResult result = new UpdateResult();
766 result.addUpdatedObject(sourceTaxon);
767 result.addUpdatedObject(targetTaxon);
768 for(TaxonDescription description : descriptions){
769
770 String moveMessage = String.format("Description moved from %s", sourceTaxon);
771 if(description.isProtectedTitleCache()){
772 String separator = "";
773 if(!StringUtils.isBlank(description.getTitleCache())){
774 separator = " - ";
775 }
776 description.setTitleCache(description.getTitleCache() + separator + moveMessage, true);
777 }
778 Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
779 annotation.setAnnotationType(AnnotationType.TECHNICAL());
780 description.addAnnotation(annotation);
781 targetTaxon.addDescription(description);
782 }
783 return result;
784 }
785
786 @Override
787 @Transactional(readOnly = false)
788 public UpdateResult moveTaxonDescriptions(UUID sourceTaxonUuid, UUID targetTaxonUuid) {
789 Taxon sourceTaxon = HibernateProxyHelper.deproxy(taxonDao.load(sourceTaxonUuid), Taxon.class);
790 Taxon targetTaxon = HibernateProxyHelper.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
791 return moveTaxonDescriptions(sourceTaxon, targetTaxon);
792
793 }
794
795 @Override
796 @Transactional(readOnly = false)
797 public UpdateResult moveTaxonDescription(UUID descriptionUuid, UUID targetTaxonUuid){
798 UpdateResult result = new UpdateResult();
799 TaxonDescription description = HibernateProxyHelper.deproxy(dao.load(descriptionUuid), TaxonDescription.class);
800
801 Taxon sourceTaxon = description.getTaxon();
802 String moveMessage = String.format("Description moved from %s", sourceTaxon);
803 if(description.isProtectedTitleCache()){
804 String separator = "";
805 if(!StringUtils.isBlank(description.getTitleCache())){
806 separator = " - ";
807 }
808 description.setTitleCache(description.getTitleCache() + separator + moveMessage, true);
809 }
810 Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
811 annotation.setAnnotationType(AnnotationType.TECHNICAL());
812 description.addAnnotation(annotation);
813 Taxon targetTaxon = HibernateProxyHelper.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
814 targetTaxon.addDescription(description);
815 result.addUpdatedObject(targetTaxon);
816 result.addUpdatedObject(sourceTaxon);
817 // dao.merge(description);
818 return result;
819
820 }
821
822
823
824 }