ref #8263 Cache child terms in content provider
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / editor / definedterm / e4 / DefinedTermEditorE4.java
1 /**
2 * Copyright (C) 2009 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.definedterm.e4;
10
11 import java.util.Collection;
12 import java.util.HashSet;
13 import java.util.Set;
14
15 import javax.annotation.PostConstruct;
16 import javax.annotation.PreDestroy;
17 import javax.inject.Inject;
18
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.e4.core.contexts.ContextInjectionFactory;
21 import org.eclipse.e4.core.contexts.IEclipseContext;
22 import org.eclipse.e4.ui.di.Focus;
23 import org.eclipse.e4.ui.di.Persist;
24 import org.eclipse.e4.ui.model.application.ui.MDirtyable;
25 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
26 import org.eclipse.e4.ui.services.EMenuService;
27 import org.eclipse.e4.ui.workbench.modeling.EPartService;
28 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
29 import org.eclipse.jface.util.LocalSelectionTransfer;
30 import org.eclipse.jface.viewers.ISelectionChangedListener;
31 import org.eclipse.jface.viewers.StructuredSelection;
32 import org.eclipse.jface.viewers.TreeViewer;
33 import org.eclipse.swt.SWT;
34 import org.eclipse.swt.dnd.DND;
35 import org.eclipse.swt.dnd.Transfer;
36 import org.eclipse.swt.layout.FillLayout;
37 import org.eclipse.swt.widgets.Composite;
38 import org.eclipse.swt.widgets.Tree;
39 import org.eclipse.ui.IMemento;
40
41 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
42 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
43 import eu.etaxonomy.cdm.api.service.ITermService;
44 import eu.etaxonomy.cdm.api.service.IVocabularyService;
45 import eu.etaxonomy.cdm.model.term.DefinedTermBase;
46 import eu.etaxonomy.cdm.model.term.TermBase;
47 import eu.etaxonomy.cdm.model.term.TermVocabulary;
48 import eu.etaxonomy.cdm.persistence.dto.AbstractTermDto;
49 import eu.etaxonomy.cdm.persistence.dto.TermDto;
50 import eu.etaxonomy.cdm.persistence.dto.TermVocabularyDto;
51 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
52 import eu.etaxonomy.taxeditor.editor.definedterm.DefinedTermSorter;
53 import eu.etaxonomy.taxeditor.editor.definedterm.TermDtoContentProvider;
54 import eu.etaxonomy.taxeditor.editor.definedterm.TermDtoLabelProvider;
55 import eu.etaxonomy.taxeditor.editor.definedterm.input.TermEditorInput;
56 import eu.etaxonomy.taxeditor.event.EventUtility;
57 import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
58 import eu.etaxonomy.taxeditor.model.IContextListener;
59 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
60 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
61 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
62 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
63 import eu.etaxonomy.taxeditor.store.AppModelId;
64 import eu.etaxonomy.taxeditor.store.CdmStore;
65 import eu.etaxonomy.taxeditor.ui.element.LayoutConstants;
66 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
67
68 /**
69 *
70 * @author pplitzner
71 * @since Aug 22, 2017
72 *
73 */
74 public class DefinedTermEditorE4 implements IConversationEnabled, IDirtyMarkable, IPostOperationEnabled,
75 IPartContentHasDetails, IPartContentHasSupplementalData, IE4SavablePart, IContextListener {
76
77 public static final String OPEN_COMMAND_ID = "eu.etaxonomy.taxeditor.store.openDefinedTermEditor"; //$NON-NLS-1$
78
79 protected TreeViewer viewer;
80
81 protected ConversationHolder conversation;
82
83 @Inject
84 private ESelectionService selService;
85
86 @Inject
87 private MDirtyable dirty;
88
89 private ISelectionChangedListener selectionChangedListener;
90 private final int dndOperations = DND.DROP_COPY | DND.DROP_MOVE;
91
92 private TermEditorInput input =null;
93
94 @Inject
95 private MPart thisPart;
96
97 private Set<TermBase> changedTerms = new HashSet<>();
98
99 private TermDtoContentProvider contentProvider;
100
101 @Inject
102 public DefinedTermEditorE4() {
103 CdmStore.getContextManager().addContextListener(this);
104 }
105
106 @PostConstruct
107 public void createPartControl(Composite parent, EMenuService menuService,
108 IEclipseContext context) {
109 if (CdmStore.isActive()){
110 if(conversation == null){
111 conversation = CdmStore.createConversation();
112 }
113 }
114 else{
115 return;
116 }
117 FillLayout layout = new FillLayout();
118 layout.marginHeight = 0;
119 layout.marginWidth = 0;
120 layout.type = SWT.VERTICAL;
121
122 parent.setLayout(layout);
123 viewer = new TreeViewer(new Tree(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI));
124 viewer.getControl().setLayoutData(LayoutConstants.FILL());
125 contentProvider = new TermDtoContentProvider();
126 viewer.setContentProvider(contentProvider);
127 viewer.setLabelProvider(new TermDtoLabelProvider());
128 viewer.setComparator(new DefinedTermSorter());
129
130 Transfer[] transfers = new Transfer[] { LocalSelectionTransfer.getTransfer() };
131 viewer.addDragSupport(dndOperations, transfers, new DefinedTermDragListenerE4(viewer));
132 DefinedTermDropAdapterE4 dropListener = new DefinedTermDropAdapterE4(this);
133 ContextInjectionFactory.inject(dropListener, context);
134 viewer.addDropSupport(dndOperations, transfers, dropListener);
135
136 //propagate selection
137 selectionChangedListener = (event -> selService.setSelection(event.getSelection()));
138 viewer.addSelectionChangedListener(selectionChangedListener);
139
140 //create context menu
141 menuService.registerContextMenu(viewer.getControl(), AppModelId.POPUPMENU_EU_ETAXONOMY_TAXEDITOR_STORE_POPUPMENU_TERMEDITOR);
142
143 }
144
145 @Override
146 public boolean postOperation(Object objectAffectedByOperation) {
147 input.initialiseVocabularies();
148
149 Collection<AbstractTermDto> itemsToSelect = new HashSet<>();
150
151 if(objectAffectedByOperation instanceof Collection){
152 for (Object o : (Collection<?>)objectAffectedByOperation) {
153 if(o instanceof TermVocabularyDto){
154 contentProvider.removeVocabularyFromCache((TermVocabularyDto) o);
155 viewer.refresh(o);
156 }
157 else if(o instanceof TermDto){
158 contentProvider.removeVocabularyFromCache(((TermDto) o).getVocabularyDto());
159 viewer.refresh(((TermDto) o).getVocabularyDto());
160 viewer.refresh(o);
161 itemsToSelect.add((TermDto) o);
162 }
163 }
164 }
165 if(objectAffectedByOperation instanceof TermVocabularyDto){
166 contentProvider.removeVocabularyFromCache((TermVocabularyDto) objectAffectedByOperation);
167 viewer.refresh();
168 itemsToSelect.add((AbstractTermDto) objectAffectedByOperation);
169 }
170 else if(objectAffectedByOperation instanceof TermDto){
171 TermDto termDto = (TermDto) objectAffectedByOperation;
172 itemsToSelect.add(termDto);
173 contentProvider.removeVocabularyFromCache(termDto.getVocabularyDto());
174 viewer.refresh(termDto.getVocabularyDto());
175 }
176 else{
177 viewer.refresh(objectAffectedByOperation);
178 }
179 if(!itemsToSelect.isEmpty()){
180 StructuredSelection selection = new StructuredSelection(itemsToSelect);
181 viewer.setSelection(selection);
182 for (AbstractTermDto termDto : itemsToSelect) {
183 viewer.expandToLevel(termDto, 1);
184 }
185 }
186 return true;
187 }
188
189 public void init(TermEditorInput input){
190 this.input = input;
191
192 viewer.setInput(input.getVocabularies());
193 thisPart.setLabel(input.getName());
194 }
195
196 @Override
197 @Persist
198 public void save(IProgressMonitor monitor) {
199 getConversationHolder().commit();
200 for(TermBase term:changedTerms){
201 if(term.isInstanceOf(DefinedTermBase.class)){
202 DefinedTermBase definedTermBase = (DefinedTermBase) term;
203 CdmStore.getService(ITermService.class).merge(definedTermBase);
204 viewer.refresh(TermDto.fromTerm(definedTermBase));
205 }
206 else if(term.isInstanceOf(TermVocabulary.class)){
207 TermVocabulary voc = (TermVocabulary) term;
208 CdmStore.getService(IVocabularyService.class).merge(voc);
209 viewer.refresh(new TermVocabularyDto(voc.getUuid(), voc.getRepresentations(), voc.getTermType()));
210 }
211 }
212 setDirty(false);
213 input.initialiseVocabularies();
214 changedTerms.clear();
215 EventUtility.postEvent(WorkbenchEventConstants.REFRESH_SUPPLEMENTAL, true);
216 }
217
218 @Override
219 public boolean isDirty() {
220 return dirty.isDirty();
221 }
222
223 @Focus
224 public void setFocus() {
225 if(viewer!=null && viewer.getControl() != null && !viewer.getControl().isDisposed()){
226 viewer.getControl().setFocus();
227 }
228 if(conversation!=null){
229 conversation.bind();
230 }
231 if(input!=null){
232 input.bind();
233 }
234 }
235
236 @Override
237 public void update(CdmDataChangeMap changeEvents) {
238 }
239
240 @Override
241 public ConversationHolder getConversationHolder() {
242 return conversation;
243 }
244
245 @Override
246 public void changed(Object element) {
247 if(element instanceof DefinedTermBase){
248 DefinedTermBase definedTermBase = (DefinedTermBase) element;
249 TermDto termDto = TermDto.fromTerm(definedTermBase);
250 viewer.update(termDto, null);
251 changedTerms.add(definedTermBase);
252 }
253 else if(element instanceof TermVocabulary){
254 TermVocabulary vocabulary = (TermVocabulary)element;
255 TermVocabularyDto vocabularyDto = new TermVocabularyDto(vocabulary.getUuid(), vocabulary.getRepresentations(), vocabulary.getTermType());
256 viewer.update(vocabularyDto, null);
257 changedTerms.add(vocabulary);
258 }
259 setDirty(true);
260 viewer.update(element, null);
261 }
262
263 @Override
264 public void forceDirty() {
265 changed(null);
266 }
267
268 public void setDirty(boolean dirty) {
269 this.dirty.setDirty(dirty);
270 }
271
272 @Override
273 public boolean onComplete() {
274 return false;
275 }
276
277 public TreeViewer getViewer() {
278 return viewer;
279 }
280
281 @PreDestroy
282 public void dispose() {
283 if(conversation!=null){
284 conversation.unregisterForDataStoreChanges(this);
285 conversation.close();
286 conversation = null;
287 }
288 if(input!=null){
289 input.dispose();
290 }
291 this.dirty.setDirty(false);
292 }
293
294 public TermEditorInput getDefinedTermEditorInput() {
295 return input;
296 }
297
298 @Override
299 public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
300 }
301
302 @Override
303 public void contextStop(IMemento memento, IProgressMonitor monitor) {
304 //close view when workbench closes
305 try{
306 thisPart.getContext().get(EPartService.class).hidePart(thisPart);
307 }
308 catch(Exception e){
309 //nothing
310 }
311 }
312
313 @Override
314 public void contextStart(IMemento memento, IProgressMonitor monitor) {
315 }
316
317 @Override
318 public void contextRefresh(IProgressMonitor monitor) {
319 }
320
321 @Override
322 public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
323 }
324
325 }