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
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
 * <p>Abstract AbstractFilteredCdmResourceSelectionDialog class.</p>
60
 *
61
 * @author n.hoffmann
62
 * @created 04.06.2009
63
 */
64
public abstract class AbstractFilteredCdmResourceSelectionDialog<T extends ICdmBase> extends SearchDialog<T> {
65

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

    
71
	protected Set<UUID> cdmBaseToBeFiltered;
72

    
73
	protected Job searchJob;
74

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

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

    
91
	}
92

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

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

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

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

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

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

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

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

    
157
        UuidAndTitleCache uuid = dialog.getSelectedUuidAndTitleCache();
158

    
159
        return uuid;
160
    }
161

    
162
	/**
163
	 * Check if object was created during the life of this dialog. If not,
164
	 * retrieve it from the CdmStore.
165
	 *
166
	 * @param cdmUuid a {@link java.util.UUID} object.
167
	 * @return a T object.
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
	@Override
227
    protected void fillContentProvider(IProgressMonitor progressMonitor)
228
		 {
229
		try {
230
		    if (model == null){
231
		        model = new ArrayList<UuidAndTitleCache<T>>();
232
		    }
233
			if(model != null){
234
			    if (progressMonitor != null){
235
			        progressMonitor.beginTask("Looking for entities", model.size());
236
			    }
237
			    sort();
238

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

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

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

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

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

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

    
281
	public String getElementName(Object item) {
282
		return ((UuidAndTitleCache<T>) item).getTitleCache();
283
	}
284

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

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

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

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

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

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

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

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

    
382
            return titleCache;
383
		}
384
	}
385

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

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

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

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

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

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

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

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

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

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

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

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

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

    
494
			UuidAndTitleCache<?> uuidAndTitleCacheToRemove = null;
495

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

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

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

    
531
    abstract void callService(String pattern);
532

    
533
}
(2-2/45)