bf1b53bc5ae22d83fe8700600b8540499535f400
[taxeditor.git] / taxeditor-editor / src / main / java / eu / etaxonomy / taxeditor / propertysheet / name / NonViralNamePropertySource.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.taxeditor.propertysheet.name;
11
12 import java.beans.PropertyChangeEvent;
13 import java.beans.PropertyChangeListener;
14 import java.beans.PropertyChangeSupport;
15 import java.util.ArrayList;
16 import java.util.Date;
17 import java.util.List;
18 import java.util.Set;
19 import java.util.Vector;
20
21 import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor;
22 import org.eclipse.ui.views.properties.IPropertyDescriptor;
23 import org.eclipse.ui.views.properties.PropertyDescriptor;
24 import org.eclipse.ui.views.properties.TextPropertyDescriptor;
25
26 import eu.etaxonomy.cdm.common.CdmUtils;
27 import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
28 import eu.etaxonomy.cdm.model.common.User;
29 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
30 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
31 import eu.etaxonomy.cdm.model.name.NonViralName;
32 import eu.etaxonomy.cdm.model.name.Rank;
33 import eu.etaxonomy.cdm.model.reference.Generic;
34 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
35 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
36 import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
37 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
38 import eu.etaxonomy.taxeditor.propertysheet.AnnotationPropertySource;
39 import eu.etaxonomy.taxeditor.propertysheet.AnnotationsPropertyDescriptor;
40 import eu.etaxonomy.taxeditor.propertysheet.ICdmBasePropertySource;
41 import eu.etaxonomy.taxeditor.propertysheet.MarkersPropertySource;
42 import eu.etaxonomy.taxeditor.propertysheet.reference.NomenclaturalReferencePropertySource;
43 import eu.etaxonomy.taxeditor.propertysheet.reference.ReferencePropertySource;
44
45 /**
46 * @author p.ciardelli
47 * @created 06.05.2008
48 * @version 1.0
49 */
50 public class NonViralNamePropertySource implements ICdmBasePropertySource {
51
52 // The name whose properties are being displayed
53 NonViralName<?> name;
54
55 // If this is a property with a parent, the parent's property ID
56 private String parentid = "";
57
58 PropertyChangeSupport propertyChangeSupport;
59
60 // Property unique keys
61 public static final String P_ID_PARSED = "parsed";
62 public static final String P_ID_RANK = "rank";
63 public static final String P_ID_TITLECACHE = "titlecache";
64 public static final String P_ID_HOMOTYPICALGROUP = "homogroup";
65 public static final String P_ID_NAMERELATIONS = "namerelations";
66 public static final String P_ID_TYPE = "type";
67 public static final String P_ID_ANNOTATIONS = "annotations";
68 public static final String P_ID_NOMSTATUS = "nomstatus";
69 public static final String P_ID_UUID = "uuid";
70 public static final String P_ID_NUM_OF_BASES = "numberofbases";
71 public static final String P_ID_MARKERS = "markers";
72 public static final String P_ID_CREATED = "created";
73 public static final String P_ID_CREATEDBY = "createdby";
74 public static final String P_ID_NOMENCLATURAL_CODE = "nomenclaturalcode";
75 public static final String P_ID_NOMENCLATURAL_REF = "nomenclaturalref";
76 public static final String P_ID_NOMENCLATURAL_MICROREF = "nomenclaturalmicroref";
77
78 // Property display keys
79 public static final String P_PARSED = "Parsing Status";
80 public static final String P_RANK = "Rank";
81 public static final String P_TITLECACHE = "Name Cache";
82 public static final String P_HOMOTYPICALGROUP = "Homotypical Group";
83 public static final String P_NAMERELATIONS = "Name Relations";
84 public static final String P_TYPE = "Type";
85 public static final String P_ANNOTATIONS = "Annotations";
86 public static final String P_NOMSTATUS = "Nomenclatural Status";
87 public static final String P_UUID = "UUID";
88 public static final String P_NUM_OF_BASES = "Number of Bases";
89 public static final String P_MARKERS = "Markers";
90 public static final String P_CREATED = "Created";
91 public static final String P_CREATEDBY = "Created By";
92 public static final String P_NOMENCLATURAL_CODE = "Nomenclatural Code";
93 public static final String P_NOMENCLATURAL_REF = "Nomenclatural Reference";
94 public static final String P_NOMENCLATURAL_MICROREF = "Reference Detail";
95
96 protected static final String[] TOP_LEVEL_PROPERTIES = new String[] {
97 P_ID_PARSED,
98 P_ID_UUID,
99 P_ID_NOMENCLATURAL_CODE,
100 P_ID_RANK,
101 P_ID_TITLECACHE,
102 P_ID_NOMENCLATURAL_REF,
103 P_ID_NOMENCLATURAL_MICROREF,
104 P_ID_NOMSTATUS,
105 P_ID_NAMERELATIONS,
106 P_ID_ANNOTATIONS,
107 P_ID_CREATED,
108 P_ID_CREATEDBY };
109
110 // ***********************************************************
111 // RANKS
112 // ***********************************************************
113 Rank[] ranks = null;
114 String[] P_RANK_MENU = null;
115 private void populateRanks() {
116
117 // Get terms from rank vocabulary
118 List<Rank> ranksList = new ArrayList<Rank>();
119 ranksList.addAll(PreferencesUtil.getPreferredRanks());
120
121 // Populate ranks menu labels
122 List<String> ranksMenuList = new ArrayList<String>();
123 for (Rank rank : ranksList) {
124 ranksMenuList.add(rank.getLabel());
125 }
126
127 // Add an empty element for "nothing selected" in the rank drop-down
128 ranksList.add(0, null);
129 ranksMenuList.add(0, "");
130
131 // Convert rank lists to array
132 ranks = ranksList.toArray(new Rank[ranksList.size()]);
133 P_RANK_MENU = ranksMenuList.toArray(new String[ranksMenuList.size()]);
134 }
135
136 // ***********************************************************
137 // NOMENCLATURAL STATUS
138 // ***********************************************************
139
140 NomenclaturalStatusType[] nomStatusTypes = null;
141 String[] P_NOMSTATUS_MENU = null;
142 private void populateNomStatusTypes() {
143
144 // Get terms from nom status vocabulary
145 List<NomenclaturalStatusType> nomStatusTypesList = new ArrayList<NomenclaturalStatusType>();
146 List<NomenclaturalStatusType> statusVocab = PreferencesUtil.getPreferredNomenclaturalStatusTypes();
147
148 // If there is no status vocabulary, init type and status w empty arrays and return
149 if (statusVocab == null) {
150 nomStatusTypes = new NomenclaturalStatusType[]{};
151 P_NOMSTATUS_MENU = new String[]{};
152 return;
153 }
154
155 nomStatusTypesList.addAll(statusVocab);
156
157 // Populate nom status type menu labels
158 List<String> nomStatusTypesMenuList = new ArrayList<String>();
159 for (NomenclaturalStatusType nomStatusType : nomStatusTypesList) {
160 nomStatusTypesMenuList.add(nomStatusType.getLabel());
161 }
162
163 // Add an empty element for "nothing selected" in the rank drop-down
164 nomStatusTypesList.add(0, null);
165 nomStatusTypesMenuList.add(0, "");
166
167 // Convert rank lists to array
168 nomStatusTypes = nomStatusTypesList.toArray(new NomenclaturalStatusType[nomStatusTypesList.size()]);
169 P_NOMSTATUS_MENU = nomStatusTypesMenuList.toArray(new String[nomStatusTypesMenuList.size()]);
170 }
171
172 protected Vector<PropertyDescriptor> descriptors = new Vector<PropertyDescriptor>();
173 /**
174 * Add descriptor for a given property.
175 * <p>
176 * Notes on Descriptor:
177 * </p>
178 * <ul>
179 * <li>PropertyDescriptor - uneditable cell value</li>
180 * <li>ComboBoxPropertyDescriptor - dropdown list, property supplied must be integer-based</li>
181 * <li>TextPropertyDescriptor - editable cell value</li>
182 * </ul>
183 * <p>
184 * If any descriptor calls setCategory, all descriptors w/out a category are put in
185 * category "Misc".
186 * <p>
187 * <code>descriptor.setFilterFlags (new String[] { IPropertySheetEntry.FILTER_ID_EXPERT })</code> -
188 * this descriptor shown under advanced properties
189 *
190 * @param id
191 */
192 protected void addDescriptor(String id) {
193
194 // Parsed: reports whether parsing was successful
195 if (id.equals(P_ID_PARSED)) {
196 descriptors.addElement(
197 new PropertyDescriptor(P_ID_PARSED, P_PARSED));
198 }
199
200 // Rank menu
201 if (id.equals(P_ID_RANK)) {
202 if (ranks == null) {
203 populateRanks();
204 }
205 descriptors.addElement(
206 new EditorComboBoxPropertyDescriptor(P_ID_RANK, P_RANK, P_RANK_MENU));
207 }
208
209 // Title cache
210 if (id.equals(P_ID_TITLECACHE)) {
211 descriptors.addElement(
212 new PropertyDescriptor(P_ID_TITLECACHE, P_TITLECACHE));
213 }
214
215 // Homotypical group
216 if (id.equals(P_ID_HOMOTYPICALGROUP)) {
217 descriptors.addElement(
218 new PropertyDescriptor(P_ID_HOMOTYPICALGROUP, P_HOMOTYPICALGROUP));
219 }
220
221 // Name relations, listed in custom property descriptor
222 if (id.equals(P_ID_NAMERELATIONS)) {
223 descriptors.addElement(
224 new NameRelationsPropertyDescriptor(P_ID_NAMERELATIONS, P_NAMERELATIONS, name)
225 );
226 };
227
228 // Type
229 if (id.equals(P_ID_TYPE)) {
230 descriptors.addElement(
231 new PropertyDescriptor(P_ID_TYPE, P_TYPE));
232 }
233
234 // Annotations, listed in custom property descriptor
235 if (id.equals(P_ID_ANNOTATIONS)) {
236 descriptors.addElement(
237 new AnnotationsPropertyDescriptor(P_ID_ANNOTATIONS, P_ANNOTATIONS, name) {
238 protected void saveAnnotations(Set set) {
239 setPropertyValue(P_ID_ANNOTATIONS, set);
240 }
241 }
242 );
243 };
244
245 // Nomenclatural status
246 if (id.equals(P_ID_NOMSTATUS)) {
247 if (nomStatusTypes == null) {
248 populateNomStatusTypes();
249 }
250 descriptors.addElement(
251 new ComboBoxPropertyDescriptor(P_ID_NOMSTATUS, P_NOMSTATUS, P_NOMSTATUS_MENU));
252 }
253
254 // UUID
255 if (id.equals(P_ID_UUID)) {
256 descriptors.addElement(
257 new PropertyDescriptor(P_ID_UUID, P_UUID));
258 }
259
260 // Markers
261 if (id.equals(P_ID_MARKERS)) {
262 descriptors.addElement(
263 new PropertyDescriptor(P_ID_MARKERS, P_MARKERS));
264 }
265
266 // Taxon bases referring to this name
267 if (id.equals(P_ID_NUM_OF_BASES)) {
268 descriptors.addElement(
269 new PropertyDescriptor(P_ID_NUM_OF_BASES, P_NUM_OF_BASES));
270 }
271
272 // Object created when
273 if (id.equals(P_ID_CREATED)) {
274 descriptors.addElement(
275 new PropertyDescriptor(P_ID_CREATED, P_CREATED));
276 }
277
278 // Object created by
279 if (id.equals(P_ID_CREATEDBY)) {
280 descriptors.addElement(
281 new PropertyDescriptor(P_ID_CREATEDBY, P_CREATEDBY));
282 }
283
284 // Nomenclatural code used by parser
285 if (id.equals(P_ID_NOMENCLATURAL_CODE)) {
286 descriptors.addElement(
287 new PropertyDescriptor(P_ID_NOMENCLATURAL_CODE, P_NOMENCLATURAL_CODE));
288 }
289
290 // Nomenclatural reference
291 if (id.equals(P_ID_NOMENCLATURAL_REF)) {
292 descriptors.addElement(
293 new PropertyDescriptor(P_ID_NOMENCLATURAL_REF,P_NOMENCLATURAL_REF));
294 }
295
296 // Microreference
297 if (id.equals(P_ID_NOMENCLATURAL_MICROREF)) {
298 descriptors.addElement(
299 new TextPropertyDescriptor(P_ID_NOMENCLATURAL_MICROREF,P_NOMENCLATURAL_MICROREF));
300 }
301 }
302
303 /**
304 * Constructor for top level property fields. All fields that are not subfields
305 * should be listed here.
306 * @param name
307 */
308 public NonViralNamePropertySource(NonViralName<?> name) {
309 this(name, null, TOP_LEVEL_PROPERTIES);
310 }
311
312 public NonViralNamePropertySource(NonViralName<?> name,
313 String parentid, String[] keys) {
314 this.name = name;
315 this.parentid = parentid;
316 for (String key : keys) {
317 addDescriptor(key);
318 }
319 }
320
321 public Object getEditableValue() {
322 return this;
323 }
324
325 public IPropertyDescriptor[] getPropertyDescriptors() {
326 return (IPropertyDescriptor[]) descriptors.toArray(
327 new IPropertyDescriptor[descriptors.size()]);
328 }
329
330 public Object getPropertyValue(Object id) {
331
332 // Parsed: reports whether parsing was successful
333 if (id.equals(P_ID_PARSED)) {
334 String str = null;
335 for (ParserProblem problem : name.getParsingProblems()) {
336 str = str == null ? problem.toString() : str + problem.toString();
337 }
338 return str == null ? "parsed" : str;
339 }
340
341 // Rank menu
342 if (id.equals(P_ID_RANK)) {
343 if (this.name.getRank() == null) {
344 return 0;
345 }
346 Rank rank = this.name.getRank();
347 for (int i = 0; i < ranks.length; i++) {
348 if (ranks[i] == null) continue;
349 if (rank.getUuid().equals(ranks[i].getUuid()))
350 return i;
351 }
352 return 0;
353 }
354
355 // Title cache
356 if (id.equals(P_ID_TITLECACHE)) {
357
358 // If the name has not been parsed, only show the title cache
359 if (name.getRank() == null) {
360 return CdmUtils.Nz(name.getTitleCache());
361 } else {
362
363 // Create property source for submenu
364 ScientificNamePropertySource nameFieldsPropertySource = new ScientificNamePropertySource(name);
365
366 // Add listener to notify name of all changes to nom. reference
367 nameFieldsPropertySource.addPropertyChangeListener(new PropertyChangeListener() {
368 public void propertyChange(PropertyChangeEvent evt) {
369 // if (evt.getNewValue() instanceof INomenclaturalReference) {
370 // name.setNomenclaturalReference((INomenclaturalReference) evt.getNewValue());
371 // }
372 }
373 });
374 return nameFieldsPropertySource;
375 }
376 }
377
378 // Homotypical group
379 if (id.equals(P_ID_HOMOTYPICALGROUP)) {
380 return CdmUtils.Nz(name.getHomotypicalGroup().getUuid().toString());
381 }
382
383 // Annotations, listed in custom property descriptor
384 if (id.equals(P_ID_ANNOTATIONS)) {
385 return new AnnotationPropertySource(name);
386 }
387
388 // Nomenclatural status
389 if (id.equals(P_ID_NOMSTATUS)) {
390 // return new NomStatusPropertySource(name.getStatus());
391 // if (this.name.getRank() == null) return 0;
392 Set<NomenclaturalStatus> nomStatusSet = this.name.getStatus();
393
394 if (nomStatusSet == null || nomStatusSet.size() == 0) {
395 return 0;
396 }
397 // TODO for now, only showing first nom status - change!
398 NomenclaturalStatus nomStatus = (NomenclaturalStatus) nomStatusSet.toArray()[0];
399 for (int i = 0; i < nomStatusTypes.length; i++) {
400 if (nomStatusTypes[i] == null) continue;
401 if (nomStatus.getType().getUuid().equals(nomStatusTypes[i].getUuid()))
402 return i;
403 }
404 return 0;
405 }
406
407 // Name relations, popup to edit list
408 if (id.equals(P_ID_NAMERELATIONS)) {
409 return new NameRelationsPropertySource(name);
410 }
411
412 // Type
413 if (id.equals(P_ID_TYPE)) {
414 return "";
415 }
416
417 // UUID
418 if (id.equals(P_ID_UUID)) {
419 return CdmUtils.Nz(name.getUuid().toString());
420 }
421
422 // Markers
423 if (id.equals(P_ID_MARKERS)) {
424 return new MarkersPropertySource(name.getMarkers());
425 }
426
427 // Taxon bases referring to this name
428 if (id.equals(P_ID_NUM_OF_BASES)) {
429 return name.getTaxonBases().size();
430 }
431
432 // Object created by
433 if (id.equals(P_ID_CREATED)) {
434 if (name.getCreated() == null) {
435 return "";
436 } else {
437 return formatDate(name.getCreated().toDate());
438 }
439 }
440
441 // Object created when
442 if (id.equals(P_ID_CREATEDBY)) {
443 if (name.getCreatedBy() == null) {
444 return "";
445 } else {
446 return CdmUtils.Nz(name.getCreatedBy().getUsername());
447 }
448 }
449
450 // Nomenclatural code used by parser
451 if (id.equals(P_ID_NOMENCLATURAL_CODE)) {
452 // Only shown if extending classes don't handle P_ID_NOMENCLATURAL_CODE
453 return "none (nonviral name)";
454 }
455
456 // Nomenclatural reference
457 if (id.equals(P_ID_NOMENCLATURAL_REF)) {
458
459 ReferenceBase<?> nomRef = (ReferenceBase<?>) name.getNomenclaturalReference();
460
461 // Create nom. reference as necessary
462 if (nomRef == null) {
463 nomRef = Generic.NewInstance();
464 }
465
466 // Create property source for submenu
467 ReferencePropertySource nomRefPropertySource = new NomenclaturalReferencePropertySource(nomRef);
468
469 // Add listener to notify name of all changes to nom. reference
470 nomRefPropertySource.addPropertyChangeListener(new PropertyChangeListener() {
471 public void propertyChange(PropertyChangeEvent evt) {
472 if (evt.getNewValue() instanceof INomenclaturalReference) {
473 name.setNomenclaturalReference((ReferenceBase<?>) evt.getNewValue());
474 }
475 }
476 });
477 return nomRefPropertySource;
478
479 }
480
481 // Microreference
482 if (id.equals(P_ID_NOMENCLATURAL_MICROREF)) {
483 return CdmUtils.Nz(name.getNomenclaturalMicroReference());
484 }
485 return null;
486 }
487
488
489 private Object formatDate(Date date) {
490 return String.format("%1$tm-%1$td-%1$tY %1$tH:%1$tM:%1$tS", date);
491 }
492
493 public boolean isPropertySet(Object id) {
494 return false;
495 }
496
497 public void resetPropertyValue(Object id) {}
498
499 /**
500 * Any editable fields are set in the object here.
501 *
502 * @see org.eclipse.ui.views.properties.IPropertySource#setPropertyValue(java.lang.Object, java.lang.Object)
503 */
504 public void setPropertyValue(Object id, Object value) {
505
506 // Since this is only called when the property value changes,
507 // it is a reliable place to fire the name's property change
508 // listener.
509 // name.firePropertyChange(Resources.PROPERTY_SHEET_CHANGE, null, null);
510
511 // Rank menu
512 if (id.equals(P_ID_RANK)) {
513 int index = ((Integer) value).intValue();
514 name.setRank(ranks[index]);
515 }
516
517 // Nomenclatural status
518 if (id.equals(P_ID_NOMSTATUS)) {
519 NomenclaturalStatus nomStatus;
520 int index = ((Integer) value).intValue();
521 Set<NomenclaturalStatus> nomStatusSet = name.getStatus();
522
523 if (nomStatusSet.size() > 0) {
524 nomStatus = (NomenclaturalStatus) nomStatusSet.toArray()[0];
525
526 if (index == 0) {
527 nomStatusSet.remove(nomStatus);
528 } else {
529 nomStatus.setType(nomStatusTypes[index]);
530 }
531
532 } else {
533 nomStatus = NomenclaturalStatus.NewInstance(nomStatusTypes[index]);
534 name.addStatus(nomStatus);
535 }
536 }
537
538 // Markers
539 if (id.equals(P_ID_MARKERS)) {
540 // TODO set markers
541 }
542
543 // Nomenclatural reference
544 if (id.equals(P_ID_NOMENCLATURAL_REF)) {
545 if (value instanceof INomenclaturalReference) {
546 name.setNomenclaturalReference((ReferenceBase<?>) value);
547 }
548 }
549
550 // Microreference
551 if (id.equals(P_ID_NOMENCLATURAL_MICROREF)) {
552 name.setNomenclaturalMicroReference((String) value);
553 }
554
555 // If there is no rank, generated caches will be blank, wiping out the freetext area
556 if (name.getRank() != null) {
557
558 // Reset both caches to reflect property sheet changes
559 if (!name.isProtectedTitleCache()) {
560 name.setTitleCache(name.generateTitle(), false);
561 }
562
563 if (!name.isProtectedFullTitleCache()) {
564 name.setFullTitleCache(name.generateFullTitle(), false);
565 }
566 }
567
568 // name.firePropertyChange(ITaxEditorConstants.REFRESH_NAMEVIEWER, null, null);
569
570 }
571
572 /**
573 * Any node with children must override {@link java.lang.Object#toString()}
574 * to display its name correctly
575 *
576 * @see java.lang.Object#toString()
577 */
578 public String toString() {
579 if (parentid == null || parentid.equals("")) {
580 return "";
581 }
582 if (parentid.equals(P_ID_TITLECACHE)) {
583 return name.getTitleCache();
584 }
585 if (parentid.equals(P_ID_NOMENCLATURAL_REF)) {
586 INomenclaturalReference nomenclaturalReference = (INomenclaturalReference) name.getNomenclaturalReference();
587 if (nomenclaturalReference == null) {
588 return "";
589 }
590 String microReference = name.getNomenclaturalMicroReference();
591 return CdmUtils.Nz(nomenclaturalReference.getNomenclaturalCitation(microReference));
592 }
593 return super.toString();
594 }
595
596 public void addPropertyChangeListener(
597 PropertyChangeListener listener) {
598 this.propertyChangeSupport.addPropertyChangeListener(listener);
599 }
600
601 public NonViralName<?> getName() {
602 return name;
603 }
604 }