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