Project

General

Profile

Download (16.3 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.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
66
		SearchDialog<T> {//implements IConversationEnabled {
67

    
68
//	private final ConversationHolder conversation = null;
69

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

    
75
	protected Set<UUID> cdmBaseToBeFiltered;
76

    
77
	protected Job searchJob;
78

    
79
	protected AbstractFilteredCdmResourceSelectionDialog(Shell shell, //ConversationHolder conversation,
80
	        String title, boolean multi, String settings, Set<T> objectsToBeFiltered) {
81
	    super(shell, title);
82
        setShellStyle(SWT.DIALOG_TRIM);
83
        setMessage(Messages.SearchDialog_patternLabel);
84
        this.settings = settings;
85
        if (objectsToBeFiltered != null){
86
            this.cdmBaseToBeFiltered = new HashSet<>();
87
            objectsToBeFiltered.forEach(filter->this.cdmBaseToBeFiltered.add(filter.getUuid()));
88
        }
89
        Cursor cursor = shell.getCursor();
90
        shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
91
        init();
92
        shell.setCursor(cursor);
93
        setListLabelProvider(createListLabelProvider());
94

    
95
	}
96

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

    
102
	protected AbstractFilteredCdmResourceSelectionDialog(Shell shell, //ConversationHolder conversation,
103
	        String title, boolean multi, String settings, T objectToBeFiltered) {
104
	    this(shell, title, multi, settings, objectToBeFiltered!=null?Collections.singleton(objectToBeFiltered):null);
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
	protected ILabelProvider createListLabelProvider() {
119
		return new FilteredCdmResourceLabelProvider();
120
	}
121

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

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

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

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

    
161
        UuidAndTitleCache uuid = dialog.getSelectedUuidAndTitleCache();
162

    
163
        return uuid;
164
    }
165

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

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

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

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

    
211
		if (cdmObject instanceof IIdentifiableEntity) {
212
			return ((IIdentifiableEntity) cdmObject).getTitleCache();
213
		}
214

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

    
220
	/**
221
	 * Set the filter input to the Agent's title cache
222
	 *
223
	 * @param cdmObject a T object.
224
	 */
225
	protected void setPattern(T cdmObject) {
226
		String pattern = getTitle(cdmObject);
227
		getSearchField().setText(pattern);
228
	}
229

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

    
243
			    contentProvider.reset();
244
				Iterator<UuidAndTitleCache<T>> iterator = model.iterator();
245
				UuidAndTitleCache<T> element;
246
				while(iterator.hasNext()){
247
				    element = iterator.next();
248

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

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

    
272
    protected void sort() {
273
        Collections.sort(model, getItemsComparator());
274
    }
275

    
276
	protected IDialogSettings getDialogSettings() {
277
		IDialogSettings settings = TaxeditorStorePlugin.getDefault().getDialogSettings().getSection(getSettings());
278

    
279
		if (settings == null) {
280
			settings = TaxeditorStorePlugin.getDefault().getDialogSettings().addNewSection(getSettings());
281
		}
282
		return settings;
283
	}
284

    
285
	public String getElementName(Object item) {
286
		return ((UuidAndTitleCache<T>) item).getTitleCache();
287
	}
288

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

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

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

    
337
    private Object getResult() {
338
        StructuredSelection selection = getCurrentSelection();
339
        if (selection == null){
340
            return null;
341
        }
342
        return selection.getFirstElement();
343
    }
344

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

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

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

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

    
386
            return titleCache;
387
		}
388
	}
389

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

    
402
	@Override
403
    protected void createButtonsForButtonBar(Composite parent) {
404
	    String[] newButtonText = getNewWizardText();
405

    
406
	    if (newButtonText!= null){
407
	        this.newButton1 = createButton(parent, this.new_id, newButtonText[0], false);
408
	        newButton1.addSelectionListener(getNewWizardButtonSelectionListener());
409

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

    
431
        super.createButtonsForButtonBar(parent);
432
        super.getButton(IDialogConstants.OK_ID).setEnabled(false);
433
    }
434

    
435
	protected SelectionListener getNewWizardButtonSelectionListener(){
436
		return new SelectionAdapter() {
437

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

    
455
			            if (status == IStatus.OK) {
456

    
457
			                T entity = (T) wizard.getEntity();
458
			                refresh();
459
			                setPattern(entity);
460

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

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

    
485
	/** {@inheritDoc} */
486
//	@Override
487
//	public void update(CdmDataChangeMap changeEvents) {}
488

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

    
498
			UuidAndTitleCache<?> uuidAndTitleCacheToRemove = null;
499

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

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

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

    
535
    abstract void callService(String pattern);
536

    
537
}
(2-2/45)