Project

General

Profile

Download (13 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.service;
10

    
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;
16
import java.util.Set;
17
import java.util.UUID;
18

    
19
import org.hibernate.Session;
20
import org.jboss.logging.Logger;
21
import org.springframework.beans.factory.annotation.Autowired;
22
import org.springframework.beans.factory.annotation.Qualifier;
23
import org.springframework.stereotype.Service;
24
import org.springframework.transaction.annotation.Transactional;
25

    
26
import eu.etaxonomy.cdm.api.application.CdmRepository;
27
import eu.etaxonomy.cdm.api.service.DeleteResult;
28
import eu.etaxonomy.cdm.api.service.config.SpecimenDeleteConfigurator;
29
import eu.etaxonomy.cdm.api.service.dto.RegistrationDTO;
30
import eu.etaxonomy.cdm.api.service.registration.IRegistrationWorkingSetService;
31
import eu.etaxonomy.cdm.api.service.registration.RegistrationWorkingSetService;
32
import eu.etaxonomy.cdm.compare.name.TypeDesignationComparator;
33
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
34
import eu.etaxonomy.cdm.model.common.VersionableEntity;
35
import eu.etaxonomy.cdm.model.name.Registration;
36
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
37
import eu.etaxonomy.cdm.model.name.TaxonName;
38
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
39
import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;
40
import eu.etaxonomy.cdm.model.occurrence.DerivationEventType;
41
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
42
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
43
import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
44
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
45
import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationDTO;
46
import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationSetDTO;
47

    
48
/**
49
 * @author a.kohlbecker
50
 * @since Nov 13, 2017
51
 */
52
@Service("specimenTypeDesignationSetService")
53
@Transactional(readOnly=true)
54
public class SpecimenTypeDesignationSetServiceImpl
55
        implements ISpecimenTypeDesignationSetService {
56

    
57
    private final Logger logger = Logger.getLogger(SpecimenTypeDesignationSetServiceImpl.class);
58

    
59
    static SpecimenDeleteConfigurator specimenDeleteConfigurer = new SpecimenDeleteConfigurator();
60
    static {
61
        specimenDeleteConfigurer.setDeleteChildren(true);
62
        specimenDeleteConfigurer.setDeleteFromDescription(true);
63
        specimenDeleteConfigurer.setDeleteFromIndividualsAssociation(true);
64
        specimenDeleteConfigurer.setDeleteFromTypeDesignation(true);
65
        specimenDeleteConfigurer.setDeleteMolecularData(true);
66
    }
67

    
68
    public static final List<String> TAXON_NAME_INIT_STRATEGY = Arrays.asList(new String []{
69
            "$",
70
            "nomenclaturalSource.citation.authorship.$",
71
            "nomenclaturalSource.citation.inReference.authorship.$",
72
            "nomenclaturalSource.citation.inReference.inReference.authorship.$",
73
            "status.type",
74
            "typeDesignations"
75
            }
76
    );
77

    
78
    @Autowired
79
    IRegistrationWorkingSetService registrationWorkingSetService;
80

    
81
    @Qualifier("cdmRepository")
82
    @Autowired
83
    CdmRepository repo;
84

    
85
    @Override
86
    public SpecimenTypeDesignationSetDTO<Registration> create(UUID registrationUuid, UUID typifiedNameUuid) {
87
        FieldUnit newfieldUnit = FieldUnit.NewInstance();
88
        Registration reg = repo.getRegistrationService().load(registrationUuid, RegistrationWorkingSetService.REGISTRATION_DTO_INIT_STRATEGY.getPropertyPaths());
89
        if(reg == null){
90
            reg = repo.getRegistrationService().newRegistration();
91
            reg.setUuid(registrationUuid);
92
        }
93
        TaxonName typifiedName = repo.getNameService().load(typifiedNameUuid, TAXON_NAME_INIT_STRATEGY);
94
        SpecimenTypeDesignationSetDTO<Registration> workingSetDto = new SpecimenTypeDesignationSetDTO<>(reg, newfieldUnit, typifiedName);
95
        return workingSetDto;
96
    }
97

    
98
    @Override
99
    @Transactional(readOnly=true)
100
    public SpecimenTypeDesignationSetDTO<Registration> load(UUID registrationUuid, IdentifiableEntity<?> baseEntity) {
101

    
102
        RegistrationDTO regDTO = registrationWorkingSetService.loadDtoByUuid(registrationUuid);
103
        // find the working set
104
        SpecimenTypeDesignationSetDTO<Registration> workingSetDto = specimenTypeDesignationSetDTO(regDTO, baseEntity);
105
        return workingSetDto;
106
    }
107

    
108
    protected SpecimenTypeDesignationSetDTO<Registration> specimenTypeDesignationSetDTO(
109
            RegistrationDTO regDTO, VersionableEntity baseEntity) {
110

    
111
        Set<TypeDesignationBase> typeDesignations = regDTO.getTypeDesignationsInWorkingSet(baseEntity);
112
        List<SpecimenTypeDesignation> specimenTypeDesignations = new ArrayList<>(typeDesignations.size());
113
        typeDesignations.forEach(td -> specimenTypeDesignations.add((SpecimenTypeDesignation)td));
114
        specimenTypeDesignations.sort(new TypeDesignationComparator());
115
        //TODO is this needed?
116
        baseEntity = regDTO.getTypeDesignationSet(baseEntity).getBaseEntity();
117

    
118
        SpecimenTypeDesignationSetDTO<Registration> dto = new SpecimenTypeDesignationSetDTO<>(regDTO.registration(),
119
                baseEntity, specimenTypeDesignations, regDTO.typifiedName());
120
        return dto;
121
    }
122

    
123
    @Override
124
    public SpecimenTypeDesignationSetDTO<Registration> fixMissingFieldUnit(SpecimenTypeDesignationSetDTO<Registration> bean) {
125

    
126
        if(bean.getFieldUnit() == null){
127
            // in case the base unit of the working set is not a FieldUnit all contained TypeDesignations must be modified
128
            // so that they are based on an empty FieldUnit with an associated Gathering Event
129

    
130
            Registration reg = repo.getRegistrationService().find(bean.getOwner().getUuid());
131
            RegistrationDTO regDTO = new RegistrationDTO(reg);
132

    
133
            FieldUnit fieldUnit = FieldUnit.NewInstance();
134
            GatheringEvent gatheringEvent = GatheringEvent.NewInstance();
135
            fieldUnit.setGatheringEvent(gatheringEvent);
136
            fieldUnit = repo.getOccurrenceService().save(fieldUnit);
137

    
138
            VersionableEntity baseEntity = bean.getBaseEntity();
139
            Set<TypeDesignationBase> typeDesignations = regDTO.getTypeDesignationsInWorkingSet(baseEntity);
140
            for(TypeDesignationBase<?> td : typeDesignations){
141
                DerivationEvent de = DerivationEvent.NewInstance(DerivationEventType.GATHERING_IN_SITU());
142
                de.addOriginal(fieldUnit);
143
                de.addDerivative(((SpecimenTypeDesignation)td).getTypeSpecimen());
144
            }
145

    
146
            repo.getRegistrationService().saveOrUpdate(reg);
147
        }
148
        return bean;
149
    }
150

    
151
    @Override
152
    @Transactional(readOnly=false)
153
    public void save(SpecimenTypeDesignationSetDTO<? extends VersionableEntity> dto) {
154

    
155
        if(dto.getOwner() instanceof Registration){
156
            Registration regPremerge = (Registration) dto.getOwner();
157

    
158
            regPremerge = repo.getRegistrationService().assureIsPersisted(regPremerge);
159

    
160
            // find the newly created type designations
161
            Set<SpecimenTypeDesignation> newTypeDesignations = findNewTypeDesignations((SpecimenTypeDesignationSetDTO<Registration>) dto);
162

    
163
            FieldUnit fieldUnit = (FieldUnit) dto.getBaseEntity();
164

    
165
            // associate the new typeDesignations with the registration
166
            for(SpecimenTypeDesignation std : newTypeDesignations){
167
                assureFieldUnit(fieldUnit, std);
168
                // here the TypeDesignation.typifiedName is also set internally
169
                dto.getTypifiedName().addTypeDesignation(std, false);
170
                regPremerge.addTypeDesignation(std);
171
            }
172

    
173
            for(SpecimenTypeDesignationDTO stdDTO : dto.getSpecimenTypeDesignationDTOs()){
174
                SpecimenTypeDesignation specimenTypeDesignation = stdDTO.asSpecimenTypeDesignation();
175
                // associate all type designations with the fieldUnit
176
                assureFieldUnit(fieldUnit, specimenTypeDesignation);
177
            }
178

    
179
            Session session = repo.getSession();
180

    
181
            session.merge(regPremerge);
182
            session.flush();
183

    
184
            // ------------------------ perform delete of removed SpecimenTypeDesignations
185
            // this step also includes the deletion of DerivedUnits which have been converted by
186
            // the DerivedUnitConverter in turn of a kindOfUnit change
187
            for(SpecimenTypeDesignation std : dto.deletedSpecimenTypeDesignations()){
188
                deleteSpecimenTypeDesignation(dto, std);
189
            }
190
        }
191

    
192

    
193
    }
194

    
195
    /**
196
     * @param dto
197
     * @param specimenDeleteConfigurer
198
     * @param std
199
     */
200
    protected void deleteSpecimenTypeDesignation(SpecimenTypeDesignationSetDTO<? extends VersionableEntity> dto, SpecimenTypeDesignation std) {
201

    
202
//        if(dto.getOwner() instanceof Registration){
203
//            Registration registration = (Registration) dto.getOwner();
204
//            registration.getTypeDesignations().clear();
205
//            repo.getRegistrationService().save(registration);
206
//        } else {
207
//            throw new RuntimeException("Unimplemented owner type");
208
//        }
209
        DerivedUnit du = std.getTypeSpecimen();
210
//        DerivationEvent derivationEvent = du.getDerivedFrom();
211

    
212
        //du.removeSpecimenTypeDesignation(std);
213
        //derivationEvent.removeDerivative(du);
214
        std.setTypeSpecimen(null);
215
        repo.getOccurrenceService().delete(du, specimenDeleteConfigurer);
216
        repo.getNameService().deleteTypeDesignation(dto.getTypifiedName(), std);
217
//        if(derivationEvent.getDerivatives().size() == 0){
218
//          getRepo().getEventBaseService().delete(derivationEvent);
219
//      }
220
    }
221

    
222
    /**
223
     * @param session
224
     * @param fieldUnit
225
     * @param specimenTypeDesignation
226
     */
227
    protected void assureFieldUnit(FieldUnit fieldUnit,
228
            SpecimenTypeDesignation specimenTypeDesignation) {
229
        try {
230
            SpecimenOrObservationBase<?> original = findEarliestOriginal(specimenTypeDesignation.getTypeSpecimen());
231
            if(original instanceof DerivedUnit){
232
                DerivedUnit du = (DerivedUnit)original;
233
                du.getDerivedFrom().addOriginal(fieldUnit);
234
            }
235
        } catch (Exception e) {
236
            // has more than one originals !!!
237
            logger.error(e);
238
        }
239
    }
240

    
241
    /**
242
     * @param std
243
     * @return
244
     * @throws Exception
245
     */
246
    private SpecimenOrObservationBase<?> findEarliestOriginal(DerivedUnit du) throws Exception {
247

    
248
        SpecimenOrObservationBase original = du;
249

    
250
        while(du != null && du.getDerivedFrom() != null && !du.getDerivedFrom().getOriginals().isEmpty()) {
251
            Iterator<SpecimenOrObservationBase> it = du.getDerivedFrom().getOriginals().iterator();
252
            SpecimenOrObservationBase nextOriginal = it.next();
253
            if(nextOriginal == null){
254
                break;
255
            }
256
            original = nextOriginal;
257
            if(original instanceof DerivedUnit){
258
                du = (DerivedUnit)original;
259
            } else {
260
                // so this must be a FieldUnit,
261
               break;
262
            }
263
            if(it.hasNext()){
264
                throw new Exception(String.format("%s has more than one originals", du.toString()));
265
            }
266
        }
267
        return original;
268
    }
269

    
270
    private Set<SpecimenTypeDesignation> findNewTypeDesignations(SpecimenTypeDesignationSetDTO<Registration> workingSetDto) {
271

    
272
        Registration reg = workingSetDto.getOwner();
273
        Set<SpecimenTypeDesignation> addCandidates = new HashSet<>();
274
        for(SpecimenTypeDesignationDTO stdDTO : workingSetDto.getSpecimenTypeDesignationDTOs()){
275
            SpecimenTypeDesignation std = stdDTO.asSpecimenTypeDesignation();
276
            if(reg.getTypeDesignations().isEmpty() || !reg.getTypeDesignations().stream().filter(td -> td.equals(std)).findFirst().isPresent()){
277
                addCandidates.add(std);
278
            }
279
        }
280
        return addCandidates;
281
    }
282

    
283
    /**
284
     * {@inheritDoc}
285
     */
286
    @Override
287
    @Transactional(readOnly=false)
288
    public void delete(SpecimenTypeDesignationSetDTO bean, boolean deleteFieldUnit) {
289

    
290
        @SuppressWarnings("unchecked")
291
        List<SpecimenTypeDesignationDTO> specimenTypeDesignationDTOs = bean.getSpecimenTypeDesignationDTOs();
292
        for(SpecimenTypeDesignationDTO stdDTO : specimenTypeDesignationDTOs){
293
          SpecimenTypeDesignation std =  stdDTO.asSpecimenTypeDesignation();
294
          deleteSpecimenTypeDesignation(bean, std);
295
          if(bean.getOwner() instanceof Registration){
296
              ((Registration)bean.getOwner()).getTypeDesignations().remove(std);
297
          }
298
        }
299

    
300
        if(deleteFieldUnit){
301
            FieldUnit fu = bean.getFieldUnit();
302
            // delete the fieldunit and all derivatives
303
            DeleteResult result = repo.getOccurrenceService().delete(fu.getUuid(), specimenDeleteConfigurer);
304
            String msg = result.toString();
305
        }
306
    }
307

    
308
}
(10-10/13)