1 package eu
.etaxonomy
.taxeditor
.ui
.dialog
.selection
;
3 import java
.text
.Collator
;
5 * Copyright (C) 2007 EDIT
6 * European Distributed Institute of Taxonomy
7 * http://www.e-taxonomy.eu
9 * The contents of this file are subject to the Mozilla Public License Version 1.1
10 * See LICENSE.TXT at the top of this package for the full license terms.
12 import java
.util
.Comparator
;
13 import java
.util
.HashSet
;
14 import java
.util
.Iterator
;
15 import java
.util
.List
;
17 import java
.util
.UUID
;
19 import org
.eclipse
.core
.runtime
.CoreException
;
20 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
21 import org
.eclipse
.core
.runtime
.IStatus
;
22 import org
.eclipse
.core
.runtime
.OperationCanceledException
;
23 import org
.eclipse
.core
.runtime
.Status
;
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
.window
.Window
;
28 import org
.eclipse
.jface
.wizard
.WizardDialog
;
29 import org
.eclipse
.swt
.SWT
;
30 import org
.eclipse
.swt
.events
.SelectionAdapter
;
31 import org
.eclipse
.swt
.events
.SelectionEvent
;
32 import org
.eclipse
.swt
.events
.SelectionListener
;
33 import org
.eclipse
.swt
.widgets
.Composite
;
34 import org
.eclipse
.swt
.widgets
.Control
;
35 import org
.eclipse
.swt
.widgets
.Link
;
36 import org
.eclipse
.swt
.widgets
.Shell
;
37 import org
.eclipse
.swt
.widgets
.Text
;
38 import org
.eclipse
.ui
.IMemento
;
40 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
41 import eu
.etaxonomy
.cdm
.api
.conversation
.IConversationEnabled
;
42 import eu
.etaxonomy
.cdm
.api
.service
.dto
.IdentifiedEntityDTO
;
43 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
44 import eu
.etaxonomy
.cdm
.model
.common
.ICdmBase
;
45 import eu
.etaxonomy
.cdm
.model
.common
.IIdentifiableEntity
;
46 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
47 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
48 import eu
.etaxonomy
.taxeditor
.newWizard
.AbstractNewEntityWizard
;
49 import eu
.etaxonomy
.taxeditor
.preference
.IPreferenceKeys
;
50 import eu
.etaxonomy
.taxeditor
.preference
.PreferencesUtil
;
51 import eu
.etaxonomy
.taxeditor
.store
.internal
.TaxeditorStorePlugin
;
53 public abstract class AbstractFilteredIdentifierSelectionDialog
<T
extends ICdmBase
> extends CdmFilteredItemsSelectionDialog
implements IConversationEnabled
{
55 private final ConversationHolder conversation
;
57 protected List
<IdentifiedEntityDTO
> model
;
58 private final Set
<T
> transientCdmObjects
= new HashSet
<T
>();
59 private final String settings
;
60 protected final int limitOfInitialElements
= 100;
62 protected T cdmBaseToBeFiltered
;
66 * <p>Constructor for AbstractFilteredCdmResourceSelectionDialog.</p>
68 * @param shell a {@link org.eclipse.swt.widgets.Shell} object.
70 * @param title a {@link java.lang.String} object.
71 * @param multi a boolean.
72 * @param settings a {@link java.lang.String} object.
73 * @param cdmObject a T object.
74 * @param <T> a T object.
76 protected AbstractFilteredIdentifierSelectionDialog(Shell shell
, ConversationHolder conversation
, String title
, boolean multi
, String settings
, T cdmObject
) {
79 setMessage("Use * for wildcard, or ? to see all entries");
80 this.settings
= settings
;
82 this.conversation
= conversation
;
83 this.cdmBaseToBeFiltered
= cdmObject
;
84 org
.eclipse
.swt
.graphics
.Cursor cursor
= shell
.getCursor();
85 shell
.setCursor(shell
.getDisplay().getSystemCursor(SWT
.CURSOR_WAIT
));
88 shell
.setCursor(cursor
);
89 String objectTitle
= getTitle(cdmObject
);
90 // if (objectTitle != null) {
91 // setInitialPattern(objectTitle);
94 setListLabelProvider(createListLabelProvider());
95 setDetailsLabelProvider(createDetailsLabelProvider());
97 setSelectionHistory(new IdentifierSelectionHistory());
101 * By default, we are returning the standard list label provider
103 * Override in subclasses if you want different behavior
107 protected ILabelProvider
createDetailsLabelProvider() {
108 return createListLabelProvider();
115 protected ILabelProvider
createListLabelProvider() {
116 return new FilteredIdentifiedEntityLabelProvider();
120 * Override in subclasses.
121 * Will run before initModel()
123 protected void init() {
128 * <p>getSelectionFromDialog</p>
130 * @param dialog a {@link eu.etaxonomy.taxeditor.ui.dialog.selection.AbstractFilteredCdmResourceSelectionDialog} object.
131 * @param <TYPE> a TYPE object.
132 * @return a TYPE object.
134 protected static <TYPE
extends CdmBase
> TYPE
getSelectionFromDialog(AbstractFilteredCdmResourceSelectionDialog
<TYPE
> dialog
) {
135 //dialog.setInitialPattern("");
136 int result
= dialog
.open();
138 if (result
== Window
.CANCEL
) {
142 UUID uuid
= dialog
.getSelectedUuidAndTitleCache().getUuid();
146 return dialog
.getCdmObjectByUuid(uuid
);
150 * Check if object was created during the life of this dialog. If not,
151 * retrieve it from the CdmStore.
153 * @param cdmUuid a {@link java.util.UUID} object.
154 * @return a T object.
156 protected T
getCdmObjectByUuid(UUID cdmUuid
) {
157 for (T cdmObject
: transientCdmObjects
) {
158 if (cdmObject
.getUuid().equals(cdmUuid
)) {
162 return getPersistentObject(cdmUuid
);
166 * <p>getPersistentObject</p>
168 * @param uuid a {@link java.util.UUID} object.
169 * @return a T object.
171 abstract protected T
getPersistentObject(UUID uuid
);
176 // protected void addObjectToModel(T cdmObject) {
177 // model.add(new UuidAndTitleCache(cdmObject.getClass(), cdmObject.getUuid(), getTitle(cdmObject)));
178 // transientCdmObjects.add(cdmObject);
182 * <p>isObjectTransient</p>
184 * @param cdmObject a T object.
187 protected boolean isObjectTransient(T cdmObject
) {
188 return (getPersistentObject(cdmObject
.getUuid()) == null);
194 * @param cdmObject a T object.
195 * @return a {@link java.lang.String} object.
197 protected String
getTitle(T cdmObject
) {
198 if(cdmObject
== null){
202 if (cdmObject
instanceof IIdentifiableEntity
) {
203 return ((IIdentifiableEntity
) cdmObject
).getTitleCache();
206 throw new IllegalArgumentException("Generic method only" +
207 " supports cdmObject of type IIdentifiableEntity." +
208 " Please implement specific method in subclass.");
214 public void refresh() {
221 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createFilter()
225 protected ItemsFilter
createFilter() {
226 return new ItemsFilter() {
229 * Always returns false to enforce refiltering even if the pattern is equal
232 public boolean equalsFilter(ItemsFilter filter
) {
237 public boolean isConsistentItem(Object item
) {
242 public boolean matchItem(Object item
) {
244 if(item
instanceof IdentifiedEntityDTO
){
245 text
= ((IdentifiedEntityDTO
) item
).getCdmEntity().getTitleCache();
246 }else if(item
instanceof String
){
247 text
= (String
) item
;
249 return text
!= null ?
matches(text
) : false;
257 * Set the filter input to the Agent's title cache
259 * @param cdmObject a T object.
261 protected void setPattern(T cdmObject
) {
262 // FilteredSelection does some very tricky caching to make sure it
263 // runs with high performance.
264 // This works for most use cases, but we want to change the model while the dialog is open
265 // and all the clever caching prevents the content provider from knowing that the model has changed
266 // I am aware, that this is a hack, but the FilteredSelectionDialog API does not offer a convenient
267 // way to solve the problem.
269 // Field lastCompletedFilter = this.getClass().getSuperclass().getSuperclass().getDeclaredField("lastCompletedFilter");
270 // lastCompletedFilter.setAccessible(true);
271 // lastCompletedFilter.set(this, null);
272 // } catch (SecurityException e) {
273 // MessagingUtils.error(getClass(), e);
274 // } catch (NoSuchFieldException e) {
275 // MessagingUtils.error(getClass(), e);
276 // } catch (IllegalArgumentException e) {
277 // MessagingUtils.error(getClass(), e);
278 // } catch (IllegalAccessException e) {
279 // MessagingUtils.error(getClass(), e);
282 // this also is not the nicest way to do it.
283 // I am still amazed, that FilteredSelectionDialog does not offer any methods to change its data
284 // once it was opened. Am I doing it wrong?
285 String pattern
= getTitle(cdmObject
);
286 ((Text
) getPatternControl()).setText(pattern
);
292 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#fillContentProvider(org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.AbstractContentProvider, org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter, org.eclipse.core.runtime.IProgressMonitor)
296 protected void fillContentProvider(AbstractContentProvider contentProvider
,
297 ItemsFilter itemsFilter
, IProgressMonitor progressMonitor
)
298 throws CoreException
{
301 progressMonitor
.beginTask("Looking for entities", model
.size());
302 filterExcludedObjects();
303 Iterator
<IdentifiedEntityDTO
> iterator
= model
.iterator();
304 IdentifiedEntityDTO element
;
305 while(iterator
.hasNext()){
306 element
= iterator
.next();
307 if (!element
.equals(cdmBaseToBeFiltered
)){
308 contentProvider
.add(element
, itemsFilter
);
310 if (progressMonitor
.isCanceled()) {
311 throw new OperationCanceledException();
313 progressMonitor
.worked(1);
316 MessagingUtils
.warn(getClass(), "Model for Filtered Selection is null:" + this.getClass().getSimpleName());
320 progressMonitor
.done();
325 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getDialogSettings()
329 protected IDialogSettings
getDialogSettings() {
330 IDialogSettings settings
= TaxeditorStorePlugin
.getDefault().getDialogSettings().getSection(getSettings());
332 if (settings
== null) {
333 settings
= TaxeditorStorePlugin
.getDefault().getDialogSettings().addNewSection(getSettings());
339 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getElementName(java.lang.Object)
343 public String
getElementName(Object item
) {
344 return ((IdentifiedEntityDTO
) item
).getCdmEntity().getTitleCache();
348 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getItemsComparator()
352 protected Comparator
getItemsComparator() {
353 return new Comparator
<IdentifiedEntityDTO
>() {
355 public int compare(IdentifiedEntityDTO entity1
,
356 IdentifiedEntityDTO entity2
) {
357 Collator collator
= Collator
.getInstance();
358 if (entity1
.getCdmEntity().getCdmUuid().equals(entity2
.getCdmEntity().getCdmUuid())){
361 int result
= collator
.compare(entity1
.getCdmEntity().getTitleCache(), entity2
.getCdmEntity().getTitleCache());
363 result
= entity1
.getCdmEntity().getCdmUuid().compareTo(entity2
.getCdmEntity().getCdmUuid());
371 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#validateItem(java.lang.Object)
375 protected IStatus
validateItem(Object item
) {
376 return Status
.OK_STATUS
;
380 * <p>getSelectedUuidAndTitleCache</p>
382 * @return a {@link eu.etaxonomy.cdm.model.common.UuidAndTitleCache} object.
384 protected IdentifiedEntityDTO
getSelectedUuidAndTitleCache() {
385 Object
[] result
= getResult();
386 return result
[0] == null ?
null : (IdentifiedEntityDTO
) result
[0];
390 * <p>Getter for the field <code>settings</code>.</p>
392 * @return a {@link java.lang.String} object.
394 public String
getSettings() {
395 if(settings
== null){
396 throw new IllegalStateException("No SETTINGS set.");
404 * @created Oct 19, 2009
407 private class IdentifierSelectionHistory
extends SelectionHistory
{
409 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#restoreItemFromMemento(org.eclipse.ui.IMemento)
412 protected Object
restoreItemFromMemento(IMemento element
) {
413 return element
.getString("resource"); //$NON-NLS-1$
416 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#storeItemToMemento(java.lang.Object,
417 * org.eclipse.ui.IMemento)
420 protected void storeItemToMemento(Object item
, IMemento element
) {
421 element
.putString("resource", item
.toString()); //$NON-NLS-1$
426 * <p>getNewWizardLinkText</p>
428 * @return a {@link java.lang.String} object.
430 protected abstract String
getNewWizardLinkText();
433 * <p>getNewEntityWizard</p>
435 * @return a {@link eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard} object.
437 protected abstract AbstractNewEntityWizard
getNewEntityWizard(String parameter
);
439 public class FilteredIdentifiedEntityLabelProvider
extends LabelProvider
{
441 public String
getText(Object element
) {
442 if (element
== null) {
445 IdentifiedEntityDTO identifiedEntity
= (IdentifiedEntityDTO
) element
;
446 String titleCache
= identifiedEntity
.getCdmEntity().getTitleCache();
447 if(PreferencesUtil
.getPreferenceStore().getBoolean(IPreferenceKeys
.SHOW_ID_IN_ENTITY_SELECTION_DIAOLOG
)){
448 titleCache
+= " ["+identifiedEntity
.getCdmEntity().getCdmUuid()+"]";
455 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createExtendedContentArea(org.eclipse.swt.widgets.Composite)
459 protected Control
createExtendedContentArea(Composite parent
) {
460 String newWizardLinkText
= getNewWizardLinkText();
461 if(newWizardLinkText
!= null){
462 Link link
= new Link(parent
, SWT
.NONE
);
463 link
.setText(newWizardLinkText
);
464 link
.addSelectionListener(getNewWizardLinkSelectionListener());
470 protected SelectionListener
getNewWizardLinkSelectionListener(){
471 return new SelectionAdapter() {
474 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
477 public void widgetSelected(SelectionEvent e
) {
479 AbstractNewEntityWizard wizard
= getNewEntityWizard(e
.text
);
481 wizard
.init(null, null);
482 if(wizard
.getEntity() != null) {
483 WizardDialog dialog
= new WizardDialog(getShell(), wizard
);
484 int status
= dialog
.open();
486 if (status
== IStatus
.OK
) {
488 T entity
= (T
) wizard
.getEntity();
489 // model.add(new UuidAndTitleCache<T>(entity.getUuid(), entity.getId(), getTitle(entity)));
492 if (getConversationHolder() != null){
493 getConversationHolder().bind();
496 //FIXME : Need to make sure this is a stable fix (ticket 3822)
497 if (getConversationHolder() != null){
498 getConversationHolder().commit();
507 * <p>getConversationHolder</p>
509 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
512 public ConversationHolder
getConversationHolder() {
518 public void update(CdmDataChangeMap changeEvents
) {}
521 * Don't want to add for example a taxon or synonym to itself
522 * so filter the list to remove the taxon in question
523 * (<code>cdmBaseToBeFiltered</code>)
524 * so it is not available in the filtered list.
526 private void filterExcludedObjects() {
527 if (model
!= null && cdmBaseToBeFiltered
!= null) {
529 IdentifiedEntityDTO identifiedEntityToRemove
= null;
531 for (IdentifiedEntityDTO identifiedEntity
: model
){
532 if ((cdmBaseToBeFiltered
.getUuid()).equals(identifiedEntity
.getCdmEntity().getCdmUuid())) {
533 identifiedEntityToRemove
= identifiedEntity
;
536 model
.remove(identifiedEntityToRemove
);