Taxa that are part of multiple classifications can now be edited.
[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.HashSet;
13 import java.util.Set;
14 import java.util.UUID;
15
16 import org.eclipse.jface.resource.ImageDescriptor;
17 import org.eclipse.ui.IEditorInput;
18 import org.eclipse.ui.IMemento;
19 import org.eclipse.ui.IPersistableElement;
20
21 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
22 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
23 import eu.etaxonomy.cdm.api.service.IClassificationService;
24 import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
25 import eu.etaxonomy.cdm.api.service.ITaxonService;
26 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
27 import eu.etaxonomy.cdm.model.taxon.ITreeNode;
28 import eu.etaxonomy.cdm.model.taxon.Synonym;
29 import eu.etaxonomy.cdm.model.taxon.Taxon;
30 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
31 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
32 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
33 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
34 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
35 import eu.etaxonomy.taxeditor.model.DataChangeBridge;
36 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
37 import eu.etaxonomy.taxeditor.store.CdmStore;
38
39 /**
40 * <p>TaxonEditorInput class.</p>
41 *
42 * @author n.hoffmann
43 * @created 19.03.2009
44 * @version 1.0
45 */
46 public class TaxonEditorInput implements IEditorInput, IConversationEnabled, IPersistableElement {
47
48 private ConversationHolder conversation;
49
50 private TaxonNode taxonNode;
51
52 private TaxonEditorInputDataChangeBehaviour dataChangeBehavior;
53
54 private TaxonBase initiallySelectedTaxonBase;
55
56 private TaxonEditorInput(TaxonNode taxonNode, ConversationHolder conversation){
57 this.conversation = conversation;
58 this.taxonNode = taxonNode;
59 }
60
61
62
63 /**
64 * <p>NewInstance</p>
65 *
66 * @param taxonNodeUuid a {@link java.util.UUID} object.
67 * @return a {@link eu.etaxonomy.taxeditor.editor.TaxonEditorInput} object.
68 * @throws java.lang.Exception if any.
69 */
70 public static TaxonEditorInput NewInstance(UUID taxonNodeUuid) throws Exception{
71 try{
72 ConversationHolder conversation = CdmStore.createConversation();
73 return NewInstance(taxonNodeUuid, conversation);
74 }catch(Exception e){
75 throw e;
76 }
77 }
78
79 /**
80 *
81 * @param taxonNodeUuid
82 * @param conversation
83 * @return
84 */
85 private static TaxonEditorInput NewInstance(UUID taxonNodeUuid, ConversationHolder conversation){
86
87
88 TaxonNode taxonNode = CdmStore.getService(ITaxonNodeService.class).load(taxonNodeUuid, null);
89
90 if(taxonNode == null){
91 EditorUtil.warningDialog("Not yet implemented", TaxonEditorInput.class, "Selected element is not type TaxonBase.");
92 return null;
93 }
94
95 return new TaxonEditorInput(taxonNode, conversation);
96 }
97
98 /**
99 * <p>NewInstanceFromTaxonBase</p>
100 *
101 * @param taxonBaseUuid a {@link java.util.UUID} object.
102 * @return a {@link eu.etaxonomy.taxeditor.editor.TaxonEditorInput} object.
103 */
104 public static TaxonEditorInput NewInstanceFromTaxonBase(UUID taxonBaseUuid){
105 ConversationHolder conversation = CdmStore.createConversation();
106
107 TaxonEditorInput input = null;
108
109 TaxonBase taxonBase = CdmStore.getService(ITaxonService.class).find(taxonBaseUuid);
110
111 if(taxonBase instanceof Taxon){
112 Taxon taxon = (Taxon) taxonBase;
113
114 if (taxon.isMisapplication()){
115 // TODO get accepted taxon
116 EditorUtil.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 input = getInputForMultipleTaxa(conversation, acceptedTaxa);
126
127 }else{
128 input = getInputForMultipleNodes(conversation, taxon.getTaxonNodes());
129 }
130 }else if(taxonBase instanceof Synonym){
131 Synonym synonym = (Synonym) taxonBase;
132
133 Set<Taxon> taxa = synonym.getAcceptedTaxa();
134 input = getInputForMultipleTaxa(conversation, taxa);
135 }
136
137 input.setInitiallySelectedTaxonBase(taxonBase);
138
139 return input;
140 }
141
142 private static TaxonEditorInput getInputForMultipleNodes(ConversationHolder conversation, Set<TaxonNode> taxonNodes){
143 if(taxonNodes.size() == 1){
144 TaxonNode taxonNode = taxonNodes.iterator().next();
145 return NewInstance(taxonNode.getUuid(), conversation);
146 }else if(taxonNodes.size() > 1){
147 TaxonNode taxonNode = ChooseFromMultipleTaxonNodesDialog.choose(taxonNodes);
148 if(taxonNode != null){
149 return NewInstance(taxonNode.getUuid(), conversation);
150 }
151 }else if(taxonNodes.size() == 0){
152 // this is an undesired state
153 EditorUtil.warningDialog("Incorrect state", TaxonEditorInput.class, "The accepted taxon is not part of any classification. This should not have happened.");
154 }
155 return null;
156 }
157
158 private static TaxonEditorInput getInputForMultipleTaxa(ConversationHolder conversation, Set<Taxon> taxa){
159 if(taxa.size() == 1){
160 Taxon taxon = taxa.iterator().next();
161 Set<TaxonNode> nodes = taxon.getTaxonNodes();
162 return getInputForMultipleNodes(conversation, nodes);
163 }else if(taxa.size() > 1){
164 // FIXME implement a dialog that shows all possible taxa and let the user choose which he wants to open.
165 EditorUtil.warningDialog("Not implemented yet", TaxonEditorInput.class, "There are multiple accepted taxa for the current selection. We currently do not know which one you want to open." +
166 " This case is not handled yet by the software.");
167 }else if(taxa.size() == 0){
168 // this is an undesired state
169 EditorUtil.warningDialog("Incorrect state", TaxonEditorInput.class, "Trying to open accepted taxon for a synonym or misapplication but" +
170 " no accepted taxa are present. This should not have happened.");
171 }
172 return null;
173 }
174
175 /**
176 * <p>NewEmptyInstance</p>
177 *
178 * @param parentNodeUuid a {@link java.util.UUID} object.
179 * @return a {@link eu.etaxonomy.taxeditor.editor.TaxonEditorInput} object.
180 */
181 public static TaxonEditorInput NewEmptyInstance(UUID parentNodeUuid){
182 ConversationHolder conversation = CdmStore.createConversation();
183
184 TaxonNameBase<?, ?> name = PreferencesUtil.getPreferredNomenclaturalCode().getNewTaxonNameInstance(null);
185 ITreeNode parentNode = CdmStore.getService(IClassificationService.class).getTreeNodeByUuid(parentNodeUuid);
186
187 Taxon newTaxon = Taxon.NewInstance(name, parentNode.getReference());
188 TaxonNode newTaxonNode = parentNode.addChildTaxon(newTaxon, parentNode.getReference(), parentNode.getMicroReference(), null);
189
190 // add the new taxon to the editors persistence context
191 UUID newTaxonNodeUuid = CdmStore.getService(ITaxonNodeService.class).save(newTaxonNode);
192
193 return new TaxonEditorInput(newTaxonNode, conversation);
194 }
195
196 /* (non-Javadoc)
197 * @see org.eclipse.ui.IEditorInput#exists()
198 */
199 /**
200 * <p>exists</p>
201 *
202 * @return a boolean.
203 */
204 public boolean exists() {
205 return taxonNode != null;
206 }
207
208 /* (non-Javadoc)
209 * @see org.eclipse.ui.IEditorInput#getImageDescriptor()
210 */
211 /**
212 * <p>getImageDescriptor</p>
213 *
214 * @return a {@link org.eclipse.jface.resource.ImageDescriptor} object.
215 */
216 public ImageDescriptor getImageDescriptor() {
217 return null;
218 }
219
220 /* (non-Javadoc)
221 * @see org.eclipse.ui.IEditorInput#getName()
222 */
223 /**
224 * <p>getName</p>
225 *
226 * @return a {@link java.lang.String} object.
227 */
228 public String getName() {
229 if(getTaxon() == null){
230 return null;
231 }
232 TaxonNameBase<?, ?> name = getTaxon().getName();
233 if (name == null || name.getTitleCache() == null) {
234 return "New taxon";
235 } else {
236 return name.getTitleCache();
237 }
238 }
239
240 /* (non-Javadoc)
241 * @see org.eclipse.ui.IEditorInput#getPersistable()
242 */
243 /**
244 * <p>getPersistable</p>
245 *
246 * @return a {@link org.eclipse.ui.IPersistableElement} object.
247 */
248 public IPersistableElement getPersistable() {
249 // if(CdmStore.isActive()){
250 // TaxonNode test = CdmStore.getTaxonTreeService().getTaxonNodeByUuid(taxonNode.getUuid());
251 // boolean isPersistable = CdmStore.getTaxonTreeService().getTaxonNodeByUuid(taxonNode.getUuid()) != null;
252 // if (isPersistable) {
253 // return this;
254 // }
255 // }
256 return null;
257 }
258
259 /* (non-Javadoc)
260 * @see org.eclipse.ui.IEditorInput#getToolTipText()
261 */
262 /**
263 * <p>getToolTipText</p>
264 *
265 * @return a {@link java.lang.String} object.
266 */
267 public String getToolTipText() {
268 return getName();
269 }
270
271 /* (non-Javadoc)
272 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
273 */
274 /** {@inheritDoc} */
275 public Object getAdapter(Class adapter) {
276
277 if (adapter == Taxon.class) {
278 return taxonNode.getTaxon();
279 }
280
281 if (adapter == TaxonNode.class) {
282 return taxonNode;
283 }
284
285 return null;
286 }
287
288 /**
289 * {@inheritDoc}
290 *
291 * Overrides equals to ensure that a taxon can only be edited by
292 * one editor at a time.
293 */
294 public boolean equals(Object obj) {
295 if (TaxonEditorInput.class.equals(obj.getClass())
296 && getTaxon() != null
297 && getTaxon().equals(((TaxonEditorInput) obj).getTaxon())){
298 if(((TaxonEditorInput) obj).getInitiallySelectedTaxonBase() != null){
299 setInitiallySelectedTaxonBase(((TaxonEditorInput) obj).getInitiallySelectedTaxonBase());
300 }
301 return true;
302 }
303 return false;
304 }
305
306 /**
307 * <p>getTaxon</p>
308 *
309 * @return the taxon
310 */
311 public Taxon getTaxon(){
312 return taxonNode.getTaxon();
313 }
314
315 /**
316 * <p>Getter for the field <code>taxonNode</code>.</p>
317 *
318 * @return the taxonNode
319 */
320 public TaxonNode getTaxonNode() {
321 return taxonNode;
322 }
323
324 /*
325 * (non-Javadoc)
326 * @see eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder()
327 */
328 /**
329 * <p>getConversationHolder</p>
330 *
331 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
332 */
333 public ConversationHolder getConversationHolder() {
334 return conversation;
335 }
336
337 /*
338 * (non-Javadoc)
339 * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
340 */
341 /** {@inheritDoc} */
342 public void update(CdmDataChangeMap events) {
343 if(dataChangeBehavior == null){
344 dataChangeBehavior = new TaxonEditorInputDataChangeBehaviour(this);
345 }
346
347 DataChangeBridge.handleDataChange(events, dataChangeBehavior);
348 }
349
350 /* (non-Javadoc)
351 * @see org.eclipse.ui.IPersistableElement#getFactoryId()
352 */
353 /**
354 * <p>getFactoryId</p>
355 *
356 * @return a {@link java.lang.String} object.
357 */
358 public String getFactoryId() {
359 return TaxonEditorInputFactory.getFactoryId();
360 }
361
362 /* (non-Javadoc)
363 * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento)
364 */
365 /** {@inheritDoc} */
366 public void saveState(IMemento memento) {
367 TaxonEditorInputFactory.saveState(memento, this);
368 }
369
370
371 /**
372 * <p>Setter for the field <code>initiallySelectedTaxonBase</code>.</p>
373 *
374 * @param taxonBase a {@link eu.etaxonomy.cdm.model.taxon.TaxonBase} object.
375 */
376 public void setInitiallySelectedTaxonBase(TaxonBase taxonBase) {
377 this.initiallySelectedTaxonBase = taxonBase;
378 }
379
380 /**
381 * <p>Getter for the field <code>initiallySelectedTaxonBase</code>.</p>
382 *
383 * @return a {@link eu.etaxonomy.cdm.model.taxon.TaxonBase} object.
384 */
385 public TaxonBase getInitiallySelectedTaxonBase() {
386 return initiallySelectedTaxonBase;
387 }
388 }