Moving editor sources back into trunk
[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.apache.log4j.Logger;
22 import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor;
23 import org.eclipse.ui.views.properties.IPropertyDescriptor;
24 import org.eclipse.ui.views.properties.IPropertySource;
25 import org.eclipse.ui.views.properties.PropertyDescriptor;
26 import org.eclipse.ui.views.properties.TextPropertyDescriptor;
27
28 import eu.etaxonomy.cdm.common.CdmUtils;
29 import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
30 import eu.etaxonomy.cdm.model.common.TermVocabulary;
31 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
32 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
33 import eu.etaxonomy.cdm.model.name.NonViralName;
34 import eu.etaxonomy.cdm.model.name.Rank;
35 import eu.etaxonomy.cdm.model.reference.Generic;
36 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
37 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
38 import eu.etaxonomy.taxeditor.propertysheet.AnnotationsPropertyDescriptor;
39 import eu.etaxonomy.taxeditor.propertysheet.MarkersPropertySource;
40 import eu.etaxonomy.taxeditor.propertysheet.reference.NomenclaturalReferencePropertySource;
41 import eu.etaxonomy.taxeditor.propertysheet.reference.ReferencePropertySource;
42 import eu.etaxonomy.taxeditor.store.CdmStore;
43 import eu.etaxonomy.taxeditor.store.preference.PreferencesUtil;
44
45 /**
46 * @author p.ciardelli
47 * @created 06.05.2008
48 * @version 1.0
49 */
50 public class NonViralNamePropertySource implements IPropertySource {
51 private static final Logger logger = Logger
52 .getLogger(NonViralNamePropertySource.class);
53
54 // The name whose properties are being displayed
55 NonViralName name;
56
57 // If this is a property with a parent, the parent's property ID
58 private String parentid = "";
59
60 PropertyChangeSupport propertyChangeSupport;
61
62 // Property unique keys
63 public static final String P_ID_PARSED = "parsed";
64 public static final String P_ID_RANK = "rank";
65 public static final String P_ID_TITLECACHE = "titlecache";
66 public static final String P_ID_HOMOTYPICALGROUP = "homogroup";
67 public static final String P_ID_NAMERELATIONS = "namerelations";
68 public static final String P_ID_TYPE = "type";
69 public static final String P_ID_ANNOTATIONS = "annotations";
70 public static final String P_ID_NOMSTATUS = "nomstatus";
71 public static final String P_ID_UUID = "uuid";
72 public static final String P_ID_NUM_OF_BASES = "numberofbases";
73 public static final String P_ID_MARKERS = "markers";
74 public static final String P_ID_CREATED = "created";
75 public static final String P_ID_CREATEDBY = "createdby";
76 public static final String P_ID_NOMENCLATURAL_CODE = "nomenclaturalcode";
77 public static final String P_ID_NOMENCLATURAL_REF = "nomenclaturalref";
78 public static final String P_ID_NOMENCLATURAL_MICROREF = "nomenclaturalmicroref";
79
80 // Property display keys
81 public static final String P_PARSED = "Parsing Status";
82 public static final String P_RANK = "Rank";
83 public static final String P_TITLECACHE = "Name Cache";
84 public static final String P_HOMOTYPICALGROUP = "Homotypical Group";
85 public static final String P_NAMERELATIONS = "Name Relations";
86 public static final String P_TYPE = "Type";
87 public static final String P_ANNOTATIONS = "Annotations";
88 public static final String P_NOMSTATUS = "Nomenclatural Status";
89 public static final String P_UUID = "UUID";
90 public static final String P_NUM_OF_BASES = "Number of Bases";
91 public static final String P_MARKERS = "Markers";
92 public static final String P_CREATED = "Created";
93 public static final String P_CREATEDBY = "Created By";
94 public static final String P_NOMENCLATURAL_CODE = "Nomenclatural Code";
95 public static final String P_NOMENCLATURAL_REF = "Nomenclatural Reference";
96 public static final String P_NOMENCLATURAL_MICROREF = "Reference Detail";
97
98 protected static final String[] TOP_LEVEL_PROPERTIES = new String[] {
99 P_ID_PARSED,
100 P_ID_UUID,
101 P_ID_NOMENCLATURAL_CODE,
102 P_ID_RANK,
103 P_ID_TITLECACHE,
104 P_ID_NOMENCLATURAL_REF,
105 P_ID_NOMENCLATURAL_MICROREF,
106 P_ID_NOMSTATUS,
107 P_ID_NAMERELATIONS,
108 P_ID_ANNOTATIONS,
109 P_ID_CREATED,
110 P_ID_CREATEDBY };
111
112 // ***********************************************************
113 // RANKS
114 // ***********************************************************
115 Rank[] ranks = null;
116 String[] P_RANK_MENU = null;
117 private void populateRanks() {
118
119 // Get terms from rank vocabulary
120 List<Rank> ranksList = new ArrayList<Rank>();
121 ranksList.addAll(PreferencesUtil.getPreferredRanks());
122
123 // Populate ranks menu labels
124 List<String> ranksMenuList = new ArrayList<String>();
125 for (Rank rank : ranksList) {
126 ranksMenuList.add(rank.getLabel());
127 }
128
129 // Add an empty element for "nothing selected" in the rank drop-down
130 ranksList.add(0, null);
131 ranksMenuList.add(0, "");
132
133 // Convert rank lists to array
134 ranks = ranksList.toArray(new Rank[ranksList.size()]);
135 P_RANK_MENU = ranksMenuList.toArray(new String[ranksMenuList.size()]);
136 }
137
138 // ***********************************************************
139 // NOMENCLATURAL STATUS
140 // ***********************************************************
141 // static TermVocabulary<NomenclaturalStatusType> nomStatusVocabulary =
142 // TaxEditorPlugin.getDefault().getNomStatusVocabulary();
143 NomenclaturalStatusType[] nomStatusTypes = null;
144 String[] P_NOMSTATUS_MENU = null;
145 private void populateNomStatusTypes() {
146
147 // Get terms from nom status vocabulary
148 List<NomenclaturalStatusType> nomStatusTypesList = new ArrayList<NomenclaturalStatusType>();
149 TermVocabulary<NomenclaturalStatusType> statusVocab =
150 CdmStore.getDefault().getNomStatus();
151
152 // If there is no status vocabulary, init type and status w empty arrays and return
153 if (statusVocab == null) {
154 nomStatusTypes = new NomenclaturalStatusType[]{};
155 P_NOMSTATUS_MENU = new String[]{};
156 return;
157 }
158
159 nomStatusTypesList.addAll(statusVocab.getTerms());
160
161 // Populate nom status type menu labels
162 List<String> nomStatusTypesMenuList = new ArrayList<String>();
163 for (NomenclaturalStatusType nomStatusType : nomStatusTypesList) {
164 nomStatusTypesMenuList.add(nomStatusType.getLabel());
165 }
166
167 // Add an empty element for "nothing selected" in the rank drop-down
168 nomStatusTypesList.add(0, null);
169 nomStatusTypesMenuList.add(0, "");
170
171 // Convert rank lists to array
172 nomStatusTypes = nomStatusTypesList.toArray(new NomenclaturalStatusType[nomStatusTypesList.size()]);
173 P_NOMSTATUS_MENU = nomStatusTypesMenuList.toArray(new String[nomStatusTypesMenuList.size()]);
174 }
175
176 protected Vector<PropertyDescriptor> descriptors = new Vector<PropertyDescriptor>();
177 /**
178 * Add descriptor for a given property.
179 * <p>
180 * Notes on Descriptor:
181 * </p>
182 * <ul>
183 * <li>PropertyDescriptor - uneditable cell value</li>
184 * <li>ComboBoxPropertyDescriptor - dropdown list, property supplied must be integer-based</li>
185 * <li>TextPropertyDescriptor - editable cell value</li>
186 * </ul>
187 * <p>
188 * If any descriptor calls setCategory, all descriptors w/out a category are put in
189 * category "Misc".
190 * <p>
191 * <code>descriptor.setFilterFlags (new String[] { IPropertySheetEntry.FILTER_ID_EXPERT })</code> -
192 * this descriptor shown under advanced properties
193 *
194 * @param id
195 */
196 protected void addDescriptor(String id) {
197
198 // Parsed: reports whether parsing was successful
199 if (id.equals(P_ID_PARSED)) {
200 descriptors.addElement(
201 new PropertyDescriptor(P_ID_PARSED, P_PARSED));
202 }
203
204 // Rank menu
205 if (id.equals(P_ID_RANK)) {
206 if (ranks == null) {
207 populateRanks();
208 }
209 descriptors.addElement(
210 new EditorComboBoxPropertyDescriptor(P_ID_RANK, P_RANK, P_RANK_MENU));
211 }
212
213 // Title cache
214 if (id.equals(P_ID_TITLECACHE)) {
215 descriptors.addElement(
216 new PropertyDescriptor(P_ID_TITLECACHE, P_TITLECACHE));
217 }
218
219 // Homotypical group
220 if (id.equals(P_ID_HOMOTYPICALGROUP)) {
221 descriptors.addElement(
222 new PropertyDescriptor(P_ID_HOMOTYPICALGROUP, P_HOMOTYPICALGROUP));
223 }
224
225 // Name relations, listed in custom property descriptor
226 if (id.equals(P_ID_NAMERELATIONS)) {
227 descriptors.addElement(
228 new NameRelationsPropertyDescriptor(P_ID_NAMERELATIONS, P_NAMERELATIONS, name)
229 );
230 };
231
232 // Type
233 if (id.equals(P_ID_TYPE)) {
234 descriptors.addElement(
235 new PropertyDescriptor(P_ID_TYPE, P_TYPE));
236 }
237
238 // Annotations, listed in custom property descriptor
239 if (id.equals(P_ID_ANNOTATIONS)) {
240 descriptors.addElement(
241 new AnnotationsPropertyDescriptor(P_ID_ANNOTATIONS, P_ANNOTATIONS, name) {
242 protected void saveAnnotations(Set set) {
243 setPropertyValue(P_ID_ANNOTATIONS, set);
244 }
245 }
246 );
247 };
248
249 // Nomenclatural status
250 if (id.equals(P_ID_NOMSTATUS)) {
251 if (nomStatusTypes == null) {
252 populateNomStatusTypes();
253 }
254 descriptors.addElement(
255 new ComboBoxPropertyDescriptor(P_ID_NOMSTATUS, P_NOMSTATUS, P_NOMSTATUS_MENU));
256 }
257
258 // UUID
259 if (id.equals(P_ID_UUID)) {
260 descriptors.addElement(
261 new PropertyDescriptor(P_ID_UUID, P_UUID));
262 }
263
264 // Markers
265 if (id.equals(P_ID_MARKERS)) {
266 descriptors.addElement(
267 new PropertyDescriptor(P_ID_MARKERS, P_MARKERS));
268 }
269
270 // Taxon bases referring to this name
271 if (id.equals(P_ID_NUM_OF_BASES)) {
272 descriptors.addElement(
273 new PropertyDescriptor(P_ID_NUM_OF_BASES, P_NUM_OF_BASES));
274 }
275
276 // Object created when
277 if (id.equals(P_ID_CREATED)) {
278 descriptors.addElement(
279 new PropertyDescriptor(P_ID_CREATED, P_CREATED));
280 }
281
282 // Object created by
283 if (id.equals(P_ID_CREATEDBY)) {
284 descriptors.addElement(
285 new PropertyDescriptor(P_ID_CREATEDBY, P_CREATEDBY));
286 }
287
288 // Nomenclatural code used by parser
289 if (id.equals(P_ID_NOMENCLATURAL_CODE)) {
290 descriptors.addElement(
291 new PropertyDescriptor(P_ID_NOMENCLATURAL_CODE, P_NOMENCLATURAL_CODE));
292 }
293
294 // Nomenclatural reference
295 if (id.equals(P_ID_NOMENCLATURAL_REF)) {
296 descriptors.addElement(
297 new PropertyDescriptor(P_ID_NOMENCLATURAL_REF,P_NOMENCLATURAL_REF));
298 }
299
300 // Microreference
301 if (id.equals(P_ID_NOMENCLATURAL_MICROREF)) {
302 descriptors.addElement(
303 new TextPropertyDescriptor(P_ID_NOMENCLATURAL_MICROREF,P_NOMENCLATURAL_MICROREF));
304 }
305 }
306
307 /**
308 * Constructor for top level property fields. All fields that are not subfields
309 * should be listed here.
310 * @param name
311 */
312 public NonViralNamePropertySource(NonViralName name) {
313 this(name, null, TOP_LEVEL_PROPERTIES);
314 }
315
316 public NonViralNamePropertySource(NonViralName name,
317 String parentid, String[] keys) {
318 this.name = name;
319 this.parentid = parentid;
320 for (String key : keys) {
321 addDescriptor(key);
322 }
323 }
324
325 public Object getEditableValue() {
326 return this;
327 }
328
329 public IPropertyDescriptor[] getPropertyDescriptors() {
330 return (IPropertyDescriptor[]) descriptors.toArray(
331 new IPropertyDescriptor[descriptors.size()]);
332 }
333
334 public Object getPropertyValue(Object id) {
335
336 // Parsed: reports whether parsing was successful
337 if (id.equals(P_ID_PARSED)) {
338 return name.getHasProblem() == true ? "problem" : "parsed" ;
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.getAnnotations());
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, name.getNameRelations());
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(((IIdentifiableEntity) name.getCreatedBy()).generateTitle());
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 }