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