Project

General

Profile

Download (25.8 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 eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeCacheStrategy;
25
import eu.etaxonomy.cdm.model.common.CdmBase;
26
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
27
import eu.etaxonomy.cdm.model.common.TermVocabulary;
28
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
29
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
30
import eu.etaxonomy.cdm.model.name.TaxonName;
31
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
32
import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;
33
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
34
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
35
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
36
import eu.etaxonomy.cdm.vaadin.model.EntityReference;
37
import eu.etaxonomy.cdm.vaadin.model.TypedEntityReference;
38
import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationValidationException;
39

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

    
61

    
62
    private static final String TYPE_STATUS_SEPARATOR = "; ";
63

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

    
66
    private static final String TYPE_DESIGNATION_SEPARATOR = ", ";
67

    
68
    private Collection<TypeDesignationBase> typeDesignations;
69

    
70
    private int workingSetIdAutoIncrement = 0;
71

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

    
78
    private EntityReference typifiedName;
79

    
80
    private String finalString = null;
81

    
82
    final NullTypeDesignationStatus NULL_STATUS = new NullTypeDesignationStatus();
83

    
84
    private List<String> probelms = new ArrayList<>();
85

    
86
    private boolean printCitation = false;
87

    
88
    /**
89
     * @param containgEntity
90
     * @param taxonName
91
     * @throws RegistrationValidationException
92
     *
93
     */
94
    public TypeDesignationSetManager(Collection<TypeDesignationBase> typeDesignations) throws RegistrationValidationException {
95
        this.typeDesignations = typeDesignations;
96
        this.typifiedName = findTypifiedName();
97
        mapAndSort();
98
    }
99

    
100
    /**
101
     * @param typifiedName2
102
     */
103
    public TypeDesignationSetManager(TaxonName typifiedName) {
104
        this.typeDesignations = new ArrayList<>();
105
        this.typifiedName = new EntityReference(typifiedName.getId(), typifiedName.getTitleCache());
106
    }
107

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

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

    
132

    
133
    /**
134
     *
135
     * @param containgEntity
136
     * @param byBaseEntityByTypeStatus
137
     * @param td
138
     */
139
    private void mapTypeDesignation(Map<TypedEntityReference, TypeDesignationWorkingSet> byBaseEntityByTypeStatus,
140
            TypeDesignationBase<?> td){
141

    
142
        TypeDesignationStatusBase<?> status = td.getTypeStatus();
143

    
144
        try {
145
            final IdentifiableEntity<?> baseEntity = baseEntity(td);
146
            final TypedEntityReference<IdentifiableEntity<?>> baseEntityReference = makeEntityReference(baseEntity);
147

    
148
            EntityReference typeDesignationEntityReference = new EntityReference(td.getId(), stringify(td));
149

    
150
            TypeDesignationWorkingSet typedesignationWorkingSet;
151
            if(!byBaseEntityByTypeStatus.containsKey(baseEntityReference)){
152
                byBaseEntityByTypeStatus.put(baseEntityReference, new TypeDesignationWorkingSet(baseEntity, baseEntityReference));
153
            }
154

    
155
            typedesignationWorkingSet = byBaseEntityByTypeStatus.get(baseEntityReference);
156
            typedesignationWorkingSet.insert(status, typeDesignationEntityReference);
157
        } catch (DataIntegrityException e){
158
            probelms.add(e.getMessage());
159
        }
160
    }
161

    
162
    /**
163
     * @param td
164
     * @return
165
     * @throws DataIntegrityException
166
     */
167
    protected IdentifiableEntity<?> baseEntity(TypeDesignationBase<?> td) throws DataIntegrityException {
168

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

    
187
    /**
188
     * @param td
189
     * @return
190
     */
191
    protected TypedEntityReference<IdentifiableEntity<?>> makeEntityReference(IdentifiableEntity<?> baseEntity) {
192
;
193
        String label = "";
194
        if(baseEntity  instanceof FieldUnit){
195
                label = ((FieldUnit)baseEntity).getTitleCache();
196
        }
197

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

    
200
        return baseEntityReference;
201
    }
202

    
203

    
204
    private LinkedHashMap<TypedEntityReference, TypeDesignationWorkingSet> orderByTypeByBaseEntity(
205
            Map<TypedEntityReference, TypeDesignationWorkingSet> stringsByTypeByBaseEntity){
206

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

    
222
            Class type1 = o1.getType();
223
            Class type2 = o2.getType();
224

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

    
238
       // new LinkedHashMap for the ordered FieldUnitOrTypeName keys
239
       LinkedHashMap<TypedEntityReference, TypeDesignationWorkingSet> stringsOrderedbyBaseEntityOrderdByType = new LinkedHashMap<>(stringsByTypeByBaseEntity.size());
240

    
241
       for(TypedEntityReference baseEntityRef : baseEntityKeyList){
242

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

    
263
        return stringsOrderedbyBaseEntityOrderdByType;
264
    }
265

    
266
    /*
267
    private LinkedHashMap<TypedEntityReference, LinkedHashMap<String, Collection<EntityReference>>> buildOrderedRepresentations(){
268

    
269
        orderedStringsByOrderedTypes.keySet().forEach(
270
                key -> orderedRepresentations.put(
271
                        getTypeDesignationStytusLabel(key),
272
                        orderedStringsByOrderedTypes.get(key))
273
                );
274
        return orderedRepresentations;
275
    }
276
*/
277

    
278
    public TypeDesignationSetManager buildString(){
279

    
280
        if(finalString == null){
281

    
282
            finalString = "";
283
            if(getTypifiedNameCache() != null){
284
                finalString += getTypifiedNameCache() + " ";
285
            }
286

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

    
341
    /**
342
     * FIXME use the validation framework validators and to store the validation problems!!!
343
     *
344
     * @return
345
     * @throws RegistrationValidationException
346
     */
347
    private EntityReference findTypifiedName() throws RegistrationValidationException {
348

    
349
        List<String> problems = new ArrayList<>();
350

    
351
        TaxonName typifiedName = null;
352

    
353
        for(TypeDesignationBase<?> typeDesignation : typeDesignations){
354
            typeDesignation.getTypifiedNames();
355
            if(typeDesignation.getTypifiedNames().isEmpty()){
356

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

    
378
        }
379
        if(!problems.isEmpty()){
380
            // FIXME use the validation framework
381
            throw new RegistrationValidationException("Inconsistent type designations", problems);
382
        }
383

    
384
        if(typifiedName != null){
385
            return new EntityReference(typifiedName.getId(), typifiedName.getTitleCache());
386
        }
387
        return null;
388
    }
389

    
390

    
391
    /**
392
     * @return the title cache of the typifying name or <code>null</code>
393
     */
394
    public String getTypifiedNameCache() {
395
        if(typifiedName != null){
396
            return typifiedName.getLabel();
397
        }
398
        return null;
399
    }
400

    
401
    /**
402
     * @return the title cache of the typifying name or <code>null</code>
403
     */
404
    public EntityReference getTypifiedName() {
405

    
406
       return typifiedName;
407
    }
408

    
409
    /**
410
     * @return
411
     */
412
    public Collection<TypeDesignationBase> getTypeDesignations() {
413
        return typeDesignations;
414
    }
415

    
416
    /**
417
     * @param ref
418
     * @return
419
     */
420
    public TypeDesignationBase findTypeDesignation(EntityReference typeDesignationRef) {
421
        for(TypeDesignationBase td : typeDesignations){
422
            if(td.getId() == typeDesignationRef.getId()){
423
                return td;
424
            }
425
        }
426
        // TODO Auto-generated method stub
427
        return null;
428
    }
429

    
430

    
431
    public LinkedHashMap<TypedEntityReference, TypeDesignationWorkingSet> getOrderdTypeDesignationWorkingSets() {
432
        return orderedByTypesByBaseEntity;
433
    }
434

    
435
    /**
436
     * @param td
437
     * @return
438
     */
439
    private String stringify(TypeDesignationBase td) {
440

    
441
        if(td instanceof NameTypeDesignation){
442
            return stringify((NameTypeDesignation)td);
443
        } else {
444
            return stringify((SpecimenTypeDesignation)td, false);
445
        }
446
    }
447

    
448

    
449
    /**
450
     * @param td
451
     * @return
452
     */
453
    protected String stringify(NameTypeDesignation td) {
454

    
455
        StringBuffer sb = new StringBuffer();
456

    
457
        if(td.getTypeName() != null){
458
            sb.append(td.getTypeName().getTitleCache());
459
        }
460
        if(td.getCitation() != null){
461
            sb.append(" ").append(td.getCitation().getTitleCache());
462
            if(td.getCitationMicroReference() != null){
463
                sb.append(":").append(td.getCitationMicroReference());
464
            }
465
        }
466
        if(td.isNotDesignated()){
467
            sb.append(" not designated");
468
        }
469
        if(td.isRejectedType()){
470
            sb.append(" rejected");
471
        }
472
        if(td.isConservedType()){
473
            sb.append(" conserved");
474
        }
475
        return sb.toString();
476
    }
477

    
478
    /**
479
     * @param td
480
     * @return
481
     */
482
    private String stringify(SpecimenTypeDesignation td, boolean useFullTitleCache) {
483
        String  result = "";
484

    
485
        if(useFullTitleCache){
486
            if(td.getTypeSpecimen() != null){
487
                String nameTitleCache = td.getTypeSpecimen().getTitleCache();
488
                if(getTypifiedNameCache() != null){
489
                    nameTitleCache = nameTitleCache.replace(getTypifiedNameCache(), "");
490
                }
491
                result += nameTitleCache;
492
            }
493
        } else {
494
            if(td.getTypeSpecimen() != null){
495
                DerivedUnit du = td.getTypeSpecimen();
496
                if(du.isProtectedTitleCache()){
497
                    result += du.getTitleCache();
498
                } else {
499
                    DerivedUnitFacadeCacheStrategy cacheStrategy = new DerivedUnitFacadeCacheStrategy();
500
                    result += cacheStrategy.getTitleCache(du, true);
501
                }
502
            }
503
        }
504

    
505
        if(isPrintCitation() && td.getCitation() != null){
506
            if(td.getCitation().getAbbrevTitle() != null){
507
                result += " " + td.getCitation().getAbbrevTitle();
508
            } else {
509
                result += " " + td.getCitation().getTitleCache();
510
            }
511
            if(td.getCitationMicroReference() != null){
512
                result += " :" + td.getCitationMicroReference();
513
            }
514
        }
515
        if(td.isNotDesignated()){
516
            result += " not designated";
517
        }
518

    
519
        return result;
520
    }
521

    
522
    /**
523
     * @param td
524
     * @return
525
     * @deprecated
526
     */
527
    @Deprecated
528
    private FieldUnit findFieldUnit(SpecimenTypeDesignation td) {
529

    
530
        DerivedUnit du = td.getTypeSpecimen();
531
        return findFieldUnit(du);
532
    }
533

    
534
    private FieldUnit findFieldUnit(DerivedUnit du) {
535

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

    
558
        return null;
559
    }
560

    
561
    public String print() {
562
        return finalString.trim();
563
    }
564

    
565
    /**
566
     * @return the printCitation
567
     */
568
    public boolean isPrintCitation() {
569
        return printCitation;
570
    }
571

    
572
    /**
573
     * @param printCitation the printCitation to set
574
     */
575
    public void setPrintCitation(boolean printCitation) {
576
        this.printCitation = printCitation;
577
    }
578

    
579
    /**
580
     * TypeDesignations which refer to the same FieldUnit (SpecimenTypeDesignation) or TaxonName
581
     * (NameTypeDesignation) form a working set. The <code>TypeDesignationWorkingSet</code> internally
582
     * works with EnityReferences to the actual TypeDesignations.
583
     *
584
     * The EntityReferences for TypeDesignations are grouped by the according TypeDesignationStatus.
585
     * The TypeDesignationStatusBase keys can be ordered by the term order defined in the vocabulary.
586
     *
587
     * A workingset can be referenced by the <code>workingSetId</code>, this is a autoincrement
588
     * value which is created during the process of determining the workingsets in a collection of
589
     * TypeDesignations.
590
     *
591
     * TODO: consider using a concatenation of baseEntity.getClass() + baseEntity.getId() as workingset identifier
592
     */
593
    public class TypeDesignationWorkingSet extends LinkedHashMap<TypeDesignationStatusBase<?>, Collection<EntityReference>> {
594

    
595
        private static final long serialVersionUID = -1329007606500890729L;
596

    
597
        String workingSetRepresentation = null;
598

    
599
        TypedEntityReference<IdentifiableEntity<?>> baseEntityReference;
600

    
601
        IdentifiableEntity<?> baseEntity;
602

    
603
        List<DerivedUnit> derivedUnits = null;
604

    
605
        int workingSetId = workingSetIdAutoIncrement++;
606

    
607
        /**
608
         * @param baseEntityReference
609
         */
610
        public TypeDesignationWorkingSet(IdentifiableEntity<?> baseEntity, TypedEntityReference<IdentifiableEntity<?>> baseEntityReference) {
611
            this.baseEntity = baseEntity;
612
            this.baseEntityReference = baseEntityReference;
613
        }
614

    
615
        /**
616
         * @return
617
         */
618
        public IdentifiableEntity<?> getBaseEntity() {
619
            return baseEntity;
620
        }
621

    
622
        public List<EntityReference> getTypeDesignations() {
623
            List<EntityReference> typeDesignations = new ArrayList<>();
624
            this.values().forEach(typeDesignationReferences -> typeDesignationReferences.forEach(td -> typeDesignations.add(td)));
625
            return typeDesignations;
626
        }
627

    
628
        /**
629
         * @param status
630
         * @param typeDesignationEntityReference
631
         */
632
        public void insert(TypeDesignationStatusBase<?> status, EntityReference typeDesignationEntityReference) {
633

    
634
            if(status == null){
635
                status = NULL_STATUS;
636
            }
637
            if(!containsKey(status)){
638
                put(status, new ArrayList<EntityReference>());
639
            }
640
            get(status).add(typeDesignationEntityReference);
641
        }
642

    
643
        /**
644
         * @return the workingSetId
645
         */
646
        public int getWorkingSetId() {
647
            return workingSetId;
648
        }
649

    
650
        /**
651
         * @param workingSetId the workingSetId to set
652
         */
653
        public void setWorkingSetId(int workingSetId) {
654
            this.workingSetId = workingSetId;
655
        }
656

    
657
        public String getRepresentation() {
658
            return workingSetRepresentation;
659
        }
660

    
661
        public void setRepresentation(String representation){
662
            this.workingSetRepresentation = representation;
663
        }
664

    
665
        /**
666
         * A reference to the entity which is the common base entity for all TypeDesignations in this workingset.
667
         * For a {@link SpecimenTypeDesignation} this is usually the {@link FieldUnit} if it is present. Otherwise it can also be
668
         * a {@link DerivedUnit} or something else depending on the specific use case.
669
         *
670
         * @return the baseEntityReference
671
         */
672
        public TypedEntityReference getBaseEntityReference() {
673
            return baseEntityReference;
674
        }
675

    
676
        @Override
677
        public String toString(){
678
            if(workingSetRepresentation != null){
679
                return workingSetRepresentation;
680
            } else {
681
                return super.toString();
682
            }
683
        }
684

    
685
        /**
686
         * @return
687
         */
688
        public boolean isSpecimenTypeDesigationWorkingSet() {
689
            return SpecimenOrObservationBase.class.isAssignableFrom(baseEntityReference.getType());
690
        }
691

    
692
        public TypeDesignationWorkingSetType getWorkingsetType() {
693
            return isSpecimenTypeDesigationWorkingSet() ? TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET : TypeDesignationWorkingSetType.NAME_TYPE_DESIGNATION_WORKINGSET;
694
        }
695

    
696
    }
697

    
698
    public enum TypeDesignationWorkingSetType {
699
        SPECIMEN_TYPE_DESIGNATION_WORKINGSET,
700
        NAME_TYPE_DESIGNATION_WORKINGSET,
701
    }
702

    
703
    @SuppressWarnings({ "deprecation", "serial" })
704
    class NullTypeDesignationStatus extends TypeDesignationStatusBase<NullTypeDesignationStatus>{
705

    
706
        /**
707
         * {@inheritDoc}
708
         */
709
        @Override
710
        public void resetTerms() {
711
            // empty
712

    
713
        }
714

    
715
        /**
716
         * {@inheritDoc}
717
         */
718
        @Override
719
        protected void setDefaultTerms(TermVocabulary<NullTypeDesignationStatus> termVocabulary) {
720
            // empty
721
        }
722

    
723
    }
724

    
725
}
(6-6/7)