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
.SpecimenDeleteConfigurator
;
48 import eu
.etaxonomy
.cdm
.api
.service
.dto
.DerivateDTO
;
49 import eu
.etaxonomy
.cdm
.api
.service
.dto
.DerivateDataDTO
;
50 import eu
.etaxonomy
.cdm
.api
.service
.dto
.DerivateDataDTO
.ContigFile
;
51 import eu
.etaxonomy
.cdm
.api
.service
.dto
.DerivateDataDTO
.MolecularData
;
52 import eu
.etaxonomy
.cdm
.api
.service
.dto
.FieldUnitDTO
;
53 import eu
.etaxonomy
.cdm
.api
.service
.dto
.PreservedSpecimenDTO
;
54 import eu
.etaxonomy
.cdm
.api
.service
.exception
.ReferencedObjectUndeletableException
;
55 import eu
.etaxonomy
.cdm
.api
.service
.molecular
.ISequenceService
;
56 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
57 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
58 import eu
.etaxonomy
.cdm
.api
.service
.search
.ILuceneIndexToolProvider
;
59 import eu
.etaxonomy
.cdm
.api
.service
.search
.ISearchResultBuilder
;
60 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneSearch
;
61 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneSearch
.TopGroupsWithMaxScore
;
62 import eu
.etaxonomy
.cdm
.api
.service
.search
.QueryFactory
;
63 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResult
;
64 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResultBuilder
;
65 import eu
.etaxonomy
.cdm
.api
.service
.util
.TaxonRelationshipEdge
;
66 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
67 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
68 import eu
.etaxonomy
.cdm
.model
.CdmBaseType
;
69 import eu
.etaxonomy
.cdm
.model
.agent
.AgentBase
;
70 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
71 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTerm
;
72 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTermBase
;
73 import eu
.etaxonomy
.cdm
.model
.common
.ICdmBase
;
74 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
75 import eu
.etaxonomy
.cdm
.model
.common
.UuidAndTitleCache
;
76 import eu
.etaxonomy
.cdm
.model
.description
.CategoricalData
;
77 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
78 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
79 import eu
.etaxonomy
.cdm
.model
.description
.IndividualsAssociation
;
80 import eu
.etaxonomy
.cdm
.model
.description
.QuantitativeData
;
81 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
82 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
83 import eu
.etaxonomy
.cdm
.model
.location
.Country
;
84 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
85 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
86 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
87 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentationPart
;
88 import eu
.etaxonomy
.cdm
.model
.media
.MediaUtils
;
89 import eu
.etaxonomy
.cdm
.model
.molecular
.AmplificationResult
;
90 import eu
.etaxonomy
.cdm
.model
.molecular
.DnaSample
;
91 import eu
.etaxonomy
.cdm
.model
.molecular
.Sequence
;
92 import eu
.etaxonomy
.cdm
.model
.molecular
.SingleRead
;
93 import eu
.etaxonomy
.cdm
.model
.name
.SpecimenTypeDesignation
;
94 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
95 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationStatusBase
;
96 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivationEvent
;
97 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnit
;
98 import eu
.etaxonomy
.cdm
.model
.occurrence
.DeterminationEvent
;
99 import eu
.etaxonomy
.cdm
.model
.occurrence
.FieldUnit
;
100 import eu
.etaxonomy
.cdm
.model
.occurrence
.GatheringEvent
;
101 import eu
.etaxonomy
.cdm
.model
.occurrence
.MediaSpecimen
;
102 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
103 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationType
;
104 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
105 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
106 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IDefinedTermDao
;
107 import eu
.etaxonomy
.cdm
.persistence
.dao
.initializer
.AbstractBeanInitializer
;
108 import eu
.etaxonomy
.cdm
.persistence
.dao
.occurrence
.IOccurrenceDao
;
109 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
110 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
113 * @author a.babadshanjan
114 * @created 01.09.2008
117 @Transactional(readOnly
= true)
118 public class OccurrenceServiceImpl
extends IdentifiableServiceBase
<SpecimenOrObservationBase
,IOccurrenceDao
> implements IOccurrenceService
{
120 static private final Logger logger
= Logger
.getLogger(OccurrenceServiceImpl
.class);
123 private IDefinedTermDao definedTermDao
;
126 private IDescriptionService descriptionService
;
129 private ITaxonService taxonService
;
132 private ISequenceService sequenceService
;
135 private AbstractBeanInitializer beanInitializer
;
138 private ILuceneIndexToolProvider luceneIndexToolProvider
;
140 public OccurrenceServiceImpl() {
141 logger
.debug("Load OccurrenceService Bean");
146 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
149 @Transactional(readOnly
= false)
150 public void updateTitleCache(Class
<?
extends SpecimenOrObservationBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<SpecimenOrObservationBase
> cacheStrategy
, IProgressMonitor monitor
) {
152 clazz
= SpecimenOrObservationBase
.class;
154 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
159 * FIXME Candidate for harmonization
160 * move to termService
163 public Country
getCountryByIso(String iso639
) {
164 return this.definedTermDao
.getCountryByIso(iso639
);
169 * FIXME Candidate for harmonization
170 * move to termService
173 public List
<Country
> getCountryByName(String name
) {
174 List
<?
extends DefinedTermBase
> terms
= this.definedTermDao
.findByTitle(Country
.class, name
, null, null, null, null, null, null) ;
175 List
<Country
> countries
= new ArrayList
<Country
>();
176 for (int i
=0;i
<terms
.size();i
++){
177 countries
.add((Country
)terms
.get(i
));
184 protected void setDao(IOccurrenceDao dao
) {
189 public Pager
<DerivationEvent
> getDerivationEvents(SpecimenOrObservationBase occurence
, Integer pageSize
,Integer pageNumber
, List
<String
> propertyPaths
) {
190 Integer numberOfResults
= dao
.countDerivationEvents(occurence
);
192 List
<DerivationEvent
> results
= new ArrayList
<DerivationEvent
>();
193 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
194 results
= dao
.getDerivationEvents(occurence
, pageSize
, pageNumber
,propertyPaths
);
197 return new DefaultPagerImpl
<DerivationEvent
>(pageNumber
, numberOfResults
, pageSize
, results
);
201 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#countDeterminations(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.taxon.TaxonBase)
204 public int countDeterminations(SpecimenOrObservationBase occurence
, TaxonBase taxonbase
) {
205 return dao
.countDeterminations(occurence
, taxonbase
);
209 public Pager
<DeterminationEvent
> getDeterminations(SpecimenOrObservationBase occurrence
, TaxonBase taxonBase
, Integer pageSize
,Integer pageNumber
, List
<String
> propertyPaths
) {
210 Integer numberOfResults
= dao
.countDeterminations(occurrence
, taxonBase
);
212 List
<DeterminationEvent
> results
= new ArrayList
<DeterminationEvent
>();
213 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
214 results
= dao
.getDeterminations(occurrence
,taxonBase
, pageSize
, pageNumber
, propertyPaths
);
217 return new DefaultPagerImpl
<DeterminationEvent
>(pageNumber
, numberOfResults
, pageSize
, results
);
221 public Pager
<Media
> getMedia(SpecimenOrObservationBase occurence
,Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
222 Integer numberOfResults
= dao
.countMedia(occurence
);
224 List
<Media
> results
= new ArrayList
<Media
>();
225 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
226 results
= dao
.getMedia(occurence
, pageSize
, pageNumber
, propertyPaths
);
229 return new DefaultPagerImpl
<Media
>(pageNumber
, numberOfResults
, pageSize
, results
);
233 * @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)
236 public Pager
<SpecimenOrObservationBase
> list(Class
<?
extends SpecimenOrObservationBase
> type
, TaxonBase determinedAs
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
237 Integer numberOfResults
= dao
.count(type
,determinedAs
);
238 List
<SpecimenOrObservationBase
> results
= new ArrayList
<SpecimenOrObservationBase
>();
239 pageNumber
= pageNumber
== null ?
0 : pageNumber
;
240 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
241 Integer start
= pageSize
== null ?
0 : pageSize
* pageNumber
;
242 results
= dao
.list(type
,determinedAs
, pageSize
, start
, orderHints
,propertyPaths
);
244 return new DefaultPagerImpl
<SpecimenOrObservationBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
248 public List
<UuidAndTitleCache
<DerivedUnit
>> getDerivedUnitUuidAndTitleCache() {
249 return dao
.getDerivedUnitUuidAndTitleCache();
253 public List
<UuidAndTitleCache
<FieldUnit
>> getFieldUnitUuidAndTitleCache() {
254 return dao
.getFieldUnitUuidAndTitleCache();
258 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getDerivedUnitFacade(eu.etaxonomy.cdm.model.occurrence.DerivedUnit)
261 public DerivedUnitFacade
getDerivedUnitFacade(DerivedUnit derivedUnit
, List
<String
> propertyPaths
) throws DerivedUnitFacadeNotSupportedException
{
262 derivedUnit
= (DerivedUnit
)dao
.load(derivedUnit
.getUuid(), null);
263 DerivedUnitFacadeConfigurator config
= DerivedUnitFacadeConfigurator
.NewInstance();
264 config
.setThrowExceptionForNonSpecimenPreservationMethodRequest(false);
265 DerivedUnitFacade derivedUnitFacade
= DerivedUnitFacade
.NewInstance(derivedUnit
, config
);
266 beanInitializer
.initialize(derivedUnitFacade
, propertyPaths
);
267 return derivedUnitFacade
;
271 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listDerivedUnitFacades(eu.etaxonomy.cdm.model.description.DescriptionBase, java.util.List)
274 public List
<DerivedUnitFacade
> listDerivedUnitFacades(
275 DescriptionBase description
, List
<String
> propertyPaths
) {
277 List
<DerivedUnitFacade
> derivedUnitFacadeList
= new ArrayList
<DerivedUnitFacade
>();
278 IndividualsAssociation tempIndividualsAssociation
;
279 SpecimenOrObservationBase tempSpecimenOrObservationBase
;
280 List
<DescriptionElementBase
> elements
= descriptionService
.listDescriptionElements(description
, null, IndividualsAssociation
.class, null, 0, Arrays
.asList(new String
[]{"associatedSpecimenOrObservation"}));
281 for(DescriptionElementBase element
: elements
){
282 if(element
.isInstanceOf(IndividualsAssociation
.class)){
283 tempIndividualsAssociation
= HibernateProxyHelper
.deproxy(element
, IndividualsAssociation
.class);
284 if(tempIndividualsAssociation
.getAssociatedSpecimenOrObservation() != null){
285 tempSpecimenOrObservationBase
= HibernateProxyHelper
.deproxy(tempIndividualsAssociation
.getAssociatedSpecimenOrObservation(), SpecimenOrObservationBase
.class);
286 if(tempSpecimenOrObservationBase
.isInstanceOf(DerivedUnit
.class)){
288 derivedUnitFacadeList
.add(DerivedUnitFacade
.NewInstance(HibernateProxyHelper
.deproxy(tempSpecimenOrObservationBase
, DerivedUnit
.class)));
289 } catch (DerivedUnitFacadeNotSupportedException e
) {
290 logger
.warn(tempIndividualsAssociation
.getAssociatedSpecimenOrObservation().getTitleCache() + " : " +e
.getMessage());
298 beanInitializer
.initializeAll(derivedUnitFacadeList
, propertyPaths
);
300 return derivedUnitFacadeList
;
305 * @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)
308 public <T
extends SpecimenOrObservationBase
> List
<T
> listByAssociatedTaxon(Class
<T
> type
, Set
<TaxonRelationshipEdge
> includeRelationships
,
309 Taxon associatedTaxon
, Integer maxDepth
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
311 return pageByAssociatedTaxon(type
, includeRelationships
, associatedTaxon
, maxDepth
, pageSize
, pageNumber
, orderHints
, propertyPaths
).getRecords();
315 * @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)
318 public Collection
<SpecimenOrObservationBase
> listFieldUnitsByAssociatedTaxon(Taxon associatedTaxon
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
319 return pageFieldUnitsByAssociatedTaxon(null, associatedTaxon
, null, null, null, null, propertyPaths
).getRecords();
323 * @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)
326 public Pager
<SpecimenOrObservationBase
> pageFieldUnitsByAssociatedTaxon(Set
<TaxonRelationshipEdge
> includeRelationships
,
327 Taxon associatedTaxon
, Integer maxDepth
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
,
328 List
<String
> propertyPaths
) {
330 if(!getSession().contains(associatedTaxon
)){
331 associatedTaxon
= (Taxon
) taxonService
.load(associatedTaxon
.getUuid());
334 //gather the IDs of all relevant field units
335 Set
<Integer
> fieldUnitIds
= new HashSet
<Integer
>();
336 List
<SpecimenOrObservationBase
> records
= listByAssociatedTaxon(null, includeRelationships
, associatedTaxon
, maxDepth
, null, null, orderHints
, propertyPaths
);
337 for(SpecimenOrObservationBase
<?
> specimen
:records
){
338 for (FieldUnit fieldUnit
: getFieldUnits(specimen
.getUuid())) {
339 fieldUnitIds
.add(fieldUnit
.getId());
342 //dao.listByIds() does the paging of the field units. Passing the field units directly to the Pager would not work
343 List
<SpecimenOrObservationBase
> fieldUnits
= dao
.listByIds(fieldUnitIds
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
344 return new DefaultPagerImpl
<SpecimenOrObservationBase
>(pageNumber
, fieldUnitIds
.size(), pageSize
, fieldUnits
);
348 public FieldUnitDTO
assembleFieldUnitDTO(FieldUnit fieldUnit
, UUID associatedTaxonUuid
){
350 if(!getSession().contains(fieldUnit
)){
351 fieldUnit
= (FieldUnit
) load(fieldUnit
.getUuid());
353 TaxonBase associatedTaxon
= taxonService
.load(associatedTaxonUuid
);
355 FieldUnitDTO fieldUnitDTO
= new FieldUnitDTO();
357 if(fieldUnit
.getGatheringEvent()!=null){
358 GatheringEvent gatheringEvent
= fieldUnit
.getGatheringEvent();
360 NamedArea country
= gatheringEvent
.getCountry();
361 fieldUnitDTO
.setCountry(country
!=null?country
.getDescription():null);
363 AgentBase collector
= gatheringEvent
.getCollector();
364 String fieldNumber
= fieldUnit
.getFieldNumber();
365 String collectionString
= "";
366 if(collector
!=null || fieldNumber
!=null){
367 collectionString
+= collector
!=null?collector
:"";
368 if(!collectionString
.isEmpty()){
369 collectionString
+= " ";
371 collectionString
+= (fieldNumber
!=null?fieldNumber
:"");
372 collectionString
.trim();
374 fieldUnitDTO
.setCollection(collectionString
);
376 Partial gatheringDate
= gatheringEvent
.getGatheringDate();
377 fieldUnitDTO
.setDate(gatheringDate
!=null?gatheringDate
.toString():null);
381 fieldUnitDTO
.setTaxonName(associatedTaxon
.getName().getFullTitleCache());
384 Map
<eu
.etaxonomy
.cdm
.model
.occurrence
.Collection
, Integer
> collectionToCountMap
= new HashMap
<eu
.etaxonomy
.cdm
.model
.occurrence
.Collection
, Integer
>();
385 //List of accession numbers for citation
386 List
<String
> preservedSpecimenAccessionNumbers
= new ArrayList
<String
>();
388 //assemble preserved specimen DTOs
389 Set
<DerivationEvent
> derivationEvents
= fieldUnit
.getDerivationEvents();
390 for (DerivationEvent derivationEvent
: derivationEvents
) {
391 Set
<DerivedUnit
> derivatives
= derivationEvent
.getDerivatives();
392 for (DerivedUnit derivedUnit
: derivatives
) {
393 //collect accession numbers for citation
394 if(derivedUnit
.getAccessionNumber()!=null){
395 preservedSpecimenAccessionNumbers
.add(derivedUnit
.getAccessionNumber());
397 //collect collections for herbaria column
398 if(derivedUnit
.getCollection()!=null){
399 Integer herbariumCount
= collectionToCountMap
.get(derivedUnit
.getCollection());
400 if(herbariumCount
==null){
403 collectionToCountMap
.put(derivedUnit
.getCollection(), herbariumCount
+1);
405 if(derivedUnit
.getRecordBasis().equals(SpecimenOrObservationType
.PreservedSpecimen
)){
406 PreservedSpecimenDTO preservedSpecimenDTO
= assemblePreservedSpecimenDTO(derivedUnit
, fieldUnitDTO
);
407 fieldUnitDTO
.addPreservedSpecimenDTO(preservedSpecimenDTO
);
408 fieldUnitDTO
.setHasCharacterData(preservedSpecimenDTO
.isHasCharacterData());
409 fieldUnitDTO
.setHasDetailImage(preservedSpecimenDTO
.isHasDetailImage());
410 fieldUnitDTO
.setHasDna(preservedSpecimenDTO
.isHasDna());
411 fieldUnitDTO
.setHasSpecimenScan(preservedSpecimenDTO
.isHasSpecimenScan());
415 //assemble derivate data DTO
416 assembleDerivateDataDTO(fieldUnitDTO
, fieldUnit
);
418 final String separator
= ", ";
420 String citation
= "";
421 citation
+= fieldUnitDTO
.getCountry()!=null?fieldUnitDTO
.getCountry()+separator
:"";
422 if(fieldUnit
.getGatheringEvent()!=null){
423 if(fieldUnit
.getGatheringEvent().getLocality()!=null){
424 citation
+= fieldUnit
.getGatheringEvent().getLocality().getText();
425 citation
+= separator
;
427 if(fieldUnit
.getGatheringEvent().getExactLocation()!=null
428 && fieldUnit
.getGatheringEvent().getExactLocation().getLatitude()!=null
429 && fieldUnit
.getGatheringEvent().getExactLocation().getLongitude()!=null){
430 citation
+= fieldUnit
.getGatheringEvent().getExactLocation().getLatitude().toString();
431 citation
+= separator
;
432 citation
+= fieldUnit
.getGatheringEvent().getExactLocation().getLongitude().toString();
433 citation
+= separator
;
436 citation
+= fieldUnitDTO
.getCollection()!=null?fieldUnitDTO
.getCollection():"";
437 if(!preservedSpecimenAccessionNumbers
.isEmpty()){
439 for(String accessionNumber
:preservedSpecimenAccessionNumbers
){
440 if(!accessionNumber
.isEmpty()){
441 citation
+= accessionNumber
+separator
;
444 citation
= removeTail(citation
, separator
);
447 citation
= removeTail(citation
, separator
);
448 fieldUnitDTO
.setCitation(citation
);
450 //assemble herbaria string
451 String herbariaString
= "";
452 for(Entry
<eu
.etaxonomy
.cdm
.model
.occurrence
.Collection
, Integer
> e
:collectionToCountMap
.entrySet()){
453 eu
.etaxonomy
.cdm
.model
.occurrence
.Collection collection
= e
.getKey();
454 if(collection
.getCode()!=null){
455 herbariaString
+= collection
.getCode();
458 herbariaString
+= "("+e
.getValue()+")";
460 herbariaString
+= separator
;
462 herbariaString
= removeTail(herbariaString
, separator
);
463 fieldUnitDTO
.setHerbarium(herbariaString
);
470 public PreservedSpecimenDTO
assemblePreservedSpecimenDTO(DerivedUnit derivedUnit
){
471 return assemblePreservedSpecimenDTO(derivedUnit
, null);
474 public PreservedSpecimenDTO
assemblePreservedSpecimenDTO(DerivedUnit derivedUnit
, FieldUnitDTO hierarchyDTO
){
475 if(!getSession().contains(derivedUnit
)){
476 derivedUnit
= (DerivedUnit
) load(derivedUnit
.getUuid());
478 PreservedSpecimenDTO preservedSpecimenDTO
= new PreservedSpecimenDTO();
479 preservedSpecimenDTO
.setAccessionNumber(derivedUnit
.getAccessionNumber());
480 preservedSpecimenDTO
.setUuid(derivedUnit
.getUuid().toString());
482 //character state data
483 Collection
<DescriptionElementBase
> characterDataForSpecimen
= getCharacterDataForSpecimen(derivedUnit
);
484 if(!characterDataForSpecimen
.isEmpty()){
485 if(hierarchyDTO
!=null){
486 hierarchyDTO
.setHasCharacterData(true);
489 for (DescriptionElementBase descriptionElementBase
: characterDataForSpecimen
) {
490 String character
= descriptionElementBase
.getFeature().getLabel();
491 ArrayList
<Language
> languages
= new ArrayList
<Language
>(Collections
.singleton(Language
.DEFAULT()));
492 if(descriptionElementBase
instanceof QuantitativeData
){
493 QuantitativeData quantitativeData
= (QuantitativeData
)descriptionElementBase
;
494 DefaultQuantitativeDescriptionBuilder builder
= new DefaultQuantitativeDescriptionBuilder();
495 String state
= builder
.build(quantitativeData
, languages
).getText(Language
.DEFAULT());
496 preservedSpecimenDTO
.addCharacterData(character
, state
);
498 else if(descriptionElementBase
instanceof CategoricalData
){
499 CategoricalData categoricalData
= (CategoricalData
)descriptionElementBase
;
500 DefaultCategoricalDescriptionBuilder builder
= new DefaultCategoricalDescriptionBuilder();
501 String state
= builder
.build(categoricalData
, languages
).getText(Language
.DEFAULT());
502 preservedSpecimenDTO
.addCharacterData(character
, state
);
505 //check if derived unit is a type
506 Collection
<SpecimenTypeDesignation
> specimenTypeDesignations
= listTypeDesignations(derivedUnit
, null, null, null, null);
507 for (SpecimenTypeDesignation specimenTypeDesignation
: specimenTypeDesignations
) {
508 if(hierarchyDTO
!=null){
509 hierarchyDTO
.setHasType(true);
511 TypeDesignationStatusBase
<?
> typeStatus
= specimenTypeDesignation
.getTypeStatus();
512 if(typeStatus
!=null){
513 preservedSpecimenDTO
.addType(typeStatus
.getLabel());
516 //assemble sub derivates
517 preservedSpecimenDTO
.setDerivateDataDTO(assembleDerivateDataDTO(preservedSpecimenDTO
, derivedUnit
));
518 return preservedSpecimenDTO
;
523 * @param derivateDataDTO
526 private DerivateDataDTO
assembleDerivateDataDTO(DerivateDTO derivateDTO
, SpecimenOrObservationBase
<?
> specimenOrObservation
) {
527 DerivateDataDTO derivateDataDTO
= new DerivateDataDTO();
528 Collection
<DerivedUnit
> childDerivates
= getDerivedUnitsFor(specimenOrObservation
);
529 for (DerivedUnit childDerivate
: childDerivates
) {
530 //current accession number
531 String currentAccessionNumber
= childDerivate
.getAccessionNumber()!=null?childDerivate
.getAccessionNumber():"";
533 String currentHerbarium
= "";
534 eu
.etaxonomy
.cdm
.model
.occurrence
.Collection collection
= childDerivate
.getCollection();
535 if(collection
!=null){
536 currentHerbarium
= collection
.getCode()!=null?collection
.getCode():"";
538 //assemble molecular data
539 //pattern: DNAMarker [contig1, primer1_1, primer1_2, ...][contig2, primer2_1, ...]...
540 if(childDerivate
.isInstanceOf(DnaSample
.class)){
541 if(childDerivate
.getRecordBasis()==SpecimenOrObservationType
.TissueSample
){
542 //TODO implement TissueSample assembly for web service
544 if(childDerivate
.getRecordBasis()==SpecimenOrObservationType
.DnaSample
){
546 DnaSample dna
= HibernateProxyHelper
.deproxy(childDerivate
, DnaSample
.class);
547 if(!dna
.getSequences().isEmpty()){
548 derivateDTO
.setHasDna(true);
550 for(Sequence sequence
:dna
.getSequences()){
553 boldUri
= sequence
.getBoldUri();
554 } catch (URISyntaxException e1
) {
555 logger
.error("Could not create BOLD URI", e1
);
557 final DefinedTerm dnaMarker
= sequence
.getDnaMarker();
558 MolecularData molecularData
= derivateDataDTO
.addProviderLink(boldUri
!=null?boldUri
:null,dnaMarker
!=null?dnaMarker
.getLabel():"[no marker]");
560 //contig file FIXME show primer although contig not present?
561 if(sequence
.getContigFile()!=null){
562 MediaRepresentationPart contigMediaRepresentationPart
= MediaUtils
.getFirstMediaRepresentationPart(sequence
.getContigFile());
563 if(contigMediaRepresentationPart
!=null){
564 ContigFile contigFile
= molecularData
.addContigFile(contigMediaRepresentationPart
.getUri(), "contig");
566 if(sequence
.getSingleReads()!=null){
567 for (SingleRead singleRead
: sequence
.getSingleReads()) {
568 MediaRepresentationPart pherogramMediaRepresentationPart
= MediaUtils
.getFirstMediaRepresentationPart(singleRead
.getPherogram());
569 if(pherogramMediaRepresentationPart
!=null){
570 contigFile
.addPrimerLink(pherogramMediaRepresentationPart
.getUri(), "primer");
579 //assemble media data
580 else if(childDerivate
.isInstanceOf(MediaSpecimen
.class)){
582 MediaSpecimen media
= HibernateProxyHelper
.deproxy(childDerivate
, MediaSpecimen
.class);
583 String mediaUriString
= getMediaUriString(media
);
584 if(media
.getKindOfUnit()!=null){
586 if(media
.getKindOfUnit().getUuid().equals(UUID
.fromString("acda15be-c0e2-4ea8-8783-b9b0c4ad7f03"))){
587 derivateDTO
.setHasSpecimenScan(true);
588 final String imageLinkText
= currentHerbarium
+" "+currentAccessionNumber
;
589 derivateDataDTO
.addSpecimenScan(mediaUriString
==null?
"":mediaUriString
, !imageLinkText
.equals(" ")?imageLinkText
:"[no accession]");
592 else if(media
.getKindOfUnit().getUuid().equals(UUID
.fromString("31eb8d02-bf5d-437c-bcc6-87a626445f34"))){
593 derivateDTO
.setHasDetailImage(true);
595 if(media
.getMediaSpecimen()!=null && media
.getMediaSpecimen().getTitle()!=null){
596 motif
= media
.getMediaSpecimen().getTitle().getText();
598 derivateDataDTO
.addDetailImage(mediaUriString
==null?
"":mediaUriString
, motif
!=null?motif
:"[no motif]");
603 return derivateDataDTO
;
612 private String
removeTail(String string
, final String tail
) {
613 if(string
.endsWith(tail
)){
614 string
= string
.substring(0, string
.length()-tail
.length());
619 private String
getMediaUriString(MediaSpecimen mediaSpecimen
){
620 String mediaUri
= null;
621 Collection
<MediaRepresentation
> mediaRepresentations
= mediaSpecimen
.getMediaSpecimen().getRepresentations();
622 if(mediaRepresentations
!=null && !mediaRepresentations
.isEmpty()){
623 Collection
<MediaRepresentationPart
> mediaRepresentationParts
= mediaRepresentations
.iterator().next().getParts();
624 if(mediaRepresentationParts
!=null && !mediaRepresentationParts
.isEmpty()){
625 MediaRepresentationPart part
= mediaRepresentationParts
.iterator().next();
626 if(part
.getUri()!=null){
627 mediaUri
= part
.getUri().toASCIIString();
634 private Collection
<DerivedUnit
> getDerivedUnitsFor(SpecimenOrObservationBase
<?
> specimen
){
635 Collection
<DerivedUnit
> derivedUnits
= new ArrayList
<DerivedUnit
>();
636 for(DerivationEvent derivationEvent
:specimen
.getDerivationEvents()){
637 for(DerivedUnit derivative
:derivationEvent
.getDerivatives()){
638 derivedUnits
.add(derivative
);
639 derivedUnits
.addAll(getDerivedUnitsFor(derivative
));
647 * @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)
649 @SuppressWarnings("unchecked")
651 public <T
extends SpecimenOrObservationBase
> Pager
<T
> pageByAssociatedTaxon(Class
<T
> type
, Set
<TaxonRelationshipEdge
> includeRelationships
,
652 Taxon associatedTaxon
, Integer maxDepth
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
654 Set
<Taxon
> taxa
= new HashSet
<Taxon
>();
655 Set
<Integer
> occurrenceIds
= new HashSet
<Integer
>();
656 List
<T
> occurrences
= new ArrayList
<T
>();
658 // Integer limit = PagerUtils.limitFor(pageSize);
659 // Integer start = PagerUtils.startFor(pageSize, pageNumber);
661 if(!getSession().contains(associatedTaxon
)){
662 associatedTaxon
= (Taxon
) taxonService
.load(associatedTaxon
.getUuid());
665 if(includeRelationships
!= null) {
666 taxa
= taxonService
.listRelatedTaxa(associatedTaxon
, includeRelationships
, maxDepth
, null, null, propertyPaths
);
669 taxa
.add(associatedTaxon
);
671 for (Taxon taxon
: taxa
) {
672 List
<T
> perTaxonOccurrences
= dao
.listByAssociatedTaxon(type
, taxon
, null, null, orderHints
, propertyPaths
);
673 for (SpecimenOrObservationBase o
: perTaxonOccurrences
) {
674 occurrenceIds
.add(o
.getId());
677 occurrences
= (List
<T
>) dao
.listByIds(occurrenceIds
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
679 return new DefaultPagerImpl
<T
>(pageNumber
, occurrenceIds
.size(), pageSize
, occurrences
);
685 public <T
extends SpecimenOrObservationBase
> Pager
<T
> pageByAssociatedTaxon(Class
<T
> type
, Set
<TaxonRelationshipEdge
> includeRelationships
,
686 String taxonUUID
, Integer maxDepth
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
688 UUID uuid
= UUID
.fromString(taxonUUID
);
689 Taxon tax
= (Taxon
) taxonService
.load(uuid
);
690 //TODO REMOVE NULL STATEMENT
692 return pageByAssociatedTaxon( type
,includeRelationships
,tax
, maxDepth
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
698 public Pager
<SearchResult
<SpecimenOrObservationBase
>> findByFullText(
699 Class
<?
extends SpecimenOrObservationBase
> clazz
, String queryString
, Rectangle boundingBox
, List
<Language
> languages
,
700 boolean highlightFragments
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
,
701 List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
703 LuceneSearch luceneSearch
= prepareByFullTextSearch(clazz
, queryString
, boundingBox
, languages
, highlightFragments
);
705 // --- execute search
706 TopGroupsWithMaxScore topDocsResultSet
= luceneSearch
.executeSearch(pageSize
, pageNumber
);
708 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
709 idFieldMap
.put(CdmBaseType
.SPECIMEN_OR_OBSERVATIONBASE
, "id");
711 // --- initialize taxa, highlight matches ....
712 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
713 @SuppressWarnings("rawtypes")
714 List
<SearchResult
<SpecimenOrObservationBase
>> searchResults
= searchResultBuilder
.createResultSet(
715 topDocsResultSet
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
717 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupCount
: 0;
719 return new DefaultPagerImpl
<SearchResult
<SpecimenOrObservationBase
>>(pageNumber
, totalHits
, pageSize
,
729 * @param highlightFragments
732 private LuceneSearch
prepareByFullTextSearch(Class
<?
extends SpecimenOrObservationBase
> clazz
, String queryString
, Rectangle bbox
,
733 List
<Language
> languages
, boolean highlightFragments
) {
735 BooleanQuery finalQuery
= new BooleanQuery();
736 BooleanQuery textQuery
= new BooleanQuery();
738 LuceneSearch luceneSearch
= new LuceneSearch(luceneIndexToolProvider
, FieldUnit
.class);
739 QueryFactory queryFactory
= luceneIndexToolProvider
.newQueryFactoryFor(FieldUnit
.class);
742 luceneSearch
.setCdmTypRestriction(clazz
);
743 if(queryString
!= null){
744 textQuery
.add(queryFactory
.newTermQuery("titleCache", queryString
), Occur
.SHOULD
);
745 finalQuery
.add(textQuery
, Occur
.MUST
);
750 finalQuery
.add(QueryFactory
.buildSpatialQueryByRange(bbox
, "gatheringEvent.exactLocation.point"), Occur
.MUST
);
753 luceneSearch
.setQuery(finalQuery
);
756 SortField
[] sortFields
= new SortField
[]{SortField
.FIELD_SCORE
, new SortField("titleCache__sort", SortField
.STRING
, false)};
757 luceneSearch
.setSortFields(sortFields
);
759 if(highlightFragments
){
760 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
767 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getFieldUnits(eu.etaxonomy.cdm.model.occurrence.DerivedUnit)
770 public Collection
<FieldUnit
> getFieldUnits(UUID derivedUnitUuid
) {
771 //It will search recursively over all {@link DerivationEvent}s and get the "originals" ({@link SpecimenOrObservationBase})
772 //from which this DerivedUnit was derived until all FieldUnits are found.
774 //FIXME: use HQL queries to increase performance
775 SpecimenOrObservationBase
<?
> specimen
= load(derivedUnitUuid
);
776 // specimen = HibernateProxyHelper.deproxy(specimen, SpecimenOrObservationBase.class);
777 Collection
<FieldUnit
> fieldUnits
= new ArrayList
<FieldUnit
>();
779 if(specimen
.isInstanceOf(FieldUnit
.class)){
780 fieldUnits
.add(HibernateProxyHelper
.deproxy(specimen
, FieldUnit
.class));
782 else if(specimen
.isInstanceOf(DerivedUnit
.class)){
783 fieldUnits
.addAll(getFieldUnits(HibernateProxyHelper
.deproxy(specimen
, DerivedUnit
.class)));
793 private Collection
<FieldUnit
> getFieldUnits(DerivedUnit derivedUnit
) {
794 Collection
<FieldUnit
> fieldUnits
= new HashSet
<FieldUnit
>();
795 Set
<SpecimenOrObservationBase
> originals
= derivedUnit
.getOriginals();
796 if(originals
!=null && !originals
.isEmpty()){
797 for(SpecimenOrObservationBase
<?
> original
:originals
){
798 if(original
.isInstanceOf(FieldUnit
.class)){
799 fieldUnits
.add(HibernateProxyHelper
.deproxy(original
, FieldUnit
.class));
801 else if(original
.isInstanceOf(DerivedUnit
.class)){
802 fieldUnits
.addAll(getFieldUnits(HibernateProxyHelper
.deproxy(original
, DerivedUnit
.class)));
810 * @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)
813 public boolean moveSequence(DnaSample from
, DnaSample to
, Sequence sequence
) {
814 //reload specimens to avoid session conflicts
815 from
= (DnaSample
) load(from
.getUuid());
816 to
= (DnaSample
) load(to
.getUuid());
817 sequence
= sequenceService
.load(sequence
.getUuid());
819 if(from
==null || to
==null || sequence
==null){
820 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" +
821 "Operation was move "+sequence
+ " from "+from
+" to "+to
);
823 from
.removeSequence(sequence
);
825 to
.addSequence(sequence
);
831 * @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)
834 public boolean moveDerivate(SpecimenOrObservationBase
<?
> from
, SpecimenOrObservationBase
<?
> to
, DerivedUnit derivate
) {
835 //reload specimens to avoid session conflicts
836 from
= load(from
.getUuid());
837 to
= load(to
.getUuid());
838 derivate
= (DerivedUnit
) load(derivate
.getUuid());
840 if(from
==null || to
==null || derivate
==null){
841 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" +
842 "Operation was move "+derivate
+ " from "+from
+" to "+to
);
845 SpecimenOrObservationType derivateType
= derivate
.getRecordBasis();
846 SpecimenOrObservationType toType
= to
.getRecordBasis();
847 //check if type is a sub derivate type
848 if(toType
==SpecimenOrObservationType
.FieldUnit
//moving to FieldUnit always works
849 || derivateType
==SpecimenOrObservationType
.Media
//moving media always works
850 || (derivateType
.isKindOf(toType
) && toType
!=derivateType
)){ //moving only to parent derivate type
851 //remove derivation event from parent specimen of dragged object
852 DerivationEvent eventToRemove
= null;
853 for(DerivationEvent event
:from
.getDerivationEvents()){
854 if(event
.getDerivatives().contains(derivate
)){
855 eventToRemove
= event
;
859 from
.removeDerivationEvent(eventToRemove
);
861 //add new derivation event to target
862 DerivationEvent derivedFromNewOriginalEvent
= DerivationEvent
.NewSimpleInstance(to
, derivate
, eventToRemove
==null?
null:eventToRemove
.getType());
863 to
.addDerivationEvent(derivedFromNewOriginalEvent
);
864 derivate
.setDerivedFrom(derivedFromNewOriginalEvent
);
872 public Collection
<ICdmBase
> getNonCascadedAssociatedElements(SpecimenOrObservationBase
<?
> specimen
){
873 //potential fields that are not persisted cascadingly
886 --CollectingAreas TERM
894 -storedUnder CDM TaxonNameBase
897 Collection
<ICdmBase
> nonCascadedCdmEntities
= new HashSet
<ICdmBase
>();
899 //Choose the correct entry point to traverse the graph (FieldUnit or DerivedUnit)
902 if(specimen
.isInstanceOf(FieldUnit
.class)){
903 nonCascadedCdmEntities
.addAll(getFieldUnitNonCascadedAssociatedElements(HibernateProxyHelper
.deproxy(specimen
, FieldUnit
.class)));
906 else if(specimen
.isInstanceOf(DerivedUnit
.class)){
907 DerivedUnit derivedUnit
= HibernateProxyHelper
.deproxy(specimen
, DerivedUnit
.class);
908 if(derivedUnit
.getDerivedFrom()!=null){
909 Collection
<FieldUnit
> fieldUnits
= getFieldUnits(derivedUnit
);
910 for(FieldUnit fieldUnit
:fieldUnits
){
911 nonCascadedCdmEntities
.addAll(getFieldUnitNonCascadedAssociatedElements(fieldUnit
));
915 return nonCascadedCdmEntities
;
918 private Collection
<ICdmBase
> getFieldUnitNonCascadedAssociatedElements(FieldUnit fieldUnit
){
919 //get non cascaded element on SpecimenOrObservationBase level
920 Collection
<ICdmBase
> nonCascadedCdmEntities
= getSpecimenOrObservationNonCascadedAssociatedElements(fieldUnit
);
922 //get FieldUnit specific elements
923 GatheringEvent gatheringEvent
= fieldUnit
.getGatheringEvent();
924 if(gatheringEvent
!=null){
926 if(gatheringEvent
.getCountry()!=null){
927 nonCascadedCdmEntities
.add(gatheringEvent
.getCountry());
930 for (NamedArea namedArea
: gatheringEvent
.getCollectingAreas()) {
931 nonCascadedCdmEntities
.add(namedArea
);
934 for (DerivationEvent derivationEvent
: fieldUnit
.getDerivationEvents()) {
935 for (DerivedUnit derivedUnit
: derivationEvent
.getDerivatives()) {
936 nonCascadedCdmEntities
.addAll(getDerivedUnitNonCascadedAssociatedElements(derivedUnit
));
939 return nonCascadedCdmEntities
;
942 private Collection
<ICdmBase
> getDerivedUnitNonCascadedAssociatedElements(DerivedUnit derivedUnit
){
943 //get non cascaded element on SpecimenOrObservationBase level
944 Collection
<ICdmBase
> nonCascadedCdmEntities
= getSpecimenOrObservationNonCascadedAssociatedElements(derivedUnit
);
946 //get DerivedUnit specific elements
947 if(derivedUnit
.getCollection()!=null && derivedUnit
.getCollection().getInstitute()!=null){
948 for (DefinedTerm type
: derivedUnit
.getCollection().getInstitute().getTypes()) {
949 nonCascadedCdmEntities
.add(type
);
952 if(derivedUnit
.getPreservation()!=null && derivedUnit
.getPreservation().getMedium()!=null){
953 nonCascadedCdmEntities
.add(derivedUnit
.getPreservation().getMedium());
955 if(derivedUnit
.getStoredUnder()!=null){
956 nonCascadedCdmEntities
.add(derivedUnit
.getStoredUnder());
958 return nonCascadedCdmEntities
;
965 private Collection
<ICdmBase
> getSpecimenOrObservationNonCascadedAssociatedElements(
966 SpecimenOrObservationBase
<?
> specimen
) {
967 Collection
<ICdmBase
> nonCascadedCdmEntities
= new HashSet
<ICdmBase
>();
968 //scan SpecimenOrObservationBase
969 for(DeterminationEvent determinationEvent
:specimen
.getDeterminations()){
971 if(determinationEvent
.getModifier()!=null){
972 nonCascadedCdmEntities
.add(determinationEvent
.getModifier());
976 if(specimen
.getKindOfUnit()!=null){
977 nonCascadedCdmEntities
.add(specimen
.getKindOfUnit());
980 if(specimen
.getLifeStage()!=null){
981 nonCascadedCdmEntities
.add(specimen
.getLifeStage());
984 if(specimen
.getSex()!=null){
985 nonCascadedCdmEntities
.add(specimen
.getSex());
987 return nonCascadedCdmEntities
;
991 * @see eu.etaxonomy.cdm.api.service.VersionableServiceBase#isDeletable(eu.etaxonomy.cdm.model.common.VersionableEntity, eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase)
994 public DeleteResult
isDeletable(SpecimenOrObservationBase specimen
, DeleteConfiguratorBase config
) {
995 DeleteResult deleteResult
= new DeleteResult();
996 SpecimenDeleteConfigurator specimenDeleteConfigurator
= (SpecimenDeleteConfigurator
)config
;
998 //check elements found by super method
999 Set
<CdmBase
> relatedObjects
= super.isDeletable(specimen
, config
).getRelatedObjects();
1000 for (CdmBase cdmBase
: relatedObjects
) {
1001 //check for type designation
1002 if(cdmBase
.isInstanceOf(SpecimenTypeDesignation
.class) && !specimenDeleteConfigurator
.isDeleteFromTypeDesignation()){
1003 deleteResult
.setAbort();
1004 deleteResult
.addException(new ReferencedObjectUndeletableException("Specimen is a type specimen."));
1005 deleteResult
.addRelatedObject(cdmBase
);
1008 //check for IndividualsAssociations
1009 else if(cdmBase
.isInstanceOf(IndividualsAssociation
.class) && !specimenDeleteConfigurator
.isDeleteFromIndividualsAssociation()){
1010 deleteResult
.setAbort();
1011 deleteResult
.addException(new ReferencedObjectUndeletableException("Specimen is still associated via IndividualsAssociations"));
1012 deleteResult
.addRelatedObject(cdmBase
);
1015 //check for specimen/taxon description
1016 else if((cdmBase
.isInstanceOf(SpecimenDescription
.class) || cdmBase
.isInstanceOf(TaxonDescription
.class))
1017 && !specimenDeleteConfigurator
.isDeleteFromDescription()){
1018 deleteResult
.setAbort();
1019 deleteResult
.addException(new ReferencedObjectUndeletableException("Specimen is still used in a Description."));
1020 deleteResult
.addRelatedObject(cdmBase
);
1023 //check for children and parents (derivation events)
1024 else if(cdmBase
.isInstanceOf(DerivationEvent
.class)){
1025 DerivationEvent derivationEvent
= HibernateProxyHelper
.deproxy(cdmBase
, DerivationEvent
.class);
1026 //check if derivation event is empty
1027 if(!derivationEvent
.getDerivatives().isEmpty()){
1028 if(derivationEvent
.getDerivatives().size()==1 && derivationEvent
.getDerivatives().contains(specimen
)){
1029 //if it is the parent event with only one derivate then the specimen is still deletable
1032 else if(!specimenDeleteConfigurator
.isDeleteChildren()){
1033 //if not and children should not be deleted then it is undeletable
1034 deleteResult
.setAbort();
1035 deleteResult
.addException(new ReferencedObjectUndeletableException("Derivate still has child derivates."));
1036 deleteResult
.addRelatedObject(cdmBase
);
1040 //check all children if they can be deleted
1041 Set
<DerivedUnit
> derivatives
= derivationEvent
.getDerivatives();
1042 DeleteResult childResult
= new DeleteResult();
1043 for (DerivedUnit derivedUnit
: derivatives
) {
1044 childResult
.includeResult(isDeletable(derivedUnit
, specimenDeleteConfigurator
));
1046 if(!childResult
.isOk()){
1047 deleteResult
.setAbort();
1048 deleteResult
.includeResult(childResult
);
1049 deleteResult
.addRelatedObject(cdmBase
);
1055 //check for amplification
1056 else if(cdmBase
.isInstanceOf(AmplificationResult
.class) && !specimenDeleteConfigurator
.isDeleteMolecularData()){
1057 deleteResult
.setAbort();
1058 deleteResult
.addException(new ReferencedObjectUndeletableException("DnaSample is used in amplification results."));
1059 deleteResult
.addRelatedObject(cdmBase
);
1062 //check for sequence
1063 else if(cdmBase
.isInstanceOf(Sequence
.class) && !specimenDeleteConfigurator
.isDeleteMolecularData()){
1064 deleteResult
.setAbort();
1065 deleteResult
.addException(new ReferencedObjectUndeletableException("DnaSample is used in sequences."));
1066 deleteResult
.addRelatedObject(cdmBase
);
1070 if(deleteResult
.isOk()){
1071 //add all related object if deletion is OK so they can be handled by the delete() method
1072 deleteResult
.addRelatedObjects(relatedObjects
);
1074 return deleteResult
;
1078 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#delete(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.api.service.config.SpecimenDeleteConfigurator)
1081 public DeleteResult
delete(SpecimenOrObservationBase
<?
> specimen
, SpecimenDeleteConfigurator config
) {
1082 specimen
= HibernateProxyHelper
.deproxy(specimen
, SpecimenOrObservationBase
.class);
1084 if(config
.isDeleteChildren()){
1085 Set
<DerivationEvent
> derivationEvents
= specimen
.getDerivationEvents();
1086 for (DerivationEvent derivationEvent
: derivationEvents
) {
1087 Set
<DerivedUnit
> derivatives
= derivationEvent
.getDerivatives();
1088 for (DerivedUnit derivedUnit
: derivatives
) {
1089 delete(derivedUnit
, config
);
1094 DeleteResult deleteResult
= isDeletable(specimen
, config
);
1095 if(!deleteResult
.isOk()){
1096 return deleteResult
;
1099 //check related objects
1100 Set
<CdmBase
> relatedObjects
= deleteResult
.getRelatedObjects();
1102 for (CdmBase relatedObject
: relatedObjects
) {
1103 //check for TypeDesignations
1104 if(relatedObject
.isInstanceOf(SpecimenTypeDesignation
.class)){
1105 SpecimenTypeDesignation designation
= HibernateProxyHelper
.deproxy(relatedObject
, SpecimenTypeDesignation
.class);
1106 designation
.setTypeSpecimen(null);
1107 Set
<TaxonNameBase
> typifiedNames
= designation
.getTypifiedNames();
1108 for (TaxonNameBase taxonNameBase
: typifiedNames
) {
1109 taxonNameBase
.removeTypeDesignation(designation
);
1112 //delete IndividualsAssociation
1113 if(relatedObject
.isInstanceOf(IndividualsAssociation
.class)){
1114 IndividualsAssociation assciation
= HibernateProxyHelper
.deproxy(relatedObject
, IndividualsAssociation
.class);
1115 assciation
.setAssociatedSpecimenOrObservation(null);
1116 assciation
.getInDescription().removeElement(assciation
);
1118 //check for taxon description
1119 if(relatedObject
.isInstanceOf(TaxonDescription
.class)){
1120 TaxonDescription taxonDescription
= HibernateProxyHelper
.deproxy(relatedObject
, TaxonDescription
.class);
1121 taxonDescription
.setDescribedSpecimenOrObservation(null);
1123 //check for specimen description
1124 if(relatedObject
.isInstanceOf(SpecimenDescription
.class)){
1125 SpecimenDescription specimenDescription
= HibernateProxyHelper
.deproxy(relatedObject
, SpecimenDescription
.class);
1126 //check if specimen is "described" specimen
1127 if(specimenDescription
.getDescribedSpecimenOrObservation().equals(specimen
)){
1128 specimenDescription
.setDescribedSpecimenOrObservation(null);
1130 //check if description is a description of the given specimen
1131 if(specimen
.getDescriptions().contains(specimenDescription
)){
1132 specimen
.removeDescription(specimenDescription
);
1135 //check for amplification
1136 if(relatedObject
.isInstanceOf(AmplificationResult
.class)){
1137 AmplificationResult amplificationResult
= HibernateProxyHelper
.deproxy(relatedObject
, AmplificationResult
.class);
1138 amplificationResult
.getDnaSample().removeAmplificationResult(amplificationResult
);
1140 //check for sequence
1141 if(relatedObject
.isInstanceOf(Sequence
.class)){
1142 Sequence sequence
= HibernateProxyHelper
.deproxy(relatedObject
, Sequence
.class);
1143 sequence
.getDnaSample().removeSequence(sequence
);
1145 //check for children and parents (derivation events)
1146 if(relatedObject
.isInstanceOf(DerivationEvent
.class)){
1147 DerivationEvent derivationEvent
= HibernateProxyHelper
.deproxy(relatedObject
, DerivationEvent
.class);
1148 //parent derivation event (derivedFrom)
1149 if(derivationEvent
.getDerivatives().contains(specimen
) && specimen
.isInstanceOf(DerivedUnit
.class)){
1150 derivationEvent
.removeDerivative(HibernateProxyHelper
.deproxy(specimen
, DerivedUnit
.class));
1151 if(derivationEvent
.getDerivatives().isEmpty()){
1152 Set
<SpecimenOrObservationBase
> originals
= derivationEvent
.getOriginals();
1153 for (SpecimenOrObservationBase specimenOrObservationBase
: originals
) {
1154 specimenOrObservationBase
.removeDerivationEvent(derivationEvent
);
1159 //child derivation events should not occur since we delete the hierarchy from bottom to top
1164 deleteResult
.includeResult(delete(specimen
));
1165 return deleteResult
;
1169 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#deleteDerivateHierarchy(eu.etaxonomy.cdm.model.common.ICdmBase)
1172 public DeleteResult
deleteDerivateHierarchy(CdmBase from
, SpecimenDeleteConfigurator config
) {
1173 DeleteResult deleteResult
= new DeleteResult();
1174 if(from
.isInstanceOf(Sequence
.class)){
1175 if(!config
.isDeleteMolecularData()){
1176 deleteResult
.setAbort();
1177 deleteResult
.addException(new ReferencedObjectUndeletableException("deleting molecur data is not allowed in config"));
1178 return deleteResult
;
1180 Sequence sequence
= HibernateProxyHelper
.deproxy(from
, Sequence
.class);
1181 sequence
.getDnaSample().removeSequence(sequence
);
1182 deleteResult
= sequenceService
.delete(sequence
);
1184 else if(from
.isInstanceOf(SingleRead
.class)) {
1185 if(!config
.isDeleteMolecularData()){
1186 deleteResult
.setAbort();
1187 deleteResult
.addException(new ReferencedObjectUndeletableException("deleting molecur data is not allowed in config"));
1188 return deleteResult
;
1190 SingleRead singleRead
= HibernateProxyHelper
.deproxy(from
, SingleRead
.class);
1191 singleRead
.getAmplificationResult().removeSingleRead(singleRead
);
1192 deleteResult
.setStatus(Status
.OK
);
1194 else if(from
.isInstanceOf(SpecimenOrObservationBase
.class)) {
1195 deleteResult
= delete(HibernateProxyHelper
.deproxy(from
, SpecimenOrObservationBase
.class), config
);
1197 return deleteResult
;
1200 // private DeleteResult deepDelete(SpecimenOrObservationBase<?> entity, SpecimenDeleteConfigurator config){
1201 // Set<DerivationEvent> derivationEvents = entity.getDerivationEvents();
1202 // for (DerivationEvent derivationEvent : derivationEvents) {
1203 // Set<DerivedUnit> derivatives = derivationEvent.getDerivatives();
1204 // for (DerivedUnit derivedUnit : derivatives) {
1205 // DeleteResult deleteResult = deepDelete(derivedUnit, config);
1206 // if(!deleteResult.isOk()){
1207 // return deleteResult;
1211 // return delete(entity, config);
1215 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listAssociatedTaxa(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)
1218 public Collection
<IndividualsAssociation
> listIndividualsAssociations(SpecimenOrObservationBase
<?
> specimen
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
1219 return dao
.listIndividualsAssociations(specimen
, null, null, null, null);
1223 * @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)
1226 public Collection
<SpecimenTypeDesignation
> listTypeDesignations(SpecimenOrObservationBase
<?
> specimen
,
1227 Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
1228 return dao
.listTypeDesignations(specimen
, limit
, start
, orderHints
, propertyPaths
);
1232 * @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)
1235 public Collection
<DescriptionBase
<?
>> listDescriptionsWithDescriptionSpecimen(
1236 SpecimenOrObservationBase
<?
> specimen
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
,
1237 List
<String
> propertyPaths
) {
1238 return dao
.listDescriptionsWithDescriptionSpecimen(specimen
, limit
, start
, orderHints
, propertyPaths
);
1242 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getStatesForSpecimen(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)
1245 public Collection
<DescriptionElementBase
> getCharacterDataForSpecimen(SpecimenOrObservationBase
<?
> specimen
) {
1246 Collection
<DescriptionElementBase
> states
= new ArrayList
<DescriptionElementBase
>();
1248 Set
<DescriptionBase
> descriptions
= specimen
.getDescriptions();
1249 for (DescriptionBase
<?
> descriptionBase
: descriptions
) {
1250 if(descriptionBase
.isInstanceOf(SpecimenDescription
.class)){
1251 SpecimenDescription specimenDescription
= HibernateProxyHelper
.deproxy(descriptionBase
, SpecimenDescription
.class);
1252 Set
<DescriptionElementBase
> elements
= specimenDescription
.getElements();
1253 for (DescriptionElementBase descriptionElementBase
: elements
) {
1254 if(descriptionElementBase
.getFeature().isSupportsCategoricalData()
1255 ||descriptionElementBase
.getFeature().isSupportsQuantitativeData()){
1256 states
.add(descriptionElementBase
);
1266 * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getStatesForSpecimen(java.util.UUID)
1269 public Collection
<DescriptionElementBase
> getCharacterDataForSpecimen(UUID specimenUuid
) {
1270 SpecimenOrObservationBase
<?
> specimen
= load(specimenUuid
);
1272 return getCharacterDataForSpecimen(specimen
);
1275 throw new DataRetrievalFailureException("Specimen with the given uuid not found in the data base");