Merge branch 'release/5.27.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / descriptiveDataSet / character / CharacterEditor.java
1 /**
2 * Copyright (C) 2017 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 package eu.etaxonomy.taxeditor.editor.descriptiveDataSet.character;
10
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.UUID;
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.core.di.annotations.Optional;
28 import org.eclipse.e4.ui.di.Focus;
29 import org.eclipse.e4.ui.di.Persist;
30 import org.eclipse.e4.ui.di.UIEventTopic;
31 import org.eclipse.e4.ui.di.UISynchronize;
32 import org.eclipse.e4.ui.model.application.ui.MDirtyable;
33 import org.eclipse.e4.ui.services.EMenuService;
34 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
35 import org.eclipse.jface.viewers.ISelection;
36 import org.eclipse.jface.viewers.ISelectionChangedListener;
37 import org.eclipse.jface.viewers.IStructuredSelection;
38 import org.eclipse.jface.viewers.SelectionChangedEvent;
39 import org.eclipse.jface.viewers.StructuredSelection;
40 import org.eclipse.jface.viewers.TreeSelection;
41 import org.eclipse.jface.viewers.TreeViewer;
42 import org.eclipse.swt.SWT;
43 import org.eclipse.swt.custom.SashForm;
44 import org.eclipse.swt.dnd.DND;
45 import org.eclipse.swt.dnd.Transfer;
46 import org.eclipse.swt.events.ModifyEvent;
47 import org.eclipse.swt.events.ModifyListener;
48 import org.eclipse.swt.events.SelectionAdapter;
49 import org.eclipse.swt.events.SelectionEvent;
50 import org.eclipse.swt.layout.GridData;
51 import org.eclipse.swt.layout.GridLayout;
52 import org.eclipse.swt.widgets.Button;
53 import org.eclipse.swt.widgets.Composite;
54 import org.eclipse.swt.widgets.Display;
55 import org.eclipse.swt.widgets.Label;
56 import org.eclipse.swt.widgets.Text;
57 import org.eclipse.ui.forms.widgets.FormToolkit;
58
59 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
60 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
61 import eu.etaxonomy.cdm.api.service.ITermNodeService;
62 import eu.etaxonomy.cdm.api.service.ITermTreeService;
63 import eu.etaxonomy.cdm.api.service.IVocabularyService;
64 import eu.etaxonomy.cdm.api.service.UpdateResult;
65 import eu.etaxonomy.cdm.format.description.CharacterLabelBuilder;
66 import eu.etaxonomy.cdm.model.common.Language;
67 import eu.etaxonomy.cdm.model.description.Character;
68 import eu.etaxonomy.cdm.model.description.Feature;
69 import eu.etaxonomy.cdm.model.term.DefinedTerm;
70 import eu.etaxonomy.cdm.model.term.DefinedTermBase;
71 import eu.etaxonomy.cdm.model.term.Representation;
72 import eu.etaxonomy.cdm.model.term.TermNode;
73 import eu.etaxonomy.cdm.model.term.TermTree;
74 import eu.etaxonomy.cdm.model.term.TermType;
75 import eu.etaxonomy.cdm.model.term.TermVocabulary;
76 import eu.etaxonomy.cdm.model.term.VocabularyEnum;
77 import eu.etaxonomy.cdm.persistence.dto.CharacterDto;
78 import eu.etaxonomy.cdm.persistence.dto.CharacterNodeDto;
79 import eu.etaxonomy.cdm.persistence.dto.TermDto;
80 import eu.etaxonomy.cdm.persistence.dto.TermNodeDto;
81 import eu.etaxonomy.cdm.persistence.dto.TermTreeDto;
82 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
83 import eu.etaxonomy.taxeditor.editor.AppModelId;
84 import eu.etaxonomy.taxeditor.editor.definedterm.TermTreeViewerComparator;
85 import eu.etaxonomy.taxeditor.editor.l10n.Messages;
86 import eu.etaxonomy.taxeditor.event.EventUtility;
87 import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
88 import eu.etaxonomy.taxeditor.model.AbstractUtility;
89 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
90 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
91 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
92 import eu.etaxonomy.taxeditor.model.ImageResources;
93 import eu.etaxonomy.taxeditor.model.MessagingUtils;
94 import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
95 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
96 import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
97 import eu.etaxonomy.taxeditor.store.CdmStore;
98 import eu.etaxonomy.taxeditor.store.StoreUtil;
99 import eu.etaxonomy.taxeditor.termtree.CharacterTransfer;
100 import eu.etaxonomy.taxeditor.termtree.TermTreeContentProvider;
101 import eu.etaxonomy.taxeditor.termtree.TermTreeLabelProvider;
102 import eu.etaxonomy.taxeditor.termtree.e4.ICharacterEditor;
103 import eu.etaxonomy.taxeditor.termtree.e4.TermNodeDtoDragListener;
104 import eu.etaxonomy.taxeditor.termtree.e4.TermTreeDtoDropAdapter;
105 import eu.etaxonomy.taxeditor.termtree.e4.TermTreeDtoEditorComposite;
106 import eu.etaxonomy.taxeditor.termtree.e4.TermTreeEditor;
107 import eu.etaxonomy.taxeditor.ui.dialog.selection.FeatureTreeSelectionDialog;
108 import eu.etaxonomy.taxeditor.ui.dialog.selection.TermVocabularySelectionDialog;
109 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
110 import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
111
112 /**
113 * Editor for combining structure and property terms to characters.
114 * @author pplitzner
115 * @date 24.05.2017
116 */
117 public class CharacterEditor implements ICharacterEditor, IConversationEnabled, ISelectionChangedListener,
118 ModifyListener, IE4ViewerPart, IPartContentHasDetails, IPartContentHasSupplementalData,
119 IDirtyMarkable, IE4SavablePart {
120
121 private TermTreeDtoEditorComposite characterTreeEditorComposite;
122 private final FormToolkit formToolkit = new FormToolkit(Display.getDefault());
123
124 @Inject
125 private ESelectionService selService;
126
127 @Inject
128 private UISynchronize sync;
129
130 @Inject
131 private MDirtyable dirty;
132
133 private ConversationHolder conversation;
134
135 private ICdmEntitySession cdmEntitySession;
136
137 private TermVocabulary vocabulary;
138 private TreeViewer structureViewer;
139 private TreeViewer propertyViewer;
140 private Button btnAddCharacter;
141 private Button btnAddRatioTo;
142
143 private List<AbstractPostOperation> operations = new ArrayList<>();
144
145 private List<CharacterNodeDto> nodesToUpdate = new ArrayList<>();
146
147 private Map<Character, CharacterNodeDto> nodesToSave = new HashMap<>();
148
149 public CharacterEditor() {
150 }
151
152 /**
153 * Create contents of the view part.
154 */
155 @PostConstruct
156 public void createControls(Composite parent, EMenuService menuService ) {
157 if (CdmStore.isActive()){
158 if(conversation == null){
159 conversation = CdmStore.createConversation();
160 }
161 if(cdmEntitySession==null){
162 cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
163 }
164 }
165 else{
166 return;
167 }
168 parent.setLayout(new GridLayout(1, false));
169
170 Composite vocChooserComposite = new Composite(parent, SWT.NONE);
171 vocChooserComposite.setLayout(new GridLayout(4, false));
172 vocChooserComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false, false, 2, 1));
173 Label lblVocImport = new Label(vocChooserComposite, SWT.NONE);
174 lblVocImport.setText("Character vocabulary:");
175 Text txtVocabulary = new Text(vocChooserComposite, SWT.NONE);
176 txtVocabulary.setEditable(false);
177 Button btnChooseVoc = new Button(vocChooserComposite, SWT.PUSH);
178 btnChooseVoc.setImage(ImageResources.getImage(ImageResources.BROWSE_ICON));
179 btnChooseVoc.addSelectionListener(new SelectionAdapter() {
180
181 @Override
182 public void widgetSelected(SelectionEvent e) {
183 // hard-coded filter for "built-in" vocabularies Feature and Name Feature
184 Set<TermVocabulary> vocabulariesToBeFiltered = new HashSet<>();
185 vocabulariesToBeFiltered.add(CdmStore.getService(IVocabularyService.class).load(VocabularyEnum.Feature.getUuid()));
186 vocabulariesToBeFiltered.add(CdmStore.getService(IVocabularyService.class).load(VocabularyEnum.NameFeature.getUuid()));
187 if(vocabulary!=null){
188 vocabulariesToBeFiltered.add(vocabulary);
189 }
190 vocabulary = TermVocabularySelectionDialog.select("Select vocabulary for characters", btnChooseVoc.getShell(), vocabulariesToBeFiltered, TermType.Character);
191 if(vocabulary!=null){
192 txtVocabulary.setText(vocabulary.getLabel());
193 }
194 }
195 });
196
197 SashForm sashForm = new SashForm(parent, SWT.NONE);
198 sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
199 formToolkit.adapt(sashForm);
200 formToolkit.paintBordersFor(sashForm);
201
202 Composite composite = new Composite(sashForm, SWT.NONE);
203 formToolkit.adapt(composite);
204 formToolkit.paintBordersFor(composite);
205 GridLayout gl_composite = new GridLayout(1, false);
206 gl_composite.marginWidth = 0;
207 composite.setLayout(gl_composite);
208
209 structureViewer = createTreeViewer(composite, TermType.Structure, Messages.CharacterEditor_STRUCTURES);
210
211 Composite composite_1 = new Composite(sashForm, SWT.NONE);
212 formToolkit.adapt(composite_1);
213 formToolkit.paintBordersFor(composite_1);
214 GridLayout gl_composite_1 = new GridLayout(1, false);
215 gl_composite_1.marginWidth = 0;
216 composite_1.setLayout(gl_composite_1);
217
218 propertyViewer = createTreeViewer(composite_1, TermType.Property, Messages.CharacterEditor_PROPERTIES);
219 propertyViewer.addSelectionChangedListener(this);
220
221 int ops = DND.DROP_COPY | DND.DROP_MOVE;
222 Transfer[] transfers = new Transfer[] {CharacterTransfer.getInstance()};
223 propertyViewer.addDragSupport(ops, transfers, new CharacterDragListener(structureViewer, propertyViewer));
224
225 Composite composite_3 = new Composite(sashForm, SWT.NONE);
226 formToolkit.adapt(composite_3);
227 formToolkit.paintBordersFor(composite_3);
228 GridLayout gl_composite_3 = new GridLayout(2, false);
229 gl_composite_3.marginWidth = 0;
230 composite_3.setLayout(gl_composite_3);
231
232 Composite composite_4 = new Composite(composite_3, SWT.NONE);
233 formToolkit.adapt(composite_4);
234 formToolkit.paintBordersFor(composite_4);
235 GridLayout gl_composite_4 = new GridLayout(1, false);
236 gl_composite_4.marginWidth = 0;
237 composite_4.setLayout(gl_composite_4);
238
239 btnAddCharacter = new Button(composite_4, SWT.NONE);
240 btnAddCharacter.setText(">>"); //$NON-NLS-1$
241 formToolkit.adapt(btnAddCharacter, true, true);
242 btnAddCharacter.addSelectionListener(new SelectionAdapter() {
243 @Override
244 public void widgetSelected(SelectionEvent e) {
245 if(!isVocabularySet()){
246 return;
247 }
248 if (confirmSaveDirty()){
249 return;
250 }
251 ISelection structureTreeSelection = structureViewer.getSelection();
252 ISelection propertyTreeSelection = propertyViewer.getSelection();
253 if(structureTreeSelection==null || propertyTreeSelection==null || characterTreeEditorComposite.getFeatureTree()==null){
254 MessagingUtils.warningDialog(Messages.CharacterEditor_CANNOT_PERFORM_TITLE, CharacterEditor.this,
255 Messages.CharacterEditor_CANNOT_PERFORM_MESSAGE);
256 return;
257 }
258 Collection<Character> characters = createCharacters((TreeSelection)structureTreeSelection, (TreeSelection)propertyTreeSelection);
259 TermNodeDto parent = characterTreeEditorComposite.getFeatureTree().getRoot();
260 ISelection sel = characterTreeEditorComposite.getViewer().getSelection();
261
262 TermNodeDto parentNode = parent;
263 if (sel instanceof TreeSelection){
264 TreeSelection treeSel = (TreeSelection)sel;
265 Object o = treeSel.getFirstElement();
266 if (o instanceof CharacterNodeDto){
267 parentNode = (TermNodeDto)o;
268 }
269 }
270
271 for (Character character : characters) {
272 //add new Character to feature tree
273 CharacterNodeDto nodeDto = new CharacterNodeDto(CharacterDto.fromCharacter(character), parentNode, 0, parent.getTree(), null, null, null);
274 nodesToSave.put(character, nodeDto);
275 setDirty();
276 // result = CdmStore.getService(IFeatureNodeService.class).createChildFeatureNode(parent.getUuid(), character, vocabulary.getUuid());
277
278 }
279
280
281 refresh();
282 }
283 });
284 btnAddCharacter.setEnabled(false);
285
286 btnAddRatioTo = new Button(composite_4, SWT.NONE);
287 btnAddRatioTo.setText("ratio to"); //$NON-NLS-1$
288
289 btnAddRatioTo.setSize(btnAddCharacter.getSize());
290 btnAddRatioTo.setEnabled(false);
291
292 formToolkit.adapt(btnAddRatioTo, true, true);
293 btnAddRatioTo.addSelectionListener(new SelectionAdapter() {
294 @Override
295 public void widgetSelected(SelectionEvent e) {
296
297 if (confirmSaveDirty()){
298 return;
299 }
300 ISelection structureTreeSelection = structureViewer.getSelection();
301 ISelection characterSelection = characterTreeEditorComposite.getViewer().getSelection();
302 if(structureTreeSelection==null || characterSelection ==null){
303 MessagingUtils.warningDialog(Messages.CharacterEditor_CANNOT_PERFORM_TITLE, CharacterEditor.this,
304 Messages.CharacterEditor_CANNOT_PERFORM_MESSAGE);
305 return;
306 }
307
308 CharacterNodeDto character = (CharacterNodeDto)((TreeSelection)characterSelection).getFirstElement();
309 TermNode ratioToNode = (TermNode)((TreeSelection)structureTreeSelection).getFirstElement();
310 if (character == null){
311 return;
312 }
313 TermDto termDto = character.getTerm();
314 TermNodeDto structure = null;
315 TermNodeDto property = null;
316 Representation structureRepresentation = null;
317 Representation propertyRepresentation = null;
318 Representation ratioToRepresentation = ratioToNode.getTerm().getRepresentation(CdmStore.getDefaultLanguage());
319 if (termDto instanceof CharacterDto){
320 CharacterDto dto = (CharacterDto)termDto;
321 dto.setRatioTo(TermNodeDto.fromNode(ratioToNode, null));
322 structure = dto.getStructure();
323 structureRepresentation = structure.getTerm().getPreferredRepresentation(CdmStore.getDefaultLanguage());
324 property = dto.getProperty();
325 propertyRepresentation = property.getTerm().getPreferredRepresentation(CdmStore.getDefaultLanguage());
326 }
327
328 String label = null;
329 String abbrevLabel = null;
330
331 if(structureRepresentation!=null && propertyRepresentation!=null){
332 if(structureRepresentation.getLabel() != null && propertyRepresentation.getLabel() != null && ratioToRepresentation.getLabel() != null){
333 label = propertyRepresentation.getLabel() + " ratio " +structureRepresentation.getLabel()+" to " +ratioToRepresentation.getLabel() ;
334 }
335 if(structureRepresentation.getAbbreviatedLabel()!=null && propertyRepresentation.getAbbreviatedLabel()!=null && ratioToRepresentation.getAbbreviatedLabel() != null){
336 abbrevLabel = propertyRepresentation.getAbbreviatedLabel() + " ratio " +structureRepresentation.getAbbreviatedLabel()+ " to " + ratioToRepresentation.getAbbreviatedLabel();
337 }
338 }
339 if(label==null){
340 //default label
341 label = property.getTerm().getRepresentation_L10n()+ " ratio " +structure.getTerm().getRepresentation_L10n()+ " to " + ratioToNode.getTerm().getLabel() ;
342 }
343 character.getTerm().getRepresentation(CdmStore.getDefaultLanguage()).setLabel(label);
344 character.getTerm().getRepresentation(CdmStore.getDefaultLanguage()).setAbbreviatedLabel(abbrevLabel);
345
346 setDirty();
347 nodesToUpdate.add(character);
348
349 refresh();
350
351 characterTreeEditorComposite.getViewer().setSelection(new StructuredSelection(character));
352 EventUtility.postEvent(WorkbenchEventConstants.REFRESH_DETAILS, true);
353 }
354 });
355
356 characterTreeEditorComposite = addFeatureTreeEditor(composite_3);
357 initFeatureTreeComposite(TermType.Character, characterTreeEditorComposite, new TermNodeDtoDragListener(characterTreeEditorComposite.getViewer()),
358 new TermTreeDtoDropAdapter(this, characterTreeEditorComposite.getViewer(), sync),
359 null);
360
361 characterTreeEditorComposite.getLabel_title().setText(Messages.CharacterEditor_CHARACTERS);
362
363 //add context menu to character viewer
364 menuService.registerContextMenu(characterTreeEditorComposite.getViewer().getControl(),
365 AppModelId.POPUPMENU_EU_ETAXONOMY_TAXEDITOR_EDITOR_POPUPMENU_CHARACTEREDITOR);
366
367 }
368
369 private TreeViewer createTreeViewer(Composite parent, TermType termType, String labelString) {
370 Composite composite = new Composite(parent, SWT.NONE);
371 composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
372 composite.setLayout(new GridLayout(2, false));
373 Label label = new Label(composite, SWT.NONE);
374 label.setText(labelString);
375 Button btnRefresh = new Button(composite, SWT.PUSH);
376 btnRefresh.setImage(ImageResources.getImage(ImageResources.REFRESH));
377 btnRefresh.setToolTipText("Refresh");
378
379
380 TreeViewer viewer = new TreeViewer(composite);
381 viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
382 viewer.setContentProvider(new TermTreeContentProvider());
383 viewer.setLabelProvider(new TermTreeLabelProvider());
384 viewer.setComparator(new TermTreeViewerComparator());
385 viewer.addSelectionChangedListener(this);
386 viewer.setInput(CdmStore.getService(ITermTreeService.class).list(termType, null, null, null, TermTreeEditor.TREE_PROPERTY_PATH));
387 btnRefresh.addSelectionListener(new SelectionAdapter() {
388
389 @Override
390 public void widgetSelected(SelectionEvent e) {
391 viewer.setInput(CdmStore.getService(ITermTreeService.class).list(termType, null, null, null, TermTreeEditor.TREE_PROPERTY_PATH));
392 refresh(viewer);
393 }
394 });
395 return viewer;
396 }
397
398 private <T extends DefinedTermBase> TermTreeDtoEditorComposite<T> addFeatureTreeEditor(Composite composite_3) {
399 TermTreeDtoEditorComposite<T> TermTreeEditorComposite = new TermTreeDtoEditorComposite<>(composite_3, SWT.NONE);
400 TermTreeEditorComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
401 return TermTreeEditorComposite;
402 }
403
404 private void initFeatureTreeComposite(
405 TermType termType,
406 TermTreeDtoEditorComposite TermTreeEditorComposite,
407 TermNodeDtoDragListener featureNodeDragListener,
408 TermTreeDtoDropAdapter featureNodeDropAdapter,
409 Transfer[] transfers) {
410
411 TermTreeEditorComposite.init(
412 featureNodeDragListener,
413 featureNodeDropAdapter,
414 transfers,
415 this,
416 new FeatureTreeChooserListener(TermTreeEditorComposite, termType),
417 this);
418 }
419
420 @Focus
421 public void focus(){
422 if(characterTreeEditorComposite!=null){
423 characterTreeEditorComposite.getViewer().getControl().setFocus();
424 }
425 if(conversation!=null && !conversation.isBound()){
426 conversation.bind();
427 }
428 if(cdmEntitySession != null) {
429 cdmEntitySession.bind();
430 }
431 }
432
433 public static Collection<Character> createCharacters(TreeSelection structureTreeSelection, TreeSelection propertyTreeSelection){
434 Set<Character> characters = new HashSet<>();
435 //get selected structures and properties
436 Iterator<TermNode<DefinedTerm>> structureIterator = structureTreeSelection.iterator();
437
438 //create all combinations of structures and properties
439 while(structureIterator.hasNext()){
440 Object o = structureIterator.next();
441 TermNode<DefinedTerm> structureNode = null;
442 if (o instanceof TermNode){
443 structureNode = (TermNode<DefinedTerm>) o;
444 }else{
445 return null;
446
447 }
448
449 Iterator<TermNode<DefinedTerm>> propertiesIterator = propertyTreeSelection.iterator();
450 while(propertiesIterator.hasNext()){
451 TermNode<DefinedTerm> propertyNode = propertiesIterator.next();
452 Representation structureRepresentation = structureNode.getTerm().getRepresentation(PreferencesUtil.getGlobalLanguage());
453 if(structureRepresentation==null){
454 structureRepresentation = structureNode.getTerm().getRepresentation(Language.DEFAULT());
455 }
456 Representation propertyRepresentation = propertyNode.getTerm().getRepresentation(PreferencesUtil.getGlobalLanguage());
457 if(propertyRepresentation==null){
458 propertyRepresentation = propertyNode.getTerm().getRepresentation(Language.DEFAULT());
459 }
460 String label = null;
461 String abbrevLabel = null;
462 if(structureRepresentation!=null && propertyRepresentation!=null){
463 if(structureRepresentation.getLabel()!=null && propertyRepresentation.getLabel()!=null){
464 label = structureRepresentation.getLabel()+" "+propertyRepresentation.getLabel();
465 }
466 if(structureRepresentation.getAbbreviatedLabel()!=null && propertyRepresentation.getAbbreviatedLabel()!=null){
467 abbrevLabel = structureRepresentation.getAbbreviatedLabel()+" "+propertyRepresentation.getAbbreviatedLabel();
468 }
469 }
470 if(label!=null){
471 //default label
472 label = structureNode.getTerm().getLabel()+" "+propertyNode.getTerm().getLabel();
473 }
474 Character character = Character.NewInstance(structureNode, propertyNode, null, label, abbrevLabel);
475 CharacterLabelBuilder labelBuilder = CharacterLabelBuilder.NewDefaultInstance();
476 character.setLabel(labelBuilder.buildLabel(character, CdmStore.getDefaultLanguage()));
477 character.setAvailableForTaxon(true);
478 character.setAvailableForOccurrence(true);
479 characters.add(character);
480
481 }
482 }
483 return characters;
484 }
485
486 @Override
487 @Persist
488 public void save(IProgressMonitor monitor){
489 if (!conversation.isBound()) {
490 conversation.bind();
491 }
492 UpdateResult result = new UpdateResult();
493 if (nodesToSave != null && this.getVocabulary() != null) {
494 result.includeResult(CdmStore.getService(ITermNodeService.class).saveNewCharacterNodeDtoMap(this.nodesToSave, this.getVocabulary().getUuid()));
495 }
496 nodesToSave.clear();
497 TermTreeDto featureTree = characterTreeEditorComposite.getFeatureTree();
498 if (operations != null && !operations.isEmpty()){
499 for (AbstractPostOperation<TermNode> operation: operations){
500 AbstractUtility.executeOperation(operation, sync);
501 }
502 operations.clear();
503 }
504
505 // TODO: implement update method for dto
506
507 result.includeResult(CdmStore.getService(ITermNodeService.class).saveCharacterNodeDtoList(this.nodesToUpdate));
508 nodesToUpdate.clear();
509 // commit the conversation and start a new transaction immediately
510 conversation.commit(true);
511 if (result.getUpdatedObjects() != null && !result.getUpdatedObjects().isEmpty()){
512 Object o = result.getUpdatedObjects().iterator().next();
513 if (o instanceof TermNode){
514 TermNode node = (TermNode)o;
515 TermTree updateTree = (TermTree)node.getGraph();
516 if (updateTree != null){
517 characterTreeEditorComposite.setSelectedTree(updateTree);
518 }
519 }
520
521 }
522
523 // initializeTrees();
524
525 dirty.setDirty(false);
526 }
527
528 private void initializeTrees() {
529 Object[] expandedElements = characterTreeEditorComposite.getViewer().getExpandedElements();
530 characterTreeEditorComposite.getViewer().getTree().removeAll();
531 characterTreeEditorComposite.getViewer().setExpandedElements(expandedElements);
532 }
533
534 @Override
535 public boolean isDirty() {
536 return dirty.isDirty();
537 }
538
539 @PreDestroy
540 public void dispose(){
541 if(conversation!=null){
542 conversation.close();
543 conversation = null;
544 }
545 if(cdmEntitySession != null) {
546 cdmEntitySession.dispose();
547 cdmEntitySession = null;
548 }
549 dirty.setDirty(false);
550 }
551
552 public boolean isVocabularySet() {
553 if(vocabulary==null){
554 MessagingUtils.warningDialog("Character creation not possible", this.getClass(), "Please select a vocabulary for the characters.");
555 }
556 return vocabulary!=null;
557 }
558
559 public boolean confirmSaveDirty(){
560 return StoreUtil.promptCheckIsDirty(this);
561 }
562
563 public TermVocabulary getVocabulary() {
564 return vocabulary;
565 }
566
567 @Override
568 public Map<Object, List<String>> getPropertyPathsMap() {
569 List<String> propertyPaths = Arrays.asList(new String[] {
570 "children", //$NON-NLS-1$
571 "feature", //$NON-NLS-1$
572 "featureTree", //$NON-NLS-1$
573 });
574 Map<Object, List<String>> propertyPathMap =
575 new HashMap<Object, List<String>>();
576 propertyPathMap.put(TermNode.class,propertyPaths);
577 return propertyPathMap;
578 }
579
580 @Override
581 public List<TermTreeDto> getRootEntities() {
582 List<TermTreeDto> root = new ArrayList<>();
583 root.add(characterTreeEditorComposite.getFeatureTree());
584 return root;
585 }
586
587 @Override
588 public ICdmEntitySession getCdmEntitySession() {
589 return cdmEntitySession;
590 }
591
592
593 @Focus
594 public void setFocus() {
595 if(conversation!=null && !conversation.isBound()){
596 conversation.bind();
597 }
598 }
599
600 @Override
601 public void selectionChanged(SelectionChangedEvent event) {
602 //propagate selection
603 selService.setSelection(event.getSelection());
604 ISelection selStructure = null;
605 ISelection selProperty = null;
606 selStructure = structureViewer.getSelection();
607 selProperty = propertyViewer.getSelection();
608
609 if (selStructure != null && selProperty != null && selStructure instanceof TreeSelection && selProperty instanceof TreeSelection && ((TreeSelection)selStructure).getFirstElement() instanceof TermNode && ((TreeSelection)selProperty).getFirstElement() instanceof TermNode && this.vocabulary != null) {
610 btnAddCharacter.setEnabled(true);
611 }else {
612 btnAddCharacter.setEnabled(false);
613 }
614 ISelection selCharacter = this.characterTreeEditorComposite.getViewer().getSelection();
615 if (selStructure != null && selCharacter != null && selStructure instanceof TreeSelection && selCharacter instanceof TreeSelection && ((TreeSelection)selStructure).getFirstElement() instanceof TermNode && ((TreeSelection)selCharacter).getFirstElement() instanceof CharacterNodeDto) {
616 btnAddRatioTo.setEnabled(true);
617 }else {
618 btnAddRatioTo.setEnabled(false);
619 }
620 }
621
622
623 @Override
624 public void modifyText(ModifyEvent e) {
625 characterTreeEditorComposite.getFeatureTree().setTitleCache(((Text) e.widget).getText());
626 setDirty();
627 }
628
629
630
631 @Override
632 public void setDirty() {
633 dirty.setDirty(true);
634 }
635
636 @Override
637 public IStructuredSelection getSelection() {
638 return (IStructuredSelection) characterTreeEditorComposite.getViewer().getSelection();
639 }
640
641
642 @Override
643 public TermType getTermType() {
644 return TermType.Character;
645 }
646
647 public TermTreeDto getCharacterTree(){
648 return characterTreeEditorComposite.getFeatureTree();
649 }
650
651
652 public void refresh(TreeViewer viewer){
653 viewer.refresh();
654
655 characterTreeEditorComposite.getViewer().setInput(characterTreeEditorComposite.getViewer().getInput());
656 }
657
658 private class FeatureTreeChooserListener extends SelectionAdapter{
659 private TermTreeDtoEditorComposite<Feature> TermTreeEditorComposite;
660 private TermType termType;
661
662 public FeatureTreeChooserListener(TermTreeDtoEditorComposite<Feature> TermTreeEditorComposite, TermType termType) {
663 super();
664 this.TermTreeEditorComposite = TermTreeEditorComposite;
665 this.termType = termType;
666 }
667
668 @Override
669 public void widgetSelected(SelectionEvent e) {
670 TermTree tree = FeatureTreeSelectionDialog.select(TermTreeEditorComposite.getDisplay().getActiveShell(), null, termType);
671 if(tree!=null){
672 cdmEntitySession.load(tree, true);
673 TermTreeEditorComposite.setSelectedTree(tree);
674 }
675 }
676 }
677
678 @Override
679 public void update(CdmDataChangeMap arg0) {
680 }
681
682 @Override
683 public ConversationHolder getConversationHolder() {
684 return conversation;
685 }
686
687 @Override
688 public void changed(Object element) {
689 setDirty();
690 characterTreeEditorComposite.getViewer().refresh();
691 }
692
693 @Override
694 public void forceDirty() {
695 setDirty();
696 }
697
698 @Override
699 public boolean postOperation(Object objectAffectedByOperation) {
700 characterTreeEditorComposite.getViewer().refresh();
701 if(objectAffectedByOperation instanceof TermNode){
702 StructuredSelection selection = new StructuredSelection(objectAffectedByOperation);
703 characterTreeEditorComposite.getViewer().setSelection(selection);
704 }
705 return true;
706 }
707
708 @Override
709 public boolean onComplete() {
710 return false;
711 }
712
713 @Override
714 public void refresh() {
715 structureViewer.refresh();
716 propertyViewer.refresh();
717 characterTreeEditorComposite.refresh();
718
719 }
720
721 @Override
722 public TermNodeDto getNodeDtoForUuid(UUID nodeUuid){
723 return (TermNodeDto)this.characterTreeEditorComposite.getNodeUuidMap().get(nodeUuid);
724
725 }
726
727 @Override
728 public void addOperation(AbstractPostOperation operation) {
729 operations.add(operation);
730
731 }
732
733 @Inject
734 @Optional
735 private void addSaveCandidate(@UIEventTopic(WorkbenchEventConstants.ADD_SAVE_CHARACTER) CharacterNodeDto characterNodeDto) {
736
737 if (characterNodeDto != null){
738 if (nodesToUpdate.contains(characterNodeDto)){
739 nodesToUpdate.remove(characterNodeDto);
740 }
741 nodesToUpdate.add(characterNodeDto);
742 }
743
744 }
745
746 @Override
747 public TreeViewer getViewer() {
748 return this.characterTreeEditorComposite.getViewer();
749 }
750
751 @Override
752 public TermTreeDto getTreeDtoForUuid(UUID treeUuid) {
753 if (this.characterTreeEditorComposite.getFeatureTree().getUuid().equals(treeUuid)){
754 return this.characterTreeEditorComposite.getFeatureTree();
755 }
756 return null;
757 }
758
759 @Override
760 public boolean checkDuplicates(UUID termUuid, UUID treeUuid) {
761 for (TermDto dto: characterTreeEditorComposite.getFeatureTree().getTerms()){
762 if (dto != null && dto.getUuid().equals(termUuid)){
763 return true;
764 }
765 }
766 return false;
767 }
768
769 @Override
770 public void setNodeDtoForUuid(TermNodeDto node) {
771 // TODO Auto-generated method stub
772
773 }
774
775 @Override
776 public void setTreeDtoForUuid(TermTreeDto tree) {
777 // TODO Auto-generated method stub
778
779 }
780
781
782
783
784 }