2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
;
12 import java
.beans
.PropertyChangeListener
;
14 import java
.util
.ArrayList
;
15 import java
.util
.Collection
;
16 import java
.util
.HashMap
;
17 import java
.util
.HashSet
;
18 import java
.util
.List
;
20 import java
.util
.ResourceBundle
;
22 import java
.util
.UUID
;
24 import org
.apache
.log4j
.Logger
;
25 import org
.eclipse
.core
.databinding
.observable
.Realm
;
26 import org
.eclipse
.core
.databinding
.observable
.list
.WritableList
;
27 import org
.eclipse
.core
.databinding
.observable
.set
.IObservableSet
;
28 import org
.eclipse
.core
.databinding
.observable
.set
.ISetChangeListener
;
29 import org
.eclipse
.core
.databinding
.observable
.set
.SetChangeEvent
;
30 import org
.eclipse
.core
.databinding
.observable
.set
.WritableSet
;
31 import org
.eclipse
.core
.runtime
.FileLocator
;
32 import org
.eclipse
.core
.runtime
.IPath
;
33 import org
.eclipse
.core
.runtime
.Path
;
34 import org
.eclipse
.jface
.databinding
.swt
.SWTObservables
;
35 import org
.eclipse
.jface
.preference
.IPreferenceStore
;
36 import org
.eclipse
.jface
.resource
.FontRegistry
;
37 import org
.eclipse
.jface
.resource
.ImageDescriptor
;
38 import org
.eclipse
.jface
.resource
.ImageRegistry
;
39 import org
.eclipse
.jface
.util
.PropertyChangeEvent
;
40 import org
.eclipse
.swt
.SWT
;
41 import org
.eclipse
.swt
.graphics
.Font
;
42 import org
.eclipse
.swt
.graphics
.FontData
;
43 import org
.eclipse
.swt
.graphics
.Image
;
44 import org
.eclipse
.swt
.widgets
.Display
;
45 import org
.eclipse
.ui
.forms
.FormColors
;
46 import org
.eclipse
.ui
.plugin
.AbstractUIPlugin
;
47 import org
.osgi
.framework
.BundleContext
;
49 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationController
;
50 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
51 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonService
;
52 import eu
.etaxonomy
.cdm
.database
.DataSourceNotFoundException
;
53 import eu
.etaxonomy
.cdm
.database
.DbSchemaValidation
;
54 import eu
.etaxonomy
.cdm
.model
.agent
.Person
;
55 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
56 import eu
.etaxonomy
.cdm
.model
.common
.OrderedTermVocabulary
;
57 import eu
.etaxonomy
.cdm
.model
.common
.TermVocabulary
;
58 import eu
.etaxonomy
.cdm
.model
.common
.init
.TermNotFoundException
;
59 import eu
.etaxonomy
.cdm
.model
.name
.BotanicalName
;
60 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationshipType
;
61 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
62 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatusType
;
63 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
64 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
65 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
66 import eu
.etaxonomy
.taxeditor
.model
.CdmUtil
;
69 * The class controlling the plug-in life cycle.
75 public class TaxEditorPlugin
extends AbstractUIPlugin
{
76 private static final Logger logger
= Logger
77 .getLogger(TaxEditorPlugin
.class);
82 public static final String PLUGIN_ID
= "eu.etaxonomy.taxeditor.plugin";
86 private static TaxEditorPlugin plugin
;
88 private DbSchemaValidation dbSchemaValidation
= DbSchemaValidation
.VALIDATE
;
93 public TaxEditorPlugin() {
94 logger
.fatal("Fatal");
95 logger
.error("Error");
96 logger
.debug("Debug");
99 logger
.trace("Trace");
101 boolean initDatastore
= false;
102 initDatastore
= true;
104 dbSchemaValidation
= DbSchemaValidation
.CREATE
;
107 cdmApp
= getCdmApp();
114 void initDatastore() {
116 boolean useSoraya
= true;
117 // useSoraya = false;
120 genusTaxon
= getSorayasGenusTaxon();
123 BotanicalName botanicalName
= BotanicalName
.NewInstance(Rank
125 botanicalName
.setTitleCache("Hieracium L.");
126 botanicalName
.setGenusOrUninomial("Hieracium");
127 botanicalName
.setCombinationAuthorTeam(Person
.NewInstance());
128 botanicalName
.getCombinationAuthorTeam()
129 .setNomenclaturalTitle("L.");
130 genusTaxon
= Taxon
.NewInstance(botanicalName
, CdmUtil
131 .getSessionDefaultSec());
133 BotanicalName botSpecies
= BotanicalName
134 .NewInstance(Rank
.SPECIES());
135 botSpecies
.setTitleCache("Hieracium asturianum Pau");
136 botSpecies
.setGenusOrUninomial("Hieracium");
137 botSpecies
.setSpecificEpithet("asturianum");
138 botSpecies
.setCombinationAuthorTeam(Person
.NewInstance());
139 botSpecies
.getCombinationAuthorTeam().setNomenclaturalTitle("Pau");
140 Taxon childTaxon
= Taxon
.NewInstance(botSpecies
, null);
141 childTaxon
.setTaxonomicParent(genusTaxon
, null, null);
143 BotanicalName botSpecies2
= BotanicalName
.NewInstance(Rank
145 botSpecies2
.setTitleCache("Hieracium wolffii Zahn");
146 botSpecies2
.setGenusOrUninomial("Hieracium");
147 botSpecies2
.setSpecificEpithet("wolffii");
148 botSpecies2
.setCombinationAuthorTeam(Person
.NewInstance());
149 botSpecies2
.getCombinationAuthorTeam()
150 .setNomenclaturalTitle("Zahn");
151 Taxon childTaxon2
= Taxon
.NewInstance(botSpecies2
, CdmUtil
152 .getSessionDefaultSec());
153 // childTaxon2.setName(botSpecies2);
154 // childTaxon2.setSec(null);
155 childTaxon2
.setTaxonomicParent(genusTaxon
, null, null);
157 // Add some name relations to botSpecies2
158 botSpecies2
.addRelationshipFromName(botSpecies
,
159 NameRelationshipType
.BASIONYM(), null);
160 botSpecies2
.addRelationshipToName(botSpecies
, NameRelationshipType
161 .REPLACED_SYNONYM(), null);
162 logger
.warn("Name relations created");
164 // Add name status to botSpecies2
165 botSpecies2
.addStatus(NomenclaturalStatus
166 .NewInstance(NomenclaturalStatusType
.NOVUM()));
167 logger
.warn("Nom. status created");
170 getCdmApp().getTaxonService().saveTaxon(genusTaxon
);
178 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
180 public void start(BundleContext context
) throws Exception
{
181 super.start(context
);
188 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
190 public void stop(BundleContext context
) throws Exception
{
196 * Returns the shared instance
198 * @return the shared instance
200 public static TaxEditorPlugin
getDefault() {
204 /***************************************************************************
206 **************************************************************************/
208 * All CDM services are called via the application controller
210 private CdmApplicationController cdmApp
;
212 public CdmApplicationController
getCdmApp() {
213 if (cdmApp
== null) {
215 cdmApp
= CdmApplicationController
216 .NewInstance(dbSchemaValidation
);
217 } catch (DataSourceNotFoundException e
) {
218 // TODO Auto-generated catch block
220 } catch (TermNotFoundException e
) {
221 // TODO Auto-generated catch block
228 private ITaxonService taxonService
;
230 public ITaxonService
getTaxonService() {
231 if (taxonService
== null) {
232 taxonService
= getCdmApp().getTaxonService();
237 private INameService nameService
;
239 public INameService
getNameService() {
240 if (nameService
== null) {
241 nameService
= getCdmApp().getNameService();
246 /***************************************************************************
248 **************************************************************************/
250 private WritableList observableRecentNamesList
= null;
251 private WritableList observableFavoritesList
= null;
253 public WritableList
getObservableRecentNamesList() {
254 if (observableRecentNamesList
== null) {
255 observableRecentNamesList
= new WritableList();
257 return observableRecentNamesList
;
260 public WritableList
getObservableFavoritesList() {
261 if (observableFavoritesList
== null) {
262 observableFavoritesList
= new WritableList();
264 return observableFavoritesList
;
267 /***************************************************************************
269 **************************************************************************/
270 public ImageDescriptor
getImageDescriptor(String key
) {
271 return getImageRegistry().getDescriptor(key
);
274 public Image
getImage(String key
) {
275 return getImageRegistry().get(key
);
279 private ResourceBundle resourceBundle
;
280 private FormColors formColors
;
282 protected void initializeImageRegistry(ImageRegistry registry
) {
283 registerImage(registry
, ITaxEditorConstants
.EDIT_ICON
, "edit_16x16.ico");
284 registerImage(registry
, ITaxEditorConstants
.WARNING_ICON
,
286 registerImage(registry
, ITaxEditorConstants
.ACCEPTED_TAXON_ICON
,
287 "accepted_small.gif");
288 registerImage(registry
, ITaxEditorConstants
.HOMOTYPIC_SYN_ICON
,
289 "homosyn_no_bg.gif");
290 registerImage(registry
,
291 ITaxEditorConstants
.HOMOTYPIC_SYN_ORIGINAL_ICON
,
292 "homosyn_original_no_bg.gif");
293 registerImage(registry
, ITaxEditorConstants
.HETEROTYPIC_SYN_ICON
,
294 "heterosyn_no_bg.gif");
295 registerImage(registry
,
296 ITaxEditorConstants
.HETEROTYPIC_SYN_ORIGINAL_ICON
,
297 "heterosyn_original_no_bg.gif");
298 registerImage(registry
, ITaxEditorConstants
.MISAPPLIED_NAME_ICON
,
299 "misapplied_no_bg.gif");
300 registerImage(registry
, ITaxEditorConstants
.AUTONYM_ICON
,
301 "autonym_no_bg.gif");
302 registerImage(registry
, ITaxEditorConstants
.BASIONYM_ICON
,
303 "basionym_no_bg.gif");
304 registerImage(registry
, ITaxEditorConstants
.ORTHOGRAPHIC_VARIANT_ICON
,
305 "orthovariant_no_bg.gif");
306 registerImage(registry
, ITaxEditorConstants
.DB_ICON
, "db.gif");
307 registerImage(registry
, ITaxEditorConstants
.MOVE_ICON
, "correction_change.gif");
308 registerImage(registry
, ITaxEditorConstants
.ACTIVE_DELETE_ICON
,
310 registerImage(registry
, ITaxEditorConstants
.SYNONYM_TO_TAXON_ICON
,
312 registerImage(registry
, ITaxEditorConstants
.OPEN_TAXON_ICON
,
314 registerImage(registry
, ITaxEditorConstants
.ADD_CHILD_TAXON_ICON
,
316 registerImage(registry
, ITaxEditorConstants
.SWAP_SYNONYM_AND_TAXON_ICON
,
318 registerImage(registry
, ITaxEditorConstants
.QUICK_ADD_ICON
,
322 private void registerImage(ImageRegistry registry
, String key
,
325 IPath path
= new Path("icons/" + fileName
); //$NON-NLS-1$
326 URL url
= FileLocator
.find(getBundle(), path
, null);
328 ImageDescriptor desc
= ImageDescriptor
.createFromURL(url
);
329 registry
.put(key
, desc
);
331 } catch (Exception e
) {
335 /***************************************************************************
337 **************************************************************************/
338 private FontRegistry fontRegistry
;
340 private FontRegistry
getFontRegistry() {
341 if (fontRegistry
== null) {
342 fontRegistry
= new FontRegistry(Display
.getCurrent());
344 fontRegistry
.put(ITaxEditorConstants
.DATASOURCE_FONT
,
345 new FontData
[] { new FontData("Arial", 8, SWT
.NONE
) });
346 fontRegistry
.put(ITaxEditorConstants
.MENU_ITEM_ITALICS_FONT
,
347 new FontData
[] { new FontData("Arial", 9, SWT
.ITALIC
) });
348 fontRegistry
.put(ITaxEditorConstants
.ACCEPTED_TAXON_FONT
,
349 new FontData
[] { new FontData("Georgia", 12, SWT
.NONE
) });
350 fontRegistry
.put(ITaxEditorConstants
.SYNONYM_FONT
,
351 new FontData
[] { new FontData("Georgia", 10, SWT
.NONE
) });
352 fontRegistry
.put(ITaxEditorConstants
.MISAPPLIEDNAME_FONT
,
353 new FontData
[] { new FontData("Georgia", 10, SWT
.NONE
) });
354 fontRegistry
.put(ITaxEditorConstants
.CHOOSE_NAME_TEXT_FONT
,
355 new FontData
[] { new FontData("Arial", 12, SWT
.BOLD
) });
360 public Font
getFont(String key
) {
361 return getFontRegistry().get(key
);
364 /***************************************************************************
366 **************************************************************************/
367 protected void initializeDefaultPreferences(IPreferenceStore store
) {
368 store
.setDefault(ITaxEditorConstants
.CODE_PREFERENCE
,
369 ITaxEditorConstants
.DEFAULT_CODE_PREFERENCE
);
372 /***************************************************************************
374 **************************************************************************/
376 public ReferenceBase
getSec() {
377 return getCdmApp().getReferenceService().getReferenceByUuid(
378 UUID
.fromString("f3593c18-a8d2-4e51-bdad-0befbf8fb2d1"));
381 private List
<Taxon
> rootTaxa
;
383 public List
<Taxon
> getSessionRootTaxa() {
384 if (rootTaxa
== null) {
385 rootTaxa
= new ArrayList
<Taxon
>();
387 .addAll(getCdmApp().getTaxonService().getRootTaxa(getSec(), null, false));
388 addSessionTaxa(rootTaxa
);
394 * This map of taxa to their taxonomic children is used by
395 * NameTreeContentProvider's getChildren method.
397 * key = taxon, value = key's child taxa Note that a map can have a key ==
398 * null, i.e. no parent taxon
400 private HashMap
<Taxon
, Set
<Taxon
>> taxonomicChildrenMap
;
401 private IObservableSet observableTaxonSet
;
403 private Map
<Taxon
, Set
<Taxon
>> getTaxonomicChildrenMap() {
404 if (taxonomicChildrenMap
== null) {
405 taxonomicChildrenMap
= new HashMap
<Taxon
, Set
<Taxon
>>();
407 return taxonomicChildrenMap
;
411 * Returns any child taxa for this taxon that have already been requested
412 * during this session.
417 public Set
<Taxon
> getSessionTaxonomicChildren(Taxon parentTaxon
) {
418 return getTaxonomicChildrenMap().get(parentTaxon
);
421 private void addSessionTaxonomicChildren(Taxon parentTaxon
,
422 Set
<Taxon
> childTaxa
) {
423 Set
<Taxon
> sessionChildTaxa
= getSessionTaxonomicChildren(parentTaxon
);
424 if (sessionChildTaxa
== null) {
425 getTaxonomicChildrenMap().put(parentTaxon
, childTaxa
);
427 sessionChildTaxa
.addAll(childTaxa
);
431 private void addSessionTaxonomicChild(Taxon parentTaxon
, Taxon childTaxon
) {
432 Set
<Taxon
> childTaxa
= new HashSet
<Taxon
>();
433 childTaxa
.add(childTaxon
);
434 addSessionTaxonomicChildren(parentTaxon
, childTaxa
);
438 * All Taxon listen for changes to their parents
440 // PropertyChangeListener taxonomicParentListener = new PropertyChangeListener() {
442 // public void propertyChange(java.beans.PropertyChangeEvent event) {
443 // logger.warn("property change for " + event.getPropertyName());
444 // if (event.getSource() instanceof Taxon) {
446 // // Methods for removing and adding also remap taxa to their new parents.
447 // Taxon childTaxon = (Taxon) event.getSource();
448 // removeSessionTaxon(childTaxon);
449 // addSessionTaxon(childTaxon);
454 public IObservableSet
getObservableSessionTaxa() {
455 if (observableTaxonSet
== null) {
456 Realm realm
= SWTObservables
.getRealm(Display
.getDefault());
457 observableTaxonSet
= new WritableSet(realm
);
458 // observableTaxonSet.addSetChangeListener(new ISetChangeListener() {
460 // public void handleSetChange(SetChangeEvent event) {
461 // for (Object addition : event.diff.getAdditions()) {
462 // if (addition instanceof Taxon) {
463 // ((Taxon) addition).addPropertyChangeListener(
464 // "taxonomicParentCache", taxonomicParentListener);
467 // for (Object removal : event.diff.getRemovals()) {
468 // if (removal instanceof Taxon) {
470 // .removePropertyChangeListener(taxonomicParentListener);
476 return observableTaxonSet
;
479 public void removeSessionTaxon(Taxon taxon
) {
480 getObservableSessionTaxa().remove(taxon
);
481 Taxon parentTaxon
= taxon
.getTaxonomicParent();
482 Set
<Taxon
> children
= getSessionTaxonomicChildren(parentTaxon
);
483 if (children
!= null) {
484 logger
.warn("removing");
485 children
.remove(taxon
);
487 if (parentTaxon
== null) {
488 getSessionRootTaxa().remove(taxon
);
492 public void addSessionTaxa(Collection
<Taxon
> taxa
) {
493 getObservableSessionTaxa().addAll(taxa
);
494 for (Taxon taxon
: taxa
) {
495 addSessionTaxonomicChild(taxon
.getTaxonomicParent(), taxon
);
499 public void addSessionTaxon(Taxon taxon
) {
500 if (getObservableSessionTaxa().contains(taxon
)) {
503 getObservableSessionTaxa().add(taxon
);
504 addSessionTaxonomicChild(taxon
.getTaxonomicParent(), taxon
);
505 if (taxon
.getTaxonomicParent() == null) {
506 getSessionRootTaxa().add(taxon
);
510 /***************************************************************************
512 **************************************************************************/
513 OrderedTermVocabulary
<Rank
> rankVocabulary
= null;
515 public OrderedTermVocabulary
<Rank
> getRankVocabulary() {
516 if (rankVocabulary
== null) {
517 rankVocabulary
= getCdmApp().getNameService().getRankVocabulary();
519 return rankVocabulary
;
522 /***************************************************************************
523 * NOMENCLATURAL STATUS
524 **************************************************************************/
525 TermVocabulary
<NomenclaturalStatusType
> nomStatusVocabulary
= null;
527 public TermVocabulary
<NomenclaturalStatusType
> getNomStatusVocabulary() {
528 if (nomStatusVocabulary
== null) {
529 nomStatusVocabulary
= getCdmApp().getNameService()
530 .getStatusTypeVocabulary();
532 return nomStatusVocabulary
;
535 /***************************************************************************
537 **************************************************************************/
538 TermVocabulary
<NameRelationshipType
> nameRelationshipTypeVocabulary
= null;
540 public TermVocabulary
<NameRelationshipType
> getNameRelationshipTypeVocabulary() {
541 if (nameRelationshipTypeVocabulary
== null) {
542 nameRelationshipTypeVocabulary
= getCdmApp().getNameService()
543 .getNameRelationshipTypeVocabulary();
545 return nameRelationshipTypeVocabulary
;
548 public Set
<NameRelationshipType
> getSortedNameRelationshipTypes() {
549 return getNameRelationshipTypeVocabulary().getTermsOrderedByLabels(
553 /***************************************************************************
555 **************************************************************************/
556 private Taxon
getSorayasGenusTaxon() {
558 String
[] children
= new String
[] {
559 "Heterospathe annectens H.E.Moore",
560 "Heterospathe arfakiana (Becc.) H.E.Moore",
561 "Heterospathe brevicaulis Fernando",
562 "Heterospathe cagayanensis Becc.",
563 "Heterospathe califrons Fernando, Palms 45: 118 (2001).",
564 "Heterospathe clemensiae (Burret) H.E.Moore",
565 "Heterospathe delicatula H.E.Moore",
566 "Heterospathe dransfieldii Fernando",
567 "Heterospathe elata Scheff.",
568 "Heterospathe elata var. elata.",
569 "Heterospathe elata var. guamensis Becc.",
570 "Heterospathe elata var. palauensis (Becc.) Becc.",
571 "Heterospathe elegans (Becc.) Becc.",
572 "Heterospathe elmeri Becc.",
573 "Heterospathe glabra (Burret) H.E.Moore",
574 "Heterospathe glauca (Scheff.) H.E.Moore",
575 "Heterospathe humilis Becc.",
576 "Heterospathe intermedia (Becc.) Fernando",
577 "Heterospathe kajewskii Burret",
578 "Heterospathe ledermanniana Becc.",
579 "Heterospathe lepidota H.E.Moore",
580 "Heterospathe longipes (H.E.Moore) Norup",
581 "Heterospathe macgregorii (Becc.) H.E.Moore",
582 "Heterospathe micrantha (Becc.) H.E.Moore",
583 "Heterospathe minor Burret",
584 "Heterospathe muelleriana (Becc.) Becc.",
585 "Heterospathe negrosensis Becc.",
586 "Heterospathe obriensis (Becc.) H.E.Moore",
587 "Heterospathe palauensis Becc.",
588 "Heterospathe parviflora Essig",
589 "Heterospathe philippinensis (Becc.) Becc.",
590 // "Heterospathe phillipsii D.Fuller & Dowe", // <--------------
591 "Heterospathe pilosa (Burret) Burret",
592 "Heterospathe pisifera (Gaertn.) Burret",
593 "Heterospathe pulchra H.E.Moore",
594 "Heterospathe ramulosa Burret",
595 "Heterospathe salomonensis Becc.",
596 "Heterospathe scitula Fernando", "Heterospathe sensisi Becc.",
597 "Heterospathe sibuyanensis Becc.",
598 "Heterospathe sphaerocarpa Burret",
599 "Heterospathe trispatha Fernando",
600 "Heterospathe uniformis Dowe",
601 "Heterospathe versteegiana Becc.",
602 "Heterospathe woodfordiana Becc." };
604 BotanicalName genusName
= BotanicalName
605 .PARSED_NAME("Heterospathe Scheff.");
607 Taxon genusTaxon
= Taxon
.NewInstance(genusName
, CdmUtil
608 .getSessionDefaultSec());
610 for (String child
: children
) {
611 BotanicalName speciesName
= BotanicalName
.PARSED_NAME(child
);
613 Taxon childTaxon
= Taxon
.NewInstance(speciesName
, CdmUtil
614 .getSessionDefaultSec());
615 childTaxon
.setTaxonomicParent(genusTaxon
, null, null);
617 if (child
.equals("Heterospathe elegans (Becc.) Becc.")) {
618 BotanicalName basionym
= BotanicalName
619 .PARSED_NAME("Barkerwebbia elegans Becc.");
620 speciesName
.addRelationshipFromName(basionym
,
621 NameRelationshipType
.BASIONYM(), null);
622 childTaxon
.addHomotypicSynonymName(basionym
, null, null);
625 if (child
.equals("Heterospathe humilis Becc.")) {
626 BotanicalName synonymName
= BotanicalName
627 .PARSED_NAME("Barkerwebbia humilis (Becc.) Becc. ex Martelli");
628 childTaxon
.addHomotypicSynonymName(synonymName
, null, null);