Project

General

Profile

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

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

    
12
import java.text.Collator;
13
import java.util.ArrayList;
14
import java.util.Collections;
15
import java.util.Comparator;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Set;
20
import java.util.UUID;
21

    
22
import org.apache.commons.lang.StringUtils;
23
import org.eclipse.core.runtime.IProgressMonitor;
24
import org.eclipse.core.runtime.IStatus;
25
import org.eclipse.jface.dialogs.IDialogConstants;
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.viewers.StructuredSelection;
30
import org.eclipse.jface.window.Window;
31
import org.eclipse.jface.wizard.WizardDialog;
32
import org.eclipse.swt.SWT;
33
import org.eclipse.swt.events.SelectionAdapter;
34
import org.eclipse.swt.events.SelectionEvent;
35
import org.eclipse.swt.events.SelectionListener;
36
import org.eclipse.swt.graphics.Cursor;
37
import org.eclipse.swt.layout.GridData;
38
import org.eclipse.swt.layout.GridLayout;
39
import org.eclipse.swt.widgets.Button;
40
import org.eclipse.swt.widgets.Composite;
41
import org.eclipse.swt.widgets.Control;
42
import org.eclipse.swt.widgets.Shell;
43
import org.eclipse.swt.widgets.Text;
44

    
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.taxeditor.l10n.Messages;
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
		SearchDialog {//implements IConversationEnabled {
65

    
66
//	private final ConversationHolder conversation = null;
67

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

    
73
	private T selectedObject;
74

    
75
	protected Set<UUID> cdmBaseToBeFiltered;
76

    
77

    
78
	/**
79
	 * <p>Constructor for AbstractFilteredCdmResourceSelectionDialog.</p>
80
	 *
81
	 * @param shell a {@link org.eclipse.swt.widgets.Shell} object.
82
	 * @param conversation
83
	 * @param title a {@link java.lang.String} object.
84
	 * @param multi a boolean.
85
	 * @param settings a {@link java.lang.String} object.
86
	 * @param cdmObject a T object.
87
	 * @param <T> a T object.
88
	 */
89
	protected AbstractFilteredCdmResourceSelectionDialog(Shell shell, //ConversationHolder conversation,
90
	        String title, boolean multi, String settings, T cdmObject) {
91
		super(shell, title);
92
		setShellStyle(SWT.DIALOG_TRIM);
93
		setMessage(Messages.SearchDialog_patternLabel);
94
		this.settings = settings;
95
        if (cdmObject != null){
96
            this.cdmBaseToBeFiltered = new HashSet<>();
97
            this.cdmBaseToBeFiltered.add(cdmObject.getUuid());
98
        }
99
		Cursor cursor = shell.getCursor();
100
		shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
101
		init();
102
		shell.setCursor(cursor);
103
		setListLabelProvider(createListLabelProvider());
104

    
105
	}
106

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

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

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

    
132
	}
133

    
134
	/**
135
	 * <p>getSelectionFromDialog</p>
136
	 *
137
	 * @param dialog a {@link eu.etaxonomy.taxeditor.ui.dialog.selection.AbstractFilteredCdmResourceSelectionDialog} object.
138
	 * @param <TYPE> a TYPE object.
139
	 * @return a TYPE object.
140
	 */
141
	protected static <TYPE extends CdmBase> TYPE getSelectionFromDialog(AbstractFilteredCdmResourceSelectionDialog<TYPE> dialog) {
142
	    UuidAndTitleCache result = getUuidAndTitleCacheSelectionFromDialog(dialog);
143
	    if (result != null){
144
	        return dialog.getCdmObjectByUuid(result.getUuid());
145
	    } else {
146
            return null;
147
        }
148
	}
149

    
150
	/**
151
     * <p>getSelectionFromDialog</p>
152
     *
153
     * @param dialog a {@link eu.etaxonomy.taxeditor.ui.dialog.selection.AbstractFilteredCdmResourceSelectionDialog} object.
154
     * @param <TYPE> a TYPE object.
155
     * @return a TYPE object.
156
     */
157
    protected static UuidAndTitleCache getUuidAndTitleCacheSelectionFromDialog(AbstractFilteredCdmResourceSelectionDialog dialog) {
158
        if (dialog == null){
159
            return null;
160
        }
161
        int result = dialog.open();
162

    
163
        if (result == Window.CANCEL) {
164
            return null;
165
        }
166

    
167
        UuidAndTitleCache uuid = dialog.getSelectedUuidAndTitleCache();
168

    
169
        return uuid;
170
    }
171

    
172
	/**
173
	 * Check if object was created during the life of this dialog. If not,
174
	 * retrieve it from the CdmStore.
175
	 *
176
	 * @param cdmUuid a {@link java.util.UUID} object.
177
	 * @return a T object.
178
	 */
179
	protected T getCdmObjectByUuid(UUID cdmUuid) {
180
		for (T cdmObject : transientCdmObjects) {
181
			if (cdmObject.getUuid().equals(cdmUuid)) {
182
				return cdmObject;
183
			}
184
		}
185
		return getPersistentObject(cdmUuid);
186
	}
187

    
188
	/**
189
	 * <p>getPersistentObject</p>
190
	 *
191
	 * @param uuid a {@link java.util.UUID} object.
192
	 * @return a T object.
193
	 */
194
	abstract protected T getPersistentObject(UUID uuid);
195

    
196

    
197
	/**
198
	 * <p>isObjectTransient</p>
199
	 *
200
	 * @param cdmObject a T object.
201
	 * @return a boolean.
202
	 */
203
	protected boolean isObjectTransient(T cdmObject) {
204
		return (getPersistentObject(cdmObject.getUuid()) == null);
205
	}
206

    
207
	/**
208
	 * <p>getTitle</p>
209
	 *
210
	 * @param cdmObject a T object.
211
	 * @return a {@link java.lang.String} object.
212
	 */
213
	protected String getTitle(T cdmObject) {
214
		if(cdmObject == null){
215
			return "";
216
		}
217

    
218
		if (cdmObject instanceof IIdentifiableEntity) {
219
			return ((IIdentifiableEntity) cdmObject).getTitleCache();
220
		}
221

    
222
		throw new IllegalArgumentException("Generic method only" +
223
				" supports cdmObject of type IIdentifiableEntity." +
224
				" Please implement specific method in subclass.");
225
	}
226

    
227

    
228

    
229
	/**
230
	 * Set the filter input to the Agent's title cache
231
	 *
232
	 * @param cdmObject a T object.
233
	 */
234
	protected void setPattern(T cdmObject) {
235
		String pattern = getTitle(cdmObject);
236
		getSearchField().setText(pattern);
237
	}
238

    
239

    
240

    
241
	/* (non-Javadoc)
242
	* @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#fillContentProvider(org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.AbstractContentProvider, org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter, org.eclipse.core.runtime.IProgressMonitor)
243
	*/
244
	/** {@inheritDoc} */
245

    
246
	@Override
247
    protected void fillContentProvider(IProgressMonitor progressMonitor)
248
		 {
249
		try {
250
		    if (model == null){
251
		        model = new ArrayList<UuidAndTitleCache<T>>();
252
		    }
253
			if(model != null){
254
			    if (progressMonitor != null){
255
			        progressMonitor.beginTask("Looking for entities", model.size());
256
			    }
257
			    sort();
258

    
259
			    contentProvider.reset();
260
				Iterator<UuidAndTitleCache<T>> iterator = model.iterator();
261
				UuidAndTitleCache<T> element;
262
				while(iterator.hasNext()){
263
				    element = iterator.next();
264

    
265
				    if (cdmBaseToBeFiltered == null || !cdmBaseToBeFiltered.contains(element.getUuid())){
266
				        contentProvider.add(element);
267
				    }
268
				    if (progressMonitor != null){
269
    					if (progressMonitor.isCanceled()) {
270
    						return;
271
    					}
272
    					progressMonitor.worked(1);
273
				    }
274
				}
275
				this.refresh();
276
			}else{
277

    
278
				MessagingUtils.warn(getClass(), "Model for Filtered Selection is null:" + this.getClass().getSimpleName());
279
			}
280
		}
281
		finally {
282
		    if (progressMonitor != null) {
283
                progressMonitor.done();
284
            }
285
		}
286
	}
287

    
288

    
289
    protected void sort() {
290
        Collections.sort(model, getItemsComparator());
291
    }
292

    
293
    /* (non-Javadoc)
294
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getDialogSettings()
295
	 */
296
	/** {@inheritDoc} */
297

    
298
	protected IDialogSettings getDialogSettings() {
299
		IDialogSettings settings = TaxeditorStorePlugin.getDefault().getDialogSettings().getSection(getSettings());
300

    
301
		if (settings == null) {
302
			settings = TaxeditorStorePlugin.getDefault().getDialogSettings().addNewSection(getSettings());
303
		}
304
		return settings;
305
	}
306

    
307
	/* (non-Javadoc)
308
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getElementName(java.lang.Object)
309
	 */
310
	/** {@inheritDoc} */
311

    
312
	public String getElementName(Object item) {
313
		return ((UuidAndTitleCache) item).getTitleCache();
314
	}
315

    
316
	/* (non-Javadoc)
317
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getItemsComparator()
318
	 */
319
	/** {@inheritDoc} */
320

    
321
	@Override
322
    protected Comparator getItemsComparator() {
323
		return new Comparator<UuidAndTitleCache>() {
324
			@Override
325
			public int compare(UuidAndTitleCache entity1,
326
					UuidAndTitleCache entity2) {
327
				Collator collator = Collator.getInstance();
328
				if (entity1 == entity2){
329
				    return 0;
330
				}
331

    
332
				if (entity1 == null && entity2 != null){
333
				    return -1;
334
				}
335
				if (entity2 == null && entity1 != null){
336
				    return 1;
337
				}
338
				if (entity1.getUuid().equals(entity2.getUuid())){
339
                    return 0;
340
                }
341
				if (entity1.getTitleCache() == null && entity2.getTitleCache() != null){
342
				    return -1;
343
				}
344
				if (entity2.getTitleCache() == null){
345
				    return 1;
346
				}
347
				int result = collator.compare(entity1.getTitleCache(), entity2.getTitleCache());
348
				if (result == 0){
349
				    result = entity1.getUuid().compareTo(entity2.getUuid());
350
				}
351
				return result;
352
			}
353
		};
354
	}
355

    
356

    
357
	/**
358
	 * <p>getSelectedUuidAndTitleCache</p>
359
	 *
360
	 * @return a {@link eu.etaxonomy.cdm.model.common.UuidAndTitleCache} object.
361
	 */
362
	protected UuidAndTitleCache getSelectedUuidAndTitleCache() {
363
		Object result = getResult();
364
		if (result instanceof UuidAndTitleCache){
365
		    return (UuidAndTitleCache) result;
366
		}
367
		return null;
368
	}
369

    
370
	/**
371
     * @return
372
     */
373
    private Object getResult() {
374
        StructuredSelection selection = getCurrentSelection();
375
        if (selection == null){
376
            return null;
377
        }
378
        return selection.getFirstElement();
379
    }
380

    
381
    /**
382
	 * <p>Getter for the field <code>settings</code>.</p>
383
	 *
384
	 * @return a {@link java.lang.String} object.
385
	 */
386
	public String getSettings()  {
387
		if(settings == null){
388
			throw new IllegalStateException("No SETTINGS set.");
389
		}
390
		return settings;
391
	}
392

    
393

    
394

    
395
	/**
396
	 * <p>getNewWizardLinkText</p>
397
	 *
398
	 * @return a {@link java.lang.String} object.
399
	 */
400
	protected abstract String[] getNewWizardText();
401

    
402
	/**
403
	 * <p>getNewEntityWizard</p>
404
	 * @param parameter
405
	 * @return a {@link eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard} object.
406
	 */
407
	protected abstract AbstractNewEntityWizard getNewEntityWizard(String parameter);
408

    
409
	public class FilteredCdmResourceLabelProvider extends LabelProvider {
410
		@Override
411
		public String getText(Object element) {
412
			if (element == null) {
413
				return null;
414
			}
415
			UuidAndTitleCache uuidAndTitleCache = (UuidAndTitleCache) element;
416
			String titleCache = uuidAndTitleCache.getTitleCache();
417
			if(PreferencesUtil.getPreferenceStore().getBoolean(IPreferenceKeys.SHOW_ID_IN_ENTITY_SELECTION_DIAOLOG)){
418
			    titleCache += " ["+uuidAndTitleCache.getId()+"]";
419
			}
420
            return titleCache;
421
		}
422
	};
423

    
424
	/* (non-Javadoc)
425
	* @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createExtendedContentArea(org.eclipse.swt.widgets.Composite)
426
	*/
427
	/** {@inheritDoc} */
428

    
429
//	@Override
430
//    protected Control createExtendedContentArea(Composite parent) {
431
//		String newWizardLinkText = getNewWizardLinkText();
432
////        if(newWizardLinkText != null){
433
////            newButton1 = this.createButton(this.getShell(), new_id, newWizardLinkText, false);
434
////
435
////            newButton1.addSelectionListener(getNewWizardLinkSelectionListener());
436
////			return newButton1;
437
////		}
438
//		return null;
439
//	}
440

    
441
	@Override
442
    protected void createButtonsForButtonBar(Composite parent) {
443
	    String[] newButtonText = getNewWizardText();
444

    
445
	    if (newButtonText!= null){
446
	        this.newButton1 = createButton(parent, this.new_id, newButtonText[0], false);
447
	        newButton1.addSelectionListener(getNewWizardButtonSelectionListener());
448

    
449

    
450
	        if (newButtonText.length > 1){
451
	            newButton2 = createButton(parent, this.new_id2, newButtonText[1], false);
452
	            newButton2.addSelectionListener(getNewWizardButtonSelectionListener());
453

    
454
	        }
455

    
456
	    }
457
	    Button space = createButton(parent, this.space_id, " ", false);
458
	    space.setEnabled(false);
459
	    space.setVisible(false);
460
	    GridData gridData = new GridData();
461
        gridData.grabExcessHorizontalSpace = false;
462
        gridData.widthHint = 3;
463
	    space.setLayoutData(gridData);
464
	    GridLayout gridLayout = new GridLayout();
465
	    gridLayout.makeColumnsEqualWidth= false;
466
	    if (newButtonText != null){
467
	    	gridLayout.numColumns=newButtonText.length+2;
468
	    }else{
469
	    	gridLayout.numColumns=2;
470
	    }
471
	    parent.setLayout(gridLayout);
472

    
473
        super.createButtonsForButtonBar(parent);
474
        super.getButton(IDialogConstants.OK_ID).setEnabled(false);
475
    }
476

    
477
	protected SelectionListener getNewWizardButtonSelectionListener(){
478
		return new SelectionAdapter() {
479

    
480
			/* (non-Javadoc)
481
			 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
482
			 */
483
			@Override
484
			public void widgetSelected(SelectionEvent e) {
485
			    Object source = e.getSource();
486
			    String text = null;
487
			    if (source instanceof Button){
488
			        Button sourceButton = (Button) source;
489
			        text = sourceButton.getText();
490
			    }
491
			    AbstractNewEntityWizard wizard = getNewEntityWizard(text);
492
			    if(wizard!=null){
493
			        if (wizard.getEntity() == null){
494
			            wizard.init(null, null);
495
			        }
496
			        if(wizard.getEntity() != null) {
497
			            WizardDialog dialog = new WizardDialog(getShell(), wizard);
498
			            int status = dialog.open();
499

    
500
			            if (status == IStatus.OK) {
501

    
502
			                T entity = (T) wizard.getEntity();
503
			                refresh();
504
			                setPattern(entity);
505

    
506
//			                if (getConversationHolder() != null){
507
//			                    getConversationHolder().bind();
508
//			                }
509
			            }
510
			            //FIXME : Need to make sure this is a stable fix (ticket 3822)
511
//			            if (getConversationHolder() != null){
512
//			                getConversationHolder().commit();
513
//			            }
514
			        }
515
			    }
516
			}
517
		};
518
	}
519

    
520
	/**
521
	 * <p>getConversationHolder</p>
522
	 *
523
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
524
//	 */
525
//	@Override
526
//	public ConversationHolder getConversationHolder() {
527
//		return conversation;
528
//	}
529

    
530
	/** {@inheritDoc} */
531
//	@Override
532
//	public void update(CdmDataChangeMap changeEvents) {}
533

    
534
	/**
535
	 * Don't want to add for example a taxon or synonym to itself
536
	 * so filter the list to remove the taxon in question
537
	 * (<code>cdmBaseToBeFiltered</code>)
538
	 * so it is not available in the filtered list.
539
	 */
540
	private void filterExcludedObjects() {
541
		if (model != null && cdmBaseToBeFiltered != null) {
542

    
543
			UuidAndTitleCache uuidAndTitleCacheToRemove = null;
544

    
545
			for (UuidAndTitleCache uuidAndTitleCache : model){
546
				if (cdmBaseToBeFiltered != null && cdmBaseToBeFiltered.contains(uuidAndTitleCache.getUuid())) {
547
					uuidAndTitleCacheToRemove = uuidAndTitleCache;
548
				}
549
			}
550
			model.remove(uuidAndTitleCacheToRemove);
551
		}
552
	}
553
	@Override
554
	void createFilterButton(Composite searchAndFilter){
555
	    //as default no filter button available
556
	}
557

    
558
	/** {@inheritDoc} */
559
    @Override
560
    protected void search() {
561
        Control control =getSearchField();
562
        String pattern = null;
563
        if (control != null){
564
            pattern = ((Text)control).getText();
565
            if (pattern.equals("*") || pattern.equals("?")){
566
                callService(null);
567
            }else if (StringUtils.isNotBlank(pattern)){
568
                callService(pattern);
569
            }
570
            fillContentProvider(null);
571
        }
572

    
573
//        if (pattern.equals("?")){
574
//            model = CdmStore.getService(INameService.class).getUuidAndTitleCache(null, null);
575
//        }else if (pattern != null){
576
//            model = CdmStore.getService(INameService.class).getUuidAndTitleCache(limitOfInitialElements, pattern);
577
//        }
578
    }
579

    
580
    abstract void callService(String pattern);
581

    
582
}
(2-2/42)