Project

General

Profile

Download (13.9 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.name.TypeDesignationComparator;
31
import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetManager.TypeDesignationWorkingSet;
32
import eu.etaxonomy.cdm.api.service.registration.IRegistrationWorkingSetService;
33
import eu.etaxonomy.cdm.api.service.registration.RegistrationWorkingSetService;
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.model.reference.Reference;
47
import eu.etaxonomy.cdm.ref.TypedEntityReference;
48
import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationDTO;
49
import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationWorkingSetDTO;
50

    
51
/**
52
 * @author a.kohlbecker
53
 * @since Nov 13, 2017
54
 *
55
 */
56
@Service("specimenTypeDesignationWorkingSetService")
57
@Transactional(readOnly=true)
58
public class SpecimenTypeDesignationWorkingSetServiceImpl implements ISpecimenTypeDesignationWorkingSetService {
59

    
60
    private final Logger logger = Logger.getLogger(SpecimenTypeDesignationWorkingSetServiceImpl.class);
61

    
62
    static SpecimenDeleteConfigurator specimenDeleteConfigurer = new SpecimenDeleteConfigurator();
63
    static {
64
        specimenDeleteConfigurer.setDeleteChildren(true);
65
        specimenDeleteConfigurer.setDeleteFromDescription(true);
66
        specimenDeleteConfigurer.setDeleteFromIndividualsAssociation(true);
67
        specimenDeleteConfigurer.setDeleteFromTypeDesignation(true);
68
        specimenDeleteConfigurer.setDeleteMolecularData(true);
69
    }
70

    
71
    public static final List<String> TAXON_NAME_INIT_STRATEGY = Arrays.asList(new String []{
72
            "$",
73
            "nomenclaturalReference.authorship",
74
            "nomenclaturalReference.inReference.authorship",
75
            "nomenclaturalReference.inReference.inReference.authorship",
76
            "status.type",
77
            "typeDesignations"
78
            }
79
    );
80

    
81
    @Autowired
82
    IRegistrationWorkingSetService registrationWorkingSetService;
83

    
84
    @Qualifier("cdmRepository")
85
    @Autowired
86
    CdmRepository repo;
87

    
88

    
89
    /**
90
     * {@inheritDoc}
91
     */
92
    @Override
93
    public SpecimenTypeDesignationWorkingSetDTO<Registration> create(UUID registrationUuid, UUID publicationUuid, UUID typifiedNameUuid) {
94
        FieldUnit newfieldUnit = FieldUnit.NewInstance();
95
        Registration reg = repo.getRegistrationService().load(registrationUuid, RegistrationWorkingSetService.REGISTRATION_DTO_INIT_STRATEGY);
96
        if(reg == null){
97
            reg = repo.getRegistrationService().newRegistration();
98
            reg.setUuid(registrationUuid);
99
        }
100
        TaxonName typifiedName = repo.getNameService().load(typifiedNameUuid, TAXON_NAME_INIT_STRATEGY);
101
        Reference citation = repo.getReferenceService().load(publicationUuid, Arrays.asList("$"));
102
        SpecimenTypeDesignationWorkingSetDTO<Registration> workingSetDto = new SpecimenTypeDesignationWorkingSetDTO<Registration>(reg, newfieldUnit, citation, typifiedName);
103
        return workingSetDto;
104
    }
105

    
106
    /**
107
     * {@inheritDoc}
108
     */
109
    @Override
110
    @Transactional
111
    public SpecimenTypeDesignationWorkingSetDTO<Registration> load(UUID registrationUuid, TypedEntityReference<? extends IdentifiableEntity<?>> baseEntityRef) {
112

    
113
        RegistrationDTO regDTO = registrationWorkingSetService.loadDtoByUuid(registrationUuid);
114
        // find the working set
115
        TypeDesignationWorkingSet typeDesignationWorkingSet = regDTO.getTypeDesignationWorkingSet(baseEntityRef);
116
        SpecimenTypeDesignationWorkingSetDTO<Registration> workingSetDto = specimenTypeDesignationWorkingSetDTO(regDTO, typeDesignationWorkingSet.getBaseEntityReference());
117
        return workingSetDto;
118
    }
119

    
120
    protected SpecimenTypeDesignationWorkingSetDTO<Registration> specimenTypeDesignationWorkingSetDTO(RegistrationDTO regDTO, TypedEntityReference baseEntityReference) {
121

    
122
        Set<TypeDesignationBase> typeDesignations = regDTO.getTypeDesignationsInWorkingSet(baseEntityReference);
123
        List<SpecimenTypeDesignation> specimenTypeDesignations = new ArrayList<>(typeDesignations.size());
124
        typeDesignations.forEach(td -> specimenTypeDesignations.add((SpecimenTypeDesignation)td));
125
        specimenTypeDesignations.sort(new TypeDesignationComparator());
126
        VersionableEntity baseEntity = regDTO.getTypeDesignationWorkingSet(baseEntityReference).getBaseEntity();
127

    
128
        SpecimenTypeDesignationWorkingSetDTO<Registration> dto = new SpecimenTypeDesignationWorkingSetDTO<Registration>(regDTO.registration(),
129
                baseEntity, specimenTypeDesignations, regDTO.getCitation(), regDTO.getTypifiedName());
130
        return dto;
131
    }
132

    
133
    @Override
134
    public SpecimenTypeDesignationWorkingSetDTO<Registration> fixMissingFieldUnit(SpecimenTypeDesignationWorkingSetDTO<Registration> bean) {
135

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

    
140
            Registration reg = repo.getRegistrationService().find(bean.getOwner().getUuid());
141
            RegistrationDTO regDTO = new RegistrationDTO(reg);
142

    
143
            FieldUnit fieldUnit = FieldUnit.NewInstance();
144
            GatheringEvent gatheringEvent = GatheringEvent.NewInstance();
145
            fieldUnit.setGatheringEvent(gatheringEvent);
146
            fieldUnit = (FieldUnit) repo.getOccurrenceService().save(fieldUnit);
147

    
148
            VersionableEntity baseEntity = bean.getBaseEntity();
149
            Set<TypeDesignationBase> typeDesignations = regDTO.getTypeDesignationsInWorkingSet(
150
                    new TypedEntityReference(baseEntity.getClass(), baseEntity.getUuid(), baseEntity.toString())
151
                    );
152
            for(TypeDesignationBase td : typeDesignations){
153
                DerivationEvent de = DerivationEvent.NewInstance();//
154
                de.addOriginal(fieldUnit);
155
                de.addDerivative(((SpecimenTypeDesignation)td).getTypeSpecimen());
156
                de.setType(DerivationEventType.GATHERING_IN_SITU());
157
            }
158

    
159
            repo.getRegistrationService().saveOrUpdate(reg);
160
        }
161
        return bean;
162
    }
163

    
164
    /**
165
     * {@inheritDoc}
166
     */
167
    @Override
168
    @Transactional(readOnly=false)
169
    public void save(SpecimenTypeDesignationWorkingSetDTO<? extends VersionableEntity> dto) {
170

    
171
        if(dto.getOwner() instanceof Registration){
172
            Registration regPremerge = (Registration) dto.getOwner();
173

    
174
            regPremerge = repo.getRegistrationService().assureIsPersisted(regPremerge);
175

    
176
            // find the newly created type designations
177
            Set<SpecimenTypeDesignation> newTypeDesignations = findNewTypeDesignations((SpecimenTypeDesignationWorkingSetDTO<Registration>) dto);
178

    
179
            FieldUnit fieldUnit = (FieldUnit) dto.getBaseEntity();
180

    
181
            // associate the new typeDesignations with the registration
182
            for(SpecimenTypeDesignation std : newTypeDesignations){
183
                assureFieldUnit(fieldUnit, std);
184
                std.setCitation(dto.getCitation());
185
                dto.getTypifiedName().addTypeDesignation(std, false);
186
                regPremerge.addTypeDesignation(std);
187
            }
188

    
189
            for(SpecimenTypeDesignationDTO stdDTO : dto.getSpecimenTypeDesignationDTOs()){
190
                SpecimenTypeDesignation specimenTypeDesignation = stdDTO.asSpecimenTypeDesignation();
191
                // associate all type designations with the fieldUnit
192
                assureFieldUnit(fieldUnit, specimenTypeDesignation);
193
            }
194

    
195
            Session session = repo.getSession();
196

    
197
            session.merge(dto.getOwner());
198
            session.flush();
199

    
200
            // ------------------------ perform delete of removed SpecimenTypeDesignations
201
            // this step also includes the deletion of DerivedUnits which have been converted by
202
            // the DerivedUnitConverter in turn of a kindOfUnit change
203
            for(SpecimenTypeDesignation std : dto.deletedSpecimenTypeDesignations()){
204
                deleteSpecimenTypeDesignation(dto, std);
205
            }
206
        }
207

    
208

    
209
    }
210

    
211
    /**
212
     * @param dto
213
     * @param specimenDeleteConfigurer
214
     * @param std
215
     */
216
    protected void deleteSpecimenTypeDesignation(SpecimenTypeDesignationWorkingSetDTO<? extends VersionableEntity> dto, SpecimenTypeDesignation std) {
217

    
218
//        if(dto.getOwner() instanceof Registration){
219
//            Registration registration = (Registration) dto.getOwner();
220
//            registration.getTypeDesignations().clear();
221
//            repo.getRegistrationService().save(registration);
222
//        } else {
223
//            throw new RuntimeException("Unimplemented owner type");
224
//        }
225
        DerivedUnit du = std.getTypeSpecimen();
226
//        DerivationEvent derivationEvent = du.getDerivedFrom();
227

    
228
        //du.removeSpecimenTypeDesignation(std);
229
        //derivationEvent.removeDerivative(du);
230
        std.setTypeSpecimen(null);
231
        repo.getOccurrenceService().delete(du, specimenDeleteConfigurer);
232
        repo.getNameService().deleteTypeDesignation(dto.getTypifiedName(), std);
233
//        if(derivationEvent.getDerivatives().size() == 0){
234
//          getRepo().getEventBaseService().delete(derivationEvent);
235
//      }
236
    }
237

    
238
    /**
239
     * @param session
240
     * @param fieldUnit
241
     * @param specimenTypeDesignation
242
     */
243
    protected void assureFieldUnit(FieldUnit fieldUnit,
244
            SpecimenTypeDesignation specimenTypeDesignation) {
245
        try {
246
            SpecimenOrObservationBase<?> original = findEarliestOriginal(specimenTypeDesignation.getTypeSpecimen());
247
            if(original instanceof DerivedUnit){
248
                DerivedUnit du = (DerivedUnit)original;
249
                du.getDerivedFrom().addOriginal(fieldUnit);
250
            }
251
        } catch (Exception e) {
252
            // has more than one originals !!!
253
            logger.error(e);
254
        }
255
    }
256

    
257
    /**
258
     * @param std
259
     * @return
260
     * @throws Exception
261
     */
262
    private SpecimenOrObservationBase<?> findEarliestOriginal(DerivedUnit du) throws Exception {
263

    
264
        SpecimenOrObservationBase original = du;
265

    
266
        while(du != null && du.getDerivedFrom() != null && !du.getDerivedFrom().getOriginals().isEmpty()) {
267
            Iterator<SpecimenOrObservationBase> it = du.getDerivedFrom().getOriginals().iterator();
268
            SpecimenOrObservationBase nextOriginal = it.next();
269
            if(nextOriginal == null){
270
                break;
271
            }
272
            original = nextOriginal;
273
            if(original instanceof DerivedUnit){
274
                du = (DerivedUnit)original;
275
            } else {
276
                // so this must be a FieldUnit,
277
               break;
278
            }
279
            if(it.hasNext()){
280
                throw new Exception(String.format("%s has more than one originals", du.toString()));
281
            }
282
        }
283
        return original;
284
    }
285

    
286
    private Set<SpecimenTypeDesignation> findNewTypeDesignations(SpecimenTypeDesignationWorkingSetDTO<Registration> workingSetDto) {
287

    
288
        Registration reg = workingSetDto.getOwner();
289
        Set<SpecimenTypeDesignation> addCandidates = new HashSet<>();
290
        for(SpecimenTypeDesignationDTO stdDTO : workingSetDto.getSpecimenTypeDesignationDTOs()){
291
            SpecimenTypeDesignation std = stdDTO.asSpecimenTypeDesignation();
292
            if(reg.getTypeDesignations().isEmpty() || !reg.getTypeDesignations().stream().filter(td -> td.equals(std)).findFirst().isPresent()){
293
                addCandidates.add(std);
294
            }
295
        }
296
        return addCandidates;
297
    }
298

    
299
    /**
300
     * {@inheritDoc}
301
     */
302
    @Override
303
    @Transactional(readOnly=false)
304
    public void delete(SpecimenTypeDesignationWorkingSetDTO bean, boolean deleteFieldUnit) {
305

    
306
        @SuppressWarnings("unchecked")
307
        List<SpecimenTypeDesignationDTO> specimenTypeDesignationDTOs = bean.getSpecimenTypeDesignationDTOs();
308
        for(SpecimenTypeDesignationDTO stdDTO : specimenTypeDesignationDTOs){
309
          SpecimenTypeDesignation std =  stdDTO.asSpecimenTypeDesignation();
310
          deleteSpecimenTypeDesignation(bean, std);
311
          if(bean.getOwner() instanceof Registration){
312
              ((Registration)bean.getOwner()).getTypeDesignations().remove(std);
313
          }
314
        }
315

    
316
        if(deleteFieldUnit){
317
            FieldUnit fu = bean.getFieldUnit();
318
            // delete the fieldunit and all derivatives
319
            DeleteResult result = repo.getOccurrenceService().delete(fu.getUuid(), specimenDeleteConfigurer);
320
            String msg = result.toString();
321
        }
322
    }
323

    
324
}
(5-5/7)