Merge branch 'release/5.44.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / view / search / derivative / DerivateLabelProvider.java
1 /**
2 * Copyright (C) 2013 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.taxeditor.view.search.derivative;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Map.Entry;
18 import java.util.Set;
19 import java.util.UUID;
20
21 import org.apache.commons.lang3.StringUtils;
22 import org.eclipse.jface.viewers.ColumnLabelProvider;
23 import org.eclipse.jface.viewers.TreeNode;
24 import org.eclipse.swt.graphics.Image;
25
26 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
27 import eu.etaxonomy.cdm.api.service.molecular.ISequenceService;
28 import eu.etaxonomy.cdm.common.CdmUtils;
29 import eu.etaxonomy.cdm.format.CdmFormatterFactory;
30 import eu.etaxonomy.cdm.format.ICdmFormatter.FormatKey;
31 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
32 import eu.etaxonomy.cdm.model.common.CdmBase;
33 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
34 import eu.etaxonomy.cdm.model.common.Identifier;
35 import eu.etaxonomy.cdm.model.molecular.DnaSample;
36 import eu.etaxonomy.cdm.model.molecular.Sequence;
37 import eu.etaxonomy.cdm.model.molecular.SingleRead;
38 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
39 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
40 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
41 import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
42 import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
43 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
44 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
45 import eu.etaxonomy.cdm.model.term.DefinedTerm;
46 import eu.etaxonomy.cdm.model.term.IdentifierType;
47 import eu.etaxonomy.cdm.strategy.cache.common.IdentifiableEntityDefaultCacheStrategy;
48 import eu.etaxonomy.cdm.strategy.cache.occurrence.DnaSampleDefaultCacheStrategy;
49 import eu.etaxonomy.taxeditor.model.ImageResources;
50 import eu.etaxonomy.taxeditor.store.CdmStore;
51
52 /**
53 * Label provider for the views to show {@link SpecimenOrObservationBase}s.<br>
54 */
55 public class DerivateLabelProvider extends ColumnLabelProvider {
56
57 private static final String NO_SAMPLE_DESIGNATION = "[no sample designation]";
58
59 private static Set<SingleRead> multiLinkSingleReads;
60
61 private static Map<DerivedUnit, Collection<SpecimenTypeDesignation>> typeDesignations;
62
63 private static DefinedTerm photoTerm = null;
64 private static DefinedTerm drawingTerm = null;
65 private static DefinedTerm specimenScanTerm = null;
66 private static DefinedTerm detailImageTerm = null;
67 private static IdentifierType sampleDesignationTerm = null;
68
69 //FIXME: move static term getters to new singleton utility class
70 private static void initializeTerms() {
71 List<DefinedTerm> preferredTerms = CdmStore.getTermManager().getPreferredTerms(DefinedTerm.class);
72 for (DefinedTerm definedTerm : preferredTerms) {
73 if(definedTerm.getUuid().equals(UUID.fromString("c5c59c42-f254-471e-96c6-09f459f7c903"))){
74 photoTerm = definedTerm;
75 }
76 else if(definedTerm.getUuid().equals(UUID.fromString("669b0409-4aa4-4695-aae4-a95ed27bad4c"))){
77 drawingTerm = definedTerm;
78 }
79 else if(definedTerm.getUuid().equals(UUID.fromString("acda15be-c0e2-4ea8-8783-b9b0c4ad7f03"))){
80 specimenScanTerm = definedTerm;
81 }
82 else if(definedTerm.getUuid().equals(UUID.fromString("31eb8d02-bf5d-437c-bcc6-87a626445f34"))){
83 detailImageTerm = definedTerm;
84 }
85 }
86 List<IdentifierType> identifierTypes = CdmStore.getTermManager().getPreferredTerms(IdentifierType.class);
87 for (IdentifierType identifierType : identifierTypes) {
88 if(identifierType.getUuid().equals(UUID.fromString("fadeba12-1be3-4bc7-9ff5-361b088d86fc"))){
89 sampleDesignationTerm = identifierType;
90 }
91 }
92 }
93
94 public static DefinedTerm getLivingPlantPhotoTerm(){
95 if(photoTerm==null){
96 initializeTerms();
97 }
98 return photoTerm;
99 }
100
101 public static DefinedTerm getArtworkTerm(){
102 if(drawingTerm==null){
103 initializeTerms();
104 }
105 return drawingTerm;
106 }
107
108 public static DefinedTerm getSpecimenScanTerm(){
109 if(specimenScanTerm==null){
110 initializeTerms();
111 }
112 return specimenScanTerm;
113 }
114
115 public static DefinedTerm getDetailImageTerm(){
116 if(detailImageTerm==null){
117 initializeTerms();
118 }
119 return detailImageTerm;
120 }
121
122 public static IdentifierType getSampleDesignationTerm(){
123 if(sampleDesignationTerm==null){
124 initializeTerms();
125 }
126 return sampleDesignationTerm;
127 }
128
129 @Override
130 public String getText(Object element) {
131 if(element instanceof TreeNode){
132 element = ((TreeNode) element).getValue();
133 }
134 String text = null;
135 if(element instanceof IdentifiableEntity
136 && ((IdentifiableEntity<?>) element).isProtectedTitleCache()){
137 return ((IdentifiableEntity<?>) element).getTitleCache();
138 }
139
140 //check if collection code does not exist -> use collection name then
141 FormatKey collectionKey = FormatKey.COLLECTION_CODE;
142 text = CdmFormatterFactory.format(element, new FormatKey[]{FormatKey.COLLECTION_CODE});
143 if(CdmUtils.isBlank(text)){
144 collectionKey = FormatKey.COLLECTION_NAME;
145 }
146
147 //Use titlecache for FieldUnits
148 if(element instanceof FieldUnit){
149 text = ((FieldUnit) element).getTitleCache();
150 }
151 else if(element instanceof MediaSpecimen){
152 MediaSpecimen mediaSpecimen = (MediaSpecimen)element;
153 text = mediaSpecimen.getTitleCache();
154 }
155 else if (element instanceof DnaSample) {
156 DnaSample dnaSample = (DnaSample)element;
157 if (!(dnaSample.cacheStrategy() instanceof DnaSampleDefaultCacheStrategy)){
158 dnaSample.setCacheStrategy(new DnaSampleDefaultCacheStrategy());
159 }
160 dnaSample.setTitleCache(null);
161 text = dnaSample.getTitleCache();
162 }
163 else if (element instanceof DerivedUnit) {
164 text = CdmFormatterFactory.format(element,
165 new FormatKey[] {
166 collectionKey, FormatKey.SPACE,
167 FormatKey.MOST_SIGNIFICANT_IDENTIFIER, FormatKey.SPACE
168 });
169 }
170 else if (element instanceof Sequence) {
171 text = CdmFormatterFactory.format(element,
172 new FormatKey[] {
173 FormatKey.SEQUENCE_DNA_MARKER, FormatKey.SPACE
174 });
175 }
176 else if (element instanceof SingleRead) {
177 text = CdmFormatterFactory.format(element,
178 new FormatKey[] {
179 FormatKey.SINGLE_READ_PHEROGRAM_TITLE_CACHE, FormatKey.SPACE,
180 FormatKey.AMPLIFICATION_LABEL, FormatKey.SPACE,
181 });
182 }
183 else if(element instanceof IdentifiableEntity){
184
185 IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>) element;
186 if(identifiableEntity.isProtectedTitleCache()){
187 text = identifiableEntity.getTitleCache();
188 }
189 }
190 if(CdmUtils.isBlank(text) || text.equals(IdentifiableEntityDefaultCacheStrategy.TITLE_CACHE_GENERATION_NOT_IMPLEMENTED)){
191 if(element instanceof CdmBase){
192 text = ((CdmBase) element).getUuid().toString();
193 }
194 else{
195 text = element.toString();
196 }
197 }
198 //remove dot at the end
199 if(text.endsWith(".")){
200 text = text.substring(0, text.length()-1);
201 }
202 return text;
203 }
204
205 @Override
206 public String getToolTipText(Object element) {
207 return getDerivateText(element);
208 }
209
210 //Note AM: not sure what this method is really used for, why do we need an explicit
211 // formatting for those few use-cases where this is used?
212 public static String getDerivateText(Object element){
213 //TODO: use list of strings to assemble labels to avoid adding the separator every time and to allow null values
214 TreeNode parentNode = null;
215 TreeNode node = null;
216 Object derivate = element;
217 if(element instanceof TreeNode){
218 node = (TreeNode) element;
219 parentNode = node.getParent();
220 //unwrap specimen from TreeNode
221 derivate = node.getValue();
222 }
223
224 final String emptyString = StringUtils.EMPTY;
225 final String separator = " ";
226
227 String label = emptyString;
228
229 //Field Unit
230 if(derivate instanceof FieldUnit){
231 FieldUnit fieldUnit = (FieldUnit)derivate;
232 if(fieldUnit.getGatheringEvent()!=null){
233 GatheringEvent gatheringEvent = fieldUnit.getGatheringEvent();
234 label += gatheringEvent.getCountry()!=null?gatheringEvent.getCountry().getLabel()+separator:emptyString;
235 label += gatheringEvent.getLocality()!=null?gatheringEvent.getLocality().getText()+separator:emptyString;
236 label += gatheringEvent.getGatheringStartDate()!=null?gatheringEvent.getGatheringStartDate()+separator:emptyString;
237 label += gatheringEvent.getCollector()!=null?gatheringEvent.getCollector()+separator:emptyString;
238 }
239 label += fieldUnit.getFieldNumber()!=null?fieldUnit.getFieldNumber():emptyString;
240 }
241 //MediaSpecimen
242 else if(derivate instanceof MediaSpecimen){
243 label = ((MediaSpecimen)derivate).generateTitle();
244 }
245 //TissueSample + DnaSample
246 else if(derivate instanceof DnaSample
247 && ((DnaSample) derivate).getRecordBasis()==SpecimenOrObservationType.DnaSample){
248 DnaSample dnaSample = (DnaSample)derivate;
249 //AM: maybe we can use cache strategy here, unclear why only sample designation is needed; unfortunately method documentation is missing
250 if(dnaSample.getRecordBasis()==SpecimenOrObservationType.DnaSample){
251 Identifier currentSampleDesignation = getCurrentSampleDesignation(dnaSample);
252 if(currentSampleDesignation!=null && currentSampleDesignation.getIdentifier()!=null){
253 label += currentSampleDesignation.getIdentifier()+separator;
254 }
255 else{
256 label += NO_SAMPLE_DESIGNATION+separator;
257 }
258 }
259 }
260 //DerivedUnit + TissueSample
261 else if(derivate instanceof DerivedUnit){
262 DerivedUnit derivedUnit = (DerivedUnit)derivate;
263 if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.PreservedSpecimen){
264 //check for type designation
265 if(typeDesignations.get(derivedUnit)==null){
266 for (SpecimenTypeDesignation specimenTypeDesignation : derivedUnit.getSpecimenTypeDesignations()) {
267 addTypeDesignation(derivedUnit, specimenTypeDesignation);
268 }
269 }
270 //java.util.Collection<FieldUnit> fieldUnits = CdmStore.getService(IOccurrenceService.class).getFieldUnits(derivedUnit.getUuid());
271 //TODO : This is not generic anymore for performance reasons
272 Set<SpecimenOrObservationBase> originals = derivedUnit.getOriginals();
273 if(originals!=null && originals.size() ==1) {
274 SpecimenOrObservationBase<?> specimen = originals.iterator().next();
275 if(specimen instanceof FieldUnit) {
276 FieldUnit fieldUnit = (FieldUnit)specimen;
277 GatheringEvent gatheringEvent = fieldUnit.getGatheringEvent();
278 if(gatheringEvent!=null){
279 label += gatheringEvent.getCollector()!=null?gatheringEvent.getCollector()+separator:emptyString;
280 }
281 label += fieldUnit.getFieldNumber()!=null?fieldUnit.getFieldNumber()+separator:emptyString;
282 }
283 }
284
285 eu.etaxonomy.cdm.model.occurrence.Collection collection = derivedUnit.getCollection();
286 if(collection!=null){
287 label += collection.getCode()!=null?"("+collection.getCode()+")"+separator:emptyString;
288 }
289 String mostSignificantIdentifier = derivedUnit.getMostSignificantIdentifier();
290 label += mostSignificantIdentifier!=null?mostSignificantIdentifier+separator:emptyString;
291 }
292 else if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.TissueSample){
293 if(derivedUnit.getKindOfUnit()!=null){
294 label += derivedUnit.getKindOfUnit()+separator;
295 }
296 Identifier currentSampleDesignation = getCurrentSampleDesignation(derivedUnit);
297 if(currentSampleDesignation!=null && currentSampleDesignation.getIdentifier()!=null){
298 label += currentSampleDesignation.getIdentifier() + separator;
299 }
300 else{
301 label += NO_SAMPLE_DESIGNATION + separator;
302 }
303 }
304 }
305 //Sequence
306 else if(derivate instanceof Sequence){
307 Sequence sequence = (Sequence)derivate;
308 Identifier currentSampleDesignation = getCurrentSampleDesignation(sequence);
309 if(currentSampleDesignation!=null && currentSampleDesignation.getIdentifier()!=null){
310 label += currentSampleDesignation.getIdentifier()+separator;
311 }
312 else{
313 label += NO_SAMPLE_DESIGNATION+separator;
314 }
315 label += sequence.getDnaMarker()!=null?sequence.getDnaMarker():emptyString;
316 }
317 //SingleRead
318 else if(derivate instanceof SingleRead){
319 SingleRead singleRead = (SingleRead)derivate;
320 if(parentNode!=null && parentNode.getValue() instanceof Sequence){
321 Sequence sequence = (Sequence) parentNode.getValue();
322 Identifier currentSampleDesignation = getCurrentSampleDesignation(sequence);
323 if(currentSampleDesignation!=null && currentSampleDesignation.getIdentifier()!=null){
324 label = currentSampleDesignation.getIdentifier()+separator;
325 }
326 else{
327 label += NO_SAMPLE_DESIGNATION+separator;
328 }
329 label += singleRead.getPrimer()!=null?singleRead.getPrimer().getLabel()+separator:emptyString;
330 if(sequence!=null && sequence.getDnaMarker()!=null){
331 label += sequence.getDnaMarker()+separator;
332 }
333 if(singleRead.getAmplificationResult()!=null && singleRead.getAmplificationResult().getAmplification()!=null){
334 label += singleRead.getAmplificationResult().getAmplification().getLabelCache()+separator;
335 }
336 }
337 }
338 //SOOB
339 else if(derivate instanceof SpecimenOrObservationBase){
340 SpecimenOrObservationBase<?> specimen = (SpecimenOrObservationBase<?>) derivate;
341 SpecimenOrObservationType type = specimen.getRecordBasis();
342 return specimen.getTitleCache() + (type!=null?" ["+type.toString()+"]":emptyString);
343 }
344 if(label.isEmpty()){
345 label = derivate.toString();
346 }
347 //remove last comma
348 else if(label.endsWith(separator)){
349 label = label.substring(0, label.length()-separator.length());
350 }
351 return label;
352 }
353
354 @Override
355 public Image getImage(Object element) {
356 if(element instanceof TreeNode){
357 element = ((TreeNode) element).getValue();
358 }
359 if(element instanceof CdmBase){
360 CdmBase cdmBase = (CdmBase)element;
361 boolean hasCharacterData = false;
362 if(cdmBase.isInstanceOf(SpecimenOrObservationBase.class)){
363 SpecimenOrObservationBase<?> specimen = HibernateProxyHelper.deproxy(cdmBase, SpecimenOrObservationBase.class);
364 if(specimen.hasCharacterData()){
365 hasCharacterData = true;
366 }
367 }
368 if(cdmBase.isInstanceOf(FieldUnit.class)){
369 return hasCharacterData?ImageResources.getImage(ImageResources.FIELD_UNIT_CHARACTER_DATA):ImageResources.getImage(ImageResources.FIELD_UNIT);
370 }
371 else if(cdmBase.isInstanceOf(DerivedUnit.class)){
372 DerivedUnit derivedUnit = HibernateProxyHelper.deproxy(element, DerivedUnit.class);
373
374 if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.FieldUnit){
375 return hasCharacterData?ImageResources.getImage(ImageResources.FIELD_UNIT_CHARACTER_DATA):ImageResources.getImage(ImageResources.FIELD_UNIT);
376 }
377 else if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.DnaSample){
378 return hasCharacterData?ImageResources.getImage(ImageResources.DNA_SAMPLE_DERIVATE_CHARACTER_DATA):ImageResources.getImage(ImageResources.DNA_SAMPLE_DERIVATE);
379 }
380 else if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.TissueSample){
381 return hasCharacterData?ImageResources.getImage(ImageResources.TISSUE_SAMPLE_DERIVATE_CHARACTER_DATA):ImageResources.getImage(ImageResources.TISSUE_SAMPLE_DERIVATE);
382 }
383 else if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.PreservedSpecimen){
384 if(typeDesignations.get(derivedUnit)!=null && !typeDesignations.get(derivedUnit).isEmpty()){
385 return ImageResources.getImage(ImageResources.SPECIMEN_DERIVATE_TYPE);
386 }
387 return hasCharacterData?ImageResources.getImage(ImageResources.SPECIMEN_DERIVATE_CHARACTER_DATA):ImageResources.getImage(ImageResources.SPECIMEN_DERIVATE);
388 }
389 else if(derivedUnit.getRecordBasis().isMedia()
390 || derivedUnit.getRecordBasis().isKindOf(SpecimenOrObservationType.Media)){
391 if(derivedUnit.getKindOfUnit()!=null){
392 if(derivedUnit.getKindOfUnit().equals(getArtworkTerm())){
393 return hasCharacterData?ImageResources.getImage(ImageResources.ARTWORK_DERIVATE_CHARACTER_DATA):ImageResources.getImage(ImageResources.ARTWORK_DERIVATE);
394 }
395 else if(derivedUnit.getKindOfUnit().equals(getLivingPlantPhotoTerm())){
396 return hasCharacterData?ImageResources.getImage(ImageResources.LIVING_PLANT_PHOTO_DERIVATE_CHARACTER_DATA):ImageResources.getImage(ImageResources.LIVING_PLANT_PHOTO_DERIVATE);
397 }
398 else if(derivedUnit.getKindOfUnit().equals(getSpecimenScanTerm())){
399 return hasCharacterData?ImageResources.getImage(ImageResources.SPECIMEN_SCAN_DERIVATE_CHARACTER_DATA):ImageResources.getImage(ImageResources.SPECIMEN_SCAN_DERIVATE);
400 }
401 else if(derivedUnit.getKindOfUnit().equals(getDetailImageTerm())){
402 return hasCharacterData?ImageResources.getImage(ImageResources.DETAIL_IMAGE_DERIVATE_CHARACTER_DATA):ImageResources.getImage(ImageResources.DETAIL_IMAGE_DERIVATE);
403 }
404 }
405 }
406 }
407 else if(cdmBase.isInstanceOf(Sequence.class)){
408 return ImageResources.getImage(ImageResources.SEQUENCE_DERIVATE);
409 }
410
411 else if(cdmBase.isInstanceOf(SingleRead.class)){
412 if(multiLinkSingleReads!=null && multiLinkSingleReads.contains(element)){
413 return ImageResources.getImage(ImageResources.SINGLE_READ_DERIVATE_MULTILINK);
414 }
415 else{
416 return ImageResources.getImage(ImageResources.SINGLE_READ_DERIVATE);
417 }
418 }
419 }
420 return ImageResources.getImage(ImageResources.DEFAULT_DERIVATIVE);
421 }
422
423 public static Identifier getCurrentSampleDesignation(CdmBase entity) {
424 if(entity.isInstanceOf(DnaSample.class)){
425 DnaSample dnaSample = HibernateProxyHelper.deproxy(entity, DnaSample.class);
426 return dnaSample.getIdentifier(IdentifierType.uuidSampleDesignation);
427 }
428 else if(entity.isInstanceOf(Sequence.class)){
429 Sequence sequence = HibernateProxyHelper.deproxy(entity, Sequence.class);
430 if(sequence.getDnaSample()!=null){
431 return getCurrentSampleDesignation(sequence.getDnaSample());
432 }
433 }
434 return null;
435 }
436
437 private static void addTypeDesignation(DerivedUnit derivedUnit, SpecimenTypeDesignation typeDesignation){
438 Collection<SpecimenTypeDesignation> list = typeDesignations.get(derivedUnit);
439 if(list==null){
440 list = new ArrayList<>();
441 }
442 list.add(typeDesignation);
443 typeDesignations.put(derivedUnit, list);
444 }
445
446 public static Set<SingleRead> getMultiLinkSingleReads() {
447 return multiLinkSingleReads;
448 }
449
450 public void updateLabelCache(Collection<SpecimenOrObservationBase<?>> rootElements) {
451 multiLinkSingleReads = new HashSet<>();
452 typeDesignations = new HashMap<>();
453 for(Entry<SingleRead, Collection<Sequence>> entry:CdmStore.getService(ISequenceService.class).getSingleReadSequencesMap().entrySet()){
454 if(entry.getValue().size()>1){
455 multiLinkSingleReads.add(entry.getKey());
456 }
457 }
458 if(rootElements!=null){
459 Collection<DerivedUnit> derivedUnits = new ArrayList<>();
460 for (SpecimenOrObservationBase<?> specimenOrObservationBase : rootElements) {
461 List<DerivedUnit> childUnits = CdmStore.getService(IOccurrenceService.class).getAllChildDerivatives(specimenOrObservationBase.getUuid());
462 if (childUnits != null){
463 derivedUnits.addAll(childUnits);
464 }
465 if(specimenOrObservationBase.isInstanceOf(DerivedUnit.class)){
466 specimenOrObservationBase = CdmStore.getService(IOccurrenceService.class).load(specimenOrObservationBase.getUuid());
467 if (specimenOrObservationBase != null){
468 derivedUnits.add(HibernateProxyHelper.deproxy(specimenOrObservationBase, DerivedUnit.class));
469 }
470 }
471 }
472 for (DerivedUnit derivedUnit : derivedUnits) {
473 if(!derivedUnit.getSpecimenTypeDesignations().isEmpty()){
474 typeDesignations.put(derivedUnit, derivedUnit.getSpecimenTypeDesignations());
475 }
476 }
477 }
478 }
479
480 }