Project

General

Profile

Download (26.2 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.vaadin.util.converter;
10

    
11
import java.util.ArrayList;
12
import java.util.Arrays;
13
import java.util.Collection;
14
import java.util.Collections;
15
import java.util.Comparator;
16
import java.util.HashMap;
17
import java.util.LinkedHashMap;
18
import java.util.LinkedList;
19
import java.util.List;
20
import java.util.Map;
21
import java.util.Optional;
22
import java.util.Set;
23

    
24
import org.hibernate.search.hcore.util.impl.HibernateHelper;
25

    
26
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeCacheStrategy;
27
import eu.etaxonomy.cdm.model.common.CdmBase;
28
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
29
import eu.etaxonomy.cdm.model.common.TermVocabulary;
30
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
31
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
32
import eu.etaxonomy.cdm.model.name.TaxonName;
33
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
34
import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;
35
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
36
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
37
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
38
import eu.etaxonomy.cdm.vaadin.model.EntityReference;
39
import eu.etaxonomy.cdm.vaadin.model.TypedEntityReference;
40
import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationValidationException;
41

    
42
/**
43
 * Manages a collection of {@link TypeDesignationBase TypeDesignations} for the same typified name.
44
 *
45
 * Type designations are ordered by the base type which is a {@link TaxonName} for {@link NameTypeDesignation NameTypeDesignations} or
46
 * in case of {@link SpecimenTypeDesignation SpecimenTypeDesignations} the  associate {@link FieldUnit} or the {@link DerivedUnit}
47
 * if the former is missing. The type designations per base type are furthermore ordered by the {@link TypeDesignationStatusBase}.
48
 *
49
 * The TypeDesignationSetManager also provides string representations of the whole ordered set of all
50
 * {@link TypeDesignationBase TypeDesignations} and of the TypeDesignationWorkingSets:
51
 * <ul>
52
 *  <li>{@link #print()})
53
 *  <li>{@link #getOrderdTypeDesignationWorkingSets()} ... {@link TypeDesignationWorkingSet#getRepresentation()}
54
 * </ul>
55
 * Prior using the representations you need to trigger their generation by calling {@link #buildString()}
56
 *
57
 * @author a.kohlbecker
58
 * @since Mar 10, 2017
59
 *
60
 */
61
public class TypeDesignationSetManager {
62

    
63

    
64
    private static final String TYPE_STATUS_SEPARATOR = "; ";
65

    
66
    private static final String TYPE_SEPARATOR = "; ";
67

    
68
    private static final String TYPE_DESIGNATION_SEPARATOR = ", ";
69

    
70
    private Collection<TypeDesignationBase> typeDesignations;
71

    
72
    private int workingSetIdAutoIncrement = 0;
73

    
74
    /**
75
     * Groups the EntityReferences for each of the TypeDesignations by the according TypeDesignationStatus.
76
     * The TypeDesignationStatusBase keys are already ordered by the term order defined in the vocabulary.
77
     */
78
    private LinkedHashMap<TypedEntityReference, TypeDesignationWorkingSet> orderedByTypesByBaseEntity;
79

    
80
    private EntityReference typifiedNameRef;
81

    
82
    private TaxonName typifiedName;
83

    
84
    private String finalString = null;
85

    
86
    final NullTypeDesignationStatus NULL_STATUS = new NullTypeDesignationStatus();
87

    
88
    private List<String> probelms = new ArrayList<>();
89

    
90
    private boolean printCitation = false;
91

    
92
    /**
93
     * @param containgEntity
94
     * @param taxonName
95
     * @throws RegistrationValidationException
96
     *
97
     */
98
    public TypeDesignationSetManager(Collection<TypeDesignationBase> typeDesignations) throws RegistrationValidationException {
99
        this.typeDesignations = typeDesignations;
100
        findTypifiedName();
101
        mapAndSort();
102
    }
103

    
104
    /**
105
     * @param typifiedName2
106
     */
107
    public TypeDesignationSetManager(TaxonName typifiedName) {
108
        this.typeDesignations = new ArrayList<>();
109
        this.typifiedNameRef = new EntityReference(typifiedName.getId(), typifiedName.getTitleCache());
110
    }
111

    
112
    /**
113
     * Add one or more TypeDesignations to the manager. This causes re-grouping and re-ordering
114
     * of all managed TypeDesignations.
115
     *
116
     * @param containgEntity
117
     * @param typeDesignations
118
     */
119
    public void addTypeDesigations(CdmBase containgEntity, TypeDesignationBase ... typeDesignations){
120
       this.typeDesignations.addAll(Arrays.asList(typeDesignations));
121
       mapAndSort();
122
    }
123

    
124
    /**
125
     * Groups and orders all managed TypeDesignations.
126
     *
127
     * @param containgEntity
128
     */
129
    protected void mapAndSort() {
130
        finalString = null;
131
        Map<TypedEntityReference, TypeDesignationWorkingSet> byBaseEntityByTypeStatus = new HashMap<>();
132
        this.typeDesignations.forEach(td -> mapTypeDesignation(byBaseEntityByTypeStatus, td));
133
        orderedByTypesByBaseEntity = orderByTypeByBaseEntity(byBaseEntityByTypeStatus);
134
    }
135

    
136

    
137
    /**
138
     *
139
     * @param containgEntity
140
     * @param byBaseEntityByTypeStatus
141
     * @param td
142
     */
143
    private void mapTypeDesignation(Map<TypedEntityReference, TypeDesignationWorkingSet> byBaseEntityByTypeStatus,
144
            TypeDesignationBase<?> td){
145

    
146
        TypeDesignationStatusBase<?> status = td.getTypeStatus();
147

    
148
        try {
149
            final IdentifiableEntity<?> baseEntity = baseEntity(td);
150
            final TypedEntityReference<IdentifiableEntity<?>> baseEntityReference = makeEntityReference(baseEntity);
151

    
152
            EntityReference typeDesignationEntityReference = new EntityReference(td.getId(), stringify(td));
153

    
154
            TypeDesignationWorkingSet typedesignationWorkingSet;
155
            if(!byBaseEntityByTypeStatus.containsKey(baseEntityReference)){
156
                byBaseEntityByTypeStatus.put(baseEntityReference, new TypeDesignationWorkingSet(baseEntity, baseEntityReference));
157
            }
158

    
159
            typedesignationWorkingSet = byBaseEntityByTypeStatus.get(baseEntityReference);
160
            typedesignationWorkingSet.insert(status, typeDesignationEntityReference);
161
        } catch (DataIntegrityException e){
162
            probelms.add(e.getMessage());
163
        }
164
    }
165

    
166
    /**
167
     * @param td
168
     * @return
169
     * @throws DataIntegrityException
170
     */
171
    protected IdentifiableEntity<?> baseEntity(TypeDesignationBase<?> td) throws DataIntegrityException {
172

    
173
        IdentifiableEntity<?> baseEntity = null;
174
        if(td  instanceof SpecimenTypeDesignation){
175
            SpecimenTypeDesignation std = (SpecimenTypeDesignation) td;
176
            FieldUnit fu = findFieldUnit(std);
177
            if(fu != null){
178
                baseEntity = fu;
179
            } else if(((SpecimenTypeDesignation) td).getTypeSpecimen() != null){
180
                baseEntity = ((SpecimenTypeDesignation) td).getTypeSpecimen();
181
            }
182
        } else if(td instanceof NameTypeDesignation){
183
            baseEntity = ((NameTypeDesignation)td).getTypeName();
184
        }
185
        if(baseEntity == null) {
186
            throw new DataIntegrityException("Incomplete TypeDesignation, no type missin in " + td.toString());
187
        }
188
        return baseEntity;
189
    }
190

    
191
    /**
192
     * @param td
193
     * @return
194
     */
195
    protected TypedEntityReference<IdentifiableEntity<?>> makeEntityReference(IdentifiableEntity<?> baseEntity) {
196

    
197
        baseEntity = (IdentifiableEntity<?>) HibernateHelper.unproxy(baseEntity);
198
        String label = "";
199
        if(baseEntity  instanceof FieldUnit){
200
                label = ((FieldUnit)baseEntity).getTitleCache();
201
        }
202

    
203
        TypedEntityReference<IdentifiableEntity<?>> baseEntityReference = new TypedEntityReference(baseEntity.getClass(), baseEntity.getId(), label);
204

    
205
        return baseEntityReference;
206
    }
207

    
208

    
209
    private LinkedHashMap<TypedEntityReference, TypeDesignationWorkingSet> orderByTypeByBaseEntity(
210
            Map<TypedEntityReference, TypeDesignationWorkingSet> stringsByTypeByBaseEntity){
211

    
212
       // order the FieldUnit TypeName keys
213
       List<TypedEntityReference> baseEntityKeyList = new LinkedList<>(stringsByTypeByBaseEntity.keySet());
214
       Collections.sort(baseEntityKeyList, new Comparator<TypedEntityReference>(){
215
        /**
216
         * Sorts the base entities (TypedEntityReference) in the following order:
217
         *
218
         * 1. FieldUnits
219
         * 2. DerivedUnit (in case of missing FieldUnit we expect the base type to be DerivedUnit)
220
         * 3. NameType
221
         *
222
         * {@inheritDoc}
223
         */
224
        @Override
225
        public int compare(TypedEntityReference o1, TypedEntityReference o2) {
226

    
227
            Class type1 = o1.getType();
228
            Class type2 = o2.getType();
229

    
230
            if(!type1.equals(type2)) {
231
                if(type1.equals(FieldUnit.class) || type2.equals(FieldUnit.class)){
232
                    // FieldUnits first
233
                    return type1.equals(FieldUnit.class) ? -1 : 1;
234
                } else {
235
                    // name types last (in case of missing FieldUnit we expect the base type to be DerivedUnit which comes into the middle)
236
                    return type2.equals(TaxonName.class) ? -1 : 1;
237
                }
238
            } else {
239
                return o1.getLabel().compareTo(o2.getLabel());
240
            }
241
        }});
242

    
243
       // new LinkedHashMap for the ordered FieldUnitOrTypeName keys
244
       LinkedHashMap<TypedEntityReference, TypeDesignationWorkingSet> stringsOrderedbyBaseEntityOrderdByType = new LinkedHashMap<>(stringsByTypeByBaseEntity.size());
245

    
246
       for(TypedEntityReference baseEntityRef : baseEntityKeyList){
247

    
248
           TypeDesignationWorkingSet typeDesignationWorkingSet = stringsByTypeByBaseEntity.get(baseEntityRef);
249
           // order the TypeDesignationStatusBase keys
250
            List<TypeDesignationStatusBase<?>> keyList = new LinkedList<>(typeDesignationWorkingSet.keySet());
251
            Collections.sort(keyList, new Comparator<TypeDesignationStatusBase>() {
252
                @SuppressWarnings("unchecked")
253
                @Override
254
                public int compare(TypeDesignationStatusBase o1, TypeDesignationStatusBase o2) {
255
                    // fix inverted order of cdm terms by -1*
256
                    return -1 * o1.compareTo(o2);
257
                }
258
            });
259
            // new LinkedHashMap for the ordered TypeDesignationStatusBase keys
260
            TypeDesignationWorkingSet orderedStringsByOrderedTypes = new TypeDesignationWorkingSet(
261
                    typeDesignationWorkingSet.getBaseEntity(),
262
                    baseEntityRef);
263
            orderedStringsByOrderedTypes.setWorkingSetId(typeDesignationWorkingSet.workingSetId); // preserve original workingSetId
264
            keyList.forEach(key -> orderedStringsByOrderedTypes.put(key, typeDesignationWorkingSet.get(key)));
265
            stringsOrderedbyBaseEntityOrderdByType.put(baseEntityRef, orderedStringsByOrderedTypes);
266
       }
267

    
268
        return stringsOrderedbyBaseEntityOrderdByType;
269
    }
270

    
271
    /*
272
    private LinkedHashMap<TypedEntityReference, LinkedHashMap<String, Collection<EntityReference>>> buildOrderedRepresentations(){
273

    
274
        orderedStringsByOrderedTypes.keySet().forEach(
275
                key -> orderedRepresentations.put(
276
                        getTypeDesignationStytusLabel(key),
277
                        orderedStringsByOrderedTypes.get(key))
278
                );
279
        return orderedRepresentations;
280
    }
281
*/
282

    
283
    public TypeDesignationSetManager buildString(){
284

    
285
        if(finalString == null){
286

    
287
            finalString = "";
288
            if(getTypifiedNameCache() != null){
289
                finalString += getTypifiedNameCache() + " ";
290
            }
291

    
292
            int typeCount = 0;
293
            if(orderedByTypesByBaseEntity != null){
294
                for(TypedEntityReference baseEntityRef : orderedByTypesByBaseEntity.keySet()) {
295
                    StringBuilder sb = new StringBuilder();
296
                    if(typeCount++ > 0){
297
                        sb.append(TYPE_SEPARATOR);
298
                    }
299
                    boolean isNameTypeDesignation = false;
300
                    if(SpecimenOrObservationBase.class.isAssignableFrom(baseEntityRef.getType())){
301
                        sb.append("Type: ");
302
                    } else {
303
                        sb.append("NameType: ");
304
                        isNameTypeDesignation = true;
305
                    }
306
                    if(!baseEntityRef.getLabel().isEmpty()){
307
                        sb.append(baseEntityRef.getLabel()).append(" ");
308
                    }
309
                    TypeDesignationWorkingSet typeDesignationWorkingSet = orderedByTypesByBaseEntity.get(baseEntityRef);
310
                    if(!isNameTypeDesignation ){
311
                        sb.append("(");
312
                    }
313
                    int typeStatusCount = 0;
314
                    for(TypeDesignationStatusBase<?> typeStatus : typeDesignationWorkingSet.keySet()) {
315
                        if(typeStatusCount++  > 0){
316
                            sb.append(TYPE_STATUS_SEPARATOR);
317
                        }
318
                        boolean isPlural = typeDesignationWorkingSet.get(typeStatus).size() > 1;
319
                        if(!typeStatus.equals(NULL_STATUS)) {
320
                            sb.append(typeStatus.getLabel());
321
                            if(isPlural){
322
                                sb.append("s: ");
323
                            } else {
324
                                sb.append(", ");
325
                            }
326
                        }
327
                        int typeDesignationCount = 0;
328
                        for(EntityReference typeDesignationEntityReference : typeDesignationWorkingSet.get(typeStatus)) {
329
                            if(typeDesignationCount++  > 0){
330
                                sb.append(TYPE_DESIGNATION_SEPARATOR);
331
                            }
332
                            sb.append(typeDesignationEntityReference.getLabel());
333
                        }
334
                    }
335
                    if(!isNameTypeDesignation ){
336
                        sb.append(")");
337
                    }
338
                    typeDesignationWorkingSet.setRepresentation(sb.toString());
339
                    finalString += typeDesignationWorkingSet.getRepresentation();
340
                }
341
            }
342
        }
343
        return this;
344
    }
345

    
346
    /**
347
     * FIXME use the validation framework validators and to store the validation problems!!!
348
     *
349
     * @return
350
     * @throws RegistrationValidationException
351
     */
352
    private void findTypifiedName() throws RegistrationValidationException {
353

    
354
        List<String> problems = new ArrayList<>();
355

    
356
        TaxonName typifiedName = null;
357

    
358
        for(TypeDesignationBase<?> typeDesignation : typeDesignations){
359
            typeDesignation.getTypifiedNames();
360
            if(typeDesignation.getTypifiedNames().isEmpty()){
361

    
362
                //TODO instead throw RegistrationValidationException()
363
                problems.add("Missing typifiedName in " + typeDesignation.toString());
364
                continue;
365
            }
366
            if(typeDesignation.getTypifiedNames().size() > 1){
367
              //TODO instead throw RegistrationValidationException()
368
                problems.add("Multiple typifiedName in " + typeDesignation.toString());
369
                continue;
370
            }
371
            if(typifiedName == null){
372
                // remember
373
                typifiedName = typeDesignation.getTypifiedNames().iterator().next();
374
            } else {
375
                // compare
376
                TaxonName otherTypifiedName = typeDesignation.getTypifiedNames().iterator().next();
377
                if(typifiedName.getId() != otherTypifiedName.getId()){
378
                  //TODO instead throw RegistrationValidationException()
379
                    problems.add("Multiple typifiedName in " + typeDesignation.toString());
380
                }
381
            }
382

    
383
        }
384
        if(!problems.isEmpty()){
385
            // FIXME use the validation framework
386
            throw new RegistrationValidationException("Inconsistent type designations", problems);
387
        }
388

    
389
        if(typifiedName != null){
390
            // ON SUCCESS -------------------
391
            this.typifiedName = typifiedName;
392
            this.typifiedNameRef = new EntityReference(typifiedName.getId(), typifiedName.getTitleCache());
393

    
394
        }
395
    }
396

    
397

    
398
    /**
399
     * @return the title cache of the typifying name or <code>null</code>
400
     */
401
    public String getTypifiedNameCache() {
402
        if(typifiedNameRef != null){
403
            return typifiedNameRef.getLabel();
404
        }
405
        return null;
406
    }
407

    
408
    /**
409
     * @return the title cache of the typifying name or <code>null</code>
410
     */
411
    public EntityReference getTypifiedNameRef() {
412

    
413
       return typifiedNameRef;
414
    }
415

    
416
    /**
417
     * @return
418
     */
419
    public Collection<TypeDesignationBase> getTypeDesignations() {
420
        return typeDesignations;
421
    }
422

    
423
    /**
424
     * @param ref
425
     * @return
426
     */
427
    public TypeDesignationBase findTypeDesignation(EntityReference typeDesignationRef) {
428
        for(TypeDesignationBase td : typeDesignations){
429
            if(td.getId() == typeDesignationRef.getId()){
430
                return td;
431
            }
432
        }
433
        // TODO Auto-generated method stub
434
        return null;
435
    }
436

    
437

    
438
    public LinkedHashMap<TypedEntityReference, TypeDesignationWorkingSet> getOrderdTypeDesignationWorkingSets() {
439
        return orderedByTypesByBaseEntity;
440
    }
441

    
442
    /**
443
     * @param td
444
     * @return
445
     */
446
    private String stringify(TypeDesignationBase td) {
447

    
448
        if(td instanceof NameTypeDesignation){
449
            return stringify((NameTypeDesignation)td);
450
        } else {
451
            return stringify((SpecimenTypeDesignation)td, false);
452
        }
453
    }
454

    
455

    
456
    /**
457
     * @param td
458
     * @return
459
     */
460
    protected String stringify(NameTypeDesignation td) {
461

    
462
        StringBuffer sb = new StringBuffer();
463

    
464
        if(td.getTypeName() != null){
465
            sb.append(td.getTypeName().getTitleCache());
466
        }
467
        if(td.getCitation() != null){
468
            sb.append(" ").append(td.getCitation().getTitleCache());
469
            if(td.getCitationMicroReference() != null){
470
                sb.append(":").append(td.getCitationMicroReference());
471
            }
472
        }
473
        if(td.isNotDesignated()){
474
            sb.append(" not designated");
475
        }
476
        if(td.isRejectedType()){
477
            sb.append(" rejected");
478
        }
479
        if(td.isConservedType()){
480
            sb.append(" conserved");
481
        }
482
        return sb.toString();
483
    }
484

    
485
    /**
486
     * @param td
487
     * @return
488
     */
489
    private String stringify(SpecimenTypeDesignation td, boolean useFullTitleCache) {
490
        String  result = "";
491

    
492
        if(useFullTitleCache){
493
            if(td.getTypeSpecimen() != null){
494
                String nameTitleCache = td.getTypeSpecimen().getTitleCache();
495
                if(getTypifiedNameCache() != null){
496
                    nameTitleCache = nameTitleCache.replace(getTypifiedNameCache(), "");
497
                }
498
                result += nameTitleCache;
499
            }
500
        } else {
501
            if(td.getTypeSpecimen() != null){
502
                DerivedUnit du = td.getTypeSpecimen();
503
                if(du.isProtectedTitleCache()){
504
                    result += du.getTitleCache();
505
                } else {
506
                    DerivedUnitFacadeCacheStrategy cacheStrategy = new DerivedUnitFacadeCacheStrategy();
507
                    result += cacheStrategy.getTitleCache(du, true);
508
                }
509
            }
510
        }
511

    
512
        if(isPrintCitation() && td.getCitation() != null){
513
            if(td.getCitation().getAbbrevTitle() != null){
514
                result += " " + td.getCitation().getAbbrevTitle();
515
            } else {
516
                result += " " + td.getCitation().getTitleCache();
517
            }
518
            if(td.getCitationMicroReference() != null){
519
                result += " :" + td.getCitationMicroReference();
520
            }
521
        }
522
        if(td.isNotDesignated()){
523
            result += " not designated";
524
        }
525

    
526
        return result;
527
    }
528

    
529
    /**
530
     * @param td
531
     * @return
532
     * @deprecated
533
     */
534
    @Deprecated
535
    private FieldUnit findFieldUnit(SpecimenTypeDesignation td) {
536

    
537
        DerivedUnit du = td.getTypeSpecimen();
538
        return findFieldUnit(du);
539
    }
540

    
541
    private FieldUnit findFieldUnit(DerivedUnit du) {
542

    
543
        if(du == null || du.getOriginals() == null){
544
            return null;
545
        }
546
        @SuppressWarnings("rawtypes")
547
        Set<SpecimenOrObservationBase> originals = du.getDerivedFrom().getOriginals();
548
        @SuppressWarnings("rawtypes")
549
        Optional<SpecimenOrObservationBase> fieldUnit = originals.stream()
550
                .filter(original -> original instanceof FieldUnit).findFirst();
551
        if (fieldUnit.isPresent()) {
552
            return (FieldUnit) fieldUnit.get();
553
        } else {
554
            for (@SuppressWarnings("rawtypes")
555
            SpecimenOrObservationBase sob : originals) {
556
                if (sob instanceof DerivedUnit) {
557
                    FieldUnit fu = findFieldUnit((DerivedUnit) sob);
558
                    if (fu != null) {
559
                        return fu;
560
                    }
561
                }
562
            }
563
        }
564

    
565
        return null;
566
    }
567

    
568
    public String print() {
569
        return finalString.trim();
570
    }
571

    
572
    /**
573
     * @return the printCitation
574
     */
575
    public boolean isPrintCitation() {
576
        return printCitation;
577
    }
578

    
579
    /**
580
     * @param printCitation the printCitation to set
581
     */
582
    public void setPrintCitation(boolean printCitation) {
583
        this.printCitation = printCitation;
584
    }
585

    
586
    /**
587
     * @return the typifiedName
588
     */
589
    public TaxonName getTypifiedName() {
590
        return typifiedName;
591
    }
592

    
593
    /**
594
     * TypeDesignations which refer to the same FieldUnit (SpecimenTypeDesignation) or TaxonName
595
     * (NameTypeDesignation) form a working set. The <code>TypeDesignationWorkingSet</code> internally
596
     * works with EnityReferences to the actual TypeDesignations.
597
     *
598
     * The EntityReferences for TypeDesignations are grouped by the according TypeDesignationStatus.
599
     * The TypeDesignationStatusBase keys can be ordered by the term order defined in the vocabulary.
600
     *
601
     * A workingset can be referenced by the <code>workingSetId</code>, this is a autoincrement
602
     * value which is created during the process of determining the workingsets in a collection of
603
     * TypeDesignations.
604
     *
605
     * TODO: consider using a concatenation of baseEntity.getClass() + baseEntity.getId() as workingset identifier
606
     */
607
    public class TypeDesignationWorkingSet extends LinkedHashMap<TypeDesignationStatusBase<?>, Collection<EntityReference>> {
608

    
609
        private static final long serialVersionUID = -1329007606500890729L;
610

    
611
        String workingSetRepresentation = null;
612

    
613
        TypedEntityReference<IdentifiableEntity<?>> baseEntityReference;
614

    
615
        IdentifiableEntity<?> baseEntity;
616

    
617
        List<DerivedUnit> derivedUnits = null;
618

    
619
        int workingSetId = workingSetIdAutoIncrement++;
620

    
621
        /**
622
         * @param baseEntityReference
623
         */
624
        public TypeDesignationWorkingSet(IdentifiableEntity<?> baseEntity, TypedEntityReference<IdentifiableEntity<?>> baseEntityReference) {
625
            this.baseEntity = baseEntity;
626
            this.baseEntityReference = baseEntityReference;
627
        }
628

    
629
        /**
630
         * @return
631
         */
632
        public IdentifiableEntity<?> getBaseEntity() {
633
            return baseEntity;
634
        }
635

    
636
        public List<EntityReference> getTypeDesignations() {
637
            List<EntityReference> typeDesignations = new ArrayList<>();
638
            this.values().forEach(typeDesignationReferences -> typeDesignationReferences.forEach(td -> typeDesignations.add(td)));
639
            return typeDesignations;
640
        }
641

    
642
        /**
643
         * @param status
644
         * @param typeDesignationEntityReference
645
         */
646
        public void insert(TypeDesignationStatusBase<?> status, EntityReference typeDesignationEntityReference) {
647

    
648
            if(status == null){
649
                status = NULL_STATUS;
650
            }
651
            if(!containsKey(status)){
652
                put(status, new ArrayList<EntityReference>());
653
            }
654
            get(status).add(typeDesignationEntityReference);
655
        }
656

    
657
        /**
658
         * @return the workingSetId
659
         */
660
        public int getWorkingSetId() {
661
            return workingSetId;
662
        }
663

    
664
        /**
665
         * @param workingSetId the workingSetId to set
666
         */
667
        public void setWorkingSetId(int workingSetId) {
668
            this.workingSetId = workingSetId;
669
        }
670

    
671
        public String getRepresentation() {
672
            return workingSetRepresentation;
673
        }
674

    
675
        public void setRepresentation(String representation){
676
            this.workingSetRepresentation = representation;
677
        }
678

    
679
        /**
680
         * A reference to the entity which is the common base entity for all TypeDesignations in this workingset.
681
         * For a {@link SpecimenTypeDesignation} this is usually the {@link FieldUnit} if it is present. Otherwise it can also be
682
         * a {@link DerivedUnit} or something else depending on the specific use case.
683
         *
684
         * @return the baseEntityReference
685
         */
686
        public TypedEntityReference getBaseEntityReference() {
687
            return baseEntityReference;
688
        }
689

    
690
        @Override
691
        public String toString(){
692
            if(workingSetRepresentation != null){
693
                return workingSetRepresentation;
694
            } else {
695
                return super.toString();
696
            }
697
        }
698

    
699
        /**
700
         * @return
701
         */
702
        public boolean isSpecimenTypeDesigationWorkingSet() {
703
            return SpecimenOrObservationBase.class.isAssignableFrom(baseEntityReference.getType());
704
        }
705

    
706
        public TypeDesignationWorkingSetType getWorkingsetType() {
707
            return isSpecimenTypeDesigationWorkingSet() ? TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET : TypeDesignationWorkingSetType.NAME_TYPE_DESIGNATION_WORKINGSET;
708
        }
709

    
710
    }
711

    
712
    public enum TypeDesignationWorkingSetType {
713
        SPECIMEN_TYPE_DESIGNATION_WORKINGSET,
714
        NAME_TYPE_DESIGNATION_WORKINGSET,
715
    }
716

    
717
    @SuppressWarnings({ "deprecation", "serial" })
718
    class NullTypeDesignationStatus extends TypeDesignationStatusBase<NullTypeDesignationStatus>{
719

    
720
        /**
721
         * {@inheritDoc}
722
         */
723
        @Override
724
        public void resetTerms() {
725
            // empty
726

    
727
        }
728

    
729
        /**
730
         * {@inheritDoc}
731
         */
732
        @Override
733
        protected void setDefaultTerms(TermVocabulary<NullTypeDesignationStatus> termVocabulary) {
734
            // empty
735
        }
736

    
737
    }
738

    
739
}
(6-6/7)