2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.service
;
11 import java
.util
.ArrayList
;
12 import java
.util
.Arrays
;
13 import java
.util
.HashSet
;
14 import java
.util
.Iterator
;
15 import java
.util
.List
;
17 import java
.util
.UUID
;
19 import org
.apache
.logging
.log4j
.LogManager
;
20 import org
.apache
.logging
.log4j
.Logger
;
21 import org
.hibernate
.Session
;
22 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
23 import org
.springframework
.beans
.factory
.annotation
.Qualifier
;
24 import org
.springframework
.stereotype
.Service
;
25 import org
.springframework
.transaction
.annotation
.Transactional
;
27 import eu
.etaxonomy
.cdm
.api
.application
.CdmRepository
;
28 import eu
.etaxonomy
.cdm
.api
.service
.DeleteResult
;
29 import eu
.etaxonomy
.cdm
.api
.service
.config
.SpecimenDeleteConfigurator
;
30 import eu
.etaxonomy
.cdm
.api
.service
.dto
.RegistrationDTO
;
31 import eu
.etaxonomy
.cdm
.api
.service
.registration
.IRegistrationWorkingSetService
;
32 import eu
.etaxonomy
.cdm
.api
.service
.registration
.RegistrationWorkingSetService
;
33 import eu
.etaxonomy
.cdm
.compare
.name
.TypeDesignationComparator
;
34 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
35 import eu
.etaxonomy
.cdm
.model
.common
.VersionableEntity
;
36 import eu
.etaxonomy
.cdm
.model
.name
.Registration
;
37 import eu
.etaxonomy
.cdm
.model
.name
.SpecimenTypeDesignation
;
38 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
39 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationBase
;
40 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivationEvent
;
41 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivationEventType
;
42 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnit
;
43 import eu
.etaxonomy
.cdm
.model
.occurrence
.FieldUnit
;
44 import eu
.etaxonomy
.cdm
.model
.occurrence
.GatheringEvent
;
45 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
46 import eu
.etaxonomy
.cdm
.vaadin
.model
.registration
.SpecimenTypeDesignationDTO
;
47 import eu
.etaxonomy
.cdm
.vaadin
.model
.registration
.SpecimenTypeDesignationSetDTO
;
50 * @author a.kohlbecker
53 @Service("specimenTypeDesignationSetService")
54 @Transactional(readOnly
=true)
55 public class SpecimenTypeDesignationSetServiceImpl
56 implements ISpecimenTypeDesignationSetService
{
58 private final Logger logger
= LogManager
.getLogger();
60 static SpecimenDeleteConfigurator specimenDeleteConfigurer
= new SpecimenDeleteConfigurator();
62 specimenDeleteConfigurer
.setDeleteChildren(true);
63 specimenDeleteConfigurer
.setDeleteFromDescription(true);
64 specimenDeleteConfigurer
.setDeleteFromIndividualsAssociation(true);
65 specimenDeleteConfigurer
.setDeleteFromTypeDesignation(true);
66 specimenDeleteConfigurer
.setDeleteMolecularData(true);
69 public static final List
<String
> TAXON_NAME_INIT_STRATEGY
= Arrays
.asList(new String
[]{
71 "nomenclaturalSource.citation.authorship.$",
72 "nomenclaturalSource.citation.inReference.authorship.$",
73 "nomenclaturalSource.citation.inReference.inReference.authorship.$",
80 private IRegistrationWorkingSetService registrationWorkingSetService
;
82 @Qualifier("cdmRepository")
84 private CdmRepository repo
;
87 public SpecimenTypeDesignationSetDTO
<Registration
> create(UUID registrationUuid
, UUID typifiedNameUuid
) {
88 FieldUnit newfieldUnit
= FieldUnit
.NewInstance();
89 Registration reg
= repo
.getRegistrationService().load(registrationUuid
, RegistrationWorkingSetService
.REGISTRATION_DTO_INIT_STRATEGY
.getPropertyPaths());
91 reg
= repo
.getRegistrationService().newRegistration();
92 reg
.setUuid(registrationUuid
);
94 TaxonName typifiedName
= repo
.getNameService().load(typifiedNameUuid
, TAXON_NAME_INIT_STRATEGY
);
95 SpecimenTypeDesignationSetDTO
<Registration
> workingSetDto
= new SpecimenTypeDesignationSetDTO
<>(reg
, newfieldUnit
, typifiedName
);
100 @Transactional(readOnly
=true)
101 public SpecimenTypeDesignationSetDTO
<Registration
> load(UUID registrationUuid
, IdentifiableEntity
<?
> baseEntity
) {
103 RegistrationDTO regDTO
= registrationWorkingSetService
.loadDtoByUuid(registrationUuid
);
104 // find the working set
105 SpecimenTypeDesignationSetDTO
<Registration
> workingSetDto
= specimenTypeDesignationSetDTO(regDTO
, baseEntity
);
106 return workingSetDto
;
109 protected SpecimenTypeDesignationSetDTO
<Registration
> specimenTypeDesignationSetDTO(
110 RegistrationDTO regDTO
, VersionableEntity baseEntity
) {
112 @SuppressWarnings("rawtypes")
113 Set
<TypeDesignationBase
> typeDesignations
= regDTO
.getTypeDesignationsInWorkingSet(baseEntity
);
114 List
<SpecimenTypeDesignation
> specimenTypeDesignations
= new ArrayList
<>(typeDesignations
.size());
115 typeDesignations
.forEach(td
-> specimenTypeDesignations
.add((SpecimenTypeDesignation
)td
));
116 specimenTypeDesignations
.sort(new TypeDesignationComparator());
117 //TODO is this needed?
118 baseEntity
= regDTO
.getTypeDesignationSet(baseEntity
).getBaseEntity();
120 SpecimenTypeDesignationSetDTO
<Registration
> dto
= new SpecimenTypeDesignationSetDTO
<>(regDTO
.registration(),
121 baseEntity
, specimenTypeDesignations
, regDTO
.typifiedName());
126 public SpecimenTypeDesignationSetDTO
<Registration
> fixMissingFieldUnit(SpecimenTypeDesignationSetDTO
<Registration
> bean
) {
128 if(bean
.getFieldUnit() == null){
129 // in case the base unit of the working set is not a FieldUnit all contained TypeDesignations must be modified
130 // so that they are based on an empty FieldUnit with an associated Gathering Event
132 Registration reg
= repo
.getRegistrationService().find(bean
.getOwner().getUuid());
133 RegistrationDTO regDTO
= new RegistrationDTO(reg
);
135 FieldUnit fieldUnit
= FieldUnit
.NewInstance();
136 GatheringEvent gatheringEvent
= GatheringEvent
.NewInstance();
137 fieldUnit
.setGatheringEvent(gatheringEvent
);
138 fieldUnit
= repo
.getOccurrenceService().save(fieldUnit
);
140 VersionableEntity baseEntity
= bean
.getBaseEntity();
141 @SuppressWarnings("rawtypes")
142 Set
<TypeDesignationBase
> typeDesignations
= regDTO
.getTypeDesignationsInWorkingSet(baseEntity
);
143 for(TypeDesignationBase
<?
> td
: typeDesignations
){
144 DerivationEvent de
= DerivationEvent
.NewInstance(DerivationEventType
.GATHERING_IN_SITU());
145 de
.addOriginal(fieldUnit
);
146 de
.addDerivative(((SpecimenTypeDesignation
)td
).getTypeSpecimen());
149 repo
.getRegistrationService().saveOrUpdate(reg
);
155 @Transactional(readOnly
=false)
156 public void save(SpecimenTypeDesignationSetDTO
<?
extends VersionableEntity
> dto
) {
158 if(dto
.getOwner() instanceof Registration
){
159 Registration regPremerge
= (Registration
) dto
.getOwner();
161 regPremerge
= repo
.getRegistrationService().assureIsPersisted(regPremerge
);
163 // find the newly created type designations
164 Set
<SpecimenTypeDesignation
> newTypeDesignations
= findNewTypeDesignations((SpecimenTypeDesignationSetDTO
<Registration
>) dto
);
166 FieldUnit fieldUnit
= (FieldUnit
) dto
.getBaseEntity();
168 // associate the new typeDesignations with the registration
169 for(SpecimenTypeDesignation std
: newTypeDesignations
){
170 assureFieldUnit(fieldUnit
, std
);
171 // here the TypeDesignation.typifiedName is also set internally
172 dto
.getTypifiedName().addTypeDesignation(std
, false);
173 regPremerge
.addTypeDesignation(std
);
176 for(SpecimenTypeDesignationDTO stdDTO
: dto
.getSpecimenTypeDesignationDTOs()){
177 SpecimenTypeDesignation specimenTypeDesignation
= stdDTO
.asSpecimenTypeDesignation();
178 // associate all type designations with the fieldUnit
179 assureFieldUnit(fieldUnit
, specimenTypeDesignation
);
182 Session session
= repo
.getSession();
184 session
.merge(regPremerge
);
187 // ------------------------ perform delete of removed SpecimenTypeDesignations
188 // this step also includes the deletion of DerivedUnits which have been converted by
189 // the DerivedUnitConverter in turn of a kindOfUnit change
190 for(SpecimenTypeDesignation std
: dto
.deletedSpecimenTypeDesignations()){
191 deleteSpecimenTypeDesignation(dto
, std
);
198 protected void deleteSpecimenTypeDesignation(SpecimenTypeDesignationSetDTO
<?
extends VersionableEntity
> dto
, SpecimenTypeDesignation std
) {
200 // if(dto.getOwner() instanceof Registration){
201 // Registration registration = (Registration) dto.getOwner();
202 // registration.getTypeDesignations().clear();
203 // repo.getRegistrationService().save(registration);
205 // throw new RuntimeException("Unimplemented owner type");
207 DerivedUnit du
= std
.getTypeSpecimen();
208 // DerivationEvent derivationEvent = du.getDerivedFrom();
210 //du.removeSpecimenTypeDesignation(std);
211 //derivationEvent.removeDerivative(du);
212 std
.setTypeSpecimen(null);
213 repo
.getOccurrenceService().delete(du
, specimenDeleteConfigurer
);
214 repo
.getNameService().deleteTypeDesignation(dto
.getTypifiedName(), std
);
215 // if(derivationEvent.getDerivatives().size() == 0){
216 // getRepo().getEventBaseService().delete(derivationEvent);
220 protected void assureFieldUnit(FieldUnit fieldUnit
,
221 SpecimenTypeDesignation specimenTypeDesignation
) {
223 SpecimenOrObservationBase
<?
> original
= findEarliestOriginal(specimenTypeDesignation
.getTypeSpecimen());
224 if(original
instanceof DerivedUnit
){
225 DerivedUnit du
= (DerivedUnit
)original
;
226 du
.getDerivedFrom().addOriginal(fieldUnit
);
228 } catch (Exception e
) {
229 // has more than one originals !!!
234 private SpecimenOrObservationBase
<?
> findEarliestOriginal(DerivedUnit du
) throws Exception
{
236 SpecimenOrObservationBase
<?
> original
= du
;
238 while(du
!= null && du
.getDerivedFrom() != null && !du
.getDerivedFrom().getOriginals().isEmpty()) {
239 @SuppressWarnings("rawtypes")
240 Iterator
<SpecimenOrObservationBase
> it
= du
.getDerivedFrom().getOriginals().iterator();
241 SpecimenOrObservationBase
<?
> nextOriginal
= it
.next();
242 if(nextOriginal
== null){
245 original
= nextOriginal
;
246 if(original
instanceof DerivedUnit
){
247 du
= (DerivedUnit
)original
;
249 // so this must be a FieldUnit,
253 throw new Exception(String
.format("%s has more than one originals", du
.toString()));
259 private Set
<SpecimenTypeDesignation
> findNewTypeDesignations(SpecimenTypeDesignationSetDTO
<Registration
> workingSetDto
) {
261 Registration reg
= workingSetDto
.getOwner();
262 Set
<SpecimenTypeDesignation
> addCandidates
= new HashSet
<>();
263 for(SpecimenTypeDesignationDTO stdDTO
: workingSetDto
.getSpecimenTypeDesignationDTOs()){
264 SpecimenTypeDesignation std
= stdDTO
.asSpecimenTypeDesignation();
265 if(reg
.getTypeDesignations().isEmpty() || !reg
.getTypeDesignations().stream().filter(td
-> td
.equals(std
)).findFirst().isPresent()){
266 addCandidates
.add(std
);
269 return addCandidates
;
273 @Transactional(readOnly
=false)
274 public void delete(SpecimenTypeDesignationSetDTO bean
, boolean deleteFieldUnit
) {
276 @SuppressWarnings("unchecked")
277 List
<SpecimenTypeDesignationDTO
> specimenTypeDesignationDTOs
= bean
.getSpecimenTypeDesignationDTOs();
278 for(SpecimenTypeDesignationDTO stdDTO
: specimenTypeDesignationDTOs
){
279 SpecimenTypeDesignation std
= stdDTO
.asSpecimenTypeDesignation();
280 deleteSpecimenTypeDesignation(bean
, std
);
281 if(bean
.getOwner() instanceof Registration
){
282 ((Registration
)bean
.getOwner()).getTypeDesignations().remove(std
);
287 FieldUnit fu
= bean
.getFieldUnit();
288 // delete the fieldunit and all derivatives
289 DeleteResult result
= repo
.getOccurrenceService().delete(fu
.getUuid(), specimenDeleteConfigurer
);
290 String msg
= result
.toString();