Project

General

Profile

Download (15.3 KB) Statistics
| Branch: | Tag: | Revision:
1
package eu.etaxonomy.taxeditor.editor.view.derivate;
2

    
3
import java.util.Arrays;
4
import java.util.Collection;
5
import java.util.HashMap;
6
import java.util.HashSet;
7
import java.util.List;
8
import java.util.Map;
9
import java.util.Map.Entry;
10
import java.util.Set;
11
import java.util.UUID;
12

    
13
import org.eclipse.core.runtime.IProgressMonitor;
14
import org.eclipse.jface.action.MenuManager;
15
import org.eclipse.jface.util.LocalSelectionTransfer;
16
import org.eclipse.jface.viewers.AbstractTreeViewer;
17
import org.eclipse.jface.viewers.ISelection;
18
import org.eclipse.jface.viewers.ISelectionChangedListener;
19
import org.eclipse.jface.viewers.SelectionChangedEvent;
20
import org.eclipse.jface.viewers.StructuredSelection;
21
import org.eclipse.jface.viewers.TreeNode;
22
import org.eclipse.jface.viewers.TreeSelection;
23
import org.eclipse.jface.viewers.TreeViewer;
24
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.dnd.DND;
26
import org.eclipse.swt.dnd.Transfer;
27
import org.eclipse.swt.layout.GridData;
28
import org.eclipse.swt.layout.GridLayout;
29
import org.eclipse.swt.widgets.Composite;
30
import org.eclipse.swt.widgets.Control;
31
import org.eclipse.swt.widgets.Menu;
32
import org.eclipse.swt.widgets.Tree;
33
import org.eclipse.ui.IEditorInput;
34
import org.eclipse.ui.IEditorPart;
35
import org.eclipse.ui.IEditorSite;
36
import org.eclipse.ui.PartInitException;
37
import org.eclipse.ui.part.EditorPart;
38

    
39
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
40
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
41
import eu.etaxonomy.cdm.api.service.IOccurrenceService;
42
import eu.etaxonomy.cdm.api.service.molecular.ISequenceService;
43
import eu.etaxonomy.cdm.model.common.CdmBase;
44
import eu.etaxonomy.cdm.model.molecular.Sequence;
45
import eu.etaxonomy.cdm.model.molecular.SingleRead;
46
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
47
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
48
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
49
import eu.etaxonomy.taxeditor.editor.EditorUtil;
50
import eu.etaxonomy.taxeditor.editor.Messages;
51
import eu.etaxonomy.taxeditor.editor.view.derivate.searchFilter.DerivateSearchCompositeController;
52
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
53
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
54
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
55
import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
56
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
57
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
58
import eu.etaxonomy.taxeditor.store.CdmStore;
59
import eu.etaxonomy.taxeditor.view.derivateSearch.DerivateContentProvider;
60
import eu.etaxonomy.taxeditor.view.derivateSearch.DerivateLabelProvider;
61

    
62
/**
63
 * Displays the derivate hierarchy of the specimen specified in the editor input.
64
 *
65
 */
66
public class DerivateView extends EditorPart implements IPartContentHasFactualData, IDirtyMarkable,
67
        IConversationEnabled, IPartContentHasDetails, IPartContentHasSupplementalData, IPartContentHasMedia,
68

    
69
        ISelectionChangedListener, IPostOperationEnabled/*, ICdmEntitySessionEnabled*/{
70
    public static final String ID = "eu.etaxonomy.taxeditor.editor.view.derivate.DerivateView"; //$NON-NLS-1$
71

    
72
    public static final String YOU_NEED_TO_SAVE_BEFORE_PERFORMING_THIS_ACTION = Messages.DerivateView_YOU_NEED_TO_SAVE;
73
    public static final String VIEW_HAS_UNSAVED_CHANGES = Messages.DerivateView_UNSAVED_CHANGES;
74

    
75
    private static final List<String> SPECIMEN_INIT_STRATEGY = Arrays.asList(new String[] {
76
            "descriptions",
77
            "annotations",
78
            "markers",
79
            "credits",
80
            "extensions",
81
            "rights",
82
            "sources",
83
            "derivationEvents.derivatives.annotations",
84
            "derivationEvents.derivatives.markers",
85
            "derivationEvents.derivatives.credits",
86
            "derivationEvents.derivatives.extensions",
87
            "derivationEvents.derivatives.rights",
88
            "derivationEvents.derivatives.sources"
89
    });
90

    
91
	private ConversationHolder conversation;
92

    
93
	private TreeViewer viewer;
94

    
95
    private boolean isDirty;
96

    
97
    private final int dndOperations = DND.DROP_MOVE;
98

    
99
    private DerivateLabelProvider labelProvider;
100

    
101
    private Set<SingleRead> multiLinkSingleReads;
102

    
103
    private ISelection selection = null;
104

    
105

    
106
    private DerivateContentProvider contentProvider;
107

    
108
    private DerivateSearchCompositeController derivateSearchCompositeController;
109

    
110
    /**
111
     * A map with keys being the derivative entities belonging to the {@link UUID}s passed to the constructor
112
     * and values being the root elements of the hierarchy (may be the same objects as the derivative entities)
113
     */
114
    private Map<SpecimenOrObservationBase<?>, SpecimenOrObservationBase<?>> derivateToRootEntityMap;
115

    
116
    /**
117
     * The set of root elements
118
     */
119
    private Set<SpecimenOrObservationBase<?>> rootElements;
120

    
121
    /**
122
     * Default constructor
123
     */
124
    public DerivateView() {
125
        conversation = CdmStore.createConversation();
126
    }
127

    
128
    @Override
129
    public void createPartControl(Composite parent) {
130

    
131
        parent.setLayout(new GridLayout());
132

    
133
        //---search and filter---
134
        derivateSearchCompositeController = new DerivateSearchCompositeController(parent, this);
135
        derivateSearchCompositeController.setEnabled(CdmStore.isActive());
136
        GridData gridDataSearchBar = new GridData();
137
        gridDataSearchBar.horizontalAlignment = GridData.FILL;
138
        gridDataSearchBar.grabExcessHorizontalSpace = true;
139
        derivateSearchCompositeController.setLayoutData(gridDataSearchBar);
140

    
141
        //---tree viewer---
142
        viewer = new TreeViewer(new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION));
143
        GridData gridDataTree = new GridData();
144
        gridDataTree.horizontalAlignment = GridData.FILL;
145
        gridDataTree.verticalAlignment = GridData.FILL;
146
        gridDataTree.grabExcessVerticalSpace = true;
147
        gridDataTree.grabExcessHorizontalSpace = true;
148
        viewer.getTree().setLayoutData(gridDataTree);
149
        contentProvider = new DerivateContentProvider();
150
        viewer.setContentProvider(contentProvider);
151
        labelProvider = new DerivateLabelProvider();
152
        labelProvider.setConversation(conversation);
153
        viewer.setLabelProvider(labelProvider);
154
        viewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
155
        // Propagate selection from viewer
156
        getSite().setSelectionProvider(viewer);
157
        //listen to selection changes
158
        viewer.addSelectionChangedListener(this);
159

    
160
        //create context menu
161
        MenuManager menuManager = new MenuManager();
162
        getSite().registerContextMenu(menuManager, viewer);
163
        Control control = viewer.getControl();
164
        Menu menu = menuManager.createContextMenu(control);
165
        control.setMenu(menu);
166

    
167
        //single read multi links
168
        generateMultiLinkSingleReads();
169
        labelProvider.setMultiLinkSingleReads(multiLinkSingleReads);
170

    
171
        //init tree
172
        DerivateViewEditorInput editorInput = (DerivateViewEditorInput) getEditorInput();
173
        if(editorInput.getDerivativeUUIDs()!=null){
174
            updateRootEntities(editorInput.getDerivativeUUIDs());
175
        }
176
        else{
177
            updateRootEntities();
178
        }
179

    
180
        //add drag'n'drop support
181
        Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer(),};
182
        viewer.addDragSupport(dndOperations, transfers, new DerivateDragListener(this));
183
        viewer.addDropSupport(dndOperations, transfers, new DerivateDropListener(this));
184
    }
185

    
186
    public void updateRootEntities() {
187
        updateRootEntities(null);
188
    }
189

    
190
    public void updateRootEntities(Collection<UUID> derivativeUuids) {
191
        if(derivativeUuids!=null){
192
            this.derivateToRootEntityMap = new HashMap<SpecimenOrObservationBase<?>, SpecimenOrObservationBase<?>>();
193
            this.rootElements = new HashSet<SpecimenOrObservationBase<?>>();
194
            for (UUID uuid : derivativeUuids) {
195
                SpecimenOrObservationBase<?> derivate = CdmStore.getService(IOccurrenceService.class).load(uuid, SPECIMEN_INIT_STRATEGY);
196
                if(derivate instanceof FieldUnit){
197
                    derivateToRootEntityMap.put(derivate, derivate);
198
                }
199
                else {
200
                    SpecimenOrObservationBase<?> topMostDerivate = EditorUtil.getTopMostDerivate(derivate);
201
                    if(topMostDerivate!=null){
202
                        derivateToRootEntityMap.put(derivate, topMostDerivate);
203
                    }
204
                    else{
205
                        derivateToRootEntityMap.put(derivate, derivate);
206
                    }
207
                }
208
            }
209
            for (SpecimenOrObservationBase<?> specimen : derivateToRootEntityMap.values()) {
210
                rootElements.add(specimen);
211
            }
212
        }
213
        viewer.setInput(rootElements);
214
        refreshTree();
215
    }
216

    
217
    @Override
218
    public void doSave(IProgressMonitor monitor) {
219
        String taskName = Messages.DerivateView_SAVING_HIERARCHY;
220
        if(getEditorInput() instanceof DerivateViewEditorInput){
221
            DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) getEditorInput();
222
            taskName += " "+derivateViewEditorInput.getName(); //$NON-NLS-1$
223
        }
224
        monitor.beginTask(taskName, 3);
225
        if (!conversation.isBound()) {
226
            conversation.bind();
227
        }
228
        monitor.worked(1);
229

    
230
        // commit the conversation and start a new transaction immediately
231
        conversation.commit(true);
232
//      TODO: what does this do?  merge();
233
        monitor.worked(1);
234

    
235
        this.setDirty(false);
236
        monitor.worked(1);
237
        monitor.done();
238
        firePropertyChange(PROP_DIRTY);
239
        refreshTree();
240
    }
241

    
242
    @Override
243
    public void doSaveAs() {
244
    }
245

    
246
    public Set<SpecimenOrObservationBase<?>> getRootElements() {
247
        return rootElements;
248
    }
249

    
250
    @Override
251
    public String getTitleToolTip() {
252
        if(getEditorInput() instanceof DerivateViewEditorInput){
253
            DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) getEditorInput();
254
            return derivateViewEditorInput.getName();
255
        }
256
        return Messages.DerivateView_DERIVATIVE_EDITOR;
257
    }
258

    
259
    @Override
260
    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
261
        setSite(site);
262
        setInput(input);
263
        this.derivateToRootEntityMap = new HashMap<SpecimenOrObservationBase<?>, SpecimenOrObservationBase<?>>();
264
        this.rootElements = new HashSet<SpecimenOrObservationBase<?>>();
265
    }
266

    
267
    @Override
268
    public boolean isDirty() {
269
        return isDirty;
270
    }
271

    
272
    /**
273
     * @param isDirty the isDirty to set
274
     */
275
    public void setDirty(boolean isDirty) {
276
        this.isDirty = isDirty;
277
    }
278

    
279
    @Override
280
    public boolean isSaveAsAllowed() {
281
        return false;
282
    }
283

    
284
    @Override
285
    public void setFocus() {
286
        viewer.getControl().setFocus();
287
        //make sure to bind again if maybe in another view the conversation was unbound
288
        if(!conversation.isBound()){
289
            conversation.bind();
290
        }
291
    }
292

    
293
    @Override
294
    public void update(CdmDataChangeMap changeEvents) {
295
    }
296

    
297
    @Override
298
    public ConversationHolder getConversationHolder() {
299
        return conversation;
300
    }
301

    
302
    /**
303
     * @return the viewer
304
     */
305
    public TreeViewer getViewer() {
306
        return viewer;
307
    }
308

    
309
    @Override
310
    public void changed(Object element) {
311
        setDirty(true);
312
        firePropertyChange(IEditorPart.PROP_DIRTY);
313
        viewer.refresh();
314
    }
315

    
316
    @Override
317
    public void forceDirty() {
318
        changed(null);
319
    }
320

    
321
//    @Override
322
//    public Set<SpecimenOrObservationBase<?>> getRootEntities() {
323
//        return rootElements;
324
//    }
325
//
326
//    @Override
327
//    public void merge() {
328
//        if(CdmStore.getCurrentSessionManager().isRemoting()) {
329
//            CdmApplicationState.getCurrentAppConfig().getOccurrenceService().merge(new ArrayList(getRootEntities()), true);
330
//        }
331
//    }
332
//
333
//    @Override
334
//    public Map<Object, List<String>> getPropertyPathsMap() {
335
//        List<String> specimenPropertyPaths = Arrays.asList(new String[] {
336
//                "descriptions",
337
//                "derivationEvents.derivates",
338
//                "annotations",
339
//                "markers",
340
//                "credits",
341
//                "extensions",
342
//                "rights",
343
//                "sources"
344
//        });
345
//        Map<Object, List<String>> specimenPropertyPathMap =
346
//                new HashMap<Object, List<String>>();
347
//        specimenPropertyPathMap.put(SpecimenOrObservationBase.class,specimenPropertyPaths);
348
//        return specimenPropertyPathMap;
349
//    }
350

    
351
    /**
352
     * Refreshes the derivate hierarchy tree and expands the tree
353
     * to show and select the given object.
354
     *
355
     * @param expandTo the object to which the tree should be expanded
356
     */
357
    public void refreshTree(Object expandTo){
358
        refreshTree();
359
        TreeSelection selection = (TreeSelection) viewer.getSelection();
360
        viewer.expandToLevel(selection.getFirstElement(), 1);
361
        viewer.setSelection(new StructuredSelection(new TreeNode(expandTo)));
362
    }
363

    
364
    /**
365
     * Refreshes the derivate hierarchy tree
366
     */
367
    public void refreshTree(){
368
        generateMultiLinkSingleReads();
369
        labelProvider.setMultiLinkSingleReads(multiLinkSingleReads);
370
        viewer.refresh();
371
    }
372

    
373
    //FIXME:Remoting hack to make this work for remoting
374
    //This should actually be resolved using remoting post operations
375
    public void remove(Object obj) {
376
        rootElements.remove(obj);
377
        viewer.setInput(rootElements);
378
    }
379

    
380
    private void generateMultiLinkSingleReads() {
381
        Set<SingleRead> multiLinkSingleReads = new HashSet<SingleRead>();
382
        for(Entry<SingleRead, Collection<Sequence>> entry:CdmStore.getService(ISequenceService.class).getSingleReadSequencesMap().entrySet()){
383
            if(entry.getValue().size()>1){
384
                multiLinkSingleReads.add(entry.getKey());
385
            }
386
        }
387
        this.multiLinkSingleReads = multiLinkSingleReads;
388
    }
389

    
390
    /**
391
     * @return a set of {@link SingleRead}s that have multiple parents
392
     */
393
    public Set<SingleRead> getMultiLinkSingleReads() {
394
        return this.multiLinkSingleReads;
395
    }
396

    
397
    @Override
398
    public void selectionChanged(SelectionChangedEvent event) {
399
        this.selection  = event.getSelection();
400
    }
401

    
402
    public ISelection getSelection() {
403
        return selection;
404
    }
405

    
406
    public DerivateLabelProvider getLabelProvider() {
407
        return labelProvider;
408
    }
409

    
410
    @Override
411
    public boolean postOperation(CdmBase objectAffectedByOperation) {
412
        refreshTree();
413
        if(objectAffectedByOperation!=null){
414
            changed(objectAffectedByOperation);
415
        }
416
        return true;
417
    }
418

    
419
    @Override
420
    public boolean onComplete() {
421
        return true;
422
    }
423

    
424

    
425
    @Override
426
    public boolean canAttachMedia() {
427
        return true;
428
    }
429

    
430
    public void removeHierarchy(SpecimenOrObservationBase<?> specimenOrObservationBase) {
431
        SpecimenOrObservationBase<?> rootElement = derivateToRootEntityMap.remove(specimenOrObservationBase);
432
        rootElements.remove(rootElement);
433
    }
434

    
435
    public void addHierarchy(FieldUnit fieldUnit) {
436
        rootElements.add(fieldUnit);
437
        derivateToRootEntityMap.put(fieldUnit, fieldUnit);
438
    }
439

    
440
//    @Override
441
//    public ICdmEntitySession getCdmEntitySession() {
442
//        return conversation;
443
//    }
444
}
(3-3/5)