Moved all logging and dialog functionality to the new class MessagingUtils.
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / dialog / selection / AbstractFilteredCdmEnumSelectionDialog.java
1 //$Id$
2
3 package eu.etaxonomy.taxeditor.ui.dialog.selection;
4
5 import java.lang.reflect.Field;
6 import java.text.Collator;
7 import java.util.Comparator;
8 import java.util.List;
9
10 import org.eclipse.core.runtime.CoreException;
11 import org.eclipse.core.runtime.IProgressMonitor;
12 import org.eclipse.core.runtime.IStatus;
13 import org.eclipse.core.runtime.OperationCanceledException;
14 import org.eclipse.core.runtime.Status;
15 import org.eclipse.jface.dialogs.IDialogSettings;
16 import org.eclipse.jface.viewers.ILabelProvider;
17 import org.eclipse.jface.viewers.LabelProvider;
18 import org.eclipse.jface.window.Window;
19 import org.eclipse.jface.wizard.WizardDialog;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.SelectionAdapter;
22 import org.eclipse.swt.events.SelectionEvent;
23 import org.eclipse.swt.events.SelectionListener;
24 import org.eclipse.swt.widgets.Composite;
25 import org.eclipse.swt.widgets.Control;
26 import org.eclipse.swt.widgets.Link;
27 import org.eclipse.swt.widgets.Shell;
28 import org.eclipse.swt.widgets.Text;
29 import org.eclipse.ui.IMemento;
30 import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
31
32 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
33 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
34 import eu.etaxonomy.cdm.model.common.IEnumTerm;
35 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
36 import eu.etaxonomy.taxeditor.model.MessagingUtils;
37 import eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard;
38 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
39
40 /**
41 * <p>Abstract AbstractFilteredCdmEnumSelectionDialog class.</p>
42 *
43 * @author c.mathew
44 * @created 18.07.2013
45 * @version 1.0
46 */
47 public abstract class AbstractFilteredCdmEnumSelectionDialog<T extends IEnumTerm> extends
48 FilteredItemsSelectionDialog implements IConversationEnabled {
49
50 private ConversationHolder conversation;
51
52 protected List<T> model;
53 private String settings;
54
55
56
57 /**
58 * <p>Constructor for AbstractFilteredCdmResourceSelectionDialog.</p>
59 *
60 * @param shell a {@link org.eclipse.swt.widgets.Shell} object.
61 * @param conversation
62 * @param title a {@link java.lang.String} object.
63 * @param multi a boolean.
64 * @param settings a {@link java.lang.String} object.
65 * @param cdmEnum a T object.
66 * @param <T> a T object.
67 */
68 protected AbstractFilteredCdmEnumSelectionDialog(Shell shell,
69 ConversationHolder conversation,
70 String title,
71 boolean multi,
72 String settings,
73 T cdmEnum) {
74 super(shell, multi);
75 setTitle(title);
76 setMessage("Use * for wildcard, or ? to see all entries");
77 this.settings = settings;
78
79 this.conversation = conversation;
80
81 init();
82
83 initModel();
84
85 String objectTitle = getTitle(cdmEnum);
86 if (objectTitle != null) {
87 setInitialPattern(objectTitle);
88 }
89
90 setListLabelProvider(createListLabelProvider());
91 setDetailsLabelProvider(createDetailsLabelProvider());
92
93 setSelectionHistory(new ResourceSelectionHistory());
94 }
95
96 /**
97 * By default, we are returning the standard list label provider
98 *
99 * Override in subclasses if you want different behavior
100 *
101 * @return
102 */
103 protected ILabelProvider createDetailsLabelProvider() {
104 return createListLabelProvider();
105 }
106
107 /**
108 *
109 * @return
110 */
111 protected ILabelProvider createListLabelProvider() {
112 return new FilteredCdmResourceLabelProvider();
113 }
114
115 /**
116 * Override in subclasses.
117 * Will run before initModel()
118 */
119 protected void init() {
120
121 }
122
123 /**
124 * <p>getSelectionFromDialog</p>
125 *
126 * @param dialog a {@link eu.etaxonomy.taxeditor.ui.dialog.selection.AbstractFilteredCdmResourceSelectionDialog} object.
127 * @param <TYPE> a TYPE object.
128 * @return a TYPE object.
129 */
130 protected static <TYPE extends IEnumTerm> TYPE getSelectionFromDialog(AbstractFilteredCdmEnumSelectionDialog<TYPE> dialog) {
131
132 int result = dialog.open();
133
134 if (result == Window.CANCEL) {
135 return null;
136 }
137
138 return dialog.getSelectedEnumTerm();
139 }
140
141
142 /**
143 * <p>getTitle</p>
144 *
145 * @param cdmObject a T object.
146 * @return a {@link java.lang.String} object.
147 */
148 protected String getTitle(T cdmEnum) {
149 return cdmEnum.getMessage();
150 }
151
152
153 /** {@inheritDoc} */
154 @Override
155 public void refresh() {
156 initModel();
157 super.refresh();
158 }
159
160 /**
161 * <p>initModel</p>
162 */
163 abstract protected void initModel();
164
165 /* (non-Javadoc)
166 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createFilter()
167 */
168 /** {@inheritDoc} */
169 @Override
170 protected ItemsFilter createFilter() {
171 return new ItemsFilter() {
172
173 /**
174 * Always returns false to enforce refiltering even if the pattern is equal
175 */
176 @Override
177 public boolean equalsFilter(ItemsFilter filter) {
178 return false;
179 }
180
181 @Override
182 public boolean isConsistentItem(Object item) {
183 return false;
184 }
185
186 @Override
187 public boolean matchItem(Object item) {
188 String text = null;
189 if(item instanceof IEnumTerm){
190 text = ((IEnumTerm) item).getMessage();
191 }else if(item instanceof String){
192 text = (String) item;
193 }
194 return text != null ? matches(text) : false;
195 }
196
197 };
198 }
199
200
201 /**
202 * Set the filter input to the Agent's title cache
203 *
204 * @param cdmObject a T object.
205 */
206 protected void setPattern(T cdmObject) {
207 // FilteredSelection does some very tricky caching to make sure it
208 // runs with high performance.
209 // This works for most use cases, but we want to change the model while the dialog is open
210 // and all the clever caching prevents the content provider from knowing that the model has changed
211 // I am aware, that this is a hack, but the FilteredSelectionDialog API does not offer a convenient
212 // way to solve the problem.
213 try {
214 Field lastCompletedFilter = this.getClass().getSuperclass().getSuperclass().getDeclaredField("lastCompletedFilter");
215 lastCompletedFilter.setAccessible(true);
216 lastCompletedFilter.set(this, null);
217 } catch (SecurityException e) {
218 MessagingUtils.error(getClass(), e);
219 } catch (NoSuchFieldException e) {
220 MessagingUtils.error(getClass(), e);
221 } catch (IllegalArgumentException e) {
222 MessagingUtils.error(getClass(), e);
223 } catch (IllegalAccessException e) {
224 MessagingUtils.error(getClass(), e);
225 }
226
227 // this also is not the nicest way to do it.
228 // I am still amazed, that FilteredSelectionDialog does not offer any methods to change its data
229 // once it was opened. Am I doing it wrong?
230 String pattern = getTitle(cdmObject);
231 ((Text) getPatternControl()).setText(pattern);
232 }
233
234 /* (non-Javadoc)
235 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#fillContentProvider(org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.AbstractContentProvider, org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter, org.eclipse.core.runtime.IProgressMonitor)
236 */
237 /** {@inheritDoc} */
238 @Override
239 protected void fillContentProvider(AbstractContentProvider contentProvider,
240 ItemsFilter itemsFilter, IProgressMonitor progressMonitor)
241 throws CoreException {
242 try {
243 if(model != null){
244 progressMonitor.beginTask("Looking for entities", model.size());
245 for(T element : model){
246 contentProvider.add(element, itemsFilter);
247 if (progressMonitor.isCanceled()) {
248 throw new OperationCanceledException();
249 }
250 progressMonitor.worked(1);
251 }
252 }else{
253 MessagingUtils.warn(getClass(), "Model for Filtered Selection is null:" + this.getClass().getSimpleName());
254 }
255 }
256 finally {
257 progressMonitor.done();
258 }
259 }
260
261 /* (non-Javadoc)
262 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getDialogSettings()
263 */
264 /** {@inheritDoc} */
265 @Override
266 protected IDialogSettings getDialogSettings() {
267 IDialogSettings settings = TaxeditorStorePlugin.getDefault().getDialogSettings().getSection(getSettings());
268
269 if (settings == null) {
270 settings = TaxeditorStorePlugin.getDefault().getDialogSettings().addNewSection(getSettings());
271 }
272 return settings;
273 }
274
275 /* (non-Javadoc)
276 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getElementName(java.lang.Object)
277 */
278 /** {@inheritDoc} */
279 @Override
280 public String getElementName(Object item) {
281 return ((IEnumTerm) item).getMessage();
282 }
283
284 /* (non-Javadoc)
285 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getItemsComparator()
286 */
287 /** {@inheritDoc} */
288 @Override
289 protected Comparator getItemsComparator() {
290 return new Comparator<IEnumTerm>() {
291 public int compare(IEnumTerm entity1,
292 IEnumTerm entity2) {
293 Collator collator = Collator.getInstance();
294 return collator.compare(entity1.getMessage(), entity2.getMessage());
295 }
296 };
297 }
298
299 /* (non-Javadoc)
300 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#validateItem(java.lang.Object)
301 */
302 /** {@inheritDoc} */
303 @Override
304 protected IStatus validateItem(Object item) {
305 return Status.OK_STATUS;
306 }
307
308 /**
309 * <p>getSelectedUuidAndTitleCache</p>
310 *
311 * @return a {@link eu.etaxonomy.cdm.model.common.UuidAndTitleCache} object.
312 */
313 protected T getSelectedEnumTerm() {
314 Object[] result = getResult();
315 return result[0] == null ? null : (T) result[0];
316 }
317
318 /**
319 * <p>Getter for the field <code>settings</code>.</p>
320 *
321 * @return a {@link java.lang.String} object.
322 */
323 public String getSettings() {
324 if(settings == null){
325 throw new IllegalStateException("No SETTINGS set.");
326 }
327 return settings;
328 }
329
330 /**
331 *
332 * @author n.hoffmann
333 * @created Oct 19, 2009
334 * @version 1.0
335 */
336 private class ResourceSelectionHistory extends SelectionHistory {
337 /*
338 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#restoreItemFromMemento(org.eclipse.ui.IMemento)
339 */
340 protected Object restoreItemFromMemento(IMemento element) {
341 return element.getString("resource"); //$NON-NLS-1$
342 }
343 /*
344 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#storeItemToMemento(java.lang.Object,
345 * org.eclipse.ui.IMemento)
346 */
347 protected void storeItemToMemento(Object item, IMemento element) {
348 element.putString("resource", item.toString()); //$NON-NLS-1$
349 }
350 }
351
352 /**
353 * <p>getNewWizardLinkText</p>
354 *
355 * @return a {@link java.lang.String} object.
356 */
357 protected abstract String getNewWizardLinkText();
358
359 /**
360 * <p>getNewEntityWizard</p>
361 * @param parameter
362 * @return a {@link eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard} object.
363 */
364 protected abstract AbstractNewEntityWizard getNewEntityWizard(String parameter);
365
366 public class FilteredCdmResourceLabelProvider extends LabelProvider {
367 public String getText(Object element) {
368 if (element == null) {
369 return null;
370 }
371 return ((IEnumTerm) element).getMessage();
372 }
373 };
374
375 /* (non-Javadoc)
376 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createExtendedContentArea(org.eclipse.swt.widgets.Composite)
377 */
378 /** {@inheritDoc} */
379 @Override
380 protected Control createExtendedContentArea(Composite parent) {
381 if(getNewWizardLinkText() != null){
382 Link link = new Link(parent, SWT.NONE);
383 link.setText(getNewWizardLinkText());
384 link.addSelectionListener(getNewWizardLinkSelectionListener());
385 return link;
386 }
387 return null;
388 }
389
390 protected SelectionListener getNewWizardLinkSelectionListener(){
391 return new SelectionAdapter() {
392
393 /* (non-Javadoc)
394 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
395 */
396 @Override
397 public void widgetSelected(SelectionEvent e) {
398
399 AbstractNewEntityWizard wizard = getNewEntityWizard(e.text);
400 wizard.init(null, null);
401 WizardDialog dialog = new WizardDialog(getShell(), wizard);
402 int status = dialog.open();
403
404 if (status == IStatus.OK) {
405
406 T entity = (T) wizard.getEntity();
407
408 refresh();
409 setPattern(entity);
410 getConversationHolder().bind();
411 }
412 }
413 };
414 }
415
416 /**
417 * <p>getConversationHolder</p>
418 *
419 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
420 */
421 public ConversationHolder getConversationHolder() {
422 return conversation;
423 }
424
425 /** {@inheritDoc} */
426 public void update(CdmDataChangeMap changeEvents) {}
427
428 }