Project

General

Profile

Download (17.9 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
	     if (node == null){
157
	         result.setError();
158
             result.addException(new Exception("The parent node does not exist."));
159
             return result;
160
	     }
161
	     DefinedTermBase child = HibernateProxyHelper.deproxy(termService.load(termChildUuid), DefinedTermBase.class);
162

    
163
	     if(node != null && node.getGraph() != null && !node.getGraph().isAllowDuplicates() && node.getGraph().getDistinctTerms().contains(child)){
164
	         result.setError();
165
	         result.addException(new Exception("This term tree does not allow duplicate terms."));
166
	         return result;
167
	     }
168

    
169
	     TermNode childNode;
170
         if(position<0) {
171
             childNode = node.addChild(child);
172
         }
173
         else{
174
             childNode = node.addChild(child, position);
175
         }
176
         save(childNode);
177
         result.addUpdatedObject(node);
178
         result.setCdmEntity(childNode);
179
         return result;
180
     }
181

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

    
200
	     }
201
	     return result;
202
	 }
203

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

    
230
    @Override
231
    public UpdateResult moveNode(UUID movedNodeUuid, UUID targetNodeUuid) {
232
        return moveNode(movedNodeUuid, targetNodeUuid, -1);
233
    }
234

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

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

    
264
    @Override
265
    public UpdateResult saveCharacterNodeDtoList(List<CharacterNodeDto> dtos){
266
        MergeResult<TermNode> mergeResult;
267
        UpdateResult result = new UpdateResult();
268
        List<UUID> nodeUuids = new ArrayList<>();
269

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

    
278
                    if (!dto.getInapplicableIf().equals(node.getInapplicableIf())){
279
                        node.getInapplicableIf().clear();
280
                        node.getInapplicableIf().addAll(dto.getInapplicableIf());
281
                    }
282
                    if (!dto.getOnlyApplicableIf().equals(node.getOnlyApplicableIf())){
283
                        node.getOnlyApplicableIf().clear();
284
                        node.getOnlyApplicableIf().addAll(dto.getOnlyApplicableIf());
285
                    }
286

    
287
                    Character character = null;
288
                    CharacterDto characterDto = (CharacterDto) dto.getTerm();
289
                    character = HibernateProxyHelper.deproxy(node.getTerm(), Character.class);
290
                    if (characterDto.getRatioTo() != null){
291
                        TermNode ratioToStructure = this.load(characterDto.getRatioTo().getUuid());
292
                        character.setRatioToStructure(ratioToStructure);
293
                    }else{
294
                        character.setRatioToStructure(null);
295
                    }
296

    
297
                    //supportsXXX
298
                    //TODO add all other supportsXXX (6 are missing)
299
                    character.setSupportsCategoricalData(characterDto.isSupportsCategoricalData());
300
                    character.setSupportsQuantitativeData(characterDto.isSupportsQuantitativeData());
301

    
302
                    //availableForXXX
303
                    character.setAvailableForTaxon(characterDto.isAvailableForTaxon());
304
                    character.setAvailableForOccurrence(characterDto.isAvailableForOccurrence());
305
                    character.setAvailableForTaxonName(characterDto.isAvailableForTaxonName());
306

    
307
//                  representations
308
                    for (Representation rep: dto.getTerm().getRepresentations()){
309
                        Representation oldRep = character.getRepresentation(rep.getLanguage());
310
                        if (oldRep == null){
311
                            oldRep = new Representation();
312
                            oldRep.setLanguage(rep.getLanguage());
313
                            character.addRepresentation(oldRep);
314
                        }
315
                        oldRep.setLabel(rep.getLabel());
316
                        oldRep.setAbbreviatedLabel(rep.getAbbreviatedLabel());
317
                        oldRep.setText(rep.getText());
318
                        oldRep.setPlural(rep.getPlural());
319
                    }
320
                    Set<Representation> deleteRepresentations = new HashSet<>();
321
                    if (character.getRepresentations().size() > dto.getTerm().getRepresentations().size()){
322
                        for (Representation rep: character.getRepresentations()){
323
                            if(dto.getTerm().getRepresentation(rep.getLanguage()) == null){
324
                                deleteRepresentations.add(rep);
325
                            }
326
                        }
327
                    }
328

    
329
                    if (!deleteRepresentations.isEmpty()){
330
                        for (Representation rep: deleteRepresentations){
331
                            character.removeRepresentation(rep);
332
                        }
333
                    }
334

    
335
//                  structural modifier
336
                    if (characterDto.getStructureModifier() != null){
337
                        DefinedTerm structureModifier = (DefinedTerm) termService.load(characterDto.getStructureModifier().getUuid());
338
                        character.setStructureModifier(structureModifier);
339
                    }else{
340
                        character.setStructureModifier(null);
341
                    }
342
//                  recommended measurement units
343
                    character.getRecommendedMeasurementUnits().clear();
344
                    List<UUID> uuids = new ArrayList<>();
345
                    for (TermDto termDto: characterDto.getRecommendedMeasurementUnits()){
346
                        uuids.add(termDto.getUuid());
347
                    }
348
                    List<DefinedTermBase> terms;
349
                    if (!uuids.isEmpty()){
350
                        terms = termService.load(uuids, null);
351
                        Set<MeasurementUnit> measurementUnits = new HashSet<>();
352
                        for (DefinedTermBase term: terms){
353
                            if (term instanceof MeasurementUnit){
354
                                measurementUnits.add((MeasurementUnit)term);
355
                            }
356
                        }
357
                        character.getRecommendedMeasurementUnits().addAll(measurementUnits);
358
                    }
359
//                  statistical measures
360
                    character.getRecommendedStatisticalMeasures().clear();
361
                    uuids = new ArrayList<>();
362
                    for (TermDto termDto: characterDto.getRecommendedStatisticalMeasures()){
363
                        uuids.add(termDto.getUuid());
364
                    }
365
                    if (!uuids.isEmpty()){
366
                        terms = termService.load(uuids, null);
367
                        Set<StatisticalMeasure> statisticalMeasures = new HashSet<>();
368
                        for (DefinedTermBase<?> term: terms){
369
                            if (term instanceof StatisticalMeasure){
370
                                statisticalMeasures.add((StatisticalMeasure)term);
371
                            }
372
                        }
373
                        character.getRecommendedStatisticalMeasures().addAll(statisticalMeasures);
374
                    }
375

    
376
//                  recommended mod. vocabularies
377
                    character.getRecommendedModifierEnumeration().clear();
378
                    uuids = new ArrayList<>();
379
                    for (TermVocabularyDto termDto: characterDto.getRecommendedModifierEnumeration()){
380
                        uuids.add(termDto.getUuid());
381
                    }
382
                    List<TermVocabulary> termVocs;
383
                    if (!uuids.isEmpty()){
384
                        termVocs = vocabularyService.load(uuids, null);
385
                        for (TermVocabulary voc: termVocs){
386
                            character.addRecommendedModifierEnumeration(voc);
387
                        }
388
                    }
389

    
390
//                  supported state vocabularies
391
                    character.getSupportedCategoricalEnumerations().clear();
392
                    uuids = new ArrayList<>();
393
                    for (TermVocabularyDto termDto: characterDto.getSupportedCategoricalEnumerations()){
394
                        uuids.add(termDto.getUuid());
395
                    }
396
                    if (!uuids.isEmpty()){
397
                        termVocs = vocabularyService.load(uuids, null);
398

    
399
                        for (TermVocabulary voc: termVocs){
400
                            character.addSupportedCategoricalEnumeration(voc);
401
                        }
402
                    }
403
                    node.setTerm(character);
404
                    mergeResult = dao.merge(node, true);
405
                    result.addUpdatedObject(mergeResult.getMergedEntity());
406
                }
407
            }
408
        }
409
        return result;
410
    }
411

    
412
    @Override
413
    public UpdateResult saveNewCharacterNodeDtoMap(Map<Character, CharacterNodeDto> dtos, UUID vocabularyUuid){
414
        UpdateResult result = new UpdateResult();
415
        UpdateResult resultLocal = new UpdateResult();
416
        for (Entry<Character, CharacterNodeDto> dtoEntry: dtos.entrySet()){
417
            resultLocal = createChildNode(dtoEntry.getValue().getParentUuid(), dtoEntry.getKey(), vocabularyUuid);
418
            dtoEntry.getValue().setUuid(resultLocal.getCdmEntity().getUuid());
419
            result.includeResult(resultLocal);
420
        }
421
        List<CharacterNodeDto> dtoList = new ArrayList<>(dtos.values());
422
        result.includeResult(saveCharacterNodeDtoList(dtoList));
423
        return result;
424

    
425
    }
426

    
427

    
428

    
429
}
(90-90/97)