2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.ui
.dialog
.selection
;
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
;
20 import java
.util
.UUID
;
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
;
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
;
60 * <p>Abstract AbstractFilteredCdmResourceSelectionDialog class.</p>
65 public abstract class AbstractFilteredCdmResourceSelectionDialog
<T
extends ICdmBase
> extends
66 SearchDialog
<T
> {//implements IConversationEnabled {
68 // private final ConversationHolder conversation = null;
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;
75 protected Set
<UUID
> cdmBaseToBeFiltered
;
77 protected Job searchJob
;
79 protected AbstractFilteredCdmResourceSelectionDialog(Shell shell
, //ConversationHolder conversation,
80 String title
, boolean multi
, String settings
, Set
<T
> objectsToBeFiltered
) {
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()));
89 Cursor cursor
= shell
.getCursor();
90 shell
.setCursor(shell
.getDisplay().getSystemCursor(SWT
.CURSOR_WAIT
));
92 shell
.setCursor(cursor
);
93 setListLabelProvider(createListLabelProvider());
97 protected AbstractFilteredCdmResourceSelectionDialog(Shell shell
, //ConversationHolder conversation,
98 String title
, boolean multi
, String settings
) {
99 this(shell
, title
, multi
, settings
, (Set
<T
>)null);
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);
108 * By default, we are returning the standard list label provider
110 * Override in subclasses if you want different behavior
114 protected ILabelProvider
createDetailsLabelProvider() {
115 return createListLabelProvider();
118 protected ILabelProvider
createListLabelProvider() {
119 return new FilteredCdmResourceLabelProvider();
123 * Override in subclasses.
124 * Will run before initModel()
126 protected void init() {}
129 * <p>getSelectionFromDialog</p>
131 * @param dialog a {@link eu.etaxonomy.taxeditor.ui.dialog.selection.AbstractFilteredCdmResourceSelectionDialog} object.
132 * @param <TYPE> a TYPE object.
133 * @return a TYPE object.
135 protected static <TYPE
extends CdmBase
> TYPE
getSelectionFromDialog(AbstractFilteredCdmResourceSelectionDialog
<TYPE
> dialog
) {
136 UuidAndTitleCache
<?
> result
= getUuidAndTitleCacheSelectionFromDialog(dialog
);
138 return dialog
.getCdmObjectByUuid(result
.getUuid());
145 * <p>getSelectionFromDialog</p>
147 * @param dialog a {@link eu.etaxonomy.taxeditor.ui.dialog.selection.AbstractFilteredCdmResourceSelectionDialog} object.
148 * @param <TYPE> a TYPE object.
149 * @return a TYPE object.
151 protected static UuidAndTitleCache
getUuidAndTitleCacheSelectionFromDialog(AbstractFilteredCdmResourceSelectionDialog dialog
) {
155 int result
= dialog
.open();
157 if (result
== Window
.CANCEL
) {
161 UuidAndTitleCache uuid
= dialog
.getSelectedUuidAndTitleCache();
167 * Check if object was created during the life of this dialog. If not,
168 * retrieve it from the CdmStore.
170 * @param cdmUuid a {@link java.util.UUID} object.
171 * @return a T object.
173 protected T
getCdmObjectByUuid(UUID cdmUuid
) {
174 for (T cdmObject
: transientCdmObjects
) {
175 if (cdmObject
.getUuid().equals(cdmUuid
)) {
179 return getPersistentObject(cdmUuid
);
183 * <p>getPersistentObject</p>
185 * @param uuid a {@link java.util.UUID} object.
186 * @return a T object.
188 abstract protected T
getPersistentObject(UUID uuid
);
191 * <p>isObjectTransient</p>
193 * @param cdmObject a T object.
196 protected boolean isObjectTransient(T cdmObject
) {
197 return (getPersistentObject(cdmObject
.getUuid()) == null);
203 * @param cdmObject a T object.
204 * @return a {@link java.lang.String} object.
206 protected String
getTitle(T cdmObject
) {
207 if(cdmObject
== null){
211 if (cdmObject
instanceof IIdentifiableEntity
) {
212 return ((IIdentifiableEntity
) cdmObject
).getTitleCache();
215 throw new IllegalArgumentException("Generic method only" +
216 " supports cdmObject of type IIdentifiableEntity." +
217 " Please implement specific method in subclass.");
221 * Set the filter input to the Agent's title cache
223 * @param cdmObject a T object.
225 protected void setPattern(T cdmObject
) {
226 String pattern
= getTitle(cdmObject
);
227 getSearchField().setText(pattern
);
231 protected void fillContentProvider(IProgressMonitor progressMonitor
)
235 model
= new ArrayList
<UuidAndTitleCache
<T
>>();
238 if (progressMonitor
!= null){
239 progressMonitor
.beginTask("Looking for entities", model
.size());
243 contentProvider
.reset();
244 Iterator
<UuidAndTitleCache
<T
>> iterator
= model
.iterator();
245 UuidAndTitleCache
<T
> element
;
246 while(iterator
.hasNext()){
247 element
= iterator
.next();
249 if (cdmBaseToBeFiltered
== null || !cdmBaseToBeFiltered
.contains(element
.getUuid())){
250 contentProvider
.add(element
);
252 if (progressMonitor
!= null){
253 if (progressMonitor
.isCanceled()) {
256 progressMonitor
.worked(1);
262 MessagingUtils
.warn(getClass(), "Model for Filtered Selection is null:" + this.getClass().getSimpleName());
266 if (progressMonitor
!= null) {
267 progressMonitor
.done();
272 protected void sort() {
273 Collections
.sort(model
, getItemsComparator());
276 protected IDialogSettings
getDialogSettings() {
277 IDialogSettings settings
= TaxeditorStorePlugin
.getDefault().getDialogSettings().getSection(getSettings());
279 if (settings
== null) {
280 settings
= TaxeditorStorePlugin
.getDefault().getDialogSettings().addNewSection(getSettings());
285 public String
getElementName(Object item
) {
286 return ((UuidAndTitleCache
<T
>) item
).getTitleCache();
290 protected Comparator
<UuidAndTitleCache
<T
>> getItemsComparator() {
291 return new Comparator
<UuidAndTitleCache
<T
>>() {
293 public int compare(UuidAndTitleCache
<T
> entity1
,
294 UuidAndTitleCache
<T
> entity2
) {
295 Collator collator
= Collator
.getInstance();
296 if (entity1
== entity2
){
300 if (entity1
== null && entity2
!= null){
303 if (entity2
== null && entity1
!= null){
306 if (entity1
.getUuid().equals(entity2
.getUuid())){
309 if (entity1
.getTitleCache() == null && entity2
.getTitleCache() != null){
312 if (entity2
.getTitleCache() == null){
315 int result
= collator
.compare(entity1
.getTitleCache(), entity2
.getTitleCache());
317 result
= entity1
.getUuid().compareTo(entity2
.getUuid());
325 * <p>getSelectedUuidAndTitleCache</p>
327 * @return a {@link eu.etaxonomy.cdm.model.common.UuidAndTitleCache} object.
329 protected UuidAndTitleCache
<T
> getSelectedUuidAndTitleCache() {
330 Object result
= getResult();
331 if (result
instanceof UuidAndTitleCache
){
332 return (UuidAndTitleCache
<T
>) result
;
337 private Object
getResult() {
338 StructuredSelection selection
= getCurrentSelection();
339 if (selection
== null){
342 return selection
.getFirstElement();
346 * <p>Getter for the field <code>settings</code>.</p>
348 * @return a {@link java.lang.String} object.
350 public String
getSettings() {
351 if(settings
== null){
352 throw new IllegalStateException("No SETTINGS set.");
358 * <p>getNewWizardLinkText</p>
360 * @return a {@link java.lang.String} object.
362 protected abstract String
[] getNewWizardText();
365 * <p>getNewEntityWizard</p>
367 * @return a {@link eu.etaxonomy.taxeditor.newWizard.AbstractNewEntityWizard} object.
369 protected abstract AbstractNewEntityWizard
<T
> getNewEntityWizard(String parameter
);
371 public class FilteredCdmResourceLabelProvider
extends LabelProvider
{
373 public String
getText(Object element
) {
374 if (element
== null) {
377 UuidAndTitleCache
<?
> uuidAndTitleCache
= (UuidAndTitleCache
<?
>) element
;
378 String titleCache
= uuidAndTitleCache
.getTitleCache();
379 if(PreferencesUtil
.getBooleanValue(PreferencePredicate
.ShowIdInSelectionDialog
.getKey())){
380 titleCache
+= " ["+uuidAndTitleCache
.getId()+"]";
382 if (element
instanceof EntityDTOBase
){
383 titleCache
+= "(" + ((IdentifiedEntityDTO
)element
).getIdentifier().getTypeLabel() +": " + ((IdentifiedEntityDTO
)element
).getIdentifier().getIdentifier() + ")";
391 // protected Control createExtendedContentArea(Composite parent) {
392 // String newWizardLinkText = getNewWizardLinkText();
393 //// if(newWizardLinkText != null){
394 //// newButton1 = this.createButton(this.getShell(), new_id, newWizardLinkText, false);
396 //// newButton1.addSelectionListener(getNewWizardLinkSelectionListener());
397 //// return newButton1;
403 protected void createButtonsForButtonBar(Composite parent
) {
404 String
[] newButtonText
= getNewWizardText();
406 if (newButtonText
!= null){
407 this.newButton1
= createButton(parent
, this.new_id
, newButtonText
[0], false);
408 newButton1
.addSelectionListener(getNewWizardButtonSelectionListener());
410 if (newButtonText
.length
> 1){
411 newButton2
= createButton(parent
, this.new_id2
, newButtonText
[1], false);
412 newButton2
.addSelectionListener(getNewWizardButtonSelectionListener());
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;
427 gridLayout
.numColumns
=2;
429 parent
.setLayout(gridLayout
);
431 super.createButtonsForButtonBar(parent
);
432 super.getButton(IDialogConstants
.OK_ID
).setEnabled(false);
435 protected SelectionListener
getNewWizardButtonSelectionListener(){
436 return new SelectionAdapter() {
439 public void widgetSelected(SelectionEvent e
) {
440 Object source
= e
.getSource();
442 if (source
instanceof Button
){
443 Button sourceButton
= (Button
) source
;
444 text
= sourceButton
.getText();
446 AbstractNewEntityWizard
<?
> wizard
= getNewEntityWizard(text
);
448 if (wizard
.getEntity() == null){
449 wizard
.init(null, null);
451 if(wizard
.getEntity() != null) {
452 WizardDialog dialog
= new WizardDialog(getShell(), wizard
);
453 int status
= dialog
.open();
455 if (status
== IStatus
.OK
) {
457 T entity
= (T
) wizard
.getEntity();
461 // if (getConversationHolder() != null){
462 // getConversationHolder().bind();
465 //FIXME : Need to make sure this is a stable fix (ticket 3822)
466 // if (getConversationHolder() != null){
467 // getConversationHolder().commit();
476 * <p>getConversationHolder</p>
478 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
481 // public ConversationHolder getConversationHolder() {
482 // return conversation;
487 // public void update(CdmDataChangeMap changeEvents) {}
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.
495 private void filterExcludedObjects() {
496 if (model
!= null && cdmBaseToBeFiltered
!= null) {
498 UuidAndTitleCache
<?
> uuidAndTitleCacheToRemove
= null;
500 for (UuidAndTitleCache
<?
> uuidAndTitleCache
: model
){
501 if (cdmBaseToBeFiltered
!= null && cdmBaseToBeFiltered
.contains(uuidAndTitleCache
.getUuid())) {
502 uuidAndTitleCacheToRemove
= uuidAndTitleCache
;
505 model
.remove(uuidAndTitleCacheToRemove
);
509 void createFilterButton(Composite searchAndFilter
){
510 //as default no filter button available
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("?")){
521 }else if (StringUtils
.isNotBlank(pattern
)){
522 // callService(CdmUtils.replaceNonWordCharacters(pattern, "."));
523 callService(pattern
);
525 fillContentProvider(null);
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);
535 abstract void callService(String pattern
);