8029f92937e9dd9b7637b86508d05fc917243c80
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / view / derivate / DerivateView.java
1 package eu.etaxonomy.taxeditor.editor.view.derivate;
2
3 import java.util.Collection;
4 import java.util.HashSet;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Map.Entry;
8 import java.util.Set;
9 import java.util.UUID;
10
11 import org.eclipse.core.runtime.IProgressMonitor;
12 import org.eclipse.jface.action.MenuManager;
13 import org.eclipse.jface.util.LocalSelectionTransfer;
14 import org.eclipse.jface.viewers.AbstractTreeViewer;
15 import org.eclipse.jface.viewers.ISelection;
16 import org.eclipse.jface.viewers.ISelectionChangedListener;
17 import org.eclipse.jface.viewers.SelectionChangedEvent;
18 import org.eclipse.jface.viewers.StructuredSelection;
19 import org.eclipse.jface.viewers.TreeNode;
20 import org.eclipse.jface.viewers.TreeSelection;
21 import org.eclipse.jface.viewers.TreeViewer;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.dnd.DND;
24 import org.eclipse.swt.dnd.Transfer;
25 import org.eclipse.swt.widgets.Composite;
26 import org.eclipse.swt.widgets.Control;
27 import org.eclipse.swt.widgets.Menu;
28 import org.eclipse.swt.widgets.Tree;
29 import org.eclipse.ui.IEditorInput;
30 import org.eclipse.ui.IEditorPart;
31 import org.eclipse.ui.IEditorSite;
32 import org.eclipse.ui.PartInitException;
33 import org.eclipse.ui.part.EditorPart;
34
35 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
36 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
37 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
38 import eu.etaxonomy.cdm.api.service.molecular.ISequenceService;
39 import eu.etaxonomy.cdm.model.common.CdmBase;
40 import eu.etaxonomy.cdm.model.molecular.Sequence;
41 import eu.etaxonomy.cdm.model.molecular.SingleRead;
42 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
43 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
44 import eu.etaxonomy.taxeditor.editor.Messages;
45 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
46 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
47 import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
48 import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
49 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
50 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
51 import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
52 import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
53 import eu.etaxonomy.taxeditor.store.CdmStore;
54 import eu.etaxonomy.taxeditor.view.derivateSearch.DerivateContentProvider;
55 import eu.etaxonomy.taxeditor.view.derivateSearch.DerivateLabelProvider;
56
57 /**
58 * Displays the derivate hierarchy of the specimen specified in the editor input.
59 *
60 */
61 public class DerivateView extends EditorPart implements IPartContentHasFactualData, IDirtyMarkable,
62 IConversationEnabled, IPartContentHasDetails, IPartContentHasSupplementalData, IPartContentHasMedia,
63 ISelectionChangedListener, IPostOperationEnabled , ICdmEntitySessionEnabled {
64
65 public static final String ID = "eu.etaxonomy.taxeditor.editor.view.derivate.DerivateView"; //$NON-NLS-1$
66
67 public static final String YOU_NEED_TO_SAVE_BEFORE_PERFORMING_THIS_ACTION = Messages.DerivateView_YOU_NEED_TO_SAVE;
68 public static final String VIEW_HAS_UNSAVED_CHANGES = Messages.DerivateView_UNSAVED_CHANGES;
69
70 private ConversationHolder conversation;
71
72 private TreeViewer viewer;
73
74 private boolean isDirty;
75
76 private final int dndOperations = DND.DROP_MOVE;
77
78 private DerivateLabelProvider labelProvider;
79
80 private Set<SingleRead> multiLinkSingleReads;
81
82 private ISelection selection = null;
83
84 private final ICdmEntitySession cdmEntitySession;
85
86 private DerivateContentProvider contentProvider;
87
88 /**
89 * Default constructor
90 */
91 public DerivateView() {
92 cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
93 }
94
95 @Override
96 public void createPartControl(Composite parent) {
97 viewer = new TreeViewer(new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION));
98 contentProvider = new DerivateContentProvider();
99 viewer.setContentProvider(contentProvider);
100 labelProvider = new DerivateLabelProvider();
101 labelProvider.setConversation(conversation);
102 viewer.setLabelProvider(labelProvider);
103 viewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
104 // Propagate selection from viewer
105 getSite().setSelectionProvider(viewer);
106 //listen to selection changes
107 viewer.addSelectionChangedListener(this);
108
109 //create context menu
110 MenuManager menuManager = new MenuManager();
111 getSite().registerContextMenu(menuManager, viewer);
112 Control control = viewer.getControl();
113 Menu menu = menuManager.createContextMenu(control);
114 control.setMenu(menu);
115
116 generateMultiLinkSingleReads();
117 labelProvider.setMultiLinkSingleReads(multiLinkSingleReads);
118 IEditorInput editorInput = getEditorInput();
119 viewer.setInput(((DerivateViewEditorInput) editorInput).getRootUUIDs());
120 //set selection to selected derivate if only one was selected
121 if(editorInput instanceof DerivateViewEditorInput){
122 Set<UUID> derivateUUIDs = ((DerivateViewEditorInput) editorInput).getDerivateUUIDs();
123 if(derivateUUIDs.size()==1){
124 SpecimenOrObservationBase<?> specimen = CdmStore.getService(IOccurrenceService.class).load(derivateUUIDs.iterator().next());
125 if(specimen!=null){
126 viewer.setSelection(new StructuredSelection(new TreeNode(specimen)));
127 }
128 }
129 }
130
131 //add drag'n'drop support
132 Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer(),};
133 viewer.addDragSupport(dndOperations, transfers, new DerivateDragListener(this));
134 viewer.addDropSupport(dndOperations, transfers, new DerivateDropListener(this));
135 }
136
137 @Override
138 public void doSave(IProgressMonitor monitor) {
139 String taskName = Messages.DerivateView_SAVING_HIERARCHY;
140 if(getEditorInput() instanceof DerivateViewEditorInput){
141 DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) getEditorInput();
142 taskName += " "+derivateViewEditorInput.getName(); //$NON-NLS-1$
143 }
144 monitor.beginTask(taskName, 3);
145 if (!conversation.isBound()) {
146 conversation.bind();
147 }
148 monitor.worked(1);
149
150 // commit the conversation and start a new transaction immediately
151 conversation.commit(true);
152 CdmStore.getService(IOccurrenceService.class).merge(getRootEntities());
153 monitor.worked(1);
154
155 this.setDirty(false);
156 monitor.worked(1);
157 monitor.done();
158 firePropertyChange(PROP_DIRTY);
159 refreshTree();
160 }
161
162 @Override
163 public void doSaveAs() {
164 }
165
166 @Override
167 public String getTitleToolTip() {
168 if(getEditorInput() instanceof DerivateViewEditorInput){
169 DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) getEditorInput();
170 return derivateViewEditorInput.getName();
171 }
172 return Messages.DerivateView_DERIVATIVE_EDITOR;
173 }
174
175 @Override
176 public void init(IEditorSite site, IEditorInput input) throws PartInitException {
177 setSite(site);
178 setInput(input);
179 if(input instanceof DerivateViewEditorInput){
180 DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) input;
181 conversation = derivateViewEditorInput.getConversationHolder();
182 setPartName(derivateViewEditorInput.getName());
183 }
184 }
185
186 @Override
187 public boolean isDirty() {
188 return isDirty;
189 }
190
191 /**
192 * @param isDirty the isDirty to set
193 */
194 public void setDirty(boolean isDirty) {
195 this.isDirty = isDirty;
196 }
197
198 @Override
199 public boolean isSaveAsAllowed() {
200 return false;
201 }
202
203 @Override
204 public void setFocus() {
205 viewer.getControl().setFocus();
206 //make sure to bind again if maybe in another view the conversation was unbound
207 if(!conversation.isBound()){
208 conversation.bind();
209 }
210 cdmEntitySession.bind();
211 }
212
213 @Override
214 public void update(CdmDataChangeMap changeEvents) {
215 }
216
217 @Override
218 public ConversationHolder getConversationHolder() {
219 return conversation;
220 }
221
222 /**
223 * @return the viewer
224 */
225 public TreeViewer getViewer() {
226 return viewer;
227 }
228
229 @Override
230 public void changed(Object element) {
231 setDirty(true);
232 firePropertyChange(IEditorPart.PROP_DIRTY);
233 viewer.refresh();
234 }
235
236 @Override
237 public void forceDirty() {
238 changed(null);
239 }
240
241 /**
242 * Refreshes the derivate hierarchy tree and expands the tree
243 * to show and select the given object.
244 *
245 * @param expandTo the object to which the tree should be expanded
246 */
247 public void refreshTree(Object expandTo){
248 refreshTree();
249 TreeSelection selection = (TreeSelection) viewer.getSelection();
250 viewer.expandToLevel(selection.getFirstElement(), 1);
251 viewer.setSelection(new StructuredSelection(new TreeNode(expandTo)));
252 }
253
254 /**
255 * Refreshes the derivate hierarchy tree
256 */
257 public void refreshTree(){
258 generateMultiLinkSingleReads();
259 labelProvider.setMultiLinkSingleReads(multiLinkSingleReads);
260 viewer.refresh();
261 }
262
263 private void generateMultiLinkSingleReads() {
264 Set<SingleRead> multiLinkSingleReads = new HashSet<SingleRead>();
265 for(Entry<SingleRead, Collection<Sequence>> entry:CdmStore.getService(ISequenceService.class).getSingleReadSequencesMap().entrySet()){
266 if(entry.getValue().size()>1){
267 multiLinkSingleReads.add(entry.getKey());
268 }
269 }
270 this.multiLinkSingleReads = multiLinkSingleReads;
271 }
272
273 /**
274 * @return a set of {@link SingleRead}s that have multiple parents
275 */
276 public Set<SingleRead> getMultiLinkSingleReads() {
277 return this.multiLinkSingleReads;
278 }
279
280 @Override
281 public void selectionChanged(SelectionChangedEvent event) {
282 this.selection = event.getSelection();
283 }
284
285 public ISelection getSelection() {
286 return selection;
287 }
288
289 public DerivateLabelProvider getLabelProvider() {
290 return labelProvider;
291 }
292
293 @Override
294 public boolean postOperation(CdmBase objectAffectedByOperation) {
295 refreshTree();
296 if(objectAffectedByOperation!=null){
297 changed(objectAffectedByOperation);
298 }
299 return true;
300 }
301
302 @Override
303 public boolean onComplete() {
304 return true;
305 }
306
307 @Override
308 public void dispose() {
309 cdmEntitySession.dispose();
310 super.dispose();
311 }
312
313 /* (non-Javadoc)
314 * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getCdmEntitySession()
315 */
316 @Override
317 public ICdmEntitySession getCdmEntitySession() {
318 return cdmEntitySession;
319 }
320
321 /* (non-Javadoc)
322 * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getRootEntities()
323 */
324 @Override
325 public List<SpecimenOrObservationBase> getRootEntities() {
326 return contentProvider.getRootElements();
327 }
328
329 /* (non-Javadoc)
330 * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getPropertyPathsMap()
331 */
332 @Override
333 public Map<Object, List<String>> getPropertyPathsMap() {
334 // TODO Auto-generated method stub
335 return null;
336 }
337
338 @Override
339 public boolean canAttachMedia() {
340 return true;
341 }
342 }