Compare taxon editor input based on taxon node instead of taxon
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / TaxonEditorInput.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.editor;
11
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.UUID;
19
20 import org.eclipse.jface.resource.ImageDescriptor;
21 import org.eclipse.ui.IEditorInput;
22 import org.eclipse.ui.IMemento;
23 import org.eclipse.ui.IPersistableElement;
24
25 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
26 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
27 import eu.etaxonomy.cdm.api.service.IClassificationService;
28 import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
29 import eu.etaxonomy.cdm.api.service.ITaxonService;
30 import eu.etaxonomy.cdm.model.common.CdmBase;
31 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
32 import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
33 import eu.etaxonomy.cdm.model.taxon.Synonym;
34 import eu.etaxonomy.cdm.model.taxon.Taxon;
35 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
36 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
37 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
38 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
39 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
40 import eu.etaxonomy.taxeditor.model.DataChangeBridge;
41 import eu.etaxonomy.taxeditor.model.MessagingUtils;
42 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
43 import eu.etaxonomy.taxeditor.store.CdmStore;
44
45
46 /**
47 * <p>TaxonEditorInput class.</p>
48 *
49 * @author n.hoffmann
50 * @created 19.03.2009
51 * @version 1.0
52 */
53 public class TaxonEditorInput extends CdmEntitySessionInput implements IEditorInput, IConversationEnabled, IPersistableElement {
54
55 private final ConversationHolder conversation;
56
57 private TaxonNode taxonNode;
58
59 private TaxonEditorInputDataChangeBehaviour dataChangeBehavior;
60
61 private TaxonBase initiallySelectedTaxonBase;
62
63 private enum CdmType {
64 TAXON_NODE,
65 TAXON_BASE,
66 PARENT_TAXON_NODE
67 }
68
69 private TaxonEditorInput(UUID uuid, CdmType type) {
70 super(true);
71 this.conversation = CdmStore.createConversation();
72 switch(type) {
73 case PARENT_TAXON_NODE:
74 initForParentTaxonNode(uuid);
75 break;
76 case TAXON_BASE:
77 initForTaxonBase(uuid);
78 break;
79 case TAXON_NODE:
80 initForTaxonNode(uuid);
81 break;
82 }
83 }
84
85 private void init(TaxonNode taxonNode) {
86 this.taxonNode = taxonNode;
87 }
88
89
90 /**
91 * <p>NewInstance</p>
92 *
93 * @param taxonNodeUuid a {@link java.util.UUID} object.
94 * @return a {@link eu.etaxonomy.taxeditor.editor.TaxonEditorInput} object.
95 * @throws java.lang.Exception if any.
96 */
97 private void initForTaxonNode(UUID taxonNodeUuid) {
98
99
100 TaxonNode taxonNode = CdmStore.getService(ITaxonNodeService.class).load(taxonNodeUuid, getTaxonNodePropertyPaths());
101
102 if(taxonNode == null){
103 MessagingUtils.warningDialog("Not yet implemented", TaxonEditorInput.class, "Selected element is not type TaxonBase.");
104 }
105 init(taxonNode);
106
107 }
108
109 private void initForTaxonBase(UUID taxonBaseUuid) {
110 TaxonBase taxonBase = CdmStore.getService(ITaxonService.class).load(taxonBaseUuid, getTaxonBasePropertyPaths());
111 if (taxonBase != null){
112 if(taxonBase.isInstanceOf(Taxon.class)){
113 Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);
114
115 if (taxon.getTaxonNodes().size() == 0 && taxon.isMisapplication()){
116 // TODO get accepted taxon
117 MessagingUtils.info("trying to open Mispplied Name ");
118
119 Set<Taxon> acceptedTaxa = new HashSet<Taxon>();
120 Set<TaxonRelationship> relations = taxon.getRelationsFromThisTaxon();
121 for(TaxonRelationship relation : relations){
122 if(relation.getType().equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR())){
123 acceptedTaxa.add(relation.getToTaxon());
124 }
125 }
126 setInputForMultipleTaxa(conversation, acceptedTaxa);
127
128 }else{
129 setInputForMultipleNodes(conversation, taxon.getTaxonNodes());
130 }
131 }else if(taxonBase instanceof Synonym){
132 Synonym synonym = (Synonym) taxonBase;
133
134 Set<Taxon> taxa = synonym.getAcceptedTaxa();
135 setInputForMultipleTaxa(conversation, taxa);
136 }
137 }
138 }
139
140
141 /**
142 * <p>NewEmptyInstance</p>
143 *
144 * @param parentNodeUuid a {@link java.util.UUID} object.
145 * @return a {@link eu.etaxonomy.taxeditor.editor.TaxonEditorInput} object.
146 */
147 private void initForParentTaxonNode(UUID parentNodeUuid){
148
149
150 TaxonNameBase<?, ?> name = PreferencesUtil.getPreferredNomenclaturalCode().getNewTaxonNameInstance(null);
151 ITaxonTreeNode parentNode = CdmStore.getService(IClassificationService.class).getTreeNodeByUuid(parentNodeUuid);
152
153 Taxon newTaxon = Taxon.NewInstance(name, parentNode.getReference());
154 TaxonNode newTaxonNode = parentNode.addChildTaxon(newTaxon, parentNode.getReference(), parentNode.getMicroReference());
155
156 // add the new taxon to the editors persistence context
157 UUID newTaxonNodeUuid = CdmStore.getService(ITaxonNodeService.class).save(newTaxonNode).getUuid();
158
159 initForTaxonNode(newTaxonNodeUuid);
160 }
161
162
163
164
165 private void setInputForMultipleNodes(ConversationHolder conversation, Set<TaxonNode> taxonNodes){
166 if(taxonNodes.size() == 1){
167 TaxonNode taxonNode = taxonNodes.iterator().next();
168 init(taxonNode);
169 }else if(taxonNodes.size() > 1){
170 TaxonNode taxonNode = ChooseFromMultipleTaxonNodesDialog.choose(taxonNodes);
171 if(taxonNode != null){
172 init(taxonNode);
173 }
174 } else if (taxonNodes.size() == 0) {
175 // this is an undesired state
176 MessagingUtils.warningDialog("Incorrect state",TaxonEditorInput.class,"The accepted "
177 + "taxon is not part of any classification. Editing with the "
178 + "name editor is currently not implemented. Try to edit the taxon with the bulk editor.");
179 }
180 }
181
182 private void setInputForMultipleTaxa(ConversationHolder conversation, Set<Taxon> taxa){
183 if(taxa.size() == 1){
184 Taxon taxon = taxa.iterator().next();
185 Set<TaxonNode> nodes = taxon.getTaxonNodes();
186 setInputForMultipleNodes(conversation, nodes);
187 }else if(taxa.size() > 1){
188 Set<TaxonNode> taxonNodes = new HashSet<TaxonNode>();
189 for ( Taxon taxon : taxa ){
190 taxonNodes.addAll(taxon.getTaxonNodes());
191 }
192 setInputForMultipleNodes(conversation, taxonNodes);
193 }else if(taxa.size() == 0){
194 // this is an undesired state
195 MessagingUtils.warningDialog("Incorrect state", TaxonEditorInput.class, "Trying to open accepted taxon for a synonym or misapplication but" +
196 " no accepted taxa are present. This should not have happened.");
197 }
198 }
199
200 /**
201 * <p>NewInstance</p>
202 *
203 * @param taxonNodeUuid a {@link java.util.UUID} object.
204 * @return a {@link eu.etaxonomy.taxeditor.editor.TaxonEditorInput} object.
205 * @throws java.lang.Exception if any.
206 */
207 public static TaxonEditorInput NewInstance(UUID taxonNodeUuid) throws Exception {
208 return new TaxonEditorInput(taxonNodeUuid, CdmType.TAXON_NODE);
209
210 }
211
212 /**
213 * <p>NewInstanceFromTaxonBase</p>
214 *
215 * @param taxonBaseUuid a {@link java.util.UUID} object.
216 * @return a {@link eu.etaxonomy.taxeditor.editor.TaxonEditorInput} object.
217 */
218 public static TaxonEditorInput NewInstanceFromTaxonBase(UUID taxonBaseUuid){
219 return new TaxonEditorInput(taxonBaseUuid, CdmType.TAXON_BASE);
220 }
221
222
223 /**
224 * <p>NewEmptyInstance</p>
225 *
226 * @param parentNodeUuid a {@link java.util.UUID} object.
227 * @return a {@link eu.etaxonomy.taxeditor.editor.TaxonEditorInput} object.
228 */
229 public static TaxonEditorInput NewEmptyInstance(UUID parentNodeUuid){
230 return new TaxonEditorInput(parentNodeUuid, CdmType.PARENT_TAXON_NODE);
231 }
232
233 /* (non-Javadoc)
234 * @see org.eclipse.ui.IEditorInput#exists()
235 */
236 /**
237 * <p>exists</p>
238 *
239 * @return a boolean.
240 */
241 @Override
242 public boolean exists() {
243 return taxonNode != null;
244 }
245
246 /* (non-Javadoc)
247 * @see org.eclipse.ui.IEditorInput#getImageDescriptor()
248 */
249 /**
250 * <p>getImageDescriptor</p>
251 *
252 * @return a {@link org.eclipse.jface.resource.ImageDescriptor} object.
253 */
254 @Override
255 public ImageDescriptor getImageDescriptor() {
256 return null;
257 }
258
259 /* (non-Javadoc)
260 * @see org.eclipse.ui.IEditorInput#getName()
261 */
262 /**
263 * <p>getName</p>
264 *
265 * @return a {@link java.lang.String} object.
266 */
267 @Override
268 public String getName() {
269 if(getTaxon() == null){
270 return null;
271 }
272 TaxonNameBase<?, ?> name = getTaxon().getName();
273 if (name == null || name.getTitleCache() == null) {
274 return "New taxon";
275 } else {
276 return name.getTitleCache();
277 }
278 }
279
280 /* (non-Javadoc)
281 * @see org.eclipse.ui.IEditorInput#getPersistable()
282 */
283 /**
284 * <p>getPersistable</p>
285 *
286 * @return a {@link org.eclipse.ui.IPersistableElement} object.
287 */
288 @Override
289 public IPersistableElement getPersistable() {
290 // if(CdmStore.isActive()){
291 // TaxonNode test = CdmStore.getTaxonTreeService().getTaxonNodeByUuid(taxonNode.getUuid());
292 // boolean isPersistable = CdmStore.getTaxonTreeService().getTaxonNodeByUuid(taxonNode.getUuid()) != null;
293 // if (isPersistable) {
294 // return this;
295 // }
296 // }
297 return null;
298 }
299
300 /* (non-Javadoc)
301 * @see org.eclipse.ui.IEditorInput#getToolTipText()
302 */
303 /**
304 * <p>getToolTipText</p>
305 *
306 * @return a {@link java.lang.String} object.
307 */
308 @Override
309 public String getToolTipText() {
310 return getName();
311 }
312
313 /* (non-Javadoc)
314 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
315 */
316 /** {@inheritDoc} */
317 @Override
318 public Object getAdapter(Class adapter) {
319
320 if (adapter == Taxon.class) {
321 return getTaxon();
322 }
323
324 if (adapter == TaxonNode.class) {
325 return taxonNode;
326 }
327
328 return null;
329 }
330
331 /**
332 * {@inheritDoc}
333 *
334 * Overrides equals to ensure that a taxon can only be edited by
335 * one editor at a time.
336 */
337 @Override
338 public boolean equals(Object obj) {
339 if (TaxonEditorInput.class.equals(obj.getClass())
340 && getTaxonNode() != null
341 && getTaxonNode().equals(((TaxonEditorInput) obj).getTaxonNode())
342 ){
343 if(((TaxonEditorInput) obj).getInitiallySelectedTaxonBase() != null){
344 setInitiallySelectedTaxonBase(((TaxonEditorInput) obj).getInitiallySelectedTaxonBase());
345 }
346 return true;
347 }
348 return false;
349 }
350
351 /**
352 * <p>getTaxon</p>
353 *
354 * @return the taxon
355 */
356 public Taxon getTaxon(){
357 Taxon taxon = CdmBase.deproxy(taxonNode.getTaxon(), Taxon.class);
358 return taxon;
359 }
360
361 /**
362 * <p>Getter for the field <code>taxonNode</code>.</p>
363 *
364 * @return the taxonNode
365 */
366 public TaxonNode getTaxonNode() {
367 return taxonNode;
368 }
369
370 /*
371 * (non-Javadoc)
372 * @see eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder()
373 */
374 /**
375 * <p>getConversationHolder</p>
376 *
377 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
378 */
379 @Override
380 public ConversationHolder getConversationHolder() {
381 return conversation;
382 }
383
384 /*
385 * (non-Javadoc)
386 * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
387 */
388 /** {@inheritDoc} */
389 @Override
390 public void update(CdmDataChangeMap events) {
391 if(dataChangeBehavior == null){
392 dataChangeBehavior = new TaxonEditorInputDataChangeBehaviour(this);
393 }
394
395 DataChangeBridge.handleDataChange(events, dataChangeBehavior);
396 }
397
398 /* (non-Javadoc)
399 * @see org.eclipse.ui.IPersistableElement#getFactoryId()
400 */
401 /**
402 * <p>getFactoryId</p>
403 *
404 * @return a {@link java.lang.String} object.
405 */
406 @Override
407 public String getFactoryId() {
408 return TaxonEditorInputFactory.getFactoryId();
409 }
410
411 /* (non-Javadoc)
412 * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento)
413 */
414 /** {@inheritDoc} */
415 @Override
416 public void saveState(IMemento memento) {
417 TaxonEditorInputFactory.saveState(memento, this);
418 }
419
420
421 /**
422 * <p>Setter for the field <code>initiallySelectedTaxonBase</code>.</p>
423 *
424 * @param taxonBase a {@link eu.etaxonomy.cdm.model.taxon.TaxonBase} object.
425 */
426 public void setInitiallySelectedTaxonBase(TaxonBase taxonBase) {
427 this.initiallySelectedTaxonBase = taxonBase;
428 }
429
430 /**
431 * <p>Getter for the field <code>initiallySelectedTaxonBase</code>.</p>
432 *
433 * @return a {@link eu.etaxonomy.cdm.model.taxon.TaxonBase} object.
434 */
435 public TaxonBase getInitiallySelectedTaxonBase() {
436 return initiallySelectedTaxonBase;
437 }
438
439 // @Override
440 // public String toString() {
441 // return String.format("%s[%s]", this.getClass().getSimpleName(), getTaxon());
442 // }
443
444
445 /* (non-Javadoc)
446 * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getRootEntities()
447 */
448 @Override
449 public List<TaxonNode> getRootEntities() {
450 return Arrays.asList(taxonNode);
451 }
452
453 /* (non-Javadoc)
454 * @see eu.etaxonomy.taxeditor.editor.CdmEntitySessionInput#merge()
455 */
456 @Override
457 public void merge() {
458 CdmStore.getService(ITaxonNodeService.class).merge(taxonNode, true);
459
460 }
461
462 @Override
463 public Map<Object, List<String>> getPropertyPathsMap() {
464 return null;
465 }
466
467 private List<String> getTaxonNodePropertyPaths() {
468 List<String> taxonNodePropertyPaths = new ArrayList<String>();
469 for(String propertyPath : getTaxonBasePropertyPaths()) {
470 taxonNodePropertyPaths.add("taxon." + propertyPath);
471 }
472 return taxonNodePropertyPaths;
473 }
474
475 private List<String> getTaxonBasePropertyPaths() {
476 List<String> taxonBasePropertyPaths = Arrays.asList(new String[] {
477 "sec",
478 "createdBy",
479 "updatedBy",
480 "annotations",
481 "markers",
482 "credits",
483 "extensions",
484 "rights",
485 "sources",
486 "descriptions",
487 "relationsToThisTaxon",
488 "relationsFromThisTaxon",
489 "taxonNodes",
490 "descriptions.descriptionElements.feature",
491 "descriptions.descriptionElements.area",
492 "descriptions.descriptionElements.status",
493 "descriptions.markers",
494 "name.descriptions",
495 "name.typeDesignations",
496 "name.status",
497 "name.nomenclaturalReference.inReference",
498 "name.taxonBases.taxonNodes",
499 "name.relationsFromThisName",
500 "name.relationsToThisName",
501 "name.homotypicalGroup.typifiedNames.taxonBases.synonymRelations.synonym.name.status",
502 "name.homotypicalGroup.typifiedNames.relationsToThisName.fromName",
503 "synonymRelations.synonym.name.status.type",
504 "synonymRelations.synonym.name.relationsToThisName.fromName",
505 "synonymRelations.synonym.name.nomenclaturalReference.inReference.authorship",
506 "synonymRelations.synonym.name.nomenclaturalReference.authorship",
507 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.synonymRelations"
508 });
509
510 return taxonBasePropertyPaths;
511 }
512
513 }