Project

General

Profile

Download (15.3 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2007 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

    
11
package eu.etaxonomy.taxeditor.ui.dialog.selection;
12

    
13
import java.lang.reflect.Field;
14
import java.text.Collator;
15
import java.util.Comparator;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Set;
19
import java.util.UUID;
20

    
21
import org.eclipse.core.runtime.CoreException;
22
import org.eclipse.core.runtime.IProgressMonitor;
23
import org.eclipse.core.runtime.IStatus;
24
import org.eclipse.core.runtime.OperationCanceledException;
25
import org.eclipse.core.runtime.Status;
26
import org.eclipse.jface.dialogs.IDialogSettings;
27
import org.eclipse.jface.viewers.ILabelProvider;
28
import org.eclipse.jface.viewers.LabelProvider;
29
import org.eclipse.jface.window.Window;
30
import org.eclipse.jface.wizard.WizardDialog;
31
import org.eclipse.swt.SWT;
32
import org.eclipse.swt.events.SelectionAdapter;
33
import org.eclipse.swt.events.SelectionEvent;
34
import org.eclipse.swt.events.SelectionListener;
35
import org.eclipse.swt.widgets.Composite;
36
import org.eclipse.swt.widgets.Control;
37
import org.eclipse.swt.widgets.Link;
38
import org.eclipse.swt.widgets.Shell;
39
import org.eclipse.swt.widgets.Text;
40
import org.eclipse.ui.IMemento;
41
import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
42

    
43
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
44
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
45
import eu.etaxonomy.cdm.model.common.CdmBase;
46
import eu.etaxonomy.cdm.model.common.ICdmBase;
47
import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
48
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
49
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
50
import eu.etaxonomy.taxeditor.model.MessagingUtils;
51
import eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard;
52
import eu.etaxonomy.taxeditor.preference.IPreferenceKeys;
53
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
54
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
55

    
56
/**
57
 * <p>Abstract AbstractFilteredCdmResourceSelectionDialog class.</p>
58
 *
59
 * @author n.hoffmann
60
 * @created 04.06.2009
61
 * @version 1.0
62
 */
63
public abstract class AbstractFilteredCdmResourceSelectionDialog<T extends ICdmBase> extends
64
		FilteredItemsSelectionDialog implements IConversationEnabled {
65

    
66
	private final ConversationHolder conversation;
67

    
68
	protected List<UuidAndTitleCache<T>> model;
69
	private final Set<T> transientCdmObjects = new HashSet<T>();
70
	private final String settings;
71

    
72
	protected T cdmBaseToBeFiltered;
73

    
74

    
75
	/**
76
	 * <p>Constructor for AbstractFilteredCdmResourceSelectionDialog.</p>
77
	 *
78
	 * @param shell a {@link org.eclipse.swt.widgets.Shell} object.
79
	 * @param conversation
80
	 * @param title a {@link java.lang.String} object.
81
	 * @param multi a boolean.
82
	 * @param settings a {@link java.lang.String} object.
83
	 * @param cdmObject a T object.
84
	 * @param <T> a T object.
85
	 */
86
	protected AbstractFilteredCdmResourceSelectionDialog(Shell shell, ConversationHolder conversation, String title, boolean multi, String settings, T cdmObject) {
87
		super(shell, multi);
88
		setTitle(title);
89
		setMessage("Use * for wildcard, or ? to see all entries");
90
		this.settings = settings;
91

    
92
		this.conversation = conversation;
93

    
94
		init();
95

    
96
		initModel();
97

    
98
		String objectTitle = getTitle(cdmObject);
99
		if (objectTitle != null) {
100
			setInitialPattern(objectTitle);
101
		}
102

    
103
		setListLabelProvider(createListLabelProvider());
104
		setDetailsLabelProvider(createDetailsLabelProvider());
105

    
106
		setSelectionHistory(new ResourceSelectionHistory());
107
	}
108

    
109
	/**
110
	 * By default, we are returning the standard list label provider
111
	 *
112
	 * Override in subclasses if you want different behavior
113
	 *
114
	 * @return
115
	 */
116
	protected ILabelProvider createDetailsLabelProvider() {
117
		return createListLabelProvider();
118
	}
119

    
120
	/**
121
	 *
122
	 * @return
123
	 */
124
	protected ILabelProvider createListLabelProvider() {
125
		return new FilteredCdmResourceLabelProvider();
126
	}
127

    
128
	/**
129
	 * Override in subclasses.
130
	 * Will run before initModel()
131
	 */
132
	protected void init() {
133

    
134
	}
135

    
136
	/**
137
	 * <p>getSelectionFromDialog</p>
138
	 *
139
	 * @param dialog a {@link eu.etaxonomy.taxeditor.ui.dialog.selection.AbstractFilteredCdmResourceSelectionDialog} object.
140
	 * @param <TYPE> a TYPE object.
141
	 * @return a TYPE object.
142
	 */
143
	protected static <TYPE extends CdmBase> TYPE getSelectionFromDialog(AbstractFilteredCdmResourceSelectionDialog<TYPE> dialog) {
144
		//dialog.setInitialPattern("");
145
		int result = dialog.open();
146

    
147
		if (result == Window.CANCEL) {
148
			return null;
149
		}
150

    
151
		UUID uuid = dialog.getSelectedUuidAndTitleCache().getUuid();
152
		if(uuid == null){
153
			return null;
154
		}
155
		return dialog.getCdmObjectByUuid(uuid);
156
	}
157

    
158
	/**
159
	 * Check if object was created during the life of this dialog. If not,
160
	 * retrieve it from the CdmStore.
161
	 *
162
	 * @param cdmUuid a {@link java.util.UUID} object.
163
	 * @return a T object.
164
	 */
165
	protected T getCdmObjectByUuid(UUID cdmUuid) {
166
		for (T cdmObject : transientCdmObjects) {
167
			if (cdmObject.getUuid().equals(cdmUuid)) {
168
				return cdmObject;
169
			}
170
		}
171
		return getPersistentObject(cdmUuid);
172
	}
173

    
174
	/**
175
	 * <p>getPersistentObject</p>
176
	 *
177
	 * @param uuid a {@link java.util.UUID} object.
178
	 * @return a T object.
179
	 */
180
	abstract protected T getPersistentObject(UUID uuid);
181

    
182
	/**
183
	 * @param cdmObject
184
	 */
185
//	protected void addObjectToModel(T cdmObject) {
186
//		model.add(new UuidAndTitleCache(cdmObject.getClass(), cdmObject.getUuid(), getTitle(cdmObject)));
187
//		transientCdmObjects.add(cdmObject);
188
//	}
189

    
190
	/**
191
	 * <p>isObjectTransient</p>
192
	 *
193
	 * @param cdmObject a T object.
194
	 * @return a boolean.
195
	 */
196
	protected boolean isObjectTransient(T cdmObject) {
197
		return (getPersistentObject(cdmObject.getUuid()) == null);
198
	}
199

    
200
	/**
201
	 * <p>getTitle</p>
202
	 *
203
	 * @param cdmObject a T object.
204
	 * @return a {@link java.lang.String} object.
205
	 */
206
	protected String getTitle(T cdmObject) {
207
		if(cdmObject == null){
208
			return "";
209
		}
210

    
211
		if (cdmObject instanceof IIdentifiableEntity) {
212
			return ((IIdentifiableEntity) cdmObject).getTitleCache();
213
		}
214

    
215
		throw new IllegalArgumentException("Generic method only" +
216
				" supports cdmObject of type IIdentifiableEntity." +
217
				" Please implement specific method in subclass.");
218
	}
219

    
220

    
221
	/** {@inheritDoc} */
222
	@Override
223
	public void refresh() {
224
		//initModel();
225
		filterExcludedObjects();
226
		super.refresh();
227
	}
228

    
229
	/**
230
	 * <p>initModel</p>
231
	 */
232
	abstract protected void initModel();
233

    
234
	/* (non-Javadoc)
235
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createFilter()
236
	 */
237
	/** {@inheritDoc} */
238
	@Override
239
	protected ItemsFilter createFilter() {
240
		return new ItemsFilter() {
241

    
242
			/**
243
			 * Always returns false to enforce refiltering even if the pattern is equal
244
			 */
245
			@Override
246
			public boolean equalsFilter(ItemsFilter filter) {
247
				return false;
248
			}
249

    
250
			@Override
251
			public boolean isConsistentItem(Object item) {
252
				return false;
253
			}
254

    
255
			@Override
256
			public boolean matchItem(Object item) {
257
				String text = null;
258
				if(item instanceof UuidAndTitleCache){
259
					text = ((UuidAndTitleCache) item).getTitleCache();
260
				}else if(item instanceof String){
261
					text = (String) item;
262
				}
263
				return text != null ? matches(text) : false;
264
			}
265

    
266
		};
267
	}
268

    
269

    
270
	/**
271
	 * Set the filter input to the Agent's title cache
272
	 *
273
	 * @param cdmObject a T object.
274
	 */
275
	protected void setPattern(T cdmObject) {
276
		// FilteredSelection does some very tricky caching to make sure it
277
		// runs with high performance.
278
		// This works for most use cases, but we want to change the model while the dialog is open
279
		// and all the clever caching prevents the content provider from knowing that the model has changed
280
		// I am aware, that this is a hack, but the FilteredSelectionDialog API does not offer a convenient
281
		// way to solve the problem.
282
		try {
283
			Field lastCompletedFilter = this.getClass().getSuperclass().getSuperclass().getDeclaredField("lastCompletedFilter");
284
			lastCompletedFilter.setAccessible(true);
285
			lastCompletedFilter.set(this, null);
286
		} catch (SecurityException e) {
287
			MessagingUtils.error(getClass(), e);
288
		} catch (NoSuchFieldException e) {
289
			MessagingUtils.error(getClass(), e);
290
		} catch (IllegalArgumentException e) {
291
			MessagingUtils.error(getClass(), e);
292
		} catch (IllegalAccessException e) {
293
			MessagingUtils.error(getClass(), e);
294
		}
295

    
296
		// this also is not the nicest way to do it.
297
		// I am still amazed, that FilteredSelectionDialog does not offer any methods to change its data
298
		// once it was opened. Am I doing it wrong?
299
		String pattern = getTitle(cdmObject);
300
		((Text) getPatternControl()).setText(pattern);
301
	}
302

    
303
	/* (non-Javadoc)
304
	* @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#fillContentProvider(org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.AbstractContentProvider, org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter, org.eclipse.core.runtime.IProgressMonitor)
305
	*/
306
	/** {@inheritDoc} */
307
	@Override
308
	protected void fillContentProvider(AbstractContentProvider contentProvider,
309
		ItemsFilter itemsFilter, IProgressMonitor progressMonitor)
310
		throws CoreException {
311
		try {
312
			if(model != null){
313
				progressMonitor.beginTask("Looking for entities", model.size());
314
				for(UuidAndTitleCache<T> element : model){
315
					contentProvider.add(element, itemsFilter);
316
					if (progressMonitor.isCanceled()) {
317
						throw new OperationCanceledException();
318
					}
319
					progressMonitor.worked(1);
320
				}
321
			}else{
322
				MessagingUtils.warn(getClass(), "Model for Filtered Selection is null:" + this.getClass().getSimpleName());
323
			}
324
		}
325
		finally {
326
			progressMonitor.done();
327
		}
328
	}
329

    
330
	/* (non-Javadoc)
331
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getDialogSettings()
332
	 */
333
	/** {@inheritDoc} */
334
	@Override
335
	protected IDialogSettings getDialogSettings() {
336
		IDialogSettings settings = TaxeditorStorePlugin.getDefault().getDialogSettings().getSection(getSettings());
337

    
338
		if (settings == null) {
339
			settings = TaxeditorStorePlugin.getDefault().getDialogSettings().addNewSection(getSettings());
340
		}
341
		return settings;
342
	}
343

    
344
	/* (non-Javadoc)
345
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getElementName(java.lang.Object)
346
	 */
347
	/** {@inheritDoc} */
348
	@Override
349
	public String getElementName(Object item) {
350
		return ((UuidAndTitleCache) item).getTitleCache();
351
	}
352

    
353
	/* (non-Javadoc)
354
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getItemsComparator()
355
	 */
356
	/** {@inheritDoc} */
357
	@Override
358
	protected Comparator getItemsComparator() {
359
		return new Comparator<UuidAndTitleCache>() {
360
			@Override
361
			public int compare(UuidAndTitleCache entity1,
362
					UuidAndTitleCache entity2) {
363
				Collator collator = Collator.getInstance();
364
				return collator.compare(entity1.getTitleCache(), entity2.getTitleCache());
365
			}
366
		};
367
	}
368

    
369
	/* (non-Javadoc)
370
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#validateItem(java.lang.Object)
371
	 */
372
	/** {@inheritDoc} */
373
	@Override
374
	protected IStatus validateItem(Object item) {
375
		return Status.OK_STATUS;
376
	}
377

    
378
	/**
379
	 * <p>getSelectedUuidAndTitleCache</p>
380
	 *
381
	 * @return a {@link eu.etaxonomy.cdm.model.common.UuidAndTitleCache} object.
382
	 */
383
	protected UuidAndTitleCache getSelectedUuidAndTitleCache() {
384
		Object[] result = getResult();
385
		return result[0] == null ? null : (UuidAndTitleCache) result[0];
386
	}
387

    
388
	/**
389
	 * <p>Getter for the field <code>settings</code>.</p>
390
	 *
391
	 * @return a {@link java.lang.String} object.
392
	 */
393
	public String getSettings()  {
394
		if(settings == null){
395
			throw new IllegalStateException("No SETTINGS set.");
396
		}
397
		return settings;
398
	}
399

    
400
	/**
401
	 *
402
	 * @author n.hoffmann
403
	 * @created Oct 19, 2009
404
	 * @version 1.0
405
	 */
406
	private class ResourceSelectionHistory extends SelectionHistory {
407
	    /*
408
	    * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#restoreItemFromMemento(org.eclipse.ui.IMemento)
409
	   	*/
410
		@Override
411
		protected Object restoreItemFromMemento(IMemento element) {
412
			return element.getString("resource"); //$NON-NLS-1$
413
	  	}
414
	  	/*
415
	  	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#storeItemToMemento(java.lang.Object,
416
	  	 *      org.eclipse.ui.IMemento)
417
	  	 */
418
		@Override
419
		protected void storeItemToMemento(Object item, IMemento element) {
420
			element.putString("resource", item.toString()); //$NON-NLS-1$
421
		}
422
	}
423

    
424
	/**
425
	 * <p>getNewWizardLinkText</p>
426
	 *
427
	 * @return a {@link java.lang.String} object.
428
	 */
429
	protected abstract String getNewWizardLinkText();
430

    
431
	/**
432
	 * <p>getNewEntityWizard</p>
433
	 * @param parameter
434
	 * @return a {@link eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard} object.
435
	 */
436
	protected abstract AbstractNewEntityWizard getNewEntityWizard(String parameter);
437

    
438
	public class FilteredCdmResourceLabelProvider extends LabelProvider {
439
		@Override
440
		public String getText(Object element) {
441
			if (element == null) {
442
				return null;
443
			}
444
			UuidAndTitleCache uuidAndTitleCache = (UuidAndTitleCache) element;
445
			String titleCache = uuidAndTitleCache.getTitleCache();
446
			if(PreferencesUtil.getPreferenceStore().getBoolean(IPreferenceKeys.SHOW_ID_IN_ENTITY_SELECTION_DIAOLOG)){
447
			    titleCache += " ["+uuidAndTitleCache.getId()+"]";
448
			}
449
            return titleCache;
450
		}
451
	};
452

    
453
	/* (non-Javadoc)
454
	* @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createExtendedContentArea(org.eclipse.swt.widgets.Composite)
455
	*/
456
	/** {@inheritDoc} */
457
	@Override
458
	protected Control createExtendedContentArea(Composite parent) {
459
		String newWizardLinkText = getNewWizardLinkText();
460
        if(newWizardLinkText != null){
461
			Link link = new Link(parent, SWT.NONE);
462
			link.setText(newWizardLinkText);
463
			link.addSelectionListener(getNewWizardLinkSelectionListener());
464
			return link;
465
		}
466
		return null;
467
	}
468

    
469
	protected SelectionListener getNewWizardLinkSelectionListener(){
470
		return new SelectionAdapter() {
471

    
472
			/* (non-Javadoc)
473
			 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
474
			 */
475
			@Override
476
			public void widgetSelected(SelectionEvent e) {
477

    
478
				AbstractNewEntityWizard wizard = getNewEntityWizard(e.text);
479

    
480
				wizard.init(null, null);
481
				if(wizard.getEntity() != null) {
482
					WizardDialog dialog = new WizardDialog(getShell(), wizard);
483
					int status = dialog.open();
484

    
485
					if (status == IStatus.OK) {
486

    
487
						T entity = (T) wizard.getEntity();
488
						model.add(new UuidAndTitleCache<T>(entity.getUuid(),
489
						        entity.getId(),
490
						        getTitle(entity)));
491
						refresh();
492
						setPattern(entity);
493
						getConversationHolder().bind();
494
					}
495
					//FIXME : Need to make sure this is a stable fix (ticket 3822)
496
					getConversationHolder().commit();
497
				}
498
			}
499
		};
500
	}
501

    
502
	/**
503
	 * <p>getConversationHolder</p>
504
	 *
505
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
506
	 */
507
	@Override
508
	public ConversationHolder getConversationHolder() {
509
		return conversation;
510
	}
511

    
512
	/** {@inheritDoc} */
513
	@Override
514
	public void update(CdmDataChangeMap changeEvents) {}
515

    
516
	/**
517
	 * Don't want to add for example a taxon or synonym to itself
518
	 * so filter the list to remove the taxon in question
519
	 * (<code>cdmBaseToBeFiltered</code>)
520
	 * so it is not available in the filtered list.
521
	 */
522
	private void filterExcludedObjects() {
523
		if (model != null && cdmBaseToBeFiltered != null) {
524

    
525
			UuidAndTitleCache uuidAndTitleCacheToRemove = null;
526

    
527
			for (UuidAndTitleCache uuidAndTitleCache : model){
528
				if ((cdmBaseToBeFiltered.getUuid()).equals(uuidAndTitleCache.getUuid())) {
529
					uuidAndTitleCacheToRemove = uuidAndTitleCache;
530
				}
531
			}
532
			model.remove(uuidAndTitleCacheToRemove);
533
		}
534
	}
535
}
(2-2/29)