Operation history implemented for ChangeCompositeToMisappliedName.
[taxeditor.git] / eclipseprojects / eu.etaxonomy.taxeditor / src / eu / etaxonomy / taxeditor / TaxEditorPlugin.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;
11
12 import java.net.URL;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.ResourceBundle;
20 import java.util.Set;
21 import java.util.UUID;
22
23 import org.apache.log4j.Logger;
24 import org.eclipse.core.databinding.observable.Realm;
25 import org.eclipse.core.databinding.observable.list.WritableList;
26 import org.eclipse.core.databinding.observable.set.IObservableSet;
27 import org.eclipse.core.databinding.observable.set.WritableSet;
28 import org.eclipse.core.runtime.FileLocator;
29 import org.eclipse.core.runtime.IPath;
30 import org.eclipse.core.runtime.Path;
31 import org.eclipse.jface.databinding.swt.SWTObservables;
32 import org.eclipse.jface.preference.IPreferenceStore;
33 import org.eclipse.jface.resource.FontRegistry;
34 import org.eclipse.jface.resource.ImageDescriptor;
35 import org.eclipse.jface.resource.ImageRegistry;
36 import org.eclipse.swt.SWT;
37 import org.eclipse.swt.graphics.Font;
38 import org.eclipse.swt.graphics.FontData;
39 import org.eclipse.swt.graphics.Image;
40 import org.eclipse.swt.widgets.Display;
41 import org.eclipse.ui.forms.FormColors;
42 import org.eclipse.ui.plugin.AbstractUIPlugin;
43 import org.osgi.framework.BundleContext;
44
45 import eu.etaxonomy.cdm.api.application.CdmApplicationController;
46 import eu.etaxonomy.cdm.api.service.ITaxonService;
47 import eu.etaxonomy.cdm.database.DataSourceNotFoundException;
48 import eu.etaxonomy.cdm.database.DbSchemaValidation;
49 import eu.etaxonomy.cdm.model.agent.Person;
50 import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
51 import eu.etaxonomy.cdm.model.common.TermVocabulary;
52 import eu.etaxonomy.cdm.model.common.init.TermNotFoundException;
53 import eu.etaxonomy.cdm.model.name.BotanicalName;
54 import eu.etaxonomy.cdm.model.name.NameRelationshipType;
55 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
56 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
57 import eu.etaxonomy.cdm.model.name.Rank;
58 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
59 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
60 import eu.etaxonomy.cdm.model.taxon.Taxon;
61 import eu.etaxonomy.taxeditor.model.CdmUtil;
62
63 /**
64 * The class controlling the plug-in life cycle.
65 *
66 * @author p.ciardelli
67 * @created 15.05.2008
68 * @version 1.0
69 */
70 public class TaxEditorPlugin extends AbstractUIPlugin {
71 private static final Logger logger = Logger.getLogger(TaxEditorPlugin.class);
72
73 /**
74 * The plug-in ID
75 */
76 public static final String PLUGIN_ID = "eu.etaxonomy.taxeditor.plugin";
77 /**
78 * The shared instance
79 */
80 private static TaxEditorPlugin plugin;
81
82 private DbSchemaValidation dbSchemaValidation = DbSchemaValidation.VALIDATE;
83 /**
84 * The constructor
85 */
86 public TaxEditorPlugin() {
87 logger.fatal("Fatal");
88 logger.error("Error");
89 logger.debug("Debug");
90 logger.info("Info");
91 logger.warn("Warn");
92 logger.trace("Trace");
93
94 boolean initDatastore = false;
95 // initDatastore = true;
96 if (initDatastore) {
97 dbSchemaValidation = DbSchemaValidation.CREATE;
98 }
99
100 cdmApp = getCdmApp();
101
102 if (initDatastore) {
103 initDatastore();
104 }
105
106 }
107
108 void initDatastore() {
109
110 boolean useSoraya = true;
111 // useSoraya = false;
112 Taxon genusTaxon;
113 if (useSoraya) {
114 genusTaxon = getSorayasGenusTaxon();
115 } else {
116
117 BotanicalName botanicalName = BotanicalName.NewInstance(Rank.GENUS());
118 botanicalName.setTitleCache("Hieracium L.");
119 botanicalName.setGenusOrUninomial("Hieracium");
120 botanicalName.setCombinationAuthorTeam(Person.NewInstance());
121 botanicalName.getCombinationAuthorTeam().setNomenclaturalTitle("L.");
122 genusTaxon = Taxon.NewInstance(botanicalName, CdmUtil.getSessionDefaultSec());
123
124 BotanicalName botSpecies = BotanicalName.NewInstance(Rank.SPECIES());
125 botSpecies.setTitleCache("Hieracium asturianum Pau");
126 botSpecies.setGenusOrUninomial("Hieracium");
127 botSpecies.setSpecificEpithet("asturianum");
128 botSpecies.setCombinationAuthorTeam(Person.NewInstance());
129 botSpecies.getCombinationAuthorTeam().setNomenclaturalTitle("Pau");
130 Taxon childTaxon = Taxon.NewInstance(botSpecies, null);
131 childTaxon.setTaxonomicParent(genusTaxon, null, null);
132
133 BotanicalName botSpecies2= BotanicalName.NewInstance(Rank.SPECIES());
134 botSpecies2.setTitleCache("Hieracium wolffii Zahn");
135 botSpecies2.setGenusOrUninomial("Hieracium");
136 botSpecies2.setSpecificEpithet("wolffii");
137 botSpecies2.setCombinationAuthorTeam(Person.NewInstance());
138 botSpecies2.getCombinationAuthorTeam().setNomenclaturalTitle("Zahn");
139 Taxon childTaxon2 = Taxon.NewInstance(botSpecies2, CdmUtil.getSessionDefaultSec());
140 // childTaxon2.setName(botSpecies2);
141 // childTaxon2.setSec(null);
142 childTaxon2.setTaxonomicParent(genusTaxon, null, null);
143
144 // Add some name relations to botSpecies2
145 botSpecies2.addRelationshipFromName(botSpecies, NameRelationshipType.BASIONYM(), null);
146 botSpecies2.addRelationshipToName(botSpecies, NameRelationshipType.REPLACED_SYNONYM(), null);
147 logger.warn("Name relations created");
148
149 // Add name status to botSpecies2
150 botSpecies2.addStatus(NomenclaturalStatus.NewInstance(NomenclaturalStatusType.NOVUM()));
151 logger.warn("Nom. status created");
152 }
153
154 getCdmApp().getTaxonService().saveTaxon(genusTaxon);
155
156 // System.exit(-1);
157 }
158
159 /*
160 * (non-Javadoc)
161 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
162 */
163 public void start(BundleContext context) throws Exception {
164 super.start(context);
165 plugin = this;
166 }
167
168 /*
169 * (non-Javadoc)
170 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
171 */
172 public void stop(BundleContext context) throws Exception {
173 plugin = null;
174 super.stop(context);
175 }
176
177 /**
178 * Returns the shared instance
179 *
180 * @return the shared instance
181 */
182 public static TaxEditorPlugin getDefault() {
183 return plugin;
184 }
185
186 /* ***************************************************************************************
187 CDM SERVICES
188 ************************************************************************************** */
189 /**
190 * All CDM services are called via the application controller
191 */
192 private CdmApplicationController cdmApp;
193
194 public CdmApplicationController getCdmApp() {
195 if (cdmApp == null) {
196 try {
197 cdmApp = CdmApplicationController.NewInstance(dbSchemaValidation);
198 } catch (DataSourceNotFoundException e) {
199 // TODO Auto-generated catch block
200 e.printStackTrace();
201 } catch (TermNotFoundException e) {
202 // TODO Auto-generated catch block
203 e.printStackTrace();
204 }
205 }
206 return cdmApp;
207 }
208
209 private ITaxonService taxonService;
210
211 public ITaxonService getTaxonService() {
212 if (taxonService == null) {
213 taxonService = getCdmApp().getTaxonService();
214 }
215 return taxonService;
216 }
217
218 /* ***************************************************************************************
219 OBSERVABLE LISTS
220 ************************************************************************************** */
221 /**
222 * The dataset of taxa for this session
223 */
224 private WritableList observableTaxonTreeList = null;
225 /**
226 * Keeps track of which taxa have been opened for editing
227 */
228 private WritableList observableRecentNamesList = null;
229 public WritableSet observableSynonymSet = null;
230 private WritableList observableFavoritesList = null;
231 public WritableList getObservableTaxonTreeList() {
232 if (observableTaxonTreeList == null) {
233 observableTaxonTreeList = new WritableList();
234 ReferenceBase sec = getCdmApp().getReferenceService().getReferenceByUuid(UUID.fromString("f3593c18-a8d2-4e51-bdad-0befbf8fb2d1"));
235 observableTaxonTreeList.addAll(getCdmApp().getTaxonService().getRootTaxa(sec));
236 }
237 return observableTaxonTreeList;
238 }
239
240 public WritableList getObservableRecentNamesList() {
241 if (observableRecentNamesList == null) {
242 observableRecentNamesList = new WritableList();
243 }
244 return observableRecentNamesList;
245 }
246
247
248 public WritableList getObservableFavoritesList() {
249 if (observableFavoritesList == null) {
250 observableFavoritesList = new WritableList();
251 }
252 return observableFavoritesList;
253 }
254
255 public WritableSet getObservableSynonymSet() {
256 if (observableSynonymSet == null) {
257 observableSynonymSet = new WritableSet();
258 }
259 return observableSynonymSet;
260 }
261
262 /* ***************************************************************************************
263 IMAGE REGISTRY
264 ************************************************************************************** */
265 public ImageDescriptor getImageDescriptor(String key) {
266 return getImageRegistry().getDescriptor(key);
267 }
268
269 public Image getImage(String key) {
270 return getImageRegistry().get(key);
271 }
272 // Resource bundle.
273 private ResourceBundle resourceBundle;
274 private FormColors formColors;
275
276 protected void initializeImageRegistry(ImageRegistry registry) {
277 registerImage(registry, ITaxEditorConstants.EDIT_ICON, "edit_16x16.ico"); //$NON-NLS-1$
278 registerImage(registry, ITaxEditorConstants.WARNING_ICON, "warn_tsk.gif"); //$NON-NLS-1$
279 registerImage(registry, ITaxEditorConstants.ACCEPTED_TAXON_ICON, "accepted_small.gif"); //$NON-NLS-1$
280 registerImage(registry, ITaxEditorConstants.HOMOTYPIC_SYN_ICON, "homosyn_no_bg.gif"); //$NON-NLS-1$
281 registerImage(registry, ITaxEditorConstants.HOMOTYPIC_SYN_ORIGINAL_ICON, "homosyn_original_no_bg.gif"); //$NON-NLS-1$
282 registerImage(registry, ITaxEditorConstants.HETEROTYPIC_SYN_ICON, "heterosyn_no_bg.gif"); //$NON-NLS-1$
283 registerImage(registry, ITaxEditorConstants.HETEROTYPIC_SYN_ORIGINAL_ICON, "heterosyn_original_no_bg.gif"); //$NON-NLS-1$
284 registerImage(registry, ITaxEditorConstants.MISAPPLIED_NAME_ICON, "misapplied_no_bg.gif"); //$NON-NLS-1$
285 registerImage(registry, ITaxEditorConstants.AUTONYM_ICON, "autonym_no_bg.gif"); //$NON-NLS-1$
286 registerImage(registry, ITaxEditorConstants.BASIONYM_ICON, "basionym_no_bg.gif"); //$NON-NLS-1$
287 registerImage(registry, ITaxEditorConstants.DB_ICON, "db.gif"); //$NON-NLS-1$
288 registerImage(registry, ITaxEditorConstants.MOVE_ICON, "move_no_bg.gif"); //$NON-NLS-1$
289 }
290 private void registerImage(ImageRegistry registry, String key,
291 String fileName) {
292 try {
293 IPath path = new Path("icons/" + fileName); //$NON-NLS-1$
294 URL url = FileLocator.find(getBundle(), path, null);
295 if (url != null) {
296 ImageDescriptor desc = ImageDescriptor.createFromURL(url);
297 registry.put(key, desc);
298 }
299 } catch (Exception e) {
300 }
301 }
302
303 /* ***************************************************************************************
304 FONT REGISTRY
305 ************************************************************************************** */
306 private FontRegistry fontRegistry;
307
308 private FontRegistry getFontRegistry() {
309 if (fontRegistry == null) {
310 fontRegistry = new FontRegistry(Display.getCurrent());
311
312 fontRegistry.put(ITaxEditorConstants.MENU_ITEM_ITALICS, new FontData[]{new FontData("Arial", 9, SWT.ITALIC)});
313 fontRegistry.put(ITaxEditorConstants.ACCEPTED_TAXON_FONT, new FontData[]{new FontData("Georgia", 12, SWT.NONE)});
314 fontRegistry.put(ITaxEditorConstants.SYNONYM_FONT, new FontData[]{new FontData("Georgia", 10, SWT.NONE)});
315 fontRegistry.put(ITaxEditorConstants.MISAPPLIEDNAME_FONT, new FontData[]{new FontData("Georgia", 10, SWT.NONE)});
316 }
317 return fontRegistry;
318 }
319
320 public Font getFont(String key) {
321 return getFontRegistry().get(key);
322 }
323
324 /* ***************************************************************************************
325 PREFERENCES
326 ************************************************************************************** */
327 protected void initializeDefaultPreferences(IPreferenceStore store) {
328 store.setDefault(ITaxEditorConstants.CODE_PREFERENCE, ITaxEditorConstants.DEFAULT_CODE_PREFERENCE);
329 }
330
331 /* ***************************************************************************************
332 TAXONOMIC TREE
333 ************************************************************************************** */
334
335 public ReferenceBase getSec() {
336 return getCdmApp().getReferenceService().getReferenceByUuid(UUID.fromString("f3593c18-a8d2-4e51-bdad-0befbf8fb2d1"));
337 }
338
339 private List<Taxon> rootTaxa;
340
341 public List<Taxon> getSessionRootTaxa() {
342 if (rootTaxa == null) {
343 rootTaxa = new ArrayList<Taxon>();
344 rootTaxa.addAll(getCdmApp().getTaxonService().getRootTaxa(getSec()));
345 }
346 return rootTaxa;
347 }
348
349 /**
350 * This map of taxa to their taxonomic children is used by
351 * NameTreeContentProvider's getChildren method.
352 *
353 * key = taxon, value = key's child taxa
354 * Note that a map can have a key == null, i.e. no parent taxon
355 */
356 private HashMap<Taxon, Set<Taxon>> taxonomicChildrenMap;
357 private IObservableSet observableTaxonSet;
358
359 private Map<Taxon, Set<Taxon>> getTaxonomicChildrenMap() {
360 if (taxonomicChildrenMap == null) {
361 taxonomicChildrenMap = new HashMap<Taxon, Set<Taxon>>();
362 for (Taxon rootTaxon : getSessionRootTaxa()) {
363 taxonomicChildrenMap.put(rootTaxon, rootTaxon.getTaxonomicChildren());
364 }
365 }
366 return taxonomicChildrenMap;
367 }
368
369 /**
370 * Returns any child taxa for this taxon that have already been requested during
371 * this session.
372 *
373 * @param parentTaxon
374 * @return
375 */
376 public Set<Taxon> getSessionTaxonomicChildren(Taxon parentTaxon) {
377 return TaxEditorPlugin.getDefault().getTaxonomicChildrenMap().get(parentTaxon);
378 }
379
380 private void addSessionTaxonomicChildren(Taxon parentTaxon,
381 Set<Taxon> childTaxa) {
382 Set<Taxon> sessionChildTaxa = getSessionTaxonomicChildren(parentTaxon);
383 if (sessionChildTaxa == null) {
384 getTaxonomicChildrenMap().put(parentTaxon, childTaxa);
385 } else {
386 sessionChildTaxa.addAll(childTaxa);
387 }
388 }
389
390 private void addSessionTaxonomicChild(Taxon parentTaxon,
391 Taxon childTaxon) {
392 Set<Taxon> childTaxa = new HashSet<Taxon>();
393 childTaxa.add(childTaxon);
394 addSessionTaxonomicChildren(parentTaxon, childTaxa);
395 }
396
397 public IObservableSet getObservableSessionTaxa() {
398 if (observableTaxonSet == null) {
399 Realm realm = SWTObservables.getRealm(Display.getDefault());
400 observableTaxonSet = new WritableSet(realm);
401 }
402 return observableTaxonSet;
403 }
404
405 public void removeSessionTaxon(Taxon taxon) {
406 getObservableSessionTaxa().remove(taxon);
407 Taxon parentTaxon = taxon.getTaxonomicParent();
408 Set<Taxon> children = getSessionTaxonomicChildren(parentTaxon);
409 if (children != null) {
410 children.remove(taxon);
411 }
412 }
413
414 public void addSessionTaxa(Collection<Taxon> taxa) {
415 getObservableSessionTaxa().addAll(taxa);
416 for (Taxon taxon : taxa) {
417 addSessionTaxonomicChild(taxon.getTaxonomicParent(), taxon);
418 }
419 }
420
421 public void addSessionTaxon(Taxon taxon) {
422 getObservableSessionTaxa().add(taxon);
423 addSessionTaxonomicChild(taxon.getTaxonomicParent(), taxon);
424 }
425
426 /* ***************************************************************************************
427 RANKS
428 ************************************************************************************** */
429 OrderedTermVocabulary<Rank> rankVocabulary = null;
430
431 public OrderedTermVocabulary<Rank> getRankVocabulary() {
432 if (rankVocabulary == null) {
433 rankVocabulary = getCdmApp().getNameService().getRankVocabulary();
434 }
435 return rankVocabulary;
436 }
437
438 /* ***************************************************************************************
439 NOMENCLATURAL STATUS
440 ************************************************************************************** */
441 TermVocabulary<NomenclaturalStatusType> nomStatusVocabulary = null;
442
443 public TermVocabulary<NomenclaturalStatusType> getNomStatusVocabulary() {
444 if (nomStatusVocabulary == null) {
445 nomStatusVocabulary = getCdmApp().getNameService().getStatusTypeVocabulary();
446 }
447 return nomStatusVocabulary;
448 }
449
450 /* ***************************************************************************************
451 NAME RELATIONS
452 ************************************************************************************** */
453 TermVocabulary<NameRelationshipType> nameRelationshipTypeVocabulary = null;
454
455 public TermVocabulary<NameRelationshipType> getNameRelationshipTypeVocabulary() {
456 if (nameRelationshipTypeVocabulary == null) {
457 nameRelationshipTypeVocabulary = getCdmApp().getNameService().getNameRelationshipTypeVocabulary();
458 }
459 return nameRelationshipTypeVocabulary;
460 }
461
462
463 /* ***************************************************************************************
464 SORAYA DATA
465 ************************************************************************************** */
466 private Taxon getSorayasGenusTaxon() {
467
468 String [] children = new String[] {"Heterospathe annectens H.E.Moore",
469 "Heterospathe arfakiana (Becc.) H.E.Moore",
470 "Heterospathe brevicaulis Fernando",
471 "Heterospathe cagayanensis Becc.",
472 "Heterospathe califrons Fernando, Palms 45: 118 (2001).",
473 "Heterospathe clemensiae (Burret) H.E.Moore",
474 "Heterospathe delicatula H.E.Moore",
475 "Heterospathe dransfieldii Fernando",
476 "Heterospathe elata Scheff.",
477 "Heterospathe elata var. elata.",
478 "Heterospathe elata var. guamensis Becc.",
479 "Heterospathe elata var. palauensis (Becc.) Becc.",
480 "Heterospathe elegans (Becc.) Becc.",
481 "Heterospathe elmeri Becc.",
482 "Heterospathe glabra (Burret) H.E.Moore",
483 "Heterospathe glauca (Scheff.) H.E.Moore",
484 "Heterospathe humilis Becc.",
485 "Heterospathe intermedia (Becc.) Fernando",
486 "Heterospathe kajewskii Burret",
487 "Heterospathe ledermanniana Becc.",
488 "Heterospathe lepidota H.E.Moore",
489 "Heterospathe longipes (H.E.Moore) Norup",
490 "Heterospathe macgregorii (Becc.) H.E.Moore",
491 "Heterospathe micrantha (Becc.) H.E.Moore",
492 "Heterospathe minor Burret",
493 "Heterospathe muelleriana (Becc.) Becc.",
494 "Heterospathe negrosensis Becc.",
495 "Heterospathe obriensis (Becc.) H.E.Moore",
496 "Heterospathe palauensis Becc.",
497 "Heterospathe parviflora Essig",
498 "Heterospathe philippinensis (Becc.) Becc.",
499 // "Heterospathe phillipsii D.Fuller & Dowe", // <--------------
500 "Heterospathe pilosa (Burret) Burret",
501 "Heterospathe pisifera (Gaertn.) Burret",
502 "Heterospathe pulchra H.E.Moore",
503 "Heterospathe ramulosa Burret",
504 "Heterospathe salomonensis Becc.",
505 "Heterospathe scitula Fernando",
506 "Heterospathe sensisi Becc.",
507 "Heterospathe sibuyanensis Becc.",
508 "Heterospathe sphaerocarpa Burret",
509 "Heterospathe trispatha Fernando",
510 "Heterospathe uniformis Dowe",
511 "Heterospathe versteegiana Becc.",
512 "Heterospathe woodfordiana Becc."};
513
514 BotanicalName genusName = BotanicalName.PARSED_NAME("Heterospathe Scheff.");
515
516 Taxon genusTaxon = Taxon.NewInstance(genusName, CdmUtil.getSessionDefaultSec());
517
518 for (String child : children) {
519 BotanicalName speciesName = BotanicalName.PARSED_NAME(child);
520
521 Taxon childTaxon = Taxon.NewInstance(speciesName, CdmUtil.getSessionDefaultSec());
522 childTaxon.setTaxonomicParent(genusTaxon, null, null);
523
524 if (child.equals("Heterospathe elegans (Becc.) Becc.")) {
525 BotanicalName basionym = BotanicalName.PARSED_NAME("Barkerwebbia elegans Becc.");
526 speciesName.addRelationshipFromName(basionym, NameRelationshipType.BASIONYM(), null);
527 childTaxon.addHomotypicSynonymName(basionym, null, null);
528 }
529
530 if (child.equals("Heterospathe humilis Becc.")) {
531 BotanicalName synonymName = BotanicalName.PARSED_NAME("Barkerwebbia humilis (Becc.) Becc. ex Martelli");
532 childTaxon.addHomotypicSynonymName(synonymName, null, null);
533 }
534 }
535
536 return genusTaxon;
537 }
538
539 public List<TaxonNameBase> getNameByName(String searchText) {
540 // TODO make sure last character is %
541 return getCdmApp().getNameService().getNamesByName(searchText);
542 }
543 }