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