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