Project

General

Profile

Download (19.6 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2017 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.taxeditor.editor.descriptiveDataSet.character;
11

    
12
import java.util.ArrayList;
13
import java.util.Arrays;
14
import java.util.Collection;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Map;
20
import java.util.Set;
21

    
22
import javax.annotation.PostConstruct;
23
import javax.annotation.PreDestroy;
24
import javax.inject.Inject;
25

    
26
import org.eclipse.core.runtime.IProgressMonitor;
27
import org.eclipse.e4.ui.di.Focus;
28
import org.eclipse.e4.ui.di.Persist;
29
import org.eclipse.e4.ui.di.UISynchronize;
30
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
31
import org.eclipse.e4.ui.services.EMenuService;
32
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
33
import org.eclipse.jface.viewers.ISelection;
34
import org.eclipse.jface.viewers.ISelectionChangedListener;
35
import org.eclipse.jface.viewers.IStructuredSelection;
36
import org.eclipse.jface.viewers.SelectionChangedEvent;
37
import org.eclipse.jface.viewers.StructuredSelection;
38
import org.eclipse.jface.viewers.TreeSelection;
39
import org.eclipse.swt.SWT;
40
import org.eclipse.swt.custom.SashForm;
41
import org.eclipse.swt.dnd.Transfer;
42
import org.eclipse.swt.events.ModifyEvent;
43
import org.eclipse.swt.events.ModifyListener;
44
import org.eclipse.swt.events.SelectionAdapter;
45
import org.eclipse.swt.events.SelectionEvent;
46
import org.eclipse.swt.layout.GridData;
47
import org.eclipse.swt.layout.GridLayout;
48
import org.eclipse.swt.widgets.Button;
49
import org.eclipse.swt.widgets.Composite;
50
import org.eclipse.swt.widgets.Display;
51
import org.eclipse.swt.widgets.Label;
52
import org.eclipse.swt.widgets.Text;
53
import org.eclipse.ui.forms.widgets.FormToolkit;
54

    
55
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
56
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
57
import eu.etaxonomy.cdm.api.service.IFeatureNodeService;
58
import eu.etaxonomy.cdm.api.service.ITermService;
59
import eu.etaxonomy.cdm.api.service.ITermTreeService;
60
import eu.etaxonomy.cdm.api.service.IVocabularyService;
61
import eu.etaxonomy.cdm.model.description.Character;
62
import eu.etaxonomy.cdm.model.description.Feature;
63
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
64
import eu.etaxonomy.cdm.model.term.Representation;
65
import eu.etaxonomy.cdm.model.term.TermNode;
66
import eu.etaxonomy.cdm.model.term.TermTree;
67
import eu.etaxonomy.cdm.model.term.TermType;
68
import eu.etaxonomy.cdm.model.term.TermVocabulary;
69
import eu.etaxonomy.cdm.model.term.VocabularyEnum;
70
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
71
import eu.etaxonomy.taxeditor.editor.AppModelId;
72
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
73
import eu.etaxonomy.taxeditor.featuretree.CharacterTransfer;
74
import eu.etaxonomy.taxeditor.featuretree.FeatureNodeTransfer;
75
import eu.etaxonomy.taxeditor.featuretree.e4.FeatureNodeDragListener;
76
import eu.etaxonomy.taxeditor.featuretree.e4.FeatureTreeDropAdapter;
77
import eu.etaxonomy.taxeditor.featuretree.e4.FeatureTreeEditorComposite;
78
import eu.etaxonomy.taxeditor.featuretree.e4.IFeatureTreeEditor;
79
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
80
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
81
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
82
import eu.etaxonomy.taxeditor.model.ImageResources;
83
import eu.etaxonomy.taxeditor.model.MessagingUtils;
84
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
85
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
86
import eu.etaxonomy.taxeditor.store.CdmStore;
87
import eu.etaxonomy.taxeditor.ui.dialog.selection.FeatureTreeSelectionDialog;
88
import eu.etaxonomy.taxeditor.ui.dialog.selection.TermVocabularySelectionDialog;
89
import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
90

    
91
/**
92
 * Editor for combining structure and property terms to characters.
93
 * @author pplitzner
94
 * @date 24.05.2017
95
 *
96
 */
97
public class CharacterEditor implements IFeatureTreeEditor,IConversationEnabled, ISelectionChangedListener,
98
        ModifyListener, IE4ViewerPart, IPartContentHasDetails, IPartContentHasSupplementalData, IDirtyMarkable {
99

    
100
    private FeatureTreeEditorComposite<Character> characterTreeEditorComposite;
101
    private FeatureTreeEditorComposite<DefinedTermBase> propertiesTreeEditorComposite;
102
    private FeatureTreeEditorComposite<DefinedTermBase> structuresTreeEditorComposite;
103
    private final FormToolkit formToolkit = new FormToolkit(Display.getDefault());
104

    
105
    @Inject
106
    private ESelectionService selService;
107

    
108
    @Inject
109
    private UISynchronize sync;
110

    
111
    @Inject
112
    private MDirtyable dirty;
113

    
114
    private ConversationHolder conversation;
115

    
116
    private ICdmEntitySession cdmEntitySession;
117
    private Composite composite;
118

    
119
    private TermVocabulary vocabulary;
120

    
121
    public CharacterEditor() {
122
    }
123

    
124
    /**
125
     * Create contents of the view part.
126
     */
127
    @PostConstruct
128
    public void createControls(Composite parent, EMenuService menuService ) {
129
        if (CdmStore.isActive()){
130
            if(conversation == null){
131
                conversation = CdmStore.createConversation();
132
            }
133
            if(cdmEntitySession!=null){
134
                cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
135
            }
136
        }
137
        else{
138
            return;
139
        }
140
        parent.setLayout(new GridLayout(1, false));
141

    
142
        Composite vocChooserComposite = new Composite(parent, SWT.NONE);
143
        vocChooserComposite.setLayout(new GridLayout(3, false));
144
        vocChooserComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false, false, 2, 1));
145
        Label lblVocImport = new Label(vocChooserComposite, SWT.NONE);
146
        lblVocImport.setText("Character vocabulary");
147
        Text txtVocabulary = new Text(vocChooserComposite, SWT.NONE);
148
        txtVocabulary.setEditable(false);
149
        Button btnChooseVoc = new Button(vocChooserComposite, SWT.PUSH);
150
        btnChooseVoc.setImage(ImageResources.getImage(ImageResources.BROWSE_ICON));
151
        btnChooseVoc.addSelectionListener(new SelectionAdapter() {
152

    
153
            @Override
154
            public void widgetSelected(SelectionEvent e) {
155
                // hard-coded filter for "built-in" vocabularies Feature and Name Feature
156
                Set<TermVocabulary> vocabulariesToBeFiltered = new HashSet<>();
157
                vocabulariesToBeFiltered.add(CdmStore.getService(IVocabularyService.class).load(VocabularyEnum.Feature.getUuid()));
158
                vocabulariesToBeFiltered.add(CdmStore.getService(IVocabularyService.class).load(VocabularyEnum.NameFeature.getUuid()));
159
                if(vocabulary!=null){
160
                    vocabulariesToBeFiltered.add(vocabulary);
161
                }
162
                vocabulary = TermVocabularySelectionDialog.select("Select vocabulary for characters", btnChooseVoc.getShell(), vocabulariesToBeFiltered, TermType.Character);
163
                if(vocabulary!=null){
164
                    txtVocabulary.setText(vocabulary.getLabel());
165
                }
166
            }
167
        });
168

    
169
        SashForm sashForm = new SashForm(parent, SWT.NONE);
170
        sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
171
        formToolkit.adapt(sashForm);
172
        formToolkit.paintBordersFor(sashForm);
173

    
174
        composite = new Composite(sashForm, SWT.NONE);
175
        formToolkit.adapt(composite);
176
        formToolkit.paintBordersFor(composite);
177
        GridLayout gl_composite = new GridLayout(1, false);
178
        gl_composite.marginWidth = 0;
179
        composite.setLayout(gl_composite);
180

    
181
        structuresTreeEditorComposite = addFeatureTreeEditor(composite);
182

    
183
        initFeatureTreeComposite(TermType.Structure, structuresTreeEditorComposite,
184
                new FeatureNodeDragListener(structuresTreeEditorComposite.getViewer()), null, null, null, null);
185

    
186
        structuresTreeEditorComposite.getLabel_title().setText(Messages.CharacterEditor_STRUCTURES);
187

    
188
        Composite composite_1 = new Composite(sashForm, SWT.NONE);
189
        formToolkit.adapt(composite_1);
190
        formToolkit.paintBordersFor(composite_1);
191
        GridLayout gl_composite_1 = new GridLayout(1, false);
192
        gl_composite_1.marginWidth = 0;
193
        composite_1.setLayout(gl_composite_1);
194

    
195
        propertiesTreeEditorComposite = addFeatureTreeEditor(composite_1);
196
        initFeatureTreeComposite(TermType.Property, propertiesTreeEditorComposite,
197
                new CharacterDragListener(structuresTreeEditorComposite.getViewer(), propertiesTreeEditorComposite.getViewer()),
198
                null,
199
                new Transfer[] {CharacterTransfer.getInstance()},
200
                null,
201
                null
202

    
203
        );
204
        propertiesTreeEditorComposite.getLabel_title().setText(Messages.CharacterEditor_PROPERTIES);
205

    
206
        Composite composite_3 = new Composite(sashForm, SWT.NONE);
207
        formToolkit.adapt(composite_3);
208
        formToolkit.paintBordersFor(composite_3);
209
        GridLayout gl_composite_3 = new GridLayout(2, false);
210
        gl_composite_3.marginWidth = 0;
211
        composite_3.setLayout(gl_composite_3);
212

    
213
        Button btnAddCharacter = new Button(composite_3, SWT.NONE);
214
        btnAddCharacter.setText(">>"); //$NON-NLS-1$
215
        formToolkit.adapt(btnAddCharacter, true, true);
216
        btnAddCharacter.addSelectionListener(new SelectionAdapter() {
217
            @Override
218
            public void widgetSelected(SelectionEvent e) {
219
                if(!isVocabularySet()){
220
                    return;
221
                }
222
                ISelection structureTreeSelection = structuresTreeEditorComposite.getViewer().getSelection();
223
                ISelection propertyTreeSelection = propertiesTreeEditorComposite.getViewer().getSelection();
224
                if(structureTreeSelection==null || propertyTreeSelection==null || characterTreeEditorComposite.getFeatureTree()==null){
225
                    MessagingUtils.warningDialog(Messages.CharacterEditor_CANNOT_PERFORM_TITLE, CharacterEditor.this,
226
                            Messages.CharacterEditor_CANNOT_PERFORM_MESSAGE);
227
                    return;
228
                }
229
                Collection<Character> characters = createCharacters((TreeSelection)structureTreeSelection, (TreeSelection)propertyTreeSelection);
230
                TermNode<Character> parent = ((TermTree<Character>) characterTreeEditorComposite.getViewer().getInput()).getRoot();
231
                for (Character character : characters) {
232
                    //add new Character to feature tree
233
                    CdmStore.getService(IFeatureNodeService.class).createChildFeatureNode(parent.getUuid(), character, vocabulary.getUuid());
234
                }
235
                characterTreeEditorComposite.getViewer().refresh();
236
            }
237
        });
238

    
239
        characterTreeEditorComposite = addFeatureTreeEditor(composite_3);
240
        initFeatureTreeComposite(TermType.Character, characterTreeEditorComposite, new FeatureNodeDragListener(characterTreeEditorComposite.getViewer()),
241
                new CharacterDropAdapter(this, characterTreeEditorComposite.getViewer(), sync),
242

    
243
                new Transfer[] {FeatureNodeTransfer.getInstance(), CharacterTransfer.getInstance()},
244
                this,
245
                this);
246

    
247
        characterTreeEditorComposite.getLabel_title().setText(Messages.CharacterEditor_CHARACTERS);
248

    
249
        //add context menu to character viewer
250
        menuService.registerContextMenu(characterTreeEditorComposite.getViewer().getControl(),
251
                AppModelId.POPUPMENU_EU_ETAXONOMY_TAXEDITOR_EDITOR_POPUPMENU_CHARACTEREDITOR);
252

    
253
    }
254

    
255
    private <T extends DefinedTermBase> FeatureTreeEditorComposite<T> addFeatureTreeEditor(Composite composite_3) {
256
        FeatureTreeEditorComposite<T> featureTreeEditorComposite = new FeatureTreeEditorComposite<>(composite_3, SWT.NONE);
257
        featureTreeEditorComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
258
        return featureTreeEditorComposite;
259
    }
260

    
261
    private void initFeatureTreeComposite(
262
            TermType termType,
263
            FeatureTreeEditorComposite featureTreeEditorComposite,
264
            FeatureNodeDragListener featureNodeDragListener,
265
            FeatureTreeDropAdapter featureNodeDropAdapter,
266
            Transfer[] transfers,
267
            ISelectionChangedListener viewerSelectionChangedListener,
268
            ModifyListener modifyListener) {
269

    
270
        featureTreeEditorComposite.init(
271
                featureNodeDragListener,
272
                featureNodeDropAdapter,
273
                transfers,
274
                viewerSelectionChangedListener,
275
                new FeatureTreeChooserListener(featureTreeEditorComposite, termType),
276
                modifyListener);
277
    }
278

    
279
    @Focus
280
    public void focus(){
281
        if(characterTreeEditorComposite!=null){
282
            characterTreeEditorComposite.getViewer().getControl().setFocus();
283
        }
284
        if(conversation!=null && !conversation.isBound()){
285
            conversation.bind();
286
        }
287
        if(cdmEntitySession != null) {
288
            cdmEntitySession.bind();
289
        }
290
    }
291

    
292
    public static Collection<Character> createCharacters(TreeSelection structureTreeSelection, TreeSelection propertyTreeSelection){
293
        Set<Character> characters = new HashSet<>();
294
        //get selected structures and properties
295
        Iterator<TermNode<DefinedTermBase>> structureIterator = structureTreeSelection.iterator();
296

    
297
        //create all combinations of structures and properties
298
        while(structureIterator.hasNext()){
299
            TermNode<DefinedTermBase> structureNode = structureIterator.next();
300
            Iterator<TermNode<DefinedTermBase>> propertiesIterator = propertyTreeSelection.iterator();
301
            while(propertiesIterator.hasNext()){
302
                TermNode<DefinedTermBase> propertyNode = propertiesIterator.next();
303
                Representation structureRepresentation = structureNode.getTerm().getRepresentation(PreferencesUtil.getGlobalLanguage());
304
                Representation propertyRepresentation = propertyNode.getTerm().getRepresentation(PreferencesUtil.getGlobalLanguage());
305
                String label = null;
306
                String abbrevLabel = null;
307
                if(structureRepresentation.getLabel()!=null && propertyRepresentation.getLabel()!=null){
308
                    label = structureRepresentation.getLabel()+" "+propertyRepresentation.getLabel();
309
                }
310
                if(structureRepresentation.getAbbreviatedLabel()!=null && propertyRepresentation.getAbbreviatedLabel()!=null){
311
                    abbrevLabel = structureRepresentation.getAbbreviatedLabel()+" "+propertyRepresentation.getAbbreviatedLabel();
312
                }
313
                //create new Character
314
                Character character = Character.NewInstance(structureNode, propertyNode, null, label, abbrevLabel);
315
                characters.add(character);
316
            }
317
        }
318
        return characters;
319
    }
320

    
321
    @Override
322
    @Persist
323
    public void save(IProgressMonitor monitor){
324
        if (!conversation.isBound()) {
325
            conversation.bind();
326
        }
327

    
328
        // commit the conversation and start a new transaction immediately
329
        conversation.commit(true);
330

    
331
        TermTree<Character> featureTree = characterTreeEditorComposite.getFeatureTree();
332
        if(featureTree!=null){
333
            //save characters because they can be modified in this editor
334
            featureTree.getDistinctTerms().forEach(character->CdmStore.getService(ITermService.class).merge(character,true));
335
        }
336
        CdmStore.getService(ITermTreeService.class).saveOrUpdate(featureTree);
337

    
338

    
339
        dirty.setDirty(false);
340
    }
341

    
342
    @Override
343
    public boolean isDirty() {
344
        return dirty.isDirty();
345
    }
346

    
347
    @PreDestroy
348
    public void dispose(){
349
        if(conversation!=null){
350
            conversation.close();
351
            conversation = null;
352
        }
353
        if(cdmEntitySession != null) {
354
            cdmEntitySession.dispose();
355
            cdmEntitySession = null;
356
        }
357
        dirty.setDirty(false);
358
    }
359

    
360
    public boolean isVocabularySet() {
361
        if(vocabulary==null){
362
            MessagingUtils.warningDialog("Character creation not possible", this.getClass(), "Please select a vocabulary for the characters.");
363
        }
364
        return vocabulary!=null;
365
    }
366

    
367
    public TermVocabulary getVocabulary() {
368
        return vocabulary;
369
    }
370

    
371
    @Override
372
    public Map<Object, List<String>> getPropertyPathsMap() {
373
        List<String> propertyPaths = Arrays.asList(new String[] {
374
                "children", //$NON-NLS-1$
375
                "feature", //$NON-NLS-1$
376
                "featureTree", //$NON-NLS-1$
377
        });
378
        Map<Object, List<String>> propertyPathMap =
379
                new HashMap<Object, List<String>>();
380
        propertyPathMap.put(TermNode.class,propertyPaths);
381
        return propertyPathMap;
382
    }
383

    
384
    @Override
385
    public List<TermTree<Character>> getRootEntities() {
386
        List<TermTree<Character>> root = new ArrayList<>();
387
        root.add(characterTreeEditorComposite.getFeatureTree());
388
        return root;
389
    }
390

    
391
    @Override
392
    public ICdmEntitySession getCdmEntitySession() {
393
        return cdmEntitySession;
394
    }
395

    
396
    @Focus
397
    public void setFocus() {
398
        if(conversation!=null && !conversation.isBound()){
399
            conversation.bind();
400
        }
401
    }
402

    
403
    @Override
404
    public void selectionChanged(SelectionChangedEvent event) {
405
        //propagate selection
406
        selService.setSelection(event.getSelection());
407
    }
408

    
409

    
410
    @Override
411
    public void modifyText(ModifyEvent e) {
412
        characterTreeEditorComposite.getFeatureTree().setTitleCache(((Text) e.widget).getText(), true);
413
        setDirty();
414
    }
415

    
416

    
417
    private void setDirty() {
418
        dirty.setDirty(true);
419
    }
420

    
421
    @Override
422
    public IStructuredSelection getSelection() {
423
        return (IStructuredSelection) characterTreeEditorComposite.getViewer().getSelection();
424
    }
425

    
426
    public TermTree<Character> getCharacterTree(){
427
        return characterTreeEditorComposite.getFeatureTree();
428
    }
429

    
430
    @Override
431
    public void refresh(){
432
        structuresTreeEditorComposite.getViewer().refresh();
433
        propertiesTreeEditorComposite.getViewer().refresh();
434
        characterTreeEditorComposite.getViewer().refresh();
435
    }
436

    
437
    private class FeatureTreeChooserListener extends SelectionAdapter{
438
        private FeatureTreeEditorComposite<Feature> featureTreeEditorComposite;
439
        private TermType termType;
440

    
441
        public FeatureTreeChooserListener(FeatureTreeEditorComposite<Feature> featureTreeEditorComposite, TermType termType) {
442
            super();
443
            this.featureTreeEditorComposite = featureTreeEditorComposite;
444
            this.termType = termType;
445
        }
446

    
447
        @Override
448
        public void widgetSelected(SelectionEvent e) {
449
            TermTree<Feature> tree = FeatureTreeSelectionDialog.select(featureTreeEditorComposite.getDisplay().getActiveShell(), null, termType);
450
            if(tree!=null){
451
                featureTreeEditorComposite.setSelectedTree(tree);
452
            }
453
        }
454
    }
455

    
456
    @Override
457
    public void update(CdmDataChangeMap arg0) {
458
    }
459

    
460
    @Override
461
    public ConversationHolder getConversationHolder() {
462
        return conversation;
463
    }
464

    
465
    @Override
466
    public void changed(Object element) {
467
        setDirty();
468
        characterTreeEditorComposite.getViewer().refresh();
469
    }
470

    
471
    @Override
472
    public void forceDirty() {
473
        setDirty();
474
    }
475

    
476
    @Override
477
    public boolean postOperation(Object objectAffectedByOperation) {
478
        characterTreeEditorComposite.getViewer().refresh();
479
        if(objectAffectedByOperation instanceof TermNode){
480
            StructuredSelection selection = new StructuredSelection(objectAffectedByOperation);
481
            characterTreeEditorComposite.getViewer().setSelection(selection);
482
        }
483
        return true;
484
    }
485

    
486
    @Override
487
    public boolean onComplete() {
488
        return false;
489
    }
490

    
491
}
(3-3/3)