1
|
/**
|
2
|
* Copyright (C) 2015 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.api.service.dto;
|
10
|
|
11
|
import java.util.ArrayList;
|
12
|
import java.util.Collection;
|
13
|
import java.util.Collections;
|
14
|
import java.util.EnumSet;
|
15
|
import java.util.HashMap;
|
16
|
import java.util.List;
|
17
|
import java.util.Map;
|
18
|
import java.util.Set;
|
19
|
import java.util.regex.Pattern;
|
20
|
|
21
|
import eu.etaxonomy.cdm.common.CdmUtils;
|
22
|
import eu.etaxonomy.cdm.common.URI;
|
23
|
import eu.etaxonomy.cdm.format.CdmFormatterFactory;
|
24
|
import eu.etaxonomy.cdm.format.ICdmFormatter.FormatKey;
|
25
|
import eu.etaxonomy.cdm.format.description.DefaultCategoricalDescriptionBuilder;
|
26
|
import eu.etaxonomy.cdm.format.description.DefaultQuantitativeDescriptionBuilder;
|
27
|
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
|
28
|
import eu.etaxonomy.cdm.model.common.Language;
|
29
|
import eu.etaxonomy.cdm.model.description.CategoricalData;
|
30
|
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
|
31
|
import eu.etaxonomy.cdm.model.description.QuantitativeData;
|
32
|
import eu.etaxonomy.cdm.model.media.Media;
|
33
|
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
|
34
|
import eu.etaxonomy.cdm.model.name.TaxonName;
|
35
|
import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;
|
36
|
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
|
37
|
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
|
38
|
import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
|
39
|
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
|
40
|
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
|
41
|
import eu.etaxonomy.cdm.model.taxon.Taxon;
|
42
|
import eu.etaxonomy.cdm.ref.TypedEntityReference;
|
43
|
|
44
|
/**
|
45
|
* @author pplitzner
|
46
|
* @since Mar 26, 2015
|
47
|
*/
|
48
|
public class DerivedUnitDTO extends SpecimenOrObservationBaseDTO{
|
49
|
|
50
|
private static final long serialVersionUID = 2345864166579381295L;
|
51
|
|
52
|
private String accessionNumber;
|
53
|
private String specimenShortTitle;
|
54
|
private TypedEntityReference<TaxonName> storedUnder;
|
55
|
private URI preferredStableUri;
|
56
|
|
57
|
private List<TypedEntityReference<Taxon>> associatedTaxa;
|
58
|
private Map<String, List<String>> types;
|
59
|
|
60
|
private String originalLabelInfo;
|
61
|
private String exsiccatum;
|
62
|
private String mostSignificantIdentifier;
|
63
|
|
64
|
private CollectionDTO collection;
|
65
|
|
66
|
private String catalogNumber;
|
67
|
|
68
|
private String barcode;
|
69
|
|
70
|
private String preservationMethod;
|
71
|
|
72
|
/**
|
73
|
* Constructs a new DerivedUnitDTO. All derivatives of the passed <code>DerivedUnit entity</code> will be collected and
|
74
|
* added as DerivedUnitDTO to the {@link SpecimenOrObservationBaseDTO#getDerivatives() derivative DTOs}.
|
75
|
*
|
76
|
* @param entity
|
77
|
* The entity to create the dto for
|
78
|
*
|
79
|
* @return <code>null</code> or the new DerivedUnitDTO
|
80
|
*/
|
81
|
public static DerivedUnitDTO fromEntity(DerivedUnit entity){
|
82
|
return fromEntity(entity, null, null);
|
83
|
}
|
84
|
|
85
|
/**
|
86
|
* Constructs a new DerivedUnitDTO. All derivatives of the passed <code>DerivedUnit entity</code> will be collected and
|
87
|
* added as DerivedUnitDTO to the {@link SpecimenOrObservationBaseDTO#getDerivatives() derivative DTOs}.
|
88
|
*
|
89
|
* @param entity
|
90
|
* The entity to create the dto for
|
91
|
* @param maxDepth
|
92
|
* The maximum number of derivation events levels up to which derivatives are to be collected.
|
93
|
* <code>NULL</code> means infinitely.
|
94
|
* @param specimenOrObservationTypeFilter
|
95
|
* Set of SpecimenOrObservationType to be included into the collection of {@link #getDerivatives() derivative DTOs}
|
96
|
* @return
|
97
|
* The DTO
|
98
|
*/
|
99
|
public static DerivedUnitDTO fromEntity(DerivedUnit entity, Integer maxDepth,
|
100
|
EnumSet<SpecimenOrObservationType> specimenOrObservationTypeFilter){
|
101
|
|
102
|
if(entity == null) {
|
103
|
return null;
|
104
|
}
|
105
|
DerivedUnitDTO dto = new DerivedUnitDTO(entity);
|
106
|
|
107
|
// ---- assemble derivation tree summary
|
108
|
// this data should be sufficient in clients for showing the unit in a list view
|
109
|
dto.setDerivationTreeSummary(DerivationTreeSummaryDTO.fromEntity(entity, dto.getSpecimenShortTitle()));
|
110
|
|
111
|
// ---- assemble derivatives
|
112
|
// this data is is often only required for clients in order to show the details of the derivation tree
|
113
|
dto.addAllDerivatives(dto.assembleDerivatives(entity, maxDepth, specimenOrObservationTypeFilter));
|
114
|
|
115
|
return dto;
|
116
|
}
|
117
|
|
118
|
/**
|
119
|
* @param derivedUnit
|
120
|
*/
|
121
|
public DerivedUnitDTO(DerivedUnit derivedUnit) {
|
122
|
super(derivedUnit);
|
123
|
|
124
|
// experimental feature, not yet exposed in method signature
|
125
|
boolean cleanAccessionNumber = false;
|
126
|
accessionNumber = derivedUnit.getAccessionNumber();
|
127
|
preferredStableUri = derivedUnit.getPreferredStableUri();
|
128
|
if (derivedUnit.getCollection() != null){
|
129
|
setCollectioDTO(CollectionDTO.fromCollection(HibernateProxyHelper.deproxy(derivedUnit.getCollection())));
|
130
|
if(cleanAccessionNumber && getCollection().getCode() != null) {
|
131
|
accessionNumber = accessionNumber.replaceFirst("^" + Pattern.quote(getCollection().getCode()) + "-", "");
|
132
|
}
|
133
|
}
|
134
|
setBarcode(derivedUnit.getBarcode());
|
135
|
setCatalogNumber(derivedUnit.getCatalogNumber());
|
136
|
setDerivationEvent(DerivationEventDTO.fromEntity(derivedUnit.getDerivedFrom()));
|
137
|
if (derivedUnit.getPreservation()!= null){
|
138
|
setPreservationMethod(derivedUnit.getPreservation().getMaterialMethodText());
|
139
|
}
|
140
|
setRecordBase(derivedUnit.getRecordBasis());
|
141
|
setSources(derivedUnit.getSources());
|
142
|
setSpecimenTypeDesignations(derivedUnit.getSpecimenTypeDesignations());
|
143
|
|
144
|
// -------------------------------------------------------------
|
145
|
|
146
|
mostSignificantIdentifier = derivedUnit.getMostSignificantIdentifier();
|
147
|
|
148
|
//specimenShortTitle
|
149
|
setSpecimenShortTitle(composeSpecimenShortTitle(derivedUnit));
|
150
|
|
151
|
|
152
|
//preferred stable URI
|
153
|
setPreferredStableUri(derivedUnit.getPreferredStableUri());
|
154
|
|
155
|
// label
|
156
|
Collection<FieldUnit> fieldUnits = derivedUnit.collectRootUnits(FieldUnit.class);
|
157
|
if (fieldUnits.size() == 1) {
|
158
|
setSummaryLabel(fieldUnits.iterator().next().getTitleCache());
|
159
|
}
|
160
|
else{
|
161
|
setSummaryLabel("No Citation available. This specimen either has no or multiple field units.");
|
162
|
}
|
163
|
|
164
|
// character state data
|
165
|
if(derivedUnit.characterData() != null) {
|
166
|
Collection<DescriptionElementBase> characterDataForSpecimen = derivedUnit.characterData();
|
167
|
for (DescriptionElementBase descriptionElementBase : characterDataForSpecimen) {
|
168
|
String character = descriptionElementBase.getFeature().getLabel();
|
169
|
ArrayList<Language> languages = new ArrayList<>(Collections.singleton(Language.DEFAULT()));
|
170
|
if (descriptionElementBase instanceof QuantitativeData) {
|
171
|
QuantitativeData quantitativeData = (QuantitativeData) descriptionElementBase;
|
172
|
DefaultQuantitativeDescriptionBuilder builder = new DefaultQuantitativeDescriptionBuilder();
|
173
|
String state = builder.build(quantitativeData, languages).getText(Language.DEFAULT());
|
174
|
addCharacterData(character, state);
|
175
|
}
|
176
|
else if(descriptionElementBase instanceof CategoricalData){
|
177
|
CategoricalData categoricalData = (CategoricalData) descriptionElementBase;
|
178
|
DefaultCategoricalDescriptionBuilder builder = new DefaultCategoricalDescriptionBuilder();
|
179
|
String state = builder.build(categoricalData, languages).getText(Language.DEFAULT());
|
180
|
addCharacterData(character, state);
|
181
|
}
|
182
|
}
|
183
|
}
|
184
|
|
185
|
// check type designations
|
186
|
Collection<SpecimenTypeDesignation> specimenTypeDesignations = derivedUnit.getSpecimenTypeDesignations();
|
187
|
for (SpecimenTypeDesignation specimenTypeDesignation : specimenTypeDesignations) {
|
188
|
TypeDesignationStatusBase<?> typeStatus = specimenTypeDesignation.getTypeStatus();
|
189
|
Set<TaxonName> typifiedNames = specimenTypeDesignation.getTypifiedNames();
|
190
|
List<String> typedTaxaNames = new ArrayList<>();
|
191
|
for (TaxonName taxonName : typifiedNames) {
|
192
|
typedTaxaNames.add(taxonName.getTitleCache());
|
193
|
}
|
194
|
addTypes(typeStatus!=null?typeStatus.getLabel():"", typedTaxaNames);
|
195
|
}
|
196
|
|
197
|
if(derivedUnit.getStoredUnder() != null) {
|
198
|
storedUnder = TypedEntityReference.fromEntity(derivedUnit.getStoredUnder());
|
199
|
}
|
200
|
originalLabelInfo = derivedUnit.getOriginalLabelInfo();
|
201
|
exsiccatum = derivedUnit.getExsiccatum();
|
202
|
|
203
|
}
|
204
|
|
205
|
protected String composeSpecimenShortTitle(DerivedUnit derivedUnit) {
|
206
|
FormatKey collectionKey = FormatKey.COLLECTION_CODE;
|
207
|
String specimenShortTitle = CdmFormatterFactory.format(derivedUnit, collectionKey);
|
208
|
if (CdmUtils.isBlank(specimenShortTitle)) {
|
209
|
collectionKey = FormatKey.COLLECTION_NAME;
|
210
|
}
|
211
|
if(CdmUtils.isNotBlank(derivedUnit.getMostSignificantIdentifier())){
|
212
|
specimenShortTitle = CdmFormatterFactory.format(derivedUnit, new FormatKey[] {
|
213
|
collectionKey,
|
214
|
FormatKey.SPACE,
|
215
|
FormatKey.MOST_SIGNIFICANT_IDENTIFIER
|
216
|
});
|
217
|
if(!specimenShortTitle.isEmpty() && derivedUnit instanceof MediaSpecimen) {
|
218
|
Media media = ((MediaSpecimen)derivedUnit).getMediaSpecimen();
|
219
|
if(media != null && !CdmUtils.isBlank(media.getTitleCache()) ) {
|
220
|
if(media.getTitle() != null && !media.getTitle().getText().isEmpty()) {
|
221
|
specimenShortTitle += " (" + media.getTitle().getText() + ")";
|
222
|
}
|
223
|
}
|
224
|
}
|
225
|
}
|
226
|
if(CdmUtils.isBlank(specimenShortTitle)){
|
227
|
specimenShortTitle = derivedUnit.getTitleCache();
|
228
|
}
|
229
|
if(CdmUtils.isBlank(specimenShortTitle)){ //should not be necessary as titleCache should never be empty
|
230
|
specimenShortTitle = derivedUnit.getUuid().toString();
|
231
|
}
|
232
|
return specimenShortTitle;
|
233
|
}
|
234
|
|
235
|
@Override
|
236
|
protected Set<Media> collectMedia(SpecimenOrObservationBase<?> specimenOrObservation){
|
237
|
Set<Media> collectedMedia = super.collectMedia(specimenOrObservation);
|
238
|
if(specimenOrObservation instanceof MediaSpecimen) {
|
239
|
if(((MediaSpecimen)specimenOrObservation).getMediaSpecimen() != null) {
|
240
|
collectedMedia.add(((MediaSpecimen)specimenOrObservation).getMediaSpecimen());
|
241
|
}
|
242
|
}
|
243
|
return collectedMedia;
|
244
|
}
|
245
|
|
246
|
|
247
|
public String getAccessionNumber() {
|
248
|
return accessionNumber;
|
249
|
}
|
250
|
public void setAccessionNumber(String accessionNumber) {
|
251
|
this.accessionNumber = accessionNumber;
|
252
|
}
|
253
|
|
254
|
public Map<String, List<String>> getTypes() {
|
255
|
return types;
|
256
|
}
|
257
|
public void addTypes(String typeStatus, List<String> typedTaxa){
|
258
|
if(types==null){
|
259
|
types = new HashMap<>();
|
260
|
}
|
261
|
types.put(typeStatus, typedTaxa);
|
262
|
}
|
263
|
|
264
|
public List<TypedEntityReference<Taxon>> getAssociatedTaxa() {
|
265
|
return associatedTaxa;
|
266
|
}
|
267
|
public void addAssociatedTaxon(Taxon taxon){
|
268
|
if(associatedTaxa==null){
|
269
|
associatedTaxa = new ArrayList<>();
|
270
|
}
|
271
|
associatedTaxa.add(TypedEntityReference.fromEntity(taxon));
|
272
|
}
|
273
|
|
274
|
public void setPreferredStableUri(URI preferredStableUri) {
|
275
|
this.preferredStableUri = preferredStableUri;
|
276
|
}
|
277
|
public URI getPreferredStableUri() {
|
278
|
return preferredStableUri;
|
279
|
}
|
280
|
|
281
|
public String getSpecimenShortTitle() {
|
282
|
return specimenShortTitle;
|
283
|
}
|
284
|
public void setSpecimenShortTitle(String specimenIdentifier) {
|
285
|
this.specimenShortTitle = specimenIdentifier;
|
286
|
}
|
287
|
|
288
|
public String getMostSignificantIdentifier() {
|
289
|
return mostSignificantIdentifier;
|
290
|
}
|
291
|
public void setMostSignificantIdentifier(String mostSignificantIdentifier) {
|
292
|
this.mostSignificantIdentifier = mostSignificantIdentifier;
|
293
|
}
|
294
|
|
295
|
public TypedEntityReference<TaxonName> getStoredUnder() {
|
296
|
return storedUnder;
|
297
|
}
|
298
|
public void setStoredUnder(TypedEntityReference<TaxonName> storedUnder) {
|
299
|
this.storedUnder = storedUnder;
|
300
|
}
|
301
|
|
302
|
public String getOriginalLabelInfo() {
|
303
|
return originalLabelInfo;
|
304
|
}
|
305
|
public void setOriginalLabelInfo(String originalLabelInfo) {
|
306
|
this.originalLabelInfo = originalLabelInfo;
|
307
|
}
|
308
|
|
309
|
public String getExsiccatum() {
|
310
|
return exsiccatum;
|
311
|
}
|
312
|
public void setExsiccatum(String exsiccatum) {
|
313
|
this.exsiccatum = exsiccatum;
|
314
|
}
|
315
|
|
316
|
public String getCatalogNumber() {
|
317
|
return catalogNumber;
|
318
|
}
|
319
|
public void setCatalogNumber(String catalogNumber) {
|
320
|
this.catalogNumber = catalogNumber;
|
321
|
}
|
322
|
|
323
|
public String getBarcode() {
|
324
|
return barcode;
|
325
|
}
|
326
|
public void setBarcode(String barcode) {
|
327
|
this.barcode = barcode;
|
328
|
}
|
329
|
|
330
|
public String getPreservationMethod() {
|
331
|
return preservationMethod;
|
332
|
}
|
333
|
public void setPreservationMethod(String preservationMethod) {
|
334
|
this.preservationMethod = preservationMethod;
|
335
|
}
|
336
|
|
337
|
public CollectionDTO getCollection() {
|
338
|
return collection;
|
339
|
}
|
340
|
public void setCollectioDTO(CollectionDTO collection) {
|
341
|
this.collection = collection;
|
342
|
}
|
343
|
|
344
|
@Override
|
345
|
protected void updateTreeDependantData() {
|
346
|
// TODO DerivationTreeSummaryDTO should be updated here once it is refactored so that it can operate on dtos
|
347
|
}
|
348
|
}
|