Project

General

Profile

Download (16.2 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.lang3.StringUtils;
23
import org.eclipse.core.runtime.IProgressMonitor;
24
import org.eclipse.core.runtime.IStatus;
25
import org.eclipse.core.runtime.jobs.Job;
26
import org.eclipse.jface.dialogs.IDialogConstants;
27
import org.eclipse.jface.dialogs.IDialogSettings;
28
import org.eclipse.jface.viewers.ILabelProvider;
29
import org.eclipse.jface.viewers.LabelProvider;
30
import org.eclipse.jface.viewers.StructuredSelection;
31
import org.eclipse.jface.window.Window;
32
import org.eclipse.jface.wizard.WizardDialog;
33
import org.eclipse.swt.SWT;
34
import org.eclipse.swt.events.SelectionAdapter;
35
import org.eclipse.swt.events.SelectionEvent;
36
import org.eclipse.swt.events.SelectionListener;
37
import org.eclipse.swt.graphics.Cursor;
38
import org.eclipse.swt.layout.GridData;
39
import org.eclipse.swt.layout.GridLayout;
40
import org.eclipse.swt.widgets.Button;
41
import org.eclipse.swt.widgets.Composite;
42
import org.eclipse.swt.widgets.Control;
43
import org.eclipse.swt.widgets.Shell;
44
import org.eclipse.swt.widgets.Text;
45

    
46
import eu.etaxonomy.cdm.api.service.dto.EntityDTOBase;
47
import eu.etaxonomy.cdm.api.service.dto.IdentifiedEntityDTO;
48
import eu.etaxonomy.cdm.model.common.CdmBase;
49
import eu.etaxonomy.cdm.model.common.ICdmBase;
50
import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
51
import eu.etaxonomy.cdm.model.metadata.PreferencePredicate;
52
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
53
import eu.etaxonomy.taxeditor.l10n.Messages;
54
import eu.etaxonomy.taxeditor.model.MessagingUtils;
55
import eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard;
56
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
57
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
58

    
59
/**
60
 * <p>Abstract AbstractFilteredCdmResourceSelectionDialog class.</p>
61
 *
62
 * @author n.hoffmann
63
 * @created 04.06.2009
64
 */
65
public abstract class AbstractFilteredCdmResourceSelectionDialog<T extends ICdmBase> 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, //ConversationHolder conversation,
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 = shell.getCursor();
87
        shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
88
        init();
89
        shell.setCursor(cursor);
90
        setListLabelProvider(createListLabelProvider());
91

    
92
	}
93

    
94
	protected AbstractFilteredCdmResourceSelectionDialog(Shell shell, //ConversationHolder conversation,
95
	        String title, boolean multi, String settings) {
96
        this(shell, title, multi, settings, (Set<T>)null);
97
	}
98

    
99
	protected AbstractFilteredCdmResourceSelectionDialog(Shell shell, //ConversationHolder conversation,
100
	        String title, boolean multi, String settings, T objectToBeFiltered) {
101
	    this(shell, title, multi, settings, objectToBeFiltered!=null?Collections.singleton(objectToBeFiltered):null);
102
	}
103

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

    
115
	protected ILabelProvider createListLabelProvider() {
116
		return new FilteredCdmResourceLabelProvider();
117
	}
118

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

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

    
141
	/**
142
     * <p>getSelectionFromDialog</p>
143
     *
144
     * @param dialog a {@link eu.etaxonomy.taxeditor.ui.dialog.selection.AbstractFilteredCdmResourceSelectionDialog} object.
145
     * @param <TYPE> a TYPE object.
146
     * @return a TYPE object.
147
     */
148
    protected static UuidAndTitleCache getUuidAndTitleCacheSelectionFromDialog(AbstractFilteredCdmResourceSelectionDialog dialog) {
149
        if (dialog == null){
150
            return null;
151
        }
152
        int result = dialog.open();
153

    
154
        if (result == Window.CANCEL) {
155
            return null;
156
        }
157

    
158
        UuidAndTitleCache uuid = dialog.getSelectedUuidAndTitleCache();
159

    
160
        return uuid;
161
    }
162

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

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

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

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

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

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

    
217
	/**
218
	 * Set the filter input to the Agent's title cache
219
	 *
220
	 * @param cdmObject a T object.
221
	 */
222
	protected void setPattern(T cdmObject) {
223
		String pattern = getTitle(cdmObject);
224
		getSearchField().setText(pattern);
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
	public String getElementName(Object item) {
283
		return ((UuidAndTitleCache<T>) item).getTitleCache();
284
	}
285

    
286
	@Override
287
    protected Comparator<UuidAndTitleCache<T>> getItemsComparator() {
288
		return new Comparator<UuidAndTitleCache<T>>() {
289
			@Override
290
			public int compare(UuidAndTitleCache<T> entity1,
291
					UuidAndTitleCache<T> entity2) {
292
				Collator collator = Collator.getInstance();
293
				if (entity1 == entity2){
294
				    return 0;
295
				}
296

    
297
				if (entity1 == null && entity2 != null){
298
				    return -1;
299
				}
300
				if (entity2 == null && entity1 != null){
301
				    return 1;
302
				}
303
				if (entity1.getUuid().equals(entity2.getUuid())){
304
                    return 0;
305
                }
306
				if (entity1.getTitleCache() == null && entity2.getTitleCache() != null){
307
				    return -1;
308
				}
309
				if (entity2.getTitleCache() == null){
310
				    return 1;
311
				}
312
				int result = collator.compare(entity1.getTitleCache(), entity2.getTitleCache());
313
				if (result == 0){
314
				    result = entity1.getUuid().compareTo(entity2.getUuid());
315
				}
316
				return result;
317
			}
318
		};
319
	}
320

    
321
	/**
322
	 * <p>getSelectedUuidAndTitleCache</p>
323
	 *
324
	 * @return a {@link eu.etaxonomy.cdm.model.common.UuidAndTitleCache} object.
325
	 */
326
	protected UuidAndTitleCache<T> getSelectedUuidAndTitleCache() {
327
		Object result = getResult();
328
		if (result instanceof UuidAndTitleCache){
329
		    return (UuidAndTitleCache<T>) result;
330
		}
331
		return null;
332
	}
333

    
334
    private Object getResult() {
335
        StructuredSelection selection = getCurrentSelection();
336
        if (selection == null){
337
            return null;
338
        }
339
        return selection.getFirstElement();
340
    }
341

    
342
    /**
343
	 * <p>Getter for the field <code>settings</code>.</p>
344
	 *
345
	 * @return a {@link java.lang.String} object.
346
	 */
347
	public String getSettings()  {
348
		if(settings == null){
349
			throw new IllegalStateException("No SETTINGS set.");
350
		}
351
		return settings;
352
	}
353

    
354
	/**
355
	 * <p>getNewWizardLinkText</p>
356
	 *
357
	 * @return a {@link java.lang.String} object.
358
	 */
359
	protected abstract String[] getNewWizardText();
360

    
361
	/**
362
	 * <p>getNewEntityWizard</p>
363
	 * @param parameter
364
	 * @return a {@link eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard} object.
365
	 */
366
	protected abstract AbstractNewEntityWizard<T> getNewEntityWizard(String parameter);
367

    
368
	public class FilteredCdmResourceLabelProvider extends LabelProvider {
369
		@Override
370
		public String getText(Object element) {
371
			if (element == null) {
372
				return null;
373
			}
374
			UuidAndTitleCache<?> uuidAndTitleCache = (UuidAndTitleCache<?>) element;
375
			String titleCache = uuidAndTitleCache.getTitleCache();
376
			if(PreferencesUtil.getBooleanValue(PreferencePredicate.ShowIdInSelectionDialog.getKey())){
377
			    titleCache += " ["+uuidAndTitleCache.getId()+"]";
378
			}
379
			if (element instanceof EntityDTOBase){
380
			    titleCache += "(" + ((IdentifiedEntityDTO)element).getIdentifier().getTypeLabel() +": " + ((IdentifiedEntityDTO)element).getIdentifier().getIdentifier() + ")";
381
			}
382

    
383
            return titleCache;
384
		}
385
	}
386

    
387
//	@Override
388
//    protected Control createExtendedContentArea(Composite parent) {
389
//		String newWizardLinkText = getNewWizardLinkText();
390
////        if(newWizardLinkText != null){
391
////            newButton1 = this.createButton(this.getShell(), new_id, newWizardLinkText, false);
392
////
393
////            newButton1.addSelectionListener(getNewWizardLinkSelectionListener());
394
////			return newButton1;
395
////		}
396
//		return null;
397
//	}
398

    
399
	@Override
400
    protected void createButtonsForButtonBar(Composite parent) {
401
	    String[] newButtonText = getNewWizardText();
402

    
403
	    if (newButtonText!= null){
404
	        this.newButton1 = createButton(parent, this.new_id, newButtonText[0], false);
405
	        newButton1.addSelectionListener(getNewWizardButtonSelectionListener());
406

    
407
	        if (newButtonText.length > 1){
408
	            newButton2 = createButton(parent, this.new_id2, newButtonText[1], false);
409
	            newButton2.addSelectionListener(getNewWizardButtonSelectionListener());
410
	        }
411
	    }
412
	    Button space = createButton(parent, this.space_id, " ", false);
413
	    space.setEnabled(false);
414
	    space.setVisible(false);
415
	    GridData gridData = new GridData();
416
        gridData.grabExcessHorizontalSpace = false;
417
        gridData.widthHint = 3;
418
	    space.setLayoutData(gridData);
419
	    GridLayout gridLayout = new GridLayout();
420
	    gridLayout.makeColumnsEqualWidth= false;
421
	    if (newButtonText != null){
422
	    	gridLayout.numColumns=newButtonText.length+2;
423
	    }else{
424
	    	gridLayout.numColumns=2;
425
	    }
426
	    parent.setLayout(gridLayout);
427

    
428
        super.createButtonsForButtonBar(parent);
429
        super.getButton(IDialogConstants.OK_ID).setEnabled(false);
430
    }
431

    
432
	protected SelectionListener getNewWizardButtonSelectionListener(){
433
		return new SelectionAdapter() {
434

    
435
			@Override
436
			public void widgetSelected(SelectionEvent e) {
437
			    Object source = e.getSource();
438
			    String text = null;
439
			    if (source instanceof Button){
440
			        Button sourceButton = (Button) source;
441
			        text = sourceButton.getText();
442
			    }
443
			    AbstractNewEntityWizard<?> wizard = getNewEntityWizard(text);
444
			    if(wizard != null){
445
			        if (wizard.getEntity() == null){
446
			            wizard.init(null, null);
447
			        }
448
			        if(wizard.getEntity() != null) {
449
			            WizardDialog dialog = new WizardDialog(getShell(), wizard);
450
			            int status = dialog.open();
451

    
452
			            if (status == IStatus.OK) {
453

    
454
			                T entity = (T) wizard.getEntity();
455
			                refresh();
456
			                setPattern(entity);
457

    
458
//			                if (getConversationHolder() != null){
459
//			                    getConversationHolder().bind();
460
//			                }
461
			            }
462
			            //FIXME : Need to make sure this is a stable fix (ticket 3822)
463
//			            if (getConversationHolder() != null){
464
//			                getConversationHolder().commit();
465
//			            }
466
			        }
467
			    }
468
			}
469
		};
470
	}
471

    
472
	/**
473
	 * <p>getConversationHolder</p>
474
	 *
475
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
476
//	 */
477
//	@Override
478
//	public ConversationHolder getConversationHolder() {
479
//		return conversation;
480
//	}
481

    
482
	/** {@inheritDoc} */
483
//	@Override
484
//	public void update(CdmDataChangeMap changeEvents) {}
485

    
486
	/**
487
	 * Don't want to add for example a taxon or synonym to itself
488
	 * so filter the list to remove the taxon in question
489
	 * (<code>cdmBaseToBeFiltered</code>)
490
	 * so it is not available in the filtered list.
491
	 */
492
	private void filterExcludedObjects() {
493
		if (model != null && cdmBaseToBeFiltered != null) {
494

    
495
			UuidAndTitleCache<?> uuidAndTitleCacheToRemove = null;
496

    
497
			for (UuidAndTitleCache<?> uuidAndTitleCache : model){
498
				if (cdmBaseToBeFiltered != null && cdmBaseToBeFiltered.contains(uuidAndTitleCache.getUuid())) {
499
					uuidAndTitleCacheToRemove = uuidAndTitleCache;
500
				}
501
			}
502
			model.remove(uuidAndTitleCacheToRemove);
503
		}
504
	}
505
	@Override
506
	void createFilterButton(Composite searchAndFilter){
507
	    //as default no filter button available
508
	}
509

    
510
    @Override
511
    protected void search() {
512
        Control control =getSearchField();
513
        String pattern = null;
514
        if (control != null){
515
            pattern = ((Text)control).getText();
516
            if (pattern.equals("*") || pattern.equals("?")){
517
                callService(null);
518
            }else if (StringUtils.isNotBlank(pattern)){
519
//                callService(CdmUtils.replaceNonWordCharacters(pattern, "."));
520
                callService(pattern);
521
            }
522
            fillContentProvider(null);
523
        }
524

    
525
//        if (pattern.equals("?")){
526
//            model = CdmStore.getService(INameService.class).getUuidAndTitleCache(null, null);
527
//        }else if (pattern != null){
528
//            model = CdmStore.getService(INameService.class).getUuidAndTitleCache(limitOfInitialElements, pattern);
529
//        }
530
    }
531

    
532
    abstract void callService(String pattern);
533

    
534
}
(2-2/45)