Project

General

Profile

Download (17.3 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 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

    
10
package eu.etaxonomy.cdm.api.service;
11

    
12
import java.util.ArrayList;
13
import java.util.HashSet;
14
import java.util.List;
15
import java.util.Map;
16
import java.util.Map.Entry;
17
import java.util.Set;
18
import java.util.UUID;
19

    
20
import org.apache.log4j.Logger;
21
import org.springframework.beans.factory.annotation.Autowired;
22
import org.springframework.stereotype.Service;
23
import org.springframework.transaction.annotation.Transactional;
24

    
25
import eu.etaxonomy.cdm.api.service.config.NodeDeletionConfigurator.ChildHandling;
26
import eu.etaxonomy.cdm.api.service.config.TermNodeDeletionConfigurator;
27
import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
28
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
29
import eu.etaxonomy.cdm.model.common.CdmBase;
30
import eu.etaxonomy.cdm.model.description.Character;
31
import eu.etaxonomy.cdm.model.description.Feature;
32
import eu.etaxonomy.cdm.model.description.MeasurementUnit;
33
import eu.etaxonomy.cdm.model.description.StatisticalMeasure;
34
import eu.etaxonomy.cdm.model.term.DefinedTerm;
35
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
36
import eu.etaxonomy.cdm.model.term.Representation;
37
import eu.etaxonomy.cdm.model.term.TermNode;
38
import eu.etaxonomy.cdm.model.term.TermTree;
39
import eu.etaxonomy.cdm.model.term.TermType;
40
import eu.etaxonomy.cdm.model.term.TermVocabulary;
41
import eu.etaxonomy.cdm.persistence.dao.term.ITermNodeDao;
42
import eu.etaxonomy.cdm.persistence.dto.CharacterDto;
43
import eu.etaxonomy.cdm.persistence.dto.CharacterNodeDto;
44
import eu.etaxonomy.cdm.persistence.dto.MergeResult;
45
import eu.etaxonomy.cdm.persistence.dto.TermDto;
46
import eu.etaxonomy.cdm.persistence.dto.TermNodeDto;
47
import eu.etaxonomy.cdm.persistence.dto.TermVocabularyDto;
48
import eu.etaxonomy.cdm.persistence.query.OrderHint;
49

    
50
/**
51
 * @author a.mueller
52
 * @since Jul 22, 2019
53
 */
54
@Service
55
@Transactional(readOnly = false)
56
public class TermNodeServiceImpl
57
        extends VersionableServiceBase<TermNode, ITermNodeDao>
58
        implements ITermNodeService {
59

    
60
    @SuppressWarnings("unused")
61
    private static final Logger logger = Logger.getLogger(TermNodeServiceImpl.class);
62

    
63
	@Override
64
    @Autowired
65
	protected void setDao(ITermNodeDao dao) {
66
		this.dao = dao;
67
	}
68

    
69
	@Autowired
70
    private ITermService termService;
71

    
72
	@Autowired
73
	private IVocabularyService vocabularyService;
74

    
75
	@Override
76
    public List<TermNode> list(TermType termType, Integer limit, Integer start,
77
	        List<OrderHint> orderHints, List<String> propertyPaths){
78
	    return dao.list(termType, limit, start, orderHints, propertyPaths);
79
	}
80

    
81
	@Override
82
	@Transactional(readOnly = false)
83
	public DeleteResult deleteNode(UUID nodeUuid, TermNodeDeletionConfigurator config) {
84
	    DeleteResult result = new DeleteResult();
85
        TermNode<Feature> node = CdmBase.deproxy(dao.load(nodeUuid));
86
	    result = isDeletable(nodeUuid, config);
87
	    if (result.isOk()){
88
	        TermNode<Feature> parent = node.getParent();
89
            parent = CdmBase.deproxy(parent, TermNode.class);
90
	        List<TermNode> children = new ArrayList<>(node.getChildNodes());
91

    
92
	        if (config.getChildHandling().equals(ChildHandling.DELETE)){
93

    
94
	            for (TermNode child: children){
95
	                deleteNode(child.getUuid(), config);
96
	               // node.removeChild(child);
97
	            }
98
	            if (parent != null){
99
	                parent.removeChild(node);
100
	            }
101

    
102
	        } else{
103

    
104
	            if (parent != null){
105
	                parent.removeChild(node);
106
	                for (TermNode child: children){
107
	                    node.removeChild(child);
108
	                    parent.addChild(child);
109
	                }
110
	            }else{
111
	                 result.setAbort();
112
	                 result.addException(new ReferencedObjectUndeletableException("The root node can not be deleted without its child nodes"));
113
	                 return result;
114
	             }
115
	         }
116

    
117
	         dao.delete(node);
118
	         result.addDeletedObject(node);
119
	         if(parent!=null){
120
	             result.addUpdatedObject(parent);
121
	         }
122
	         if (config.isDeleteElement()){
123
	             DefinedTermBase term = node.getTerm();
124
                 termService.delete(term.getUuid());
125
                 result.addDeletedObject(term);
126
             }
127
	     }
128
	     return result;
129
	 }
130
	 private UpdateResult createChildNode(UUID parentNodeUUID, UUID nodeUuid, DefinedTermBase term, UUID vocabularyUuid){
131
	     UpdateResult result =  createChildNode(parentNodeUUID, term, vocabularyUuid);
132
	     result.getCdmEntity().setUuid(nodeUuid);
133
	     return result;
134
	 }
135

    
136

    
137
	 @Override
138
     public UpdateResult createChildNode(UUID parentNodeUuid, DefinedTermBase term, UUID vocabularyUuid){
139
	     TermVocabulary vocabulary = vocabularyService.load(vocabularyUuid);
140

    
141
	     vocabulary.addTerm(term);
142
	     vocabularyService.save(vocabulary);
143
	     return addChildNode(parentNodeUuid, term.getUuid());
144
	 }
145

    
146
     @Override
147
     public UpdateResult addChildNode(UUID nodeUUID, UUID termChildUuid){
148
         return addChildNode(nodeUUID, termChildUuid, 0);
149
     }
150

    
151
	 @Override
152
	 public UpdateResult addChildNode(UUID nodeUUID, UUID termChildUuid, int position){
153
	     UpdateResult result = new UpdateResult();
154

    
155
	     TermNode node = load(nodeUUID);
156
	     DefinedTermBase child = HibernateProxyHelper.deproxy(termService.load(termChildUuid), DefinedTermBase.class);
157

    
158
	     if(!node.getGraph().isAllowDuplicates() && node.getGraph().getDistinctTerms().contains(child)){
159
	         result.setError();
160
	         result.addException(new Exception("This term tree does not allow duplicate terms."));
161
	         return result;
162
	     }
163

    
164
	     TermNode childNode;
165
         if(position<0) {
166
             childNode = node.addChild(child);
167
         }
168
         else{
169
             childNode = node.addChild(child, position);
170
         }
171
         save(childNode);
172
         result.addUpdatedObject(node);
173
         result.setCdmEntity(childNode);
174
         return result;
175
     }
176

    
177
	 @Override
178
	 public DeleteResult isDeletable(UUID nodeUuid, TermNodeDeletionConfigurator config){
179
	     TermNode<Feature> node = load(nodeUuid);
180
	     DeleteResult result = new DeleteResult();
181
	     Set<CdmBase> references = commonService.getReferencingObjectsForDeletion(node);
182
	     for (CdmBase ref:references){
183
	         if (ref instanceof TermNode){
184
	             break;
185
	         }
186
	         if (ref instanceof TermTree){
187
	             TermTree<Feature> refTree = HibernateProxyHelper.deproxy(ref, TermTree.class);
188
	             if (node.getGraph().equals((refTree))){
189
	                 break;
190
	             }
191
	         }
192
	         result.setAbort();
193
	         result.addException(new ReferencedObjectUndeletableException("The featureNode is referenced by " + ref.getUserFriendlyDescription() +" with id " +ref.getId()));
194

    
195
	     }
196
	     return result;
197
	 }
198

    
199
    @Override
200
    public UpdateResult moveNode(UUID movedNodeUuid, UUID targetNodeUuid, int position) {
201
        UpdateResult result = new UpdateResult();
202
        List<String> propertyPaths = new ArrayList<>();
203
        propertyPaths.add("parent");
204
        propertyPaths.add("parent.children");
205
        propertyPaths.add("children");
206
        TermNode test = load(movedNodeUuid, propertyPaths);
207
        TermNode movedNode = CdmBase.deproxy(load(movedNodeUuid, propertyPaths), TermNode.class);
208
        TermNode targetNode = CdmBase.deproxy(load(targetNodeUuid, propertyPaths));
209
        TermNode parent = CdmBase.deproxy(movedNode.getParent());
210
        parent.removeChild(movedNode);
211
        if(position < 0){
212
            targetNode.addChild(movedNode);
213
        }
214
        else{
215
            targetNode.addChild(movedNode, position);
216
        }
217
        result.addUpdatedObject(targetNode);
218
        if(parent!=null){
219
            result.addUpdatedObject(parent);
220
        }
221
        result.setCdmEntity(movedNode);
222
        return result;
223
    }
224

    
225
    @Override
226
    public UpdateResult moveNode(UUID movedNodeUuid, UUID targetNodeUuid) {
227
        return moveNode(movedNodeUuid, targetNodeUuid, -1);
228
    }
229

    
230
    @Override
231
    public UpdateResult saveTermNodeDtoList(List<TermNodeDto> dtos){
232
        UpdateResult result = new UpdateResult();
233
        MergeResult<TermNode> mergeResult;
234
        List<UUID> uuids = new ArrayList<>();
235
        dtos.stream().forEach(dto -> uuids.add(dto.getUuid()));
236
        List<TermNode> nodes = dao.list(uuids, null, 0, null, null);
237
        //check all attributes for changes and adapt
238
        for (TermNode node: nodes){
239
            for (TermNodeDto dto: dtos){
240

    
241
                if (dto.getUuid().equals(node.getUuid())){
242
    //                only node changes, everything else will be handled by the operations/service methods
243
                    if (!dto.getInapplicableIf().equals(node.getInapplicableIf())){
244
                        node.getInapplicableIf().clear();
245
                        node.getInapplicableIf().addAll(dto.getInapplicableIf());
246
                    }
247
                    if (!dto.getOnlyApplicableIf().equals(node.getOnlyApplicableIf())){
248
                        node.getOnlyApplicableIf().clear();
249
                        node.getOnlyApplicableIf().addAll(dto.getOnlyApplicableIf());
250
                    }
251
                }
252
                mergeResult = dao.merge(node, true);
253
                result.addUpdatedObject(mergeResult.getMergedEntity());
254
            }
255
        }
256
        return result;
257
    }
258

    
259
    @Override
260
    public UpdateResult saveCharacterNodeDtoList(List<CharacterNodeDto> dtos){
261
        MergeResult<TermNode> mergeResult;
262
        UpdateResult result = new UpdateResult();
263
        List<UUID> nodeUuids = new ArrayList<>();
264

    
265
        dtos.stream().forEach(dto -> nodeUuids.add(dto.getUuid()));
266
        List<TermNode> nodes = dao.list(nodeUuids, null, 0, null, null);
267
        //check all attributes for changes and adapt
268
        for (TermNode<Character> node: nodes){
269
            for (CharacterNodeDto dto: dtos){
270
    //            TermNodeDto dto = dtoIterator.next();
271
                if (dto.getUuid().equals(node.getUuid())){
272

    
273
                    if (!dto.getInapplicableIf().equals(node.getInapplicableIf())){
274
                        node.getInapplicableIf().clear();
275
                        node.getInapplicableIf().addAll(dto.getInapplicableIf());
276
                    }
277
                    if (!dto.getOnlyApplicableIf().equals(node.getOnlyApplicableIf())){
278
                        node.getOnlyApplicableIf().clear();
279
                        node.getOnlyApplicableIf().addAll(dto.getOnlyApplicableIf());
280
                    }
281

    
282
                    Character character = null;
283
                    CharacterDto characterDto = (CharacterDto) dto.getTerm();
284
                    character = HibernateProxyHelper.deproxy(node.getTerm(), Character.class);
285

    
286
                    //supportsXXX
287
                    //TODO add all other supportsXXX (6 are missing)
288
                    character.setSupportsCategoricalData(characterDto.isSupportsCategoricalData());
289
                    character.setSupportsQuantitativeData(characterDto.isSupportsQuantitativeData());
290

    
291
                    //availableForXXX
292
                    character.setAvailableForTaxon(characterDto.isAvailableForTaxon());
293
                    character.setAvailableForOccurrence(characterDto.isAvailableForOccurrence());
294
                    character.setAvailableForTaxonName(characterDto.isAvailableForTaxonName());
295

    
296
//                  representations
297
                    for (Representation rep: dto.getTerm().getRepresentations()){
298
                        Representation oldRep = character.getRepresentation(rep.getLanguage());
299
                        if (oldRep == null){
300
                            oldRep = new Representation();
301
                            oldRep.setLanguage(rep.getLanguage());
302
                            character.addRepresentation(oldRep);
303
                        }
304
                        oldRep.setLabel(rep.getLabel());
305
                        oldRep.setAbbreviatedLabel(rep.getAbbreviatedLabel());
306
                        oldRep.setText(rep.getText());
307
                        oldRep.setPlural(rep.getPlural());
308
                    }
309
                    Set<Representation> deleteRepresentations = new HashSet<>();
310
                    if (character.getRepresentations().size() > dto.getTerm().getRepresentations().size()){
311
                        for (Representation rep: character.getRepresentations()){
312
                            if(dto.getTerm().getRepresentation(rep.getLanguage()) == null){
313
                                deleteRepresentations.add(rep);
314
                            }
315
                        }
316
                    }
317

    
318
                    if (!deleteRepresentations.isEmpty()){
319
                        for (Representation rep: deleteRepresentations){
320
                            character.removeRepresentation(rep);
321
                        }
322
                    }
323

    
324
//                  structural modifier
325
                    if (characterDto.getStructureModifier() != null){
326
                        DefinedTerm structureModifier = (DefinedTerm) termService.load(characterDto.getStructureModifier().getUuid());
327
                        character.setStructureModifier(structureModifier);
328
                    }else{
329
                        character.setStructureModifier(null);
330
                    }
331
//                  recommended measurement units
332
                    character.getRecommendedMeasurementUnits().clear();
333
                    List<UUID> uuids = new ArrayList<>();
334
                    for (TermDto termDto: characterDto.getRecommendedMeasurementUnits()){
335
                        uuids.add(termDto.getUuid());
336
                    }
337
                    List<DefinedTermBase> terms;
338
                    if (!uuids.isEmpty()){
339
                        terms = termService.load(uuids, null);
340
                        Set<MeasurementUnit> measurementUnits = new HashSet<>();
341
                        for (DefinedTermBase term: terms){
342
                            if (term instanceof MeasurementUnit){
343
                                measurementUnits.add((MeasurementUnit)term);
344
                            }
345
                        }
346
                        character.getRecommendedMeasurementUnits().addAll(measurementUnits);
347
                    }
348
//                  statistical measures
349
                    character.getRecommendedStatisticalMeasures().clear();
350
                    uuids = new ArrayList<>();
351
                    for (TermDto termDto: characterDto.getRecommendedStatisticalMeasures()){
352
                        uuids.add(termDto.getUuid());
353
                    }
354
                    if (!uuids.isEmpty()){
355
                        terms = termService.load(uuids, null);
356
                        Set<StatisticalMeasure> statisticalMeasures = new HashSet<>();
357
                        for (DefinedTermBase<?> term: terms){
358
                            if (term instanceof StatisticalMeasure){
359
                                statisticalMeasures.add((StatisticalMeasure)term);
360
                            }
361
                        }
362
                        character.getRecommendedStatisticalMeasures().addAll(statisticalMeasures);
363
                    }
364

    
365
//                  recommended mod. vocabularies
366
                    character.getRecommendedModifierEnumeration().clear();
367
                    uuids = new ArrayList<>();
368
                    for (TermVocabularyDto termDto: characterDto.getRecommendedModifierEnumeration()){
369
                        uuids.add(termDto.getUuid());
370
                    }
371
                    List<TermVocabulary> termVocs;
372
                    if (!uuids.isEmpty()){
373
                        termVocs = vocabularyService.load(uuids, null);
374
                        for (TermVocabulary voc: termVocs){
375
                            character.addRecommendedModifierEnumeration(voc);
376
                        }
377
                    }
378

    
379
//                  supported state vocabularies
380
                    character.getSupportedCategoricalEnumerations().clear();
381
                    uuids = new ArrayList<>();
382
                    for (TermVocabularyDto termDto: characterDto.getSupportedCategoricalEnumerations()){
383
                        uuids.add(termDto.getUuid());
384
                    }
385
                    if (!uuids.isEmpty()){
386
                        termVocs = vocabularyService.load(uuids, null);
387

    
388
                        for (TermVocabulary voc: termVocs){
389
                            character.addSupportedCategoricalEnumeration(voc);
390
                        }
391
                    }
392
                    node.setTerm(character);
393
                    mergeResult = dao.merge(node, true);
394
                    result.addUpdatedObject(mergeResult.getMergedEntity());
395
                }
396
            }
397
        }
398
        return result;
399
    }
400

    
401
    @Override
402
    public UpdateResult saveNewCharacterNodeDtoMap(Map<Character, CharacterNodeDto> dtos, UUID vocabularyUuid){
403
        UpdateResult result = new UpdateResult();
404
        UpdateResult resultLocal = new UpdateResult();
405
        for (Entry<Character, CharacterNodeDto> dtoEntry: dtos.entrySet()){
406
            resultLocal = createChildNode(dtoEntry.getValue().getParentUuid(), dtoEntry.getKey(), vocabularyUuid);
407
            dtoEntry.getValue().setUuid(resultLocal.getCdmEntity().getUuid());
408
            result.includeResult(resultLocal);
409
        }
410
        List<CharacterNodeDto> dtoList = new ArrayList<>(dtos.values());
411
        result.includeResult(saveCharacterNodeDtoList(dtoList));
412
        return result;
413

    
414
    }
415

    
416

    
417

    
418
}
(93-93/100)