Project

General

Profile

Download (15.6 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
package eu.etaxonomy.taxeditor.ui.dialog.selection;
10

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

    
21
import org.apache.commons.lang3.StringUtils;
22
import org.eclipse.core.runtime.IProgressMonitor;
23
import org.eclipse.core.runtime.IStatus;
24
import org.eclipse.core.runtime.jobs.Job;
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.api.service.dto.EntityDTOBase;
46
import eu.etaxonomy.cdm.api.service.dto.IdentifiedEntityDTO;
47
import eu.etaxonomy.cdm.model.common.CdmBase;
48
import eu.etaxonomy.cdm.model.common.ICdmBase;
49
import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
50
import eu.etaxonomy.cdm.model.metadata.PreferencePredicate;
51
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
52
import eu.etaxonomy.taxeditor.l10n.Messages;
53
import eu.etaxonomy.taxeditor.model.MessagingUtils;
54
import eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard;
55
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
56
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
57

    
58
/**
59
 * Abstract AbstractFilteredCdmResourceSelectionDialog class.
60
 *
61
 * @author n.hoffmann
62
 * @created 04.06.2009
63
 */
64
public abstract class AbstractFilteredCdmResourceSelectionDialog<T extends ICdmBase>
65
        extends SearchDialog<T> {
66

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

    
72
	protected Set<UUID> cdmBaseToBeFiltered;
73

    
74
	protected Job searchJob;
75

    
76
	protected AbstractFilteredCdmResourceSelectionDialog(Shell shell,
77
	        String title, boolean multi, String settings, Set<T> objectsToBeFiltered) {
78
	    super(shell, title);
79

    
80
	    setMessage(Messages.SearchDialog_patternLabel);
81
        this.settings = settings;
82
        if (objectsToBeFiltered != null){
83
            this.cdmBaseToBeFiltered = new HashSet<>();
84
            objectsToBeFiltered.forEach(filter->this.cdmBaseToBeFiltered.add(filter.getUuid()));
85
        }
86
        Cursor cursor = null;
87
        if (shell != null){
88
        	cursor = shell.getCursor();
89
        	shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
90
        }
91

    
92
        init();
93
        if (shell != null){
94
        	shell.setCursor(cursor);
95
        }
96
        setListLabelProvider(createListLabelProvider());
97
	}
98

    
99
	protected AbstractFilteredCdmResourceSelectionDialog(Shell shell,
100
	        String title, boolean multi, String settings) {
101
        this(shell, title, multi, settings, (Set<T>)null);
102
	}
103

    
104
	protected AbstractFilteredCdmResourceSelectionDialog(Shell shell,
105
	        String title, boolean multi, String settings, T objectToBeFiltered) {
106
	    this(shell, title, multi, settings, objectToBeFiltered!=null?Collections.singleton(objectToBeFiltered):null);
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
	protected ILabelProvider createListLabelProvider() {
121
		return new FilteredCdmResourceLabelProvider();
122
	}
123

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

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

    
146
	/**
147
     * getSelectionFromDialog
148
     */
149
    protected static <S extends ICdmBase> UuidAndTitleCache<S> getUuidAndTitleCacheSelectionFromDialog(
150
            AbstractFilteredCdmResourceSelectionDialog<S> dialog) {
151
        if (dialog == null){
152
            return null;
153
        }
154
        int result = dialog.open();
155

    
156
        if (result == Window.CANCEL) {
157
            return null;
158
        }
159

    
160
        UuidAndTitleCache<S> uuid = dialog.getSelectedUuidAndTitleCache();
161

    
162
        return uuid;
163
    }
164

    
165
	/**
166
	 * Check if object was created during the life of this dialog. If not,
167
	 * retrieve it from the CdmStore.
168
	 */
169
	protected T getCdmObjectByUuid(UUID cdmUuid) {
170
		for (T cdmObject : transientCdmObjects) {
171
			if (cdmObject.getUuid().equals(cdmUuid)) {
172
				return cdmObject;
173
			}
174
		}
175
		return getPersistentObject(cdmUuid);
176
	}
177

    
178
	/**
179
	 * <p>getPersistentObject</p>
180
	 *
181
	 * @param uuid a {@link java.util.UUID} object.
182
	 * @return a T object.
183
	 */
184
	abstract protected T getPersistentObject(UUID uuid);
185

    
186
	/**
187
	 * <p>isObjectTransient</p>
188
	 *
189
	 * @param cdmObject a T object.
190
	 * @return a boolean.
191
	 */
192
	protected boolean isObjectTransient(T cdmObject) {
193
		return (getPersistentObject(cdmObject.getUuid()) == null);
194
	}
195

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

    
207
		if (cdmObject instanceof IIdentifiableEntity) {
208
			return ((IIdentifiableEntity) cdmObject).getTitleCache();
209
		}
210

    
211
		throw new IllegalArgumentException("Generic method only" +
212
				" supports cdmObject of type IIdentifiableEntity." +
213
				" Please implement specific method in subclass.");
214
	}
215

    
216
	/**
217
	 * Set the filter input to the Agent's title cache
218
	 *
219
	 * @param cdmObject a T object.
220
	 */
221
	protected void setPattern(T cdmObject) {
222
		String pattern = getTitle(cdmObject);
223
		getSearchField().setText(pattern);
224

    
225
	}
226

    
227
	@Override
228
    protected void fillContentProvider(IProgressMonitor progressMonitor)
229
		 {
230
		try {
231
		    if (model == null){
232
		        model = new ArrayList<UuidAndTitleCache<T>>();
233
		    }
234
			if(model != null){
235
			    if (progressMonitor != null){
236
			        progressMonitor.beginTask("Looking for entities", model.size());
237
			    }
238
			    sort();
239

    
240
			    contentProvider.reset();
241
				Iterator<UuidAndTitleCache<T>> iterator = model.iterator();
242
				UuidAndTitleCache<T> element;
243
				while(iterator.hasNext()){
244
				    element = iterator.next();
245

    
246
				    if (cdmBaseToBeFiltered == null || !cdmBaseToBeFiltered.contains(element.getUuid())){
247
				        contentProvider.add(element);
248
				    }
249
				    if (progressMonitor != null){
250
    					if (progressMonitor.isCanceled()) {
251
    						return;
252
    					}
253
    					progressMonitor.worked(1);
254
				    }
255
				}
256
				this.refresh();
257
			}else{
258

    
259
				MessagingUtils.warn(getClass(), "Model for Filtered Selection is null:" + this.getClass().getSimpleName());
260
			}
261
		}
262
		finally {
263
		    if (progressMonitor != null) {
264
                progressMonitor.done();
265
            }
266
		}
267
	}
268

    
269
    protected void sort() {
270
        Collections.sort(model, getItemsComparator());
271
    }
272

    
273
	protected IDialogSettings getDialogSettings() {
274
		IDialogSettings settings = TaxeditorStorePlugin.getDefault().getDialogSettings().getSection(getSettings());
275

    
276
		if (settings == null) {
277
			settings = TaxeditorStorePlugin.getDefault().getDialogSettings().addNewSection(getSettings());
278
		}
279
		return settings;
280
	}
281

    
282
	@Override
283
    protected Comparator<UuidAndTitleCache<T>> getItemsComparator() {
284
		return new Comparator<UuidAndTitleCache<T>>() {
285
			@Override
286
			public int compare(UuidAndTitleCache<T> entity1,
287
					UuidAndTitleCache<T> entity2) {
288
				Collator collator = Collator.getInstance();
289
				if (entity1 == entity2){
290
				    return 0;
291
				}else if (entity1 == null){
292
				    return -1;
293
				}else if (entity2 == null){
294
				    return 1;
295
				}else if (entity1.getUuid().equals(entity2.getUuid())){
296
                    return 0;
297
                }else if (entity1.getTitleCache() == null && entity2.getTitleCache() != null){
298
				    return -1;
299
				}else if (entity2.getTitleCache() == null){
300
				    return 1;
301
				}
302
				int result = collator.compare(entity1.getTitleCache(), entity2.getTitleCache());
303
				if (result == 0){
304
				    result = entity1.getUuid().compareTo(entity2.getUuid());
305
				}
306
				return result;
307
			}
308
		};
309
	}
310

    
311
	/**
312
	 * getSelectedUuidAndTitleCache
313
	 */
314
	protected UuidAndTitleCache<T> getSelectedUuidAndTitleCache() {
315
		Object result = getResult();
316
		if (result instanceof UuidAndTitleCache){
317
		    return (UuidAndTitleCache<T>) result;
318
		}
319
		return null;
320
	}
321

    
322
    private Object getResult() {
323
        StructuredSelection selection = getCurrentSelection();
324
        if (selection == null){
325
            return null;
326
        }
327
        return selection.getFirstElement();
328
    }
329

    
330
    /**
331
	 * <p>Getter for the field <code>settings</code>.</p>
332
	 *
333
	 * @return a {@link java.lang.String} object.
334
	 */
335
	public String getSettings()  {
336
		if(settings == null){
337
			throw new IllegalStateException("No SETTINGS set.");
338
		}
339
		return settings;
340
	}
341

    
342
	/**
343
	 * <p>getNewWizardLinkText</p>
344
	 *
345
	 * @return a {@link java.lang.String} object.
346
	 */
347
	protected abstract String[] getNewWizardText();
348

    
349
	/**
350
	 * <p>getNewEntityWizard</p>
351
	 * @param parameter
352
	 * @return a {@link eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard} object.
353
	 */
354
	protected abstract AbstractNewEntityWizard<T> getNewEntityWizard(String parameter);
355

    
356
	public class FilteredCdmResourceLabelProvider extends LabelProvider {
357
		@Override
358
		public String getText(Object element) {
359
			if (element == null) {
360
				return null;
361
			}
362
			UuidAndTitleCache<?> uuidAndTitleCache = (UuidAndTitleCache<?>) element;
363
			String titleCache = uuidAndTitleCache.getTitleCache();
364
			if(PreferencesUtil.getBooleanValue(PreferencePredicate.ShowIdInSelectionDialog.getKey())){
365
			    titleCache += " ["+uuidAndTitleCache.getId()+"]";
366
			}
367
			if (element instanceof EntityDTOBase){
368
			    titleCache += "(" + ((IdentifiedEntityDTO)element).getIdentifier().getTypeLabel() +": " + ((IdentifiedEntityDTO)element).getIdentifier().getIdentifier() + ")";
369
			}
370

    
371
            return titleCache;
372
		}
373
	}
374

    
375
//	@Override
376
//    protected Control createExtendedContentArea(Composite parent) {
377
//		String newWizardLinkText = getNewWizardLinkText();
378
////        if(newWizardLinkText != null){
379
////            newButton1 = this.createButton(this.getShell(), new_id, newWizardLinkText, false);
380
////
381
////            newButton1.addSelectionListener(getNewWizardLinkSelectionListener());
382
////			return newButton1;
383
////		}
384
//		return null;
385
//	}
386

    
387
	@Override
388
    protected void createButtonsForButtonBar(Composite parent) {
389
	    String[] newButtonText = getNewWizardText();
390

    
391
	    if (newButtonText!= null){
392
	        this.newButton1 = createButton(parent, this.new_id, newButtonText[0], false);
393
	        newButton1.addSelectionListener(getNewWizardButtonSelectionListener());
394

    
395
	        if (newButtonText.length > 1){
396
	            newButton2 = createButton(parent, this.new_id2, newButtonText[1], false);
397
	            newButton2.addSelectionListener(getNewWizardButtonSelectionListener());
398
	        }
399
	    }
400
	    Button space = createButton(parent, this.space_id, " ", false);
401
	    space.setEnabled(false);
402
	    space.setVisible(false);
403
	    GridData gridData = new GridData();
404
        gridData.grabExcessHorizontalSpace = false;
405
        gridData.widthHint = 3;
406
	    space.setLayoutData(gridData);
407
	    GridLayout gridLayout = new GridLayout();
408
	    gridLayout.makeColumnsEqualWidth= false;
409
	    if (newButtonText != null){
410
	    	gridLayout.numColumns=newButtonText.length+2;
411
	    }else{
412
	    	gridLayout.numColumns=2;
413
	    }
414
	    parent.setLayout(gridLayout);
415

    
416
        super.createButtonsForButtonBar(parent);
417
        super.getButton(IDialogConstants.OK_ID).setEnabled(false);
418
    }
419

    
420
	protected SelectionListener getNewWizardButtonSelectionListener(){
421
		return new SelectionAdapter() {
422

    
423
			@Override
424
			public void widgetSelected(SelectionEvent e) {
425
			    Object source = e.getSource();
426
			    String text = null;
427
			    if (source instanceof Button){
428
			        Button sourceButton = (Button) source;
429
			        text = sourceButton.getText();
430
			    }
431
			    AbstractNewEntityWizard<?> wizard = getNewEntityWizard(text);
432
			    if(wizard != null){
433
			        if (wizard.getEntity() == null){
434
			            wizard.init(null, null);
435
			        }
436
			        if(wizard.getEntity() != null) {
437
			            WizardDialog dialog = new WizardDialog(getShell(), wizard);
438
			            int status = dialog.open();
439

    
440
			            if (status == IStatus.OK) {
441

    
442
			                T entity = (T) wizard.getEntity();
443
			                refresh();
444
			                setPattern(entity);
445

    
446
//			                if (getConversationHolder() != null){
447
//			                    getConversationHolder().bind();
448
//			                }
449
			            }
450
			            //FIXME : Need to make sure this is a stable fix (ticket 3822)
451
//			            if (getConversationHolder() != null){
452
//			                getConversationHolder().commit();
453
//			            }
454
			        }
455
			    }
456
			}
457
		};
458
	}
459

    
460
	/**
461
	 * Don't want to add for example a taxon or synonym to itself
462
	 * so filter the list to remove the taxon in question
463
	 * (<code>cdmBaseToBeFiltered</code>)
464
	 * so it is not available in the filtered list.
465
	 */
466
	private void filterExcludedObjects() {
467
		if (model != null && cdmBaseToBeFiltered != null) {
468

    
469
			UuidAndTitleCache<?> uuidAndTitleCacheToRemove = null;
470

    
471
			for (UuidAndTitleCache<?> uuidAndTitleCache : model){
472
				if (cdmBaseToBeFiltered != null && cdmBaseToBeFiltered.contains(uuidAndTitleCache.getUuid())) {
473
					uuidAndTitleCacheToRemove = uuidAndTitleCache;
474
				}
475
			}
476
			model.remove(uuidAndTitleCacheToRemove);
477
		}
478
	}
479

    
480
	@Override
481
	void createFilterButton(Composite searchAndFilter){
482
	    //as default no filter button available
483
	}
484

    
485
    @Override
486
    protected void search() {
487
        Control control =getSearchField();
488
        String pattern = null;
489
        if (control != null){
490
            pattern = ((Text)control).getText();
491
            if (pattern.equals("*") || pattern.equals("?") || (this instanceof CollectorSelectionDialog && StringUtils.isBlank(pattern) && ((CollectorSelectionDialog)this).collectorTeam != null)){
492
                callService(null);
493
            }else if (StringUtils.isNotBlank(pattern)){
494
//                callService(CdmUtils.replaceNonWordCharacters(pattern, "."));
495
                callService(pattern);
496
            }
497
            fillContentProvider(null);
498
        }
499

    
500
//        if (pattern.equals("?")){
501
//            model = CdmStore.getService(INameService.class).getUuidAndTitleCache(null, null);
502
//        }else if (pattern != null){
503
//            model = CdmStore.getService(INameService.class).getUuidAndTitleCache(limitOfInitialElements, pattern);
504
//        }
505
    }
506

    
507
    protected abstract void callService(String pattern);
508

    
509
}
(2-2/46)