Merge branch 'release/5.1.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / dialog / selection / AbstractFilteredCdmResourceSelectionDialog.java
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 }