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