3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
11 package eu
.etaxonomy
.cdm
.api
.service
;
13 import java
.io
.IOException
;
15 import java
.net
.URISyntaxException
;
16 import java
.util
.ArrayList
;
17 import java
.util
.Arrays
;
18 import java
.util
.Collection
;
19 import java
.util
.Collections
;
20 import java
.util
.HashMap
;
21 import java
.util
.HashSet
;
22 import java
.util
.List
;
24 import java
.util
.Map
.Entry
;
26 import java
.util
.UUID
;
28 import org
.apache
.log4j
.Logger
;
29 import org
.apache
.lucene
.index
.CorruptIndexException
;
30 import org
.apache
.lucene
.queryParser
.ParseException
;
31 import org
.apache
.lucene
.search
.BooleanClause
.Occur
;
32 import org
.apache
.lucene
.search
.BooleanQuery
;
33 import org
.apache
.lucene
.search
.SortField
;
34 import org
.hibernate
.TransientObjectException
;
35 import org
.hibernate
.search
.spatial
.impl
.Rectangle
;
36 import org
.joda
.time
.Partial
;
37 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
38 import org
.springframework
.dao
.DataRetrievalFailureException
;
39 import org
.springframework
.stereotype
.Service
;
40 import org
.springframework
.transaction
.annotation
.Transactional
;
42 import eu
.etaxonomy
.cdm
.api
.facade
.DerivedUnitFacade
;
43 import eu
.etaxonomy
.cdm
.api
.facade
.DerivedUnitFacadeConfigurator
;
44 import eu
.etaxonomy
.cdm
.api
.facade
.DerivedUnitFacadeNotSupportedException
;
45 import eu
.etaxonomy
.cdm
.api
.service
.UpdateResult
.Status
;
46 import eu
.etaxonomy
.cdm
.api
.service
.config
.DeleteConfiguratorBase
;
47 import eu
.etaxonomy
.cdm
.api
.service
.config
.FindOccurrencesConfigurator
;
48 import eu
.etaxonomy
.cdm
.api
.service
.config
.IIdentifiableEntityServiceConfigurator
;
49 import eu
.etaxonomy
.cdm
.api
.service
.config
.SpecimenDeleteConfigurator
;
50 import eu
.etaxonomy
.cdm
.api
.service
.dto
.DerivateDTO
;
51 import eu
.etaxonomy
.cdm
.api
.service
.dto
.DerivateDataDTO
;
52 import eu
.etaxonomy
.cdm
.api
.service
.dto
.DerivateDataDTO
.ContigFile
;
53 import eu
.etaxonomy
.cdm
.api
.service
.dto
.DerivateDataDTO
.MolecularData
;
54 import eu
.etaxonomy
.cdm
.api
.service
.dto
.FieldUnitDTO
;
55 import eu
.etaxonomy
.cdm
.api
.service
.dto
.PreservedSpecimenDTO
;
56 import eu
.etaxonomy
.cdm
.api
.service
.exception
.ReferencedObjectUndeletableException
;
57 import eu
.etaxonomy
.cdm
.api
.service
.molecular
.ISequenceService
;
58 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
59 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
60 import eu
.etaxonomy
.cdm
.api
.service
.search
.ILuceneIndexToolProvider
;
61 import eu
.etaxonomy
.cdm
.api
.service
.search
.ISearchResultBuilder
;
62 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneSearch
;
63 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneSearch
.TopGroupsWithMaxScore
;
64 import eu
.etaxonomy
.cdm
.api
.service
.search
.QueryFactory
;
65 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResult
;
66 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResultBuilder
;
67 import eu
.etaxonomy
.cdm
.api
.service
.util
.TaxonRelationshipEdge
;
68 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
69 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
70 import eu
.etaxonomy
.cdm
.model
.CdmBaseType
;
71 import eu
.etaxonomy
.cdm
.model
.agent
.AgentBase
;
72 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
73 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTerm
;
74 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTermBase
;
75 import eu
.etaxonomy
.cdm
.model
.common
.ICdmBase
;
76 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
77 import eu
.etaxonomy
.cdm
.model
.common
.UuidAndTitleCache
;
78 import eu
.etaxonomy
.cdm
.model
.description
.CategoricalData
;
79 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
80 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
81 import eu
.etaxonomy
.cdm
.model
.description
.IndividualsAssociation
;
82 import eu
.etaxonomy
.cdm
.model
.description
.QuantitativeData
;
83 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
84 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
85 import eu
.etaxonomy
.cdm
.model
.location
.Country
;
86 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
87 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
88 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
89 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentationPart
;
90 import eu
.etaxonomy
.cdm
.model
.media
.MediaUtils
;
91 import eu
.etaxonomy
.cdm
.model
.molecular
.AmplificationResult
;
92 import eu
.etaxonomy
.cdm
.model
.molecular
.DnaSample
;
93 import eu
.etaxonomy
.cdm
.model
.molecular
.Sequence
;
94 import eu
.etaxonomy
.cdm
.model
.molecular
.SingleRead
;
95 import eu
.etaxonomy
.cdm
.model
.name
.SpecimenTypeDesignation
;
96 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
97 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationStatusBase
;
98 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivationEvent
;
99 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnit
;
100 import eu
.etaxonomy
.cdm
.model
.occurrence
.DeterminationEvent
;
101 import eu
.etaxonomy
.cdm
.model
.occurrence
.FieldUnit
;
102 import eu
.etaxonomy
.cdm
.model
.occurrence
.GatheringEvent
;
103 import eu
.etaxonomy
.cdm
.model
.occurrence
.MediaSpecimen
;
104 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
105 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationType
;
106 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
107 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
108 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IDefinedTermDao
;
109 import eu
.etaxonomy
.cdm
.persistence
.dao
.initializer
.AbstractBeanInitializer
;
110 import eu
.etaxonomy
.cdm
.persistence
.dao
.occurrence
.IOccurrenceDao
;
111 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
112 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
115 * @author a.babadshanjan
116 * @created 01.09.2008
119 @Transactional(readOnly
= true)
120 public class OccurrenceServiceImpl
extends IdentifiableServiceBase
<SpecimenOrObservationBase
, IOccurrenceDao
> implements IOccurrenceService
{
122 static private final Logger logger
= Logger
.getLogger(OccurrenceServiceImpl
.class);
125 private IDefinedTermDao definedTermDao
;
128 private IDescriptionService descriptionService
;
131 private ITaxonService taxonService
;
134 private ISequenceService sequenceService
;
137 private AbstractBeanInitializer beanInitializer
;
140 private ILuceneIndexToolProvider luceneIndexToolProvider
;
142 private static final String SEPARATOR_STRING
= ", ";
144 public OccurrenceServiceImpl() {
145 logger
.debug("Load OccurrenceService Bean");
150 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
153 @Transactional(readOnly
= false)
154 public void updateTitleCache(Class
<?
extends SpecimenOrObservationBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<SpecimenOrObservationBase
> cacheStrategy
, IProgressMonitor monitor
) {
156 clazz
= SpecimenOrObservationBase
.class;
158 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
162 * FIXME Candidate for harmonization
163 * move to termService
166 public Country
getCountryByIso(String iso639
) {
167 return this.definedTermDao
.getCountryByIso(iso639
);
172 * FIXME Candidate for harmonization
173 * move to termService
176 public List
<Country
> getCountryByName(String name
) {
177 List
<?
extends DefinedTermBase
> terms
= this.definedTermDao
.findByTitle(Country
.class, name
, null, null, null, null, null, null);
178 List
<Country
> countries
= new ArrayList
<Country
>();
179 for (int i
= 0; i
< terms
.size(); i
++) {
180 countries
.add((Country
) terms
.get(i
));
187 protected void setDao(IOccurrenceDao dao
) {
192 public Pager
<DerivationEvent
> getDerivationEvents(SpecimenOrObservationBase occurence
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
193 Integer numberOfResults
= dao
.countDerivationEvents(occurence
);
195 List
<DerivationEvent
> results
= new ArrayList
<DerivationEvent
>();
196 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
197 results
= dao
.getDerivationEvents(occurence
, pageSize
, pageNumber
, propertyPaths
);
200 return new DefaultPagerImpl
<DerivationEvent
>(pageNumber
, numberOfResults
, pageSize
, results
);
204 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#countDeterminations(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.taxon.TaxonBase)
207 public int countDeterminations(SpecimenOrObservationBase occurence
, TaxonBase taxonbase
) {
208 return dao
.countDeterminations(occurence
, taxonbase
);
212 public Pager
<DeterminationEvent
> getDeterminations(SpecimenOrObservationBase occurrence
, TaxonBase taxonBase
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
213 Integer numberOfResults
= dao
.countDeterminations(occurrence
, taxonBase
);
215 List
<DeterminationEvent
> results
= new ArrayList
<DeterminationEvent
>();
216 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
217 results
= dao
.getDeterminations(occurrence
, taxonBase
, pageSize
, pageNumber
, propertyPaths
);
220 return new DefaultPagerImpl
<DeterminationEvent
>(pageNumber
, numberOfResults
, pageSize
, results
);
224 public Pager
<Media
> getMedia(SpecimenOrObservationBase occurence
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
225 Integer numberOfResults
= dao
.countMedia(occurence
);
227 List
<Media
> results
= new ArrayList
<Media
>();
228 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
229 results
= dao
.getMedia(occurence
, pageSize
, pageNumber
, propertyPaths
);
232 return new DefaultPagerImpl
<Media
>(pageNumber
, numberOfResults
, pageSize
, results
);
236 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#list(java.lang.Class, eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
239 public Pager
<SpecimenOrObservationBase
> list(Class
<?
extends SpecimenOrObservationBase
> type
, TaxonBase determinedAs
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
240 Integer numberOfResults
= dao
.count(type
, determinedAs
);
241 List
<SpecimenOrObservationBase
> results
= new ArrayList
<SpecimenOrObservationBase
>();
242 pageNumber
= pageNumber
== null ?
0 : pageNumber
;
243 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
244 Integer start
= pageSize
== null ?
0 : pageSize
* pageNumber
;
245 results
= dao
.list(type
, determinedAs
, pageSize
, start
, orderHints
, propertyPaths
);
247 return new DefaultPagerImpl
<SpecimenOrObservationBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
251 public List
<UuidAndTitleCache
<DerivedUnit
>> getDerivedUnitUuidAndTitleCache() {
252 return dao
.getDerivedUnitUuidAndTitleCache();
256 public List
<UuidAndTitleCache
<FieldUnit
>> getFieldUnitUuidAndTitleCache() {
257 return dao
.getFieldUnitUuidAndTitleCache();
261 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getDerivedUnitFacade(eu.etaxonomy.cdm.model.occurrence.DerivedUnit)
264 public DerivedUnitFacade
getDerivedUnitFacade(DerivedUnit derivedUnit
, List
<String
> propertyPaths
) throws DerivedUnitFacadeNotSupportedException
{
265 derivedUnit
= (DerivedUnit
) dao
.load(derivedUnit
.getUuid(), null);
266 DerivedUnitFacadeConfigurator config
= DerivedUnitFacadeConfigurator
.NewInstance();
267 config
.setThrowExceptionForNonSpecimenPreservationMethodRequest(false);
268 DerivedUnitFacade derivedUnitFacade
= DerivedUnitFacade
.NewInstance(derivedUnit
, config
);
269 beanInitializer
.initialize(derivedUnitFacade
, propertyPaths
);
270 return derivedUnitFacade
;
274 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listDerivedUnitFacades(eu.etaxonomy.cdm.model.description.DescriptionBase, java.util.List)
277 public List
<DerivedUnitFacade
> listDerivedUnitFacades(
278 DescriptionBase description
, List
<String
> propertyPaths
) {
280 List
<DerivedUnitFacade
> derivedUnitFacadeList
= new ArrayList
<DerivedUnitFacade
>();
281 IndividualsAssociation tempIndividualsAssociation
;
282 SpecimenOrObservationBase tempSpecimenOrObservationBase
;
283 List
<DescriptionElementBase
> elements
= descriptionService
.listDescriptionElements(description
, null, IndividualsAssociation
.class, null, 0, Arrays
.asList(new String
[]{"associatedSpecimenOrObservation"}));
284 for (DescriptionElementBase element
: elements
) {
285 if (element
.isInstanceOf(IndividualsAssociation
.class)) {
286 tempIndividualsAssociation
= HibernateProxyHelper
.deproxy(element
, IndividualsAssociation
.class);
287 if (tempIndividualsAssociation
.getAssociatedSpecimenOrObservation() != null) {
288 tempSpecimenOrObservationBase
= HibernateProxyHelper
.deproxy(tempIndividualsAssociation
.getAssociatedSpecimenOrObservation(), SpecimenOrObservationBase
.class);
289 if (tempSpecimenOrObservationBase
.isInstanceOf(DerivedUnit
.class)) {
291 derivedUnitFacadeList
.add(DerivedUnitFacade
.NewInstance(HibernateProxyHelper
.deproxy(tempSpecimenOrObservationBase
, DerivedUnit
.class)));
292 } catch (DerivedUnitFacadeNotSupportedException e
) {
293 logger
.warn(tempIndividualsAssociation
.getAssociatedSpecimenOrObservation().getTitleCache() + " : " + e
.getMessage());
301 beanInitializer
.initializeAll(derivedUnitFacadeList
, propertyPaths
);
303 return derivedUnitFacadeList
;
308 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listByAnyAssociation(java.lang.Class, java.util.Set, eu.etaxonomy.cdm.model.taxon.Taxon, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
311 public <T
extends SpecimenOrObservationBase
> List
<T
> listByAssociatedTaxon(Class
<T
> type
, Set
<TaxonRelationshipEdge
> includeRelationships
,
312 Taxon associatedTaxon
, Integer maxDepth
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
314 return pageByAssociatedTaxon(type
, includeRelationships
, associatedTaxon
, maxDepth
, pageSize
, pageNumber
, orderHints
, propertyPaths
).getRecords();
318 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listByAnyAssociation(java.lang.Class, java.util.Set, eu.etaxonomy.cdm.model.taxon.Taxon, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
321 public Collection
<SpecimenOrObservationBase
> listFieldUnitsByAssociatedTaxon(Taxon associatedTaxon
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
322 return pageFieldUnitsByAssociatedTaxon(null, associatedTaxon
, null, null, null, null, propertyPaths
).getRecords();
326 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#pageFieldUnitsByAssociatedTaxon(java.util.Set, eu.etaxonomy.cdm.model.taxon.Taxon, java.lang.Integer, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
329 public Pager
<SpecimenOrObservationBase
> pageFieldUnitsByAssociatedTaxon(Set
<TaxonRelationshipEdge
> includeRelationships
,
330 Taxon associatedTaxon
, Integer maxDepth
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
,
331 List
<String
> propertyPaths
) {
333 if (!getSession().contains(associatedTaxon
)) {
334 associatedTaxon
= (Taxon
) taxonService
.load(associatedTaxon
.getUuid());
337 // gather the IDs of all relevant field units
338 Set
<Integer
> fieldUnitIds
= new HashSet
<Integer
>();
339 List
<SpecimenOrObservationBase
> records
= listByAssociatedTaxon(null, includeRelationships
, associatedTaxon
, maxDepth
, null, null, orderHints
, propertyPaths
);
340 for (SpecimenOrObservationBase
<?
> specimen
: records
) {
341 for (FieldUnit fieldUnit
: getFieldUnits(specimen
.getUuid())) {
342 fieldUnitIds
.add(fieldUnit
.getId());
345 //dao.listByIds() does the paging of the field units. Passing the field units directly to the Pager would not work
346 List
<SpecimenOrObservationBase
> fieldUnits
= dao
.listByIds(fieldUnitIds
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
347 return new DefaultPagerImpl
<SpecimenOrObservationBase
>(pageNumber
, fieldUnitIds
.size(), pageSize
, fieldUnits
);
351 public FieldUnitDTO
assembleFieldUnitDTO(FieldUnit fieldUnit
, UUID associatedTaxonUuid
) {
353 if (!getSession().contains(fieldUnit
)) {
354 fieldUnit
= (FieldUnit
) load(fieldUnit
.getUuid());
356 TaxonBase associatedTaxon
= taxonService
.load(associatedTaxonUuid
);
358 FieldUnitDTO fieldUnitDTO
= new FieldUnitDTO();
360 if (fieldUnit
.getGatheringEvent() != null) {
361 GatheringEvent gatheringEvent
= fieldUnit
.getGatheringEvent();
363 NamedArea country
= gatheringEvent
.getCountry();
364 fieldUnitDTO
.setCountry(country
!= null ? country
.getDescription() : null);
366 AgentBase collector
= gatheringEvent
.getCollector();
367 String fieldNumber
= fieldUnit
.getFieldNumber();
368 String collectionString
= "";
369 if (collector
!= null || fieldNumber
!= null) {
370 collectionString
+= collector
!= null ? collector
: "";
371 if (!collectionString
.isEmpty()) {
372 collectionString
+= " ";
374 collectionString
+= (fieldNumber
!= null ? fieldNumber
: "");
375 collectionString
.trim();
377 fieldUnitDTO
.setCollection(collectionString
);
379 Partial gatheringDate
= gatheringEvent
.getGatheringDate();
380 String dateString
= null;
381 if (gatheringDate
!= null) {
382 gatheringDate
.toString();
384 else if(gatheringEvent
.getTimeperiod()!=null && gatheringEvent
.getTimeperiod().getFreeText()!=null){
385 dateString
= gatheringEvent
.getTimeperiod().getFreeText();
387 fieldUnitDTO
.setDate(dateString
);
391 fieldUnitDTO
.setTaxonName(associatedTaxon
.getName().getTitleCache());
394 Map
<eu
.etaxonomy
.cdm
.model
.occurrence
.Collection
, Integer
> collectionToCountMap
= new HashMap
<eu
.etaxonomy
.cdm
.model
.occurrence
.Collection
, Integer
>();
395 // List of accession numbers for citation
396 List
<String
> preservedSpecimenAccessionNumbers
= new ArrayList
<String
>();
398 // assemble preserved specimen DTOs
399 Set
<DerivationEvent
> derivationEvents
= fieldUnit
.getDerivationEvents();
400 for (DerivationEvent derivationEvent
: derivationEvents
) {
401 Set
<DerivedUnit
> derivatives
= derivationEvent
.getDerivatives();
402 for (DerivedUnit derivedUnit
: derivatives
) {
403 // collect accession numbers for citation
404 String mostSignificantIdentifier
= getMostSignificantIdentifier(derivedUnit
);
405 if (mostSignificantIdentifier
!= null) {
406 preservedSpecimenAccessionNumbers
.add(mostSignificantIdentifier
);
408 // collect collections for herbaria column
409 if (derivedUnit
.getCollection() != null) {
410 Integer herbariumCount
= collectionToCountMap
.get(derivedUnit
.getCollection());
411 if (herbariumCount
== null) {
414 collectionToCountMap
.put(derivedUnit
.getCollection(), herbariumCount
+ 1);
416 if (derivedUnit
.getRecordBasis().equals(SpecimenOrObservationType
.PreservedSpecimen
)) {
417 PreservedSpecimenDTO preservedSpecimenDTO
= assemblePreservedSpecimenDTO(derivedUnit
, fieldUnitDTO
);
418 fieldUnitDTO
.addPreservedSpecimenDTO(preservedSpecimenDTO
);
419 fieldUnitDTO
.setHasCharacterData(fieldUnitDTO
.isHasCharacterData() || preservedSpecimenDTO
.isHasCharacterData());
420 fieldUnitDTO
.setHasDetailImage(fieldUnitDTO
.isHasDetailImage() || preservedSpecimenDTO
.isHasDetailImage());
421 fieldUnitDTO
.setHasDna(fieldUnitDTO
.isHasDna() || preservedSpecimenDTO
.isHasDna());
422 fieldUnitDTO
.setHasSpecimenScan(fieldUnitDTO
.isHasSpecimenScan() || preservedSpecimenDTO
.isHasSpecimenScan());
426 // assemble derivate data DTO
427 assembleDerivateDataDTO(fieldUnitDTO
, fieldUnit
);
430 String citation
= fieldUnit
.getTitleCache();
431 if (!preservedSpecimenAccessionNumbers
.isEmpty()) {
433 for (String accessionNumber
: preservedSpecimenAccessionNumbers
) {
434 if (!accessionNumber
.isEmpty()) {
435 citation
+= accessionNumber
+ SEPARATOR_STRING
;
438 citation
= removeTail(citation
, SEPARATOR_STRING
);
441 fieldUnitDTO
.setCitation(citation
);
443 // assemble herbaria string
444 String herbariaString
= "";
445 for (Entry
<eu
.etaxonomy
.cdm
.model
.occurrence
.Collection
, Integer
> e
: collectionToCountMap
.entrySet()) {
446 eu
.etaxonomy
.cdm
.model
.occurrence
.Collection collection
= e
.getKey();
447 if (collection
.getCode() != null) {
448 herbariaString
+= collection
.getCode();
450 if (e
.getValue() > 1) {
451 herbariaString
+= "(" + e
.getValue() + ")";
453 herbariaString
+= SEPARATOR_STRING
;
455 herbariaString
= removeTail(herbariaString
, SEPARATOR_STRING
);
456 fieldUnitDTO
.setHerbarium(herbariaString
);
462 public PreservedSpecimenDTO
assemblePreservedSpecimenDTO(DerivedUnit derivedUnit
) {
463 return assemblePreservedSpecimenDTO(derivedUnit
, null);
467 public String
getMostSignificantIdentifier(DerivedUnit derivedUnit
) {
468 if (derivedUnit
.getAccessionNumber() != null && !derivedUnit
.getAccessionNumber().isEmpty()) {
469 return derivedUnit
.getAccessionNumber();
471 else if(derivedUnit
.getBarcode()!=null && !derivedUnit
.getBarcode().isEmpty()){
472 return derivedUnit
.getBarcode();
474 else if(derivedUnit
.getCatalogNumber()!=null && !derivedUnit
.getCatalogNumber().isEmpty()){
475 return derivedUnit
.getCatalogNumber();
480 public PreservedSpecimenDTO
assemblePreservedSpecimenDTO(DerivedUnit derivedUnit
, FieldUnitDTO fieldUnitDTO
) {
481 if (!getSession().contains(derivedUnit
)) {
482 derivedUnit
= (DerivedUnit
) load(derivedUnit
.getUuid());
484 PreservedSpecimenDTO preservedSpecimenDTO
= new PreservedSpecimenDTO();
486 // check identifiers in priority order accNo>barCode>catalogNumber
487 if (derivedUnit
.getAccessionNumber() != null && !derivedUnit
.getAccessionNumber().isEmpty()) {
488 preservedSpecimenDTO
.setAccessionNumber(derivedUnit
.getAccessionNumber());
490 else if(derivedUnit
.getBarcode()!=null && !derivedUnit
.getBarcode().isEmpty()){
491 preservedSpecimenDTO
.setAccessionNumber(derivedUnit
.getBarcode());
493 else if(derivedUnit
.getCatalogNumber()!=null && !derivedUnit
.getCatalogNumber().isEmpty()){
494 preservedSpecimenDTO
.setAccessionNumber(derivedUnit
.getCatalogNumber());
496 preservedSpecimenDTO
.setUuid(derivedUnit
.getUuid().toString());
499 Collection
<FieldUnit
> fieldUnits
= getFieldUnits(derivedUnit
);
500 if (fieldUnits
.size() == 1) {
501 preservedSpecimenDTO
.setCitation(fieldUnits
.iterator().next().getTitleCache());
504 preservedSpecimenDTO
.setCitation("No Citation available. This specimen either has no or multiple field units.");
507 // character state data
508 Collection
<DescriptionElementBase
> characterDataForSpecimen
= getCharacterDataForSpecimen(derivedUnit
);
509 if (!characterDataForSpecimen
.isEmpty()) {
510 if (fieldUnitDTO
!= null) {
511 fieldUnitDTO
.setHasCharacterData(true);
514 for (DescriptionElementBase descriptionElementBase
: characterDataForSpecimen
) {
515 String character
= descriptionElementBase
.getFeature().getLabel();
516 ArrayList
<Language
> languages
= new ArrayList
<Language
>(Collections
.singleton(Language
.DEFAULT()));
517 if (descriptionElementBase
instanceof QuantitativeData
) {
518 QuantitativeData quantitativeData
= (QuantitativeData
) descriptionElementBase
;
519 DefaultQuantitativeDescriptionBuilder builder
= new DefaultQuantitativeDescriptionBuilder();
520 String state
= builder
.build(quantitativeData
, languages
).getText(Language
.DEFAULT());
521 preservedSpecimenDTO
.addCharacterData(character
, state
);
523 else if(descriptionElementBase
instanceof CategoricalData
){
524 CategoricalData categoricalData
= (CategoricalData
) descriptionElementBase
;
525 DefaultCategoricalDescriptionBuilder builder
= new DefaultCategoricalDescriptionBuilder();
526 String state
= builder
.build(categoricalData
, languages
).getText(Language
.DEFAULT());
527 preservedSpecimenDTO
.addCharacterData(character
, state
);
530 // check type designations
531 Collection
<SpecimenTypeDesignation
> specimenTypeDesignations
= listTypeDesignations(derivedUnit
, null, null, null, null);
532 for (SpecimenTypeDesignation specimenTypeDesignation
: specimenTypeDesignations
) {
533 if (fieldUnitDTO
!= null) {
534 fieldUnitDTO
.setHasType(true);
536 TypeDesignationStatusBase
<?
> typeStatus
= specimenTypeDesignation
.getTypeStatus();
537 if (typeStatus
!= null) {
538 List
<String
> typedTaxaNames
= new ArrayList
<String
>();
539 String label
= typeStatus
.getLabel();
540 Set
<TaxonNameBase
> typifiedNames
= specimenTypeDesignation
.getTypifiedNames();
541 for (TaxonNameBase taxonNameBase
: typifiedNames
) {
542 typedTaxaNames
.add(taxonNameBase
.getFullTitleCache());
544 preservedSpecimenDTO
.addTypes(label
, typedTaxaNames
);
548 // individuals associations
549 Collection
<IndividualsAssociation
> individualsAssociations
= listIndividualsAssociations(derivedUnit
, null, null, null, null);
550 for (IndividualsAssociation individualsAssociation
: individualsAssociations
) {
551 if (individualsAssociation
.getInDescription() != null) {
552 if (individualsAssociation
.getInDescription().isInstanceOf(TaxonDescription
.class)) {
553 TaxonDescription taxonDescription
= HibernateProxyHelper
.deproxy(individualsAssociation
.getInDescription(), TaxonDescription
.class);
554 Taxon taxon
= taxonDescription
.getTaxon();
555 if (taxon
!= null && taxon
.getName() != null) {
556 preservedSpecimenDTO
.addAssociatedTaxon(taxon
.getName().getTitleCache());
561 // assemble sub derivates
562 preservedSpecimenDTO
.setDerivateDataDTO(assembleDerivateDataDTO(preservedSpecimenDTO
, derivedUnit
));
563 return preservedSpecimenDTO
;
568 * @param derivateDataDTO
571 private DerivateDataDTO
assembleDerivateDataDTO(DerivateDTO derivateDTO
, SpecimenOrObservationBase
<?
> specimenOrObservation
) {
572 DerivateDataDTO derivateDataDTO
= new DerivateDataDTO();
573 Collection
<DerivedUnit
> childDerivates
= getDerivedUnitsFor(specimenOrObservation
);
574 for (DerivedUnit childDerivate
: childDerivates
) {
575 // assemble molecular data
576 //pattern: DNAMarker [contig1, primer1_1, primer1_2, ...][contig2, primer2_1, ...]...
577 if (childDerivate
.isInstanceOf(DnaSample
.class)) {
578 if (childDerivate
.getRecordBasis() == SpecimenOrObservationType
.TissueSample
) {
579 // TODO implement TissueSample assembly for web service
581 if (childDerivate
.getRecordBasis() == SpecimenOrObservationType
.DnaSample
) {
583 DnaSample dna
= HibernateProxyHelper
.deproxy(childDerivate
, DnaSample
.class);
584 if (!dna
.getSequences().isEmpty()) {
585 derivateDTO
.setHasDna(true);
587 for (Sequence sequence
: dna
.getSequences()) {
590 boldUri
= sequence
.getBoldUri();
591 } catch (URISyntaxException e1
) {
592 logger
.error("Could not create BOLD URI", e1
);
594 final DefinedTerm dnaMarker
= sequence
.getDnaMarker();
595 MolecularData molecularData
= derivateDataDTO
.addProviderLink(boldUri
!= null ? boldUri
: null, dnaMarker
!= null ? dnaMarker
.getLabel() : "[no marker]");
598 ContigFile contigFile
= null;
599 if (sequence
.getContigFile() != null) {
600 MediaRepresentationPart contigMediaRepresentationPart
= MediaUtils
.getFirstMediaRepresentationPart(sequence
.getContigFile());
601 if (contigMediaRepresentationPart
!= null) {
602 contigFile
= molecularData
.addContigFile(contigMediaRepresentationPart
.getUri(), "contig");
605 if(contigFile
==null){
606 contigFile
= molecularData
.addContigFile(null, "[no contig]");
609 if (sequence
.getSingleReads() != null) {
611 for (SingleRead singleRead
: sequence
.getSingleReads()) {
612 MediaRepresentationPart pherogramMediaRepresentationPart
= MediaUtils
.getFirstMediaRepresentationPart(singleRead
.getPherogram());
613 if (pherogramMediaRepresentationPart
!= null) {
614 contigFile
.addPrimerLink(pherogramMediaRepresentationPart
.getUri(), "read"+readCount
++);
621 // assemble media data
622 else if (childDerivate
.isInstanceOf(MediaSpecimen
.class)) {
623 MediaSpecimen media
= HibernateProxyHelper
.deproxy(childDerivate
, MediaSpecimen
.class);
625 String mediaUriString
= getMediaUriString(media
);
626 if (media
.getKindOfUnit() != null) {
628 if (media
.getKindOfUnit().getUuid().equals(UUID
.fromString("acda15be-c0e2-4ea8-8783-b9b0c4ad7f03"))) {
629 derivateDataDTO
.addSpecimenScanUuid(media
.getMediaSpecimen().getUuid());
630 derivateDTO
.setHasSpecimenScan(true);
631 String imageLinkText
= "scan";
632 if (derivateDTO
instanceof PreservedSpecimenDTO
&& ((PreservedSpecimenDTO
) derivateDTO
).getAccessionNumber() != null) {
633 imageLinkText
= ((PreservedSpecimenDTO
) derivateDTO
).getAccessionNumber();
635 derivateDataDTO
.addSpecimenScan(mediaUriString
== null ?
"" : mediaUriString
, imageLinkText
);
638 else if (media
.getKindOfUnit().getUuid().equals(UUID
.fromString("31eb8d02-bf5d-437c-bcc6-87a626445f34"))) {
639 derivateDataDTO
.addDetailImageUuid(media
.getMediaSpecimen().getUuid());
640 derivateDTO
.setHasDetailImage(true);
642 if (media
.getMediaSpecimen() != null && media
.getMediaSpecimen().getTitle() != null) {
643 motif
= media
.getMediaSpecimen().getTitle().getText();
645 derivateDataDTO
.addDetailImage(mediaUriString
== null ?
"" : mediaUriString
, motif
!= null ? motif
: "[no motif]");
650 return derivateDataDTO
;
658 private String
removeTail(String string
, final String tail
) {
659 if (string
.endsWith(tail
)) {
660 string
= string
.substring(0, string
.length() - tail
.length());
665 private String
getMediaUriString(MediaSpecimen mediaSpecimen
) {
666 String mediaUri
= null;
667 Collection
<MediaRepresentation
> mediaRepresentations
= mediaSpecimen
.getMediaSpecimen().getRepresentations();
668 if (mediaRepresentations
!= null && !mediaRepresentations
.isEmpty()) {
669 Collection
<MediaRepresentationPart
> mediaRepresentationParts
= mediaRepresentations
.iterator().next().getParts();
670 if (mediaRepresentationParts
!= null && !mediaRepresentationParts
.isEmpty()) {
671 MediaRepresentationPart part
= mediaRepresentationParts
.iterator().next();
672 if (part
.getUri() != null) {
673 mediaUri
= part
.getUri().toASCIIString();
680 private Collection
<DerivedUnit
> getDerivedUnitsFor(SpecimenOrObservationBase
<?
> specimen
) {
681 Collection
<DerivedUnit
> derivedUnits
= new ArrayList
<DerivedUnit
>();
682 for (DerivationEvent derivationEvent
: specimen
.getDerivationEvents()) {
683 for (DerivedUnit derivative
: derivationEvent
.getDerivatives()) {
684 derivedUnits
.add(derivative
);
685 derivedUnits
.addAll(getDerivedUnitsFor(derivative
));
693 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#pageByAssociatedTaxon(java.lang.Class, java.util.Set, eu.etaxonomy.cdm.model.taxon.Taxon, java.lang.Integer, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
695 @SuppressWarnings("unchecked")
697 public <T
extends SpecimenOrObservationBase
> Pager
<T
> pageByAssociatedTaxon(Class
<T
> type
, Set
<TaxonRelationshipEdge
> includeRelationships
,
698 Taxon associatedTaxon
, Integer maxDepth
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
700 Set
<Taxon
> taxa
= new HashSet
<Taxon
>();
701 Set
<Integer
> occurrenceIds
= new HashSet
<Integer
>();
702 List
<T
> occurrences
= new ArrayList
<T
>();
704 // Integer limit = PagerUtils.limitFor(pageSize);
705 // Integer start = PagerUtils.startFor(pageSize, pageNumber);
707 if (!getSession().contains(associatedTaxon
)) {
708 associatedTaxon
= (Taxon
) taxonService
.load(associatedTaxon
.getUuid());
711 if (includeRelationships
!= null) {
712 taxa
= taxonService
.listRelatedTaxa(associatedTaxon
, includeRelationships
, maxDepth
, null, null, propertyPaths
);
715 taxa
.add(associatedTaxon
);
717 for (Taxon taxon
: taxa
) {
718 List
<T
> perTaxonOccurrences
= dao
.listByAssociatedTaxon(type
, taxon
, null, null, orderHints
, propertyPaths
);
719 for (SpecimenOrObservationBase o
: perTaxonOccurrences
) {
720 occurrenceIds
.add(o
.getId());
723 occurrences
= (List
<T
>) dao
.listByIds(occurrenceIds
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
725 return new DefaultPagerImpl
<T
>(pageNumber
, occurrenceIds
.size(), pageSize
, occurrences
);
730 public <T
extends SpecimenOrObservationBase
> Pager
<T
> pageByAssociatedTaxon(Class
<T
> type
, Set
<TaxonRelationshipEdge
> includeRelationships
,
731 String taxonUUID
, Integer maxDepth
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
733 UUID uuid
= UUID
.fromString(taxonUUID
);
734 Taxon tax
= (Taxon
) taxonService
.load(uuid
);
735 // TODO REMOVE NULL STATEMENT
737 return pageByAssociatedTaxon(type
, includeRelationships
, tax
, maxDepth
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
742 public Pager
<SearchResult
<SpecimenOrObservationBase
>> findByFullText(
743 Class
<?
extends SpecimenOrObservationBase
> clazz
, String queryString
, Rectangle boundingBox
, List
<Language
> languages
,
744 boolean highlightFragments
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
,
745 List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
747 LuceneSearch luceneSearch
= prepareByFullTextSearch(clazz
, queryString
, boundingBox
, languages
, highlightFragments
);
749 // --- execute search
750 TopGroupsWithMaxScore topDocsResultSet
= luceneSearch
.executeSearch(pageSize
, pageNumber
);
752 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
753 idFieldMap
.put(CdmBaseType
.SPECIMEN_OR_OBSERVATIONBASE
, "id");
755 // --- initialize taxa, highlight matches ....
756 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
757 @SuppressWarnings("rawtypes")
758 List
<SearchResult
<SpecimenOrObservationBase
>> searchResults
= searchResultBuilder
.createResultSet(
759 topDocsResultSet
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
761 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupCount
: 0;
763 return new DefaultPagerImpl
<SearchResult
<SpecimenOrObservationBase
>>(pageNumber
, totalHits
, pageSize
,
772 * @param highlightFragments
775 private LuceneSearch
prepareByFullTextSearch(Class
<?
extends SpecimenOrObservationBase
> clazz
, String queryString
, Rectangle bbox
,
776 List
<Language
> languages
, boolean highlightFragments
) {
778 BooleanQuery finalQuery
= new BooleanQuery();
779 BooleanQuery textQuery
= new BooleanQuery();
781 LuceneSearch luceneSearch
= new LuceneSearch(luceneIndexToolProvider
, FieldUnit
.class);
782 QueryFactory queryFactory
= luceneIndexToolProvider
.newQueryFactoryFor(FieldUnit
.class);
785 luceneSearch
.setCdmTypRestriction(clazz
);
786 if (queryString
!= null) {
787 textQuery
.add(queryFactory
.newTermQuery("titleCache", queryString
), Occur
.SHOULD
);
788 finalQuery
.add(textQuery
, Occur
.MUST
);
793 finalQuery
.add(QueryFactory
.buildSpatialQueryByRange(bbox
, "gatheringEvent.exactLocation.point"), Occur
.MUST
);
796 luceneSearch
.setQuery(finalQuery
);
799 SortField
[] sortFields
= new SortField
[] { SortField
.FIELD_SCORE
, new SortField("titleCache__sort", SortField
.STRING
, false) };
800 luceneSearch
.setSortFields(sortFields
);
802 if (highlightFragments
) {
803 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
810 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getFieldUnits(eu.etaxonomy.cdm.model.occurrence.DerivedUnit)
813 public Collection
<FieldUnit
> getFieldUnits(UUID derivedUnitUuid
) {
814 //It will search recursively over all {@link DerivationEvent}s and get the "originals" ({@link SpecimenOrObservationBase})
815 //from which this DerivedUnit was derived until all FieldUnits are found.
817 // FIXME: use HQL queries to increase performance
818 SpecimenOrObservationBase
<?
> specimen
= load(derivedUnitUuid
);
819 // specimen = HibernateProxyHelper.deproxy(specimen, SpecimenOrObservationBase.class);
820 Collection
<FieldUnit
> fieldUnits
= new ArrayList
<FieldUnit
>();
822 if (specimen
.isInstanceOf(FieldUnit
.class)) {
823 fieldUnits
.add(HibernateProxyHelper
.deproxy(specimen
, FieldUnit
.class));
825 else if(specimen
.isInstanceOf(DerivedUnit
.class)){
826 fieldUnits
.addAll(getFieldUnits(HibernateProxyHelper
.deproxy(specimen
, DerivedUnit
.class)));
835 private Collection
<FieldUnit
> getFieldUnits(DerivedUnit derivedUnit
) {
836 Collection
<FieldUnit
> fieldUnits
= new HashSet
<FieldUnit
>();
837 Set
<SpecimenOrObservationBase
> originals
= derivedUnit
.getOriginals();
838 if (originals
!= null && !originals
.isEmpty()) {
839 for (SpecimenOrObservationBase
<?
> original
: originals
) {
840 if (original
.isInstanceOf(FieldUnit
.class)) {
841 fieldUnits
.add(HibernateProxyHelper
.deproxy(original
, FieldUnit
.class));
843 else if(original
.isInstanceOf(DerivedUnit
.class)){
844 fieldUnits
.addAll(getFieldUnits(HibernateProxyHelper
.deproxy(original
, DerivedUnit
.class)));
852 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#moveSequence(eu.etaxonomy.cdm.model.molecular.DnaSample, eu.etaxonomy.cdm.model.molecular.DnaSample, eu.etaxonomy.cdm.model.molecular.Sequence)
855 public boolean moveSequence(DnaSample from
, DnaSample to
, Sequence sequence
) {
856 // reload specimens to avoid session conflicts
857 from
= (DnaSample
) load(from
.getUuid());
858 to
= (DnaSample
) load(to
.getUuid());
859 sequence
= sequenceService
.load(sequence
.getUuid());
861 if (from
== null || to
== null || sequence
== null) {
862 throw new TransientObjectException("One of the CDM entities has not been saved to the data base yet. Moving only works for persisted/saved CDM entities.\n" +
863 "Operation was move "+sequence
+ " from "+from
+" to "+to
);
865 from
.removeSequence(sequence
);
867 to
.addSequence(sequence
);
873 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#moveDerivate(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.occurrence.DerivedUnit)
876 public boolean moveDerivate(SpecimenOrObservationBase
<?
> from
, SpecimenOrObservationBase
<?
> to
, DerivedUnit derivate
) {
877 // reload specimens to avoid session conflicts
878 from
= load(from
.getUuid());
879 to
= load(to
.getUuid());
880 derivate
= (DerivedUnit
) load(derivate
.getUuid());
882 if (from
== null || to
== null || derivate
== null) {
883 throw new TransientObjectException("One of the CDM entities has not been saved to the data base yet. Moving only works for persisted/saved CDM entities.\n" +
884 "Operation was move "+derivate
+ " from "+from
+" to "+to
);
887 SpecimenOrObservationType derivateType
= derivate
.getRecordBasis();
888 SpecimenOrObservationType toType
= to
.getRecordBasis();
889 // check if type is a sub derivate type
890 if(toType
==SpecimenOrObservationType
.FieldUnit
//moving to FieldUnit always works
891 || derivateType
==SpecimenOrObservationType
.Media
//moving media always works
892 || (derivateType
.isKindOf(toType
) && toType
!=derivateType
)){ //moving only to parent derivate type
893 // remove derivation event from parent specimen of dragged object
894 DerivationEvent eventToRemove
= null;
895 for (DerivationEvent event
: from
.getDerivationEvents()) {
896 if (event
.getDerivatives().contains(derivate
)) {
897 eventToRemove
= event
;
901 from
.removeDerivationEvent(eventToRemove
);
903 // add new derivation event to target
904 DerivationEvent derivedFromNewOriginalEvent
= DerivationEvent
.NewSimpleInstance(to
, derivate
, eventToRemove
== null ?
null : eventToRemove
.getType());
905 to
.addDerivationEvent(derivedFromNewOriginalEvent
);
906 derivate
.setDerivedFrom(derivedFromNewOriginalEvent
);
914 public Collection
<ICdmBase
> getNonCascadedAssociatedElements(SpecimenOrObservationBase
<?
> specimen
) {
915 // potential fields that are not persisted cascadingly
928 --CollectingAreas TERM
936 -storedUnder CDM TaxonNameBase
939 Collection
<ICdmBase
> nonCascadedCdmEntities
= new HashSet
<ICdmBase
>();
941 //Choose the correct entry point to traverse the graph (FieldUnit or DerivedUnit)
944 if (specimen
.isInstanceOf(FieldUnit
.class)) {
945 nonCascadedCdmEntities
.addAll(getFieldUnitNonCascadedAssociatedElements(HibernateProxyHelper
.deproxy(specimen
, FieldUnit
.class)));
948 else if (specimen
.isInstanceOf(DerivedUnit
.class)) {
949 DerivedUnit derivedUnit
= HibernateProxyHelper
.deproxy(specimen
, DerivedUnit
.class);
950 if (derivedUnit
.getDerivedFrom() != null) {
951 Collection
<FieldUnit
> fieldUnits
= getFieldUnits(derivedUnit
);
952 for (FieldUnit fieldUnit
: fieldUnits
) {
953 nonCascadedCdmEntities
.addAll(getFieldUnitNonCascadedAssociatedElements(fieldUnit
));
957 return nonCascadedCdmEntities
;
960 private Collection
<ICdmBase
> getFieldUnitNonCascadedAssociatedElements(FieldUnit fieldUnit
) {
961 // get non cascaded element on SpecimenOrObservationBase level
962 Collection
<ICdmBase
> nonCascadedCdmEntities
= getSpecimenOrObservationNonCascadedAssociatedElements(fieldUnit
);
964 // get FieldUnit specific elements
965 GatheringEvent gatheringEvent
= fieldUnit
.getGatheringEvent();
966 if (gatheringEvent
!= null) {
968 if (gatheringEvent
.getCountry() != null) {
969 nonCascadedCdmEntities
.add(gatheringEvent
.getCountry());
972 for (NamedArea namedArea
: gatheringEvent
.getCollectingAreas()) {
973 nonCascadedCdmEntities
.add(namedArea
);
976 for (DerivationEvent derivationEvent
: fieldUnit
.getDerivationEvents()) {
977 for (DerivedUnit derivedUnit
: derivationEvent
.getDerivatives()) {
978 nonCascadedCdmEntities
.addAll(getDerivedUnitNonCascadedAssociatedElements(derivedUnit
));
981 return nonCascadedCdmEntities
;
984 private Collection
<ICdmBase
> getDerivedUnitNonCascadedAssociatedElements(DerivedUnit derivedUnit
) {
985 // get non cascaded element on SpecimenOrObservationBase level
986 Collection
<ICdmBase
> nonCascadedCdmEntities
= getSpecimenOrObservationNonCascadedAssociatedElements(derivedUnit
);
988 // get DerivedUnit specific elements
989 if (derivedUnit
.getCollection() != null && derivedUnit
.getCollection().getInstitute() != null) {
990 for (DefinedTerm type
: derivedUnit
.getCollection().getInstitute().getTypes()) {
991 nonCascadedCdmEntities
.add(type
);
994 if (derivedUnit
.getPreservation() != null && derivedUnit
.getPreservation().getMedium() != null) {
995 nonCascadedCdmEntities
.add(derivedUnit
.getPreservation().getMedium());
997 if (derivedUnit
.getStoredUnder() != null) {
998 nonCascadedCdmEntities
.add(derivedUnit
.getStoredUnder());
1000 return nonCascadedCdmEntities
;
1007 private Collection
<ICdmBase
> getSpecimenOrObservationNonCascadedAssociatedElements(
1008 SpecimenOrObservationBase
<?
> specimen
) {
1009 Collection
<ICdmBase
> nonCascadedCdmEntities
= new HashSet
<ICdmBase
>();
1010 // scan SpecimenOrObservationBase
1011 for (DeterminationEvent determinationEvent
: specimen
.getDeterminations()) {
1013 if (determinationEvent
.getModifier() != null) {
1014 nonCascadedCdmEntities
.add(determinationEvent
.getModifier());
1018 if (specimen
.getKindOfUnit() != null) {
1019 nonCascadedCdmEntities
.add(specimen
.getKindOfUnit());
1022 if (specimen
.getLifeStage() != null) {
1023 nonCascadedCdmEntities
.add(specimen
.getLifeStage());
1026 if (specimen
.getSex() != null) {
1027 nonCascadedCdmEntities
.add(specimen
.getSex());
1029 return nonCascadedCdmEntities
;
1033 * @see eu.etaxonomy.cdm.api.service.VersionableServiceBase#isDeletable(eu.etaxonomy.cdm.model.common.VersionableEntity, eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase)
1036 public DeleteResult
isDeletable(SpecimenOrObservationBase specimen
, DeleteConfiguratorBase config
) {
1037 DeleteResult deleteResult
= new DeleteResult();
1038 SpecimenDeleteConfigurator specimenDeleteConfigurator
= (SpecimenDeleteConfigurator
) config
;
1040 // check elements found by super method
1041 Set
<CdmBase
> relatedObjects
= super.isDeletable(specimen
, config
).getRelatedObjects();
1042 for (CdmBase cdmBase
: relatedObjects
) {
1043 // check for type designation
1044 if (cdmBase
.isInstanceOf(SpecimenTypeDesignation
.class) && !specimenDeleteConfigurator
.isDeleteFromTypeDesignation()) {
1045 deleteResult
.setAbort();
1046 deleteResult
.addException(new ReferencedObjectUndeletableException("Specimen is a type specimen."));
1047 deleteResult
.addRelatedObject(cdmBase
);
1050 // check for IndividualsAssociations
1051 else if (cdmBase
.isInstanceOf(IndividualsAssociation
.class) && !specimenDeleteConfigurator
.isDeleteFromIndividualsAssociation()) {
1052 deleteResult
.setAbort();
1053 deleteResult
.addException(new ReferencedObjectUndeletableException("Specimen is still associated via IndividualsAssociations"));
1054 deleteResult
.addRelatedObject(cdmBase
);
1057 // check for specimen/taxon description
1058 else if((cdmBase
.isInstanceOf(SpecimenDescription
.class) || cdmBase
.isInstanceOf(TaxonDescription
.class))
1059 && !specimenDeleteConfigurator
.isDeleteFromDescription()){
1060 deleteResult
.setAbort();
1061 deleteResult
.addException(new ReferencedObjectUndeletableException("Specimen is still used in a Description."));
1062 deleteResult
.addRelatedObject(cdmBase
);
1065 // check for children and parents (derivation events)
1066 else if (cdmBase
.isInstanceOf(DerivationEvent
.class)) {
1067 DerivationEvent derivationEvent
= HibernateProxyHelper
.deproxy(cdmBase
, DerivationEvent
.class);
1068 // check if derivation event is empty
1069 if (!derivationEvent
.getDerivatives().isEmpty()) {
1070 if (derivationEvent
.getDerivatives().size() == 1 && derivationEvent
.getDerivatives().contains(specimen
)) {
1071 //if it is the parent event with only one derivate then the specimen is still deletable
1074 else if(!specimenDeleteConfigurator
.isDeleteChildren()){
1075 //if not and children should not be deleted then it is undeletable
1076 deleteResult
.setAbort();
1077 deleteResult
.addException(new ReferencedObjectUndeletableException("Derivative still has child derivatives."));
1078 deleteResult
.addRelatedObject(cdmBase
);
1082 // check all children if they can be deleted
1083 Set
<DerivedUnit
> derivatives
= derivationEvent
.getDerivatives();
1084 DeleteResult childResult
= new DeleteResult();
1085 for (DerivedUnit derivedUnit
: derivatives
) {
1086 childResult
.includeResult(isDeletable(derivedUnit
, specimenDeleteConfigurator
));
1088 if (!childResult
.isOk()) {
1089 deleteResult
.setAbort();
1090 deleteResult
.includeResult(childResult
);
1091 deleteResult
.addRelatedObject(cdmBase
);
1097 // check for amplification
1098 else if (cdmBase
.isInstanceOf(AmplificationResult
.class) && !specimenDeleteConfigurator
.isDeleteMolecularData()) {
1099 deleteResult
.setAbort();
1100 deleteResult
.addException(new ReferencedObjectUndeletableException("DnaSample is used in amplification results."));
1101 deleteResult
.addRelatedObject(cdmBase
);
1104 // check for sequence
1105 else if (cdmBase
.isInstanceOf(Sequence
.class) && !specimenDeleteConfigurator
.isDeleteMolecularData()) {
1106 deleteResult
.setAbort();
1107 deleteResult
.addException(new ReferencedObjectUndeletableException("DnaSample is used in sequences."));
1108 deleteResult
.addRelatedObject(cdmBase
);
1112 if (deleteResult
.isOk()) {
1113 //add all related object if deletion is OK so they can be handled by the delete() method
1114 deleteResult
.addRelatedObjects(relatedObjects
);
1116 return deleteResult
;
1120 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#delete(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.api.service.config.SpecimenDeleteConfigurator)
1123 public DeleteResult
delete(SpecimenOrObservationBase
<?
> specimen
, SpecimenDeleteConfigurator config
) {
1124 specimen
= HibernateProxyHelper
.deproxy(specimen
, SpecimenOrObservationBase
.class);
1126 if (config
.isDeleteChildren()) {
1127 Set
<DerivationEvent
> derivationEvents
= specimen
.getDerivationEvents();
1128 for (DerivationEvent derivationEvent
: derivationEvents
) {
1129 Set
<DerivedUnit
> derivatives
= derivationEvent
.getDerivatives();
1130 for (DerivedUnit derivedUnit
: derivatives
) {
1131 delete(derivedUnit
, config
);
1136 DeleteResult deleteResult
= isDeletable(specimen
, config
);
1137 if (!deleteResult
.isOk()) {
1138 return deleteResult
;
1141 // check related objects
1142 Set
<CdmBase
> relatedObjects
= deleteResult
.getRelatedObjects();
1144 for (CdmBase relatedObject
: relatedObjects
) {
1145 // check for TypeDesignations
1146 if (relatedObject
.isInstanceOf(SpecimenTypeDesignation
.class)) {
1147 SpecimenTypeDesignation designation
= HibernateProxyHelper
.deproxy(relatedObject
, SpecimenTypeDesignation
.class);
1148 designation
.setTypeSpecimen(null);
1149 Set
<TaxonNameBase
> typifiedNames
= designation
.getTypifiedNames();
1150 for (TaxonNameBase taxonNameBase
: typifiedNames
) {
1151 taxonNameBase
.removeTypeDesignation(designation
);
1154 // delete IndividualsAssociation
1155 if (relatedObject
.isInstanceOf(IndividualsAssociation
.class)) {
1156 IndividualsAssociation assciation
= HibernateProxyHelper
.deproxy(relatedObject
, IndividualsAssociation
.class);
1157 assciation
.setAssociatedSpecimenOrObservation(null);
1158 assciation
.getInDescription().removeElement(assciation
);
1160 // check for taxon description
1161 if (relatedObject
.isInstanceOf(TaxonDescription
.class)) {
1162 TaxonDescription taxonDescription
= HibernateProxyHelper
.deproxy(relatedObject
, TaxonDescription
.class);
1163 taxonDescription
.setDescribedSpecimenOrObservation(null);
1165 // check for specimen description
1166 if (relatedObject
.isInstanceOf(SpecimenDescription
.class)) {
1167 SpecimenDescription specimenDescription
= HibernateProxyHelper
.deproxy(relatedObject
, SpecimenDescription
.class);
1168 // check if specimen is "described" specimen
1169 if (specimenDescription
.getDescribedSpecimenOrObservation().equals(specimen
)) {
1170 specimenDescription
.setDescribedSpecimenOrObservation(null);
1172 // check if description is a description of the given specimen
1173 if (specimen
.getDescriptions().contains(specimenDescription
)) {
1174 specimen
.removeDescription(specimenDescription
);
1177 // check for amplification
1178 if (relatedObject
.isInstanceOf(AmplificationResult
.class)) {
1179 AmplificationResult amplificationResult
= HibernateProxyHelper
.deproxy(relatedObject
, AmplificationResult
.class);
1180 amplificationResult
.getDnaSample().removeAmplificationResult(amplificationResult
);
1182 // check for sequence
1183 if (relatedObject
.isInstanceOf(Sequence
.class)) {
1184 Sequence sequence
= HibernateProxyHelper
.deproxy(relatedObject
, Sequence
.class);
1185 sequence
.getDnaSample().removeSequence(sequence
);
1187 // check for children and parents (derivation events)
1188 if (relatedObject
.isInstanceOf(DerivationEvent
.class)) {
1189 DerivationEvent derivationEvent
= HibernateProxyHelper
.deproxy(relatedObject
, DerivationEvent
.class);
1190 // parent derivation event (derivedFrom)
1191 if (derivationEvent
.getDerivatives().contains(specimen
) && specimen
.isInstanceOf(DerivedUnit
.class)) {
1192 derivationEvent
.removeDerivative(HibernateProxyHelper
.deproxy(specimen
, DerivedUnit
.class));
1193 if (derivationEvent
.getDerivatives().isEmpty()) {
1194 Set
<SpecimenOrObservationBase
> originals
= derivationEvent
.getOriginals();
1195 for (SpecimenOrObservationBase specimenOrObservationBase
: originals
) {
1196 specimenOrObservationBase
.removeDerivationEvent(derivationEvent
);
1201 //child derivation events should not occur since we delete the hierarchy from bottom to top
1206 deleteResult
.includeResult(delete(specimen
));
1207 return deleteResult
;
1211 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#deleteDerivateHierarchy(eu.etaxonomy.cdm.model.common.ICdmBase)
1214 public DeleteResult
deleteDerivateHierarchy(CdmBase from
, SpecimenDeleteConfigurator config
) {
1215 DeleteResult deleteResult
= new DeleteResult();
1216 if (from
.isInstanceOf(Sequence
.class)) {
1217 if (!config
.isDeleteMolecularData()) {
1218 deleteResult
.setAbort();
1219 deleteResult
.addException(new ReferencedObjectUndeletableException("deleting molecur data is not allowed in config"));
1220 return deleteResult
;
1222 Sequence sequence
= HibernateProxyHelper
.deproxy(from
, Sequence
.class);
1223 sequence
.getDnaSample().removeSequence(sequence
);
1224 deleteResult
= sequenceService
.delete(sequence
);
1226 else if(from
.isInstanceOf(SingleRead
.class)) {
1227 if (!config
.isDeleteMolecularData()) {
1228 deleteResult
.setAbort();
1229 deleteResult
.addException(new ReferencedObjectUndeletableException("deleting molecur data is not allowed in config"));
1230 return deleteResult
;
1232 SingleRead singleRead
= HibernateProxyHelper
.deproxy(from
, SingleRead
.class);
1233 singleRead
.getAmplificationResult().removeSingleRead(singleRead
);
1234 deleteResult
.setStatus(Status
.OK
);
1236 else if(from
.isInstanceOf(SpecimenOrObservationBase
.class)) {
1237 deleteResult
= delete(HibernateProxyHelper
.deproxy(from
, SpecimenOrObservationBase
.class), config
);
1239 return deleteResult
;
1242 // private DeleteResult deepDelete(SpecimenOrObservationBase<?> entity, SpecimenDeleteConfigurator config){
1243 // Set<DerivationEvent> derivationEvents = entity.getDerivationEvents();
1244 // for (DerivationEvent derivationEvent : derivationEvents) {
1245 // Set<DerivedUnit> derivatives = derivationEvent.getDerivatives();
1246 // for (DerivedUnit derivedUnit : derivatives) {
1247 // DeleteResult deleteResult = deepDelete(derivedUnit, config);
1248 // if(!deleteResult.isOk()){
1249 // return deleteResult;
1253 // return delete(entity, config);
1257 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listAssociatedTaxa(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)
1260 public Collection
<IndividualsAssociation
> listIndividualsAssociations(SpecimenOrObservationBase
<?
> specimen
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
1261 return dao
.listIndividualsAssociations(specimen
, null, null, null, null);
1265 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listTypeDesignations(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
1268 public Collection
<SpecimenTypeDesignation
> listTypeDesignations(SpecimenOrObservationBase
<?
> specimen
,
1269 Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
1270 return dao
.listTypeDesignations(specimen
, limit
, start
, orderHints
, propertyPaths
);
1274 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listDescriptionsWithDescriptionSpecimen(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
1277 public Collection
<DescriptionBase
<?
>> listDescriptionsWithDescriptionSpecimen(
1278 SpecimenOrObservationBase
<?
> specimen
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
,
1279 List
<String
> propertyPaths
) {
1280 return dao
.listDescriptionsWithDescriptionSpecimen(specimen
, limit
, start
, orderHints
, propertyPaths
);
1284 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getStatesForSpecimen(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)
1287 public Collection
<DescriptionElementBase
> getCharacterDataForSpecimen(SpecimenOrObservationBase
<?
> specimen
) {
1288 Collection
<DescriptionElementBase
> states
= new ArrayList
<DescriptionElementBase
>();
1289 if (specimen
!= null) {
1290 Set
<DescriptionBase
> descriptions
= specimen
.getDescriptions();
1291 for (DescriptionBase
<?
> descriptionBase
: descriptions
) {
1292 if (descriptionBase
.isInstanceOf(SpecimenDescription
.class)) {
1293 SpecimenDescription specimenDescription
= HibernateProxyHelper
.deproxy(descriptionBase
, SpecimenDescription
.class);
1294 Set
<DescriptionElementBase
> elements
= specimenDescription
.getElements();
1295 for (DescriptionElementBase descriptionElementBase
: elements
) {
1296 if(descriptionElementBase
.getFeature().isSupportsCategoricalData()
1297 ||descriptionElementBase
.getFeature().isSupportsQuantitativeData()){
1298 states
.add(descriptionElementBase
);
1308 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getStatesForSpecimen(java.util.UUID)
1311 public Collection
<DescriptionElementBase
> getCharacterDataForSpecimen(UUID specimenUuid
) {
1312 SpecimenOrObservationBase
<?
> specimen
= load(specimenUuid
);
1313 if (specimen
!= null) {
1314 return getCharacterDataForSpecimen(specimen
);
1317 throw new DataRetrievalFailureException("Specimen with the given uuid not found in the data base");
1323 * @see eu.etaxonomy.cdm.api.service.IdentifiableServiceBase#findByTitle(eu.etaxonomy.cdm.api.service.config.IIdentifiableEntityServiceConfigurator)
1326 public Pager
<SpecimenOrObservationBase
> findByTitle(
1327 IIdentifiableEntityServiceConfigurator
<SpecimenOrObservationBase
> config
) {
1328 if (config
instanceof FindOccurrencesConfigurator
) {
1329 FindOccurrencesConfigurator occurrenceConfig
= (FindOccurrencesConfigurator
) config
;
1330 List
<SpecimenOrObservationBase
> occurrences
= new ArrayList
<SpecimenOrObservationBase
>();
1332 if(occurrenceConfig
.getAssociatedTaxonUuid()!=null){
1333 TaxonBase taxonBase
= taxonService
.load(occurrenceConfig
.getAssociatedTaxonUuid());
1334 if(taxonBase
.isInstanceOf(Taxon
.class)){
1335 taxon
= HibernateProxyHelper
.deproxy(taxonBase
, Taxon
.class);
1338 occurrences
.addAll(dao
.findOccurrences(occurrenceConfig
.getClazz(), occurrenceConfig
.getTitleSearchString(), occurrenceConfig
.getSpecimenType(),
1339 taxon
, occurrenceConfig
.getMatchMode(), null, null, occurrenceConfig
.getOrderHints(), occurrenceConfig
.getPropertyPaths()));
1340 return new DefaultPagerImpl
<SpecimenOrObservationBase
>(config
.getPageNumber(), occurrences
.size(), config
.getPageSize(), occurrences
);
1342 return super.findByTitle(config
);
1346 public int countOccurrences(IIdentifiableEntityServiceConfigurator
<SpecimenOrObservationBase
> config
){
1347 if (config
instanceof FindOccurrencesConfigurator
) {
1348 FindOccurrencesConfigurator occurrenceConfig
= (FindOccurrencesConfigurator
) config
;
1350 if(occurrenceConfig
.getAssociatedTaxonUuid()!=null){
1351 TaxonBase taxonBase
= taxonService
.load(occurrenceConfig
.getAssociatedTaxonUuid());
1352 if(taxonBase
.isInstanceOf(Taxon
.class)){
1353 taxon
= HibernateProxyHelper
.deproxy(taxonBase
, Taxon
.class);
1356 return dao
.countOccurrences(occurrenceConfig
.getClazz(), occurrenceConfig
.getTitleSearchString(), occurrenceConfig
.getSpecimenType(),
1357 taxon
, occurrenceConfig
.getMatchMode(), null, null, occurrenceConfig
.getOrderHints(), occurrenceConfig
.getPropertyPaths());
1359 return super.countByTitle(config
);