3 * Copyright (C) 2017 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.editor
.descriptiveDataSet
.character
;
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
;
22 import javax
.annotation
.PostConstruct
;
23 import javax
.annotation
.PreDestroy
;
24 import javax
.inject
.Inject
;
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
;
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
.ITermTreeService
;
59 import eu
.etaxonomy
.cdm
.api
.service
.IVocabularyService
;
60 import eu
.etaxonomy
.cdm
.model
.description
.Character
;
61 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
62 import eu
.etaxonomy
.cdm
.model
.term
.DefinedTermBase
;
63 import eu
.etaxonomy
.cdm
.model
.term
.Representation
;
64 import eu
.etaxonomy
.cdm
.model
.term
.TermNode
;
65 import eu
.etaxonomy
.cdm
.model
.term
.TermTree
;
66 import eu
.etaxonomy
.cdm
.model
.term
.TermType
;
67 import eu
.etaxonomy
.cdm
.model
.term
.TermVocabulary
;
68 import eu
.etaxonomy
.cdm
.model
.term
.VocabularyEnum
;
69 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
70 import eu
.etaxonomy
.taxeditor
.editor
.AppModelId
;
71 import eu
.etaxonomy
.taxeditor
.editor
.l10n
.Messages
;
72 import eu
.etaxonomy
.taxeditor
.featuretree
.CharacterTransfer
;
73 import eu
.etaxonomy
.taxeditor
.featuretree
.FeatureNodeTransfer
;
74 import eu
.etaxonomy
.taxeditor
.featuretree
.e4
.FeatureNodeDragListener
;
75 import eu
.etaxonomy
.taxeditor
.featuretree
.e4
.FeatureTreeDropAdapter
;
76 import eu
.etaxonomy
.taxeditor
.featuretree
.e4
.FeatureTreeEditorComposite
;
77 import eu
.etaxonomy
.taxeditor
.featuretree
.e4
.IFeatureTreeEditor
;
78 import eu
.etaxonomy
.taxeditor
.model
.IDirtyMarkable
;
79 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasDetails
;
80 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasSupplementalData
;
81 import eu
.etaxonomy
.taxeditor
.model
.ImageResources
;
82 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
83 import eu
.etaxonomy
.taxeditor
.preference
.PreferencesUtil
;
84 import eu
.etaxonomy
.taxeditor
.session
.ICdmEntitySession
;
85 import eu
.etaxonomy
.taxeditor
.store
.CdmStore
;
86 import eu
.etaxonomy
.taxeditor
.ui
.dialog
.selection
.FeatureTreeSelectionDialog
;
87 import eu
.etaxonomy
.taxeditor
.ui
.dialog
.selection
.TermVocabularySelectionDialog
;
88 import eu
.etaxonomy
.taxeditor
.workbench
.part
.IE4ViewerPart
;
91 * Editor for combining structure and property terms to characters.
96 public class CharacterEditor
implements IFeatureTreeEditor
,IConversationEnabled
, ISelectionChangedListener
,
97 ModifyListener
, IE4ViewerPart
, IPartContentHasDetails
, IPartContentHasSupplementalData
, IDirtyMarkable
{
99 private FeatureTreeEditorComposite
<Character
> characterTreeEditorComposite
;
100 private FeatureTreeEditorComposite
<DefinedTermBase
> propertiesTreeEditorComposite
;
101 private FeatureTreeEditorComposite
<DefinedTermBase
> structuresTreeEditorComposite
;
102 private final FormToolkit formToolkit
= new FormToolkit(Display
.getDefault());
105 private ESelectionService selService
;
108 private UISynchronize sync
;
111 private MDirtyable dirty
;
113 private ConversationHolder conversation
;
115 private ICdmEntitySession cdmEntitySession
;
116 private Composite composite
;
118 private TermVocabulary vocabulary
;
120 public CharacterEditor() {
124 * Create contents of the view part.
127 public void createControls(Composite parent
, EMenuService menuService
) {
128 if (CdmStore
.isActive()){
129 if(conversation
== null){
130 conversation
= CdmStore
.createConversation();
132 if(cdmEntitySession
!=null){
133 cdmEntitySession
= CdmStore
.getCurrentSessionManager().newSession(this, true);
139 parent
.setLayout(new GridLayout(1, false));
141 Composite vocChooserComposite
= new Composite(parent
, SWT
.NONE
);
142 vocChooserComposite
.setLayout(new GridLayout(3, false));
143 vocChooserComposite
.setLayoutData(new GridData(SWT
.RIGHT
, SWT
.FILL
, false, false, 2, 1));
144 Label lblVocImport
= new Label(vocChooserComposite
, SWT
.NONE
);
145 lblVocImport
.setText("Character vocabulary");
146 Text txtVocabulary
= new Text(vocChooserComposite
, SWT
.NONE
);
147 txtVocabulary
.setEditable(false);
148 Button btnChooseVoc
= new Button(vocChooserComposite
, SWT
.PUSH
);
149 btnChooseVoc
.setImage(ImageResources
.getImage(ImageResources
.BROWSE_ICON
));
150 btnChooseVoc
.addSelectionListener(new SelectionAdapter() {
153 public void widgetSelected(SelectionEvent e
) {
154 // hard-coded filter for "built-in" vocabularies Feature and Name Feature
155 Set
<TermVocabulary
> vocabulariesToBeFiltered
= new HashSet
<>();
156 vocabulariesToBeFiltered
.add(CdmStore
.getService(IVocabularyService
.class).load(VocabularyEnum
.Feature
.getUuid()));
157 vocabulariesToBeFiltered
.add(CdmStore
.getService(IVocabularyService
.class).load(VocabularyEnum
.NameFeature
.getUuid()));
158 if(vocabulary
!=null){
159 vocabulariesToBeFiltered
.add(vocabulary
);
161 vocabulary
= TermVocabularySelectionDialog
.select("Select vocabulary for characters", btnChooseVoc
.getShell(), vocabulariesToBeFiltered
, TermType
.Character
);
162 if(vocabulary
!=null){
163 txtVocabulary
.setText(vocabulary
.getLabel());
168 SashForm sashForm
= new SashForm(parent
, SWT
.NONE
);
169 sashForm
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true, 1, 1));
170 formToolkit
.adapt(sashForm
);
171 formToolkit
.paintBordersFor(sashForm
);
173 composite
= new Composite(sashForm
, SWT
.NONE
);
174 formToolkit
.adapt(composite
);
175 formToolkit
.paintBordersFor(composite
);
176 GridLayout gl_composite
= new GridLayout(1, false);
177 gl_composite
.marginWidth
= 0;
178 composite
.setLayout(gl_composite
);
180 structuresTreeEditorComposite
= addFeatureTreeEditor(composite
);
182 initFeatureTreeComposite(TermType
.Structure
, structuresTreeEditorComposite
,
183 new FeatureNodeDragListener(structuresTreeEditorComposite
.getViewer()), null, null, null, null);
185 structuresTreeEditorComposite
.getLabel_title().setText(Messages
.CharacterEditor_STRUCTURES
);
187 Composite composite_1
= new Composite(sashForm
, SWT
.NONE
);
188 formToolkit
.adapt(composite_1
);
189 formToolkit
.paintBordersFor(composite_1
);
190 GridLayout gl_composite_1
= new GridLayout(1, false);
191 gl_composite_1
.marginWidth
= 0;
192 composite_1
.setLayout(gl_composite_1
);
194 propertiesTreeEditorComposite
= addFeatureTreeEditor(composite_1
);
195 initFeatureTreeComposite(TermType
.Property
, propertiesTreeEditorComposite
,
196 new CharacterDragListener(structuresTreeEditorComposite
.getViewer(), propertiesTreeEditorComposite
.getViewer()),
198 new Transfer
[] {CharacterTransfer
.getInstance()},
203 propertiesTreeEditorComposite
.getLabel_title().setText(Messages
.CharacterEditor_PROPERTIES
);
205 Composite composite_3
= new Composite(sashForm
, SWT
.NONE
);
206 formToolkit
.adapt(composite_3
);
207 formToolkit
.paintBordersFor(composite_3
);
208 GridLayout gl_composite_3
= new GridLayout(2, false);
209 gl_composite_3
.marginWidth
= 0;
210 composite_3
.setLayout(gl_composite_3
);
212 Button btnAddCharacter
= new Button(composite_3
, SWT
.NONE
);
213 btnAddCharacter
.setText(">>"); //$NON-NLS-1$
214 formToolkit
.adapt(btnAddCharacter
, true, true);
215 btnAddCharacter
.addSelectionListener(new SelectionAdapter() {
217 public void widgetSelected(SelectionEvent e
) {
218 if(!isVocabularySet()){
221 ISelection structureTreeSelection
= structuresTreeEditorComposite
.getViewer().getSelection();
222 ISelection propertyTreeSelection
= propertiesTreeEditorComposite
.getViewer().getSelection();
223 if(structureTreeSelection
==null || propertyTreeSelection
==null || characterTreeEditorComposite
.getFeatureTree()==null){
224 MessagingUtils
.warningDialog(Messages
.CharacterEditor_CANNOT_PERFORM_TITLE
, CharacterEditor
.this,
225 Messages
.CharacterEditor_CANNOT_PERFORM_MESSAGE
);
228 Collection
<Character
> characters
= createCharacters((TreeSelection
)structureTreeSelection
, (TreeSelection
)propertyTreeSelection
);
229 TermNode
<Character
> parent
= ((TermTree
<Character
>) characterTreeEditorComposite
.getViewer().getInput()).getRoot();
230 for (Character character
: characters
) {
231 //add new Character to feature tree
232 CdmStore
.getService(IFeatureNodeService
.class).createChildFeatureNode(parent
.getUuid(), character
, vocabulary
.getUuid());
238 characterTreeEditorComposite
= addFeatureTreeEditor(composite_3
);
239 initFeatureTreeComposite(TermType
.Character
, characterTreeEditorComposite
, new FeatureNodeDragListener(characterTreeEditorComposite
.getViewer()),
240 new CharacterDropAdapter(this, characterTreeEditorComposite
.getViewer(), sync
),
242 new Transfer
[] {FeatureNodeTransfer
.getInstance(), CharacterTransfer
.getInstance()},
246 characterTreeEditorComposite
.getLabel_title().setText(Messages
.CharacterEditor_CHARACTERS
);
248 //add context menu to character viewer
249 menuService
.registerContextMenu(characterTreeEditorComposite
.getViewer().getControl(),
250 AppModelId
.POPUPMENU_EU_ETAXONOMY_TAXEDITOR_EDITOR_POPUPMENU_CHARACTEREDITOR
);
254 private <T
extends DefinedTermBase
> FeatureTreeEditorComposite
<T
> addFeatureTreeEditor(Composite composite_3
) {
255 FeatureTreeEditorComposite
<T
> featureTreeEditorComposite
= new FeatureTreeEditorComposite
<>(composite_3
, SWT
.NONE
);
256 featureTreeEditorComposite
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true, 1, 1));
257 return featureTreeEditorComposite
;
260 private void initFeatureTreeComposite(
262 FeatureTreeEditorComposite featureTreeEditorComposite
,
263 FeatureNodeDragListener featureNodeDragListener
,
264 FeatureTreeDropAdapter featureNodeDropAdapter
,
265 Transfer
[] transfers
,
266 ISelectionChangedListener viewerSelectionChangedListener
,
267 ModifyListener modifyListener
) {
269 featureTreeEditorComposite
.init(
270 featureNodeDragListener
,
271 featureNodeDropAdapter
,
273 viewerSelectionChangedListener
,
274 new FeatureTreeChooserListener(featureTreeEditorComposite
, termType
),
280 if(characterTreeEditorComposite
!=null){
281 characterTreeEditorComposite
.getViewer().getControl().setFocus();
283 if(conversation
!=null && !conversation
.isBound()){
286 if(cdmEntitySession
!= null) {
287 cdmEntitySession
.bind();
291 public static Collection
<Character
> createCharacters(TreeSelection structureTreeSelection
, TreeSelection propertyTreeSelection
){
292 Set
<Character
> characters
= new HashSet
<>();
293 //get selected structures and properties
294 Iterator
<TermNode
<DefinedTermBase
>> structureIterator
= structureTreeSelection
.iterator();
296 //create all combinations of structures and properties
297 while(structureIterator
.hasNext()){
298 TermNode
<DefinedTermBase
> structureNode
= structureIterator
.next();
299 Iterator
<TermNode
<DefinedTermBase
>> propertiesIterator
= propertyTreeSelection
.iterator();
300 while(propertiesIterator
.hasNext()){
301 TermNode
<DefinedTermBase
> propertyNode
= propertiesIterator
.next();
302 Representation structureRepresentation
= structureNode
.getTerm().getRepresentation(PreferencesUtil
.getGlobalLanguage());
303 Representation propertyRepresentation
= propertyNode
.getTerm().getRepresentation(PreferencesUtil
.getGlobalLanguage());
305 String abbrevLabel
= null;
306 if(structureRepresentation
.getLabel()!=null && propertyRepresentation
.getLabel()!=null){
307 label
= structureRepresentation
.getLabel()+" "+propertyRepresentation
.getLabel();
309 if(structureRepresentation
.getAbbreviatedLabel()!=null && propertyRepresentation
.getAbbreviatedLabel()!=null){
310 abbrevLabel
= structureRepresentation
.getAbbreviatedLabel()+" "+propertyRepresentation
.getAbbreviatedLabel();
312 //create new Character
313 Character character
= Character
.NewInstance(structureNode
, propertyNode
, null, label
, abbrevLabel
);
314 characters
.add(character
);
322 public void save(IProgressMonitor monitor
){
323 if (!conversation
.isBound()) {
327 TermTree
<Character
> featureTree
= characterTreeEditorComposite
.getFeatureTree();
329 CdmStore
.getService(ITermTreeService
.class).merge(featureTree
);
331 // commit the conversation and start a new transaction immediately
332 conversation
.commit(true);
336 dirty
.setDirty(false);
339 private void initializeTrees() {
340 Object
[] expandedElements
= characterTreeEditorComposite
.getViewer().getExpandedElements();
341 characterTreeEditorComposite
.getViewer().getTree().removeAll();
342 TermTree tree
= (TermTree
) characterTreeEditorComposite
.getViewer().getInput();
343 characterTreeEditorComposite
.getViewer().setInput(tree
);
344 characterTreeEditorComposite
.getViewer().setExpandedElements(expandedElements
);
348 public boolean isDirty() {
349 return dirty
.isDirty();
353 public void dispose(){
354 if(conversation
!=null){
355 conversation
.close();
358 if(cdmEntitySession
!= null) {
359 cdmEntitySession
.dispose();
360 cdmEntitySession
= null;
362 dirty
.setDirty(false);
365 public boolean isVocabularySet() {
366 if(vocabulary
==null){
367 MessagingUtils
.warningDialog("Character creation not possible", this.getClass(), "Please select a vocabulary for the characters.");
369 return vocabulary
!=null;
372 public TermVocabulary
getVocabulary() {
377 public Map
<Object
, List
<String
>> getPropertyPathsMap() {
378 List
<String
> propertyPaths
= Arrays
.asList(new String
[] {
379 "children", //$NON-NLS-1$
380 "feature", //$NON-NLS-1$
381 "featureTree", //$NON-NLS-1$
383 Map
<Object
, List
<String
>> propertyPathMap
=
384 new HashMap
<Object
, List
<String
>>();
385 propertyPathMap
.put(TermNode
.class,propertyPaths
);
386 return propertyPathMap
;
390 public List
<TermTree
<Character
>> getRootEntities() {
391 List
<TermTree
<Character
>> root
= new ArrayList
<>();
392 root
.add(characterTreeEditorComposite
.getFeatureTree());
397 public ICdmEntitySession
getCdmEntitySession() {
398 return cdmEntitySession
;
402 public void setFocus() {
403 if(conversation
!=null && !conversation
.isBound()){
409 public void selectionChanged(SelectionChangedEvent event
) {
410 //propagate selection
411 selService
.setSelection(event
.getSelection());
416 public void modifyText(ModifyEvent e
) {
417 characterTreeEditorComposite
.getFeatureTree().setTitleCache(((Text
) e
.widget
).getText(), true);
422 private void setDirty() {
423 dirty
.setDirty(true);
427 public IStructuredSelection
getSelection() {
428 return (IStructuredSelection
) characterTreeEditorComposite
.getViewer().getSelection();
432 public TermType
getTermType() {
433 return TermType
.Character
;
436 public TermTree
<Character
> getCharacterTree(){
437 return characterTreeEditorComposite
.getFeatureTree();
441 public void refresh(){
442 structuresTreeEditorComposite
.getViewer().refresh();
443 propertiesTreeEditorComposite
.getViewer().refresh();
444 characterTreeEditorComposite
.getViewer().setInput(characterTreeEditorComposite
.getViewer().getInput());
447 private class FeatureTreeChooserListener
extends SelectionAdapter
{
448 private FeatureTreeEditorComposite
<Feature
> featureTreeEditorComposite
;
449 private TermType termType
;
451 public FeatureTreeChooserListener(FeatureTreeEditorComposite
<Feature
> featureTreeEditorComposite
, TermType termType
) {
453 this.featureTreeEditorComposite
= featureTreeEditorComposite
;
454 this.termType
= termType
;
458 public void widgetSelected(SelectionEvent e
) {
459 TermTree tree
= FeatureTreeSelectionDialog
.select(featureTreeEditorComposite
.getDisplay().getActiveShell(), null, termType
);
461 featureTreeEditorComposite
.setSelectedTree(tree
);
467 public void update(CdmDataChangeMap arg0
) {
471 public ConversationHolder
getConversationHolder() {
476 public void changed(Object element
) {
478 characterTreeEditorComposite
.getViewer().refresh();
482 public void forceDirty() {
487 public boolean postOperation(Object objectAffectedByOperation
) {
488 characterTreeEditorComposite
.getViewer().refresh();
489 if(objectAffectedByOperation
instanceof TermNode
){
490 StructuredSelection selection
= new StructuredSelection(objectAffectedByOperation
);
491 characterTreeEditorComposite
.getViewer().setSelection(selection
);
497 public boolean onComplete() {