Merge branch 'hotfix/4.12.1'
[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.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.core.runtime.IStatus;
24 import org.eclipse.jface.dialogs.IDialogSettings;
25 import org.eclipse.jface.viewers.ILabelProvider;
26 import org.eclipse.jface.viewers.LabelProvider;
27 import org.eclipse.jface.viewers.StructuredSelection;
28 import org.eclipse.jface.window.Window;
29 import org.eclipse.jface.wizard.WizardDialog;
30 import org.eclipse.swt.SWT;
31 import org.eclipse.swt.events.SelectionAdapter;
32 import org.eclipse.swt.events.SelectionEvent;
33 import org.eclipse.swt.events.SelectionListener;
34 import org.eclipse.swt.graphics.Cursor;
35 import org.eclipse.swt.widgets.Button;
36 import org.eclipse.swt.widgets.Composite;
37 import org.eclipse.swt.widgets.Control;
38 import org.eclipse.swt.widgets.Shell;
39 import org.eclipse.swt.widgets.Text;
40
41 import eu.etaxonomy.cdm.model.common.CdmBase;
42 import eu.etaxonomy.cdm.model.common.ICdmBase;
43 import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
44 import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
45 import eu.etaxonomy.taxeditor.l10n.Messages;
46 import eu.etaxonomy.taxeditor.model.MessagingUtils;
47 import eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard;
48 import eu.etaxonomy.taxeditor.preference.IPreferenceKeys;
49 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
50 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
51
52 /**
53 * <p>Abstract AbstractFilteredCdmResourceSelectionDialog class.</p>
54 *
55 * @author n.hoffmann
56 * @created 04.06.2009
57 * @version 1.0
58 */
59 public abstract class AbstractFilteredCdmResourceSelectionDialog<T extends ICdmBase> extends
60 SearchDialog {//implements IConversationEnabled {
61
62 // private final ConversationHolder conversation = null;
63
64 protected List<UuidAndTitleCache<T>> model;
65 private final Set<T> transientCdmObjects = new HashSet<T>();
66 private final String settings;
67 protected final int limitOfInitialElements = 100;
68
69 private T selectedObject;
70
71 protected T cdmBaseToBeFiltered;
72
73
74 /**
75 * <p>Constructor for AbstractFilteredCdmResourceSelectionDialog.</p>
76 *
77 * @param shell a {@link org.eclipse.swt.widgets.Shell} object.
78 * @param conversation
79 * @param title a {@link java.lang.String} object.
80 * @param multi a boolean.
81 * @param settings a {@link java.lang.String} object.
82 * @param cdmObject a T object.
83 * @param <T> a T object.
84 */
85 protected AbstractFilteredCdmResourceSelectionDialog(Shell shell, //ConversationHolder conversation,
86 String title, boolean multi, String settings, T cdmObject) {
87 super(shell, multi);
88 setShellStyle(SWT.DIALOG_TRIM);
89 setTitle(title);
90 setMessage(Messages.SearchDialog_patternLabel);
91 this.settings = settings;
92
93 // this.conversation = conversation;
94 this.cdmBaseToBeFiltered = cdmObject;
95 Cursor cursor = shell.getCursor();
96 shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
97 init();
98 shell.setCursor(cursor);
99 setListLabelProvider(createListLabelProvider());
100
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 /**
115 *
116 * @return
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
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 int result = dialog.open();
139
140 if (result == Window.CANCEL) {
141 return null;
142 }
143
144 UuidAndTitleCache uuid = dialog.getSelectedUuidAndTitleCache();
145 if(uuid == null){
146 return null;
147 }
148 return dialog.getCdmObjectByUuid(uuid.getUuid());
149 }
150
151 /**
152 * Check if object was created during the life of this dialog. If not,
153 * retrieve it from the CdmStore.
154 *
155 * @param cdmUuid a {@link java.util.UUID} object.
156 * @return a T object.
157 */
158 protected T getCdmObjectByUuid(UUID cdmUuid) {
159 for (T cdmObject : transientCdmObjects) {
160 if (cdmObject.getUuid().equals(cdmUuid)) {
161 return cdmObject;
162 }
163 }
164 return getPersistentObject(cdmUuid);
165 }
166
167 /**
168 * <p>getPersistentObject</p>
169 *
170 * @param uuid a {@link java.util.UUID} object.
171 * @return a T object.
172 */
173 abstract protected T getPersistentObject(UUID uuid);
174
175
176 /**
177 * <p>isObjectTransient</p>
178 *
179 * @param cdmObject a T object.
180 * @return a boolean.
181 */
182 protected boolean isObjectTransient(T cdmObject) {
183 return (getPersistentObject(cdmObject.getUuid()) == null);
184 }
185
186 /**
187 * <p>getTitle</p>
188 *
189 * @param cdmObject a T object.
190 * @return a {@link java.lang.String} object.
191 */
192 protected String getTitle(T cdmObject) {
193 if(cdmObject == null){
194 return "";
195 }
196
197 if (cdmObject instanceof IIdentifiableEntity) {
198 return ((IIdentifiableEntity) cdmObject).getTitleCache();
199 }
200
201 throw new IllegalArgumentException("Generic method only" +
202 " supports cdmObject of type IIdentifiableEntity." +
203 " Please implement specific method in subclass.");
204 }
205
206
207
208 /**
209 * Set the filter input to the Agent's title cache
210 *
211 * @param cdmObject a T object.
212 */
213 protected void setPattern(T cdmObject) {
214 String pattern = getTitle(cdmObject);
215 getSearchField().setText(pattern);
216 }
217
218
219
220 /* (non-Javadoc)
221 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#fillContentProvider(org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.AbstractContentProvider, org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter, org.eclipse.core.runtime.IProgressMonitor)
222 */
223 /** {@inheritDoc} */
224
225 @Override
226 protected void fillContentProvider(IProgressMonitor progressMonitor)
227 {
228 try {
229 if (model == null){
230 model = new ArrayList<UuidAndTitleCache<T>>();
231 }
232 if(model != null){
233 if (progressMonitor != null){
234 progressMonitor.beginTask("Looking for entities", model.size());
235 }
236 Collections.sort(model, getItemsComparator());
237 contentProvider.reset();
238 Iterator<UuidAndTitleCache<T>> iterator = model.iterator();
239 UuidAndTitleCache<T> element;
240 while(iterator.hasNext()){
241 element = iterator.next();
242 if (!element.equals(cdmBaseToBeFiltered)){
243 contentProvider.add(element);
244 }
245 if (progressMonitor != null){
246 if (progressMonitor.isCanceled()) {
247 return;
248 }
249 progressMonitor.worked(1);
250 }
251 }
252 this.refresh();
253 }else{
254
255 MessagingUtils.warn(getClass(), "Model for Filtered Selection is null:" + this.getClass().getSimpleName());
256 }
257 }
258 finally {
259 if (progressMonitor != null) {
260 progressMonitor.done();
261 }
262 }
263 }
264
265 /* (non-Javadoc)
266 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getDialogSettings()
267 */
268 /** {@inheritDoc} */
269
270 protected IDialogSettings getDialogSettings() {
271 IDialogSettings settings = TaxeditorStorePlugin.getDefault().getDialogSettings().getSection(getSettings());
272
273 if (settings == null) {
274 settings = TaxeditorStorePlugin.getDefault().getDialogSettings().addNewSection(getSettings());
275 }
276 return settings;
277 }
278
279 /* (non-Javadoc)
280 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getElementName(java.lang.Object)
281 */
282 /** {@inheritDoc} */
283
284 public String getElementName(Object item) {
285 return ((UuidAndTitleCache) item).getTitleCache();
286 }
287
288 /* (non-Javadoc)
289 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getItemsComparator()
290 */
291 /** {@inheritDoc} */
292
293 @Override
294 protected Comparator getItemsComparator() {
295 return new Comparator<UuidAndTitleCache>() {
296 @Override
297 public int compare(UuidAndTitleCache entity1,
298 UuidAndTitleCache entity2) {
299 Collator collator = Collator.getInstance();
300 if (entity1 == entity2){
301 return 0;
302 }
303
304 if (entity1 == null && entity2 != null){
305 return -1;
306 }
307 if (entity2 == null && entity1 != null){
308 return 1;
309 }
310 if (entity1.getUuid().equals(entity2.getUuid())){
311 return 0;
312 }
313 if (entity1.getTitleCache() == null && entity2.getTitleCache() != null){
314 return -1;
315 }
316 if (entity2.getTitleCache() == null){
317 return 1;
318 }
319 int result = collator.compare(entity1.getTitleCache(), entity2.getTitleCache());
320 if (result == 0){
321 result = entity1.getUuid().compareTo(entity2.getUuid());
322 }
323 return result;
324 }
325 };
326 }
327
328
329 /**
330 * <p>getSelectedUuidAndTitleCache</p>
331 *
332 * @return a {@link eu.etaxonomy.cdm.model.common.UuidAndTitleCache} object.
333 */
334 protected UuidAndTitleCache getSelectedUuidAndTitleCache() {
335 Object result = getResult();
336 if (result instanceof UuidAndTitleCache){
337 return (UuidAndTitleCache) result;
338 }
339 return null;
340 }
341
342 /**
343 * @return
344 */
345 private Object getResult() {
346 StructuredSelection selection = getCurrentSelection();
347 if (selection == null){
348 return null;
349 }
350 return selection.getFirstElement();
351 }
352
353 /**
354 * <p>Getter for the field <code>settings</code>.</p>
355 *
356 * @return a {@link java.lang.String} object.
357 */
358 public String getSettings() {
359 if(settings == null){
360 throw new IllegalStateException("No SETTINGS set.");
361 }
362 return settings;
363 }
364
365
366
367 /**
368 * <p>getNewWizardLinkText</p>
369 *
370 * @return a {@link java.lang.String} object.
371 */
372 protected abstract String[] getNewWizardText();
373
374 /**
375 * <p>getNewEntityWizard</p>
376 * @param parameter
377 * @return a {@link eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard} object.
378 */
379 protected abstract AbstractNewEntityWizard getNewEntityWizard(String parameter);
380
381 public class FilteredCdmResourceLabelProvider extends LabelProvider {
382 @Override
383 public String getText(Object element) {
384 if (element == null) {
385 return null;
386 }
387 UuidAndTitleCache uuidAndTitleCache = (UuidAndTitleCache) element;
388 String titleCache = uuidAndTitleCache.getTitleCache();
389 if(PreferencesUtil.getPreferenceStore().getBoolean(IPreferenceKeys.SHOW_ID_IN_ENTITY_SELECTION_DIAOLOG)){
390 titleCache += " ["+uuidAndTitleCache.getId()+"]";
391 }
392 return titleCache;
393 }
394 };
395
396 /* (non-Javadoc)
397 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createExtendedContentArea(org.eclipse.swt.widgets.Composite)
398 */
399 /** {@inheritDoc} */
400
401 // @Override
402 // protected Control createExtendedContentArea(Composite parent) {
403 // String newWizardLinkText = getNewWizardLinkText();
404 //// if(newWizardLinkText != null){
405 //// newButton1 = this.createButton(this.getShell(), new_id, newWizardLinkText, false);
406 ////
407 //// newButton1.addSelectionListener(getNewWizardLinkSelectionListener());
408 //// return newButton1;
409 //// }
410 // return null;
411 // }
412
413 @Override
414 protected void createButtonsForButtonBar(Composite parent) {
415 String[] newButtonText = getNewWizardText();
416 if (newButtonText!= null){
417 this.newButton1 = createButton(parent, this.new_id, newButtonText[0], false);
418 newButton1.addSelectionListener(getNewWizardButtonSelectionListener());
419 if (newButtonText.length > 1){
420 newButton2 = createButton(parent, this.new_id2, newButtonText[1], false);
421 newButton2.addSelectionListener(getNewWizardButtonSelectionListener());
422 }
423 }
424 //Label label = new Label(parent, SWT.NONE);
425 super.createButtonsForButtonBar(parent);
426 }
427
428 protected SelectionListener getNewWizardButtonSelectionListener(){
429 return new SelectionAdapter() {
430
431 /* (non-Javadoc)
432 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
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 wizard.init(null, null);
445 if(wizard.getEntity() != null) {
446 WizardDialog dialog = new WizardDialog(getShell(), wizard);
447 int status = dialog.open();
448
449 if (status == IStatus.OK) {
450
451 T entity = (T) wizard.getEntity();
452 refresh();
453 setPattern(entity);
454 // if (getConversationHolder() != null){
455 // getConversationHolder().bind();
456 // }
457 }
458 //FIXME : Need to make sure this is a stable fix (ticket 3822)
459 // if (getConversationHolder() != null){
460 // getConversationHolder().commit();
461 // }
462 }
463 }
464 }
465 };
466 }
467
468 /**
469 * <p>getConversationHolder</p>
470 *
471 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
472 // */
473 // @Override
474 // public ConversationHolder getConversationHolder() {
475 // return conversation;
476 // }
477
478 /** {@inheritDoc} */
479 // @Override
480 // public void update(CdmDataChangeMap changeEvents) {}
481
482 /**
483 * Don't want to add for example a taxon or synonym to itself
484 * so filter the list to remove the taxon in question
485 * (<code>cdmBaseToBeFiltered</code>)
486 * so it is not available in the filtered list.
487 */
488 private void filterExcludedObjects() {
489 if (model != null && cdmBaseToBeFiltered != null) {
490
491 UuidAndTitleCache uuidAndTitleCacheToRemove = null;
492
493 for (UuidAndTitleCache uuidAndTitleCache : model){
494 if ((cdmBaseToBeFiltered.getUuid()).equals(uuidAndTitleCache.getUuid())) {
495 uuidAndTitleCacheToRemove = uuidAndTitleCache;
496 }
497 }
498 model.remove(uuidAndTitleCacheToRemove);
499 }
500 }
501 @Override
502 void createFilterButton(Composite searchAndFilter){
503 //as default no filter button available
504 }
505
506 /** {@inheritDoc} */
507 @Override
508 protected void search() {
509 Control control =getSearchField();
510 String pattern = null;
511 if (control != null){
512 pattern = ((Text)control).getText();
513 if (pattern.equals("*") || pattern.equals("?")){
514 callService(null);
515 }else if (pattern != null){
516 callService(pattern);
517 }
518 fillContentProvider(null);
519 }
520
521 // if (pattern.equals("?")){
522 // model = CdmStore.getService(INameService.class).getUuidAndTitleCache(null, null);
523 // }else if (pattern != null){
524 // model = CdmStore.getService(INameService.class).getUuidAndTitleCache(limitOfInitialElements, pattern);
525 // }
526 }
527
528 abstract void callService(String pattern);
529
530 }