Project

General

Profile

Download (16.5 KB) Statistics
| Branch: | Tag: | Revision:
1
package eu.etaxonomy.taxeditor.ui.dialog.selection;
2

    
3
import java.text.Collator;
4
/**
5
* Copyright (C) 2007 EDIT
6
* European Distributed Institute of Taxonomy
7
* http://www.e-taxonomy.eu
8
*
9
* The contents of this file are subject to the Mozilla Public License Version 1.1
10
* See LICENSE.TXT at the top of this package for the full license terms.
11
*/
12
import java.util.Comparator;
13
import java.util.HashSet;
14
import java.util.Iterator;
15
import java.util.List;
16
import java.util.Set;
17
import java.util.UUID;
18

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

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

    
53
public abstract class AbstractFilteredIdentifierSelectionDialog<T extends ICdmBase> extends CdmFilteredItemsSelectionDialog implements IConversationEnabled {
54

    
55
		private final ConversationHolder conversation;
56

    
57
		protected List<IdentifiedEntityDTO> model;
58
		private final Set<T> transientCdmObjects = new HashSet<T>();
59
		private final String settings;
60
		protected final int limitOfInitialElements = 100;
61

    
62
		protected T cdmBaseToBeFiltered;
63

    
64

    
65
		/**
66
		 * <p>Constructor for AbstractFilteredCdmResourceSelectionDialog.</p>
67
		 *
68
		 * @param shell a {@link org.eclipse.swt.widgets.Shell} object.
69
		 * @param conversation
70
		 * @param title a {@link java.lang.String} object.
71
		 * @param multi a boolean.
72
		 * @param settings a {@link java.lang.String} object.
73
		 * @param cdmObject a T object.
74
		 * @param <T> a T object.
75
		 */
76
		protected AbstractFilteredIdentifierSelectionDialog(Shell shell, ConversationHolder conversation, String title, boolean multi, String settings, T cdmObject) {
77
			super(shell, multi);
78
			setTitle(title);
79
			setMessage("Use * for wildcard, or ? to see all entries");
80
			this.settings = settings;
81

    
82
			this.conversation = conversation;
83
			this.cdmBaseToBeFiltered = cdmObject;
84
			org.eclipse.swt.graphics.Cursor cursor = shell.getCursor();
85
			shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
86
			init();
87
//			initModel();
88
			shell.setCursor(cursor);
89
			String objectTitle = getTitle(cdmObject);
90
//			if (objectTitle != null) {
91
//				setInitialPattern(objectTitle);
92
//			}
93

    
94
			setListLabelProvider(createListLabelProvider());
95
			setDetailsLabelProvider(createDetailsLabelProvider());
96

    
97
			setSelectionHistory(new IdentifierSelectionHistory());
98
		}
99

    
100
		/**
101
		 * By default, we are returning the standard list label provider
102
		 *
103
		 * Override in subclasses if you want different behavior
104
		 *
105
		 * @return
106
		 */
107
		protected ILabelProvider createDetailsLabelProvider() {
108
			return createListLabelProvider();
109
		}
110

    
111
		/**
112
		 *
113
		 * @return
114
		 */
115
		protected ILabelProvider createListLabelProvider() {
116
			return new FilteredIdentifiedEntityLabelProvider();
117
		}
118

    
119
		/**
120
		 * Override in subclasses.
121
		 * Will run before initModel()
122
		 */
123
		protected void init() {
124

    
125
		}
126

    
127
		/**
128
		 * <p>getSelectionFromDialog</p>
129
		 *
130
		 * @param dialog a {@link eu.etaxonomy.taxeditor.ui.dialog.selection.AbstractFilteredCdmResourceSelectionDialog} object.
131
		 * @param <TYPE> a TYPE object.
132
		 * @return a TYPE object.
133
		 */
134
		protected static <TYPE extends CdmBase> TYPE getSelectionFromDialog(AbstractFilteredCdmResourceSelectionDialog<TYPE> dialog) {
135
			//dialog.setInitialPattern("");
136
			int result = dialog.open();
137

    
138
			if (result == Window.CANCEL) {
139
				return null;
140
			}
141

    
142
			UUID uuid = dialog.getSelectedUuidAndTitleCache().getUuid();
143
			if(uuid == null){
144
				return null;
145
			}
146
			return dialog.getCdmObjectByUuid(uuid);
147
		}
148

    
149
		/**
150
		 * Check if object was created during the life of this dialog. If not,
151
		 * retrieve it from the CdmStore.
152
		 *
153
		 * @param cdmUuid a {@link java.util.UUID} object.
154
		 * @return a T object.
155
		 */
156
		protected T getCdmObjectByUuid(UUID cdmUuid) {
157
			for (T cdmObject : transientCdmObjects) {
158
				if (cdmObject.getUuid().equals(cdmUuid)) {
159
					return cdmObject;
160
				}
161
			}
162
			return getPersistentObject(cdmUuid);
163
		}
164

    
165
		/**
166
		 * <p>getPersistentObject</p>
167
		 *
168
		 * @param uuid a {@link java.util.UUID} object.
169
		 * @return a T object.
170
		 */
171
		abstract protected T getPersistentObject(UUID uuid);
172

    
173
		/**
174
		 * @param cdmObject
175
		 */
176
//		protected void addObjectToModel(T cdmObject) {
177
//			model.add(new UuidAndTitleCache(cdmObject.getClass(), cdmObject.getUuid(), getTitle(cdmObject)));
178
//			transientCdmObjects.add(cdmObject);
179
//		}
180

    
181
		/**
182
		 * <p>isObjectTransient</p>
183
		 *
184
		 * @param cdmObject a T object.
185
		 * @return a boolean.
186
		 */
187
		protected boolean isObjectTransient(T cdmObject) {
188
			return (getPersistentObject(cdmObject.getUuid()) == null);
189
		}
190

    
191
		/**
192
		 * <p>getTitle</p>
193
		 *
194
		 * @param cdmObject a T object.
195
		 * @return a {@link java.lang.String} object.
196
		 */
197
		protected String getTitle(T cdmObject) {
198
			if(cdmObject == null){
199
				return "";
200
			}
201

    
202
			if (cdmObject instanceof IIdentifiableEntity) {
203
				return ((IIdentifiableEntity) cdmObject).getTitleCache();
204
			}
205

    
206
			throw new IllegalArgumentException("Generic method only" +
207
					" supports cdmObject of type IIdentifiableEntity." +
208
					" Please implement specific method in subclass.");
209
		}
210

    
211

    
212
		/** {@inheritDoc} */
213
		@Override
214
		public void refresh() {
215
			super.refresh();
216
		}
217

    
218

    
219

    
220
		/* (non-Javadoc)
221
		 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createFilter()
222
		 */
223
		/** {@inheritDoc} */
224
		@Override
225
		protected ItemsFilter createFilter() {
226
			return new ItemsFilter() {
227

    
228
				/**
229
				 * Always returns false to enforce refiltering even if the pattern is equal
230
				 */
231
				@Override
232
				public boolean equalsFilter(ItemsFilter filter) {
233
					return false;
234
				}
235

    
236
				@Override
237
				public boolean isConsistentItem(Object item) {
238
					return false;
239
				}
240

    
241
				@Override
242
				public boolean matchItem(Object item) {
243
					String text = null;
244
					if(item instanceof IdentifiedEntityDTO){
245
						text = ((IdentifiedEntityDTO) item).getCdmEntity().getTitleCache();
246
					}else if(item instanceof String){
247
						text = (String) item;
248
					}
249
					return text != null ? matches(text) : false;
250
				}
251

    
252
			};
253
		}
254

    
255

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

    
282
			// this also is not the nicest way to do it.
283
			// I am still amazed, that FilteredSelectionDialog does not offer any methods to change its data
284
			// once it was opened. Am I doing it wrong?
285
			String pattern = getTitle(cdmObject);
286
			((Text) getPatternControl()).setText(pattern);
287
		}
288

    
289

    
290

    
291
		/* (non-Javadoc)
292
		* @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#fillContentProvider(org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.AbstractContentProvider, org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter, org.eclipse.core.runtime.IProgressMonitor)
293
		*/
294
		/** {@inheritDoc} */
295
		@Override
296
		protected void fillContentProvider(AbstractContentProvider contentProvider,
297
			ItemsFilter itemsFilter, IProgressMonitor progressMonitor)
298
			throws CoreException {
299
			try {
300
				if(model != null){
301
					progressMonitor.beginTask("Looking for entities", model.size());
302
					filterExcludedObjects();
303
					Iterator<IdentifiedEntityDTO> iterator = model.iterator();
304
					IdentifiedEntityDTO element;
305
					while(iterator.hasNext()){
306
					    element = iterator.next();
307
					    if (!element.equals(cdmBaseToBeFiltered)){
308
					        contentProvider.add(element, itemsFilter);
309
					    }
310
						if (progressMonitor.isCanceled()) {
311
							throw new OperationCanceledException();
312
						}
313
						progressMonitor.worked(1);
314
					}
315
				}else{
316
					MessagingUtils.warn(getClass(), "Model for Filtered Selection is null:" + this.getClass().getSimpleName());
317
				}
318
			}
319
			finally {
320
				progressMonitor.done();
321
			}
322
		}
323

    
324
		/* (non-Javadoc)
325
		 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getDialogSettings()
326
		 */
327
		/** {@inheritDoc} */
328
		@Override
329
		protected IDialogSettings getDialogSettings() {
330
			IDialogSettings settings = TaxeditorStorePlugin.getDefault().getDialogSettings().getSection(getSettings());
331

    
332
			if (settings == null) {
333
				settings = TaxeditorStorePlugin.getDefault().getDialogSettings().addNewSection(getSettings());
334
			}
335
			return settings;
336
		}
337

    
338
		/* (non-Javadoc)
339
		 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getElementName(java.lang.Object)
340
		 */
341
		/** {@inheritDoc} */
342
		@Override
343
		public String getElementName(Object item) {
344
			return ((IdentifiedEntityDTO) item).getCdmEntity().getTitleCache();
345
		}
346

    
347
		/* (non-Javadoc)
348
		 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getItemsComparator()
349
		 */
350
		/** {@inheritDoc} */
351
		@Override
352
		protected Comparator getItemsComparator() {
353
			return new Comparator<IdentifiedEntityDTO>() {
354
				@Override
355
				public int compare(IdentifiedEntityDTO entity1,
356
						IdentifiedEntityDTO entity2) {
357
					Collator collator = Collator.getInstance();
358
					if (entity1.getCdmEntity().getCdmUuid().equals(entity2.getCdmEntity().getCdmUuid())){
359
					    return 0;
360
					}
361
					int result = collator.compare(entity1.getCdmEntity().getTitleCache(), entity2.getCdmEntity().getTitleCache());
362
					if (result == 0){
363
					    result = entity1.getCdmEntity().getCdmUuid().compareTo(entity2.getCdmEntity().getCdmUuid());
364
					}
365
					return result;
366
				}
367
			};
368
		}
369

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

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

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

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

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

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

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

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

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

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

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

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

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

    
506
		/**
507
		 * <p>getConversationHolder</p>
508
		 *
509
		 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
510
		 */
511
		@Override
512
		public ConversationHolder getConversationHolder() {
513
			return conversation;
514
		}
515

    
516
		/** {@inheritDoc} */
517
		@Override
518
		public void update(CdmDataChangeMap changeEvents) {}
519

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

    
529
				IdentifiedEntityDTO identifiedEntityToRemove = null;
530

    
531
				for (IdentifiedEntityDTO identifiedEntity : model){
532
					if ((cdmBaseToBeFiltered.getUuid()).equals(identifiedEntity.getCdmEntity().getCdmUuid())) {
533
						identifiedEntityToRemove = identifiedEntity;
534
					}
535
				}
536
				model.remove(identifiedEntityToRemove);
537
			}
538
		}
539

    
540

    
541

    
542
}
(3-3/38)