4 package eu
.etaxonomy
.taxeditor
.ui
.selection
;
6 import java
.util
.EnumSet
;
7 import java
.util
.Observable
;
8 import java
.util
.Observer
;
10 import org
.eclipse
.core
.runtime
.IStatus
;
11 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
12 import org
.eclipse
.jface
.wizard
.WizardDialog
;
13 import org
.eclipse
.swt
.SWT
;
14 import org
.eclipse
.swt
.events
.SelectionAdapter
;
15 import org
.eclipse
.swt
.events
.SelectionEvent
;
16 import org
.eclipse
.swt
.events
.SelectionListener
;
17 import org
.eclipse
.swt
.graphics
.Color
;
18 import org
.eclipse
.swt
.widgets
.Button
;
19 import org
.eclipse
.swt
.widgets
.Composite
;
20 import org
.eclipse
.swt
.widgets
.Label
;
21 import org
.eclipse
.swt
.widgets
.Shell
;
22 import org
.eclipse
.swt
.widgets
.Text
;
23 import org
.springframework
.security
.core
.GrantedAuthority
;
25 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
26 import eu
.etaxonomy
.cdm
.api
.conversation
.IConversationEnabled
;
27 import eu
.etaxonomy
.cdm
.api
.service
.IAgentService
;
28 import eu
.etaxonomy
.cdm
.api
.service
.ICollectionService
;
29 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
30 import eu
.etaxonomy
.cdm
.api
.service
.IOccurrenceService
;
31 import eu
.etaxonomy
.cdm
.api
.service
.IReferenceService
;
32 import eu
.etaxonomy
.cdm
.api
.service
.IService
;
33 import eu
.etaxonomy
.cdm
.api
.service
.IUserService
;
34 import eu
.etaxonomy
.cdm
.api
.service
.molecular
.IAmplificationService
;
35 import eu
.etaxonomy
.cdm
.api
.service
.molecular
.IPrimerService
;
36 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
37 import eu
.etaxonomy
.cdm
.model
.agent
.Institution
;
38 import eu
.etaxonomy
.cdm
.model
.agent
.Person
;
39 import eu
.etaxonomy
.cdm
.model
.agent
.Team
;
40 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
41 import eu
.etaxonomy
.cdm
.model
.common
.Group
;
42 import eu
.etaxonomy
.cdm
.model
.common
.ICdmBase
;
43 import eu
.etaxonomy
.cdm
.model
.common
.IIdentifiableEntity
;
44 import eu
.etaxonomy
.cdm
.model
.common
.User
;
45 import eu
.etaxonomy
.cdm
.model
.molecular
.Amplification
;
46 import eu
.etaxonomy
.cdm
.model
.molecular
.Primer
;
47 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
48 import eu
.etaxonomy
.cdm
.model
.occurrence
.Collection
;
49 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
50 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
51 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
52 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.CRUD
;
53 import eu
.etaxonomy
.taxeditor
.model
.AbstractUtility
;
54 import eu
.etaxonomy
.taxeditor
.model
.ImageResources
;
55 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
56 import eu
.etaxonomy
.taxeditor
.preference
.Resources
;
57 import eu
.etaxonomy
.taxeditor
.store
.CdmStore
;
58 import eu
.etaxonomy
.taxeditor
.store
.LoginManager
;
59 import eu
.etaxonomy
.taxeditor
.store
.StoreUtil
;
60 import eu
.etaxonomy
.taxeditor
.ui
.dialog
.selection
.SelectionDialogFactory
;
61 import eu
.etaxonomy
.taxeditor
.ui
.element
.AbstractCdmFormElement
;
62 import eu
.etaxonomy
.taxeditor
.ui
.element
.CdmFormFactory
;
63 import eu
.etaxonomy
.taxeditor
.ui
.element
.CdmPropertyChangeEvent
;
64 import eu
.etaxonomy
.taxeditor
.ui
.element
.ICdmFormElement
;
65 import eu
.etaxonomy
.taxeditor
.ui
.element
.IEnableableFormElement
;
66 import eu
.etaxonomy
.taxeditor
.ui
.element
.IEntityElement
;
67 import eu
.etaxonomy
.taxeditor
.ui
.element
.ILabeledElement
;
68 import eu
.etaxonomy
.taxeditor
.ui
.element
.ISelectableElement
;
69 import eu
.etaxonomy
.taxeditor
.ui
.element
.LayoutConstants
;
70 import eu
.etaxonomy
.taxeditor
.ui
.element
.SelectionArbitrator
;
71 import eu
.etaxonomy
.taxeditor
.ui
.section
.grantedAuthority
.GrantedAuthorityLabelTextProvider
;
75 * Abstract AbstractSelectionElement class.
79 * @created Nov 17, 2009
83 public class EntitySelectionElement
<T
extends ICdmBase
> extends
84 AbstractCdmFormElement
implements SelectionListener
, IEnableableFormElement
, ISelectableElement
, IEntityElement
<T
>, ILabeledElement
, IConversationEnabled
, Observer
{
86 private static final EnumSet
<CRUD
> UPDATE
= EnumSet
.of(CRUD
.UPDATE
);
87 private static final EnumSet
<CRUD
> DELETE
= EnumSet
.of(CRUD
.DELETE
);
88 private static final EnumSet
<CRUD
> CREATE
= EnumSet
.of(CRUD
.CREATE
);
91 * Bitmask for configuring functionality of selection element
93 public static final int NOTHING
= 0; // 000
94 public static final int EDITABLE
= 1 << 0; // 001
95 public static final int DELETABLE
= 1 << 1; // 010
96 public static final int SELECTABLE
= 1 << 2; // 100
97 public static final int ALL
= EDITABLE
| DELETABLE
| SELECTABLE
; // 111
101 protected Label label
;
103 protected Button button_selection
;
105 private SelectionArbitrator selectionArbitrator
;
107 protected Button button_edit
;
109 private final String labelString
;
111 private Composite selectableComposite
;
113 private Button button_remove
;
115 private final boolean isEditable
;
117 private final boolean isDeletable
;
119 private final ConversationHolder conversation
;
120 private Class
<T
> clazz
;
124 * Constructor for AbstractSelectionElement.
128 * a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
130 * @param conversation
132 * @param parentElement
133 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
136 * a {@link java.lang.String} object.
141 * @param isSelectable
150 public EntitySelectionElement(CdmFormFactory formFactory
,
151 ConversationHolder conversation
, ICdmFormElement parentElement
,
152 String labelString
, T entity
, int mode
, int style
) {
153 super(formFactory
, parentElement
);
155 this.isEditable
= (mode
& EDITABLE
) == EDITABLE
;
156 this.isDeletable
= (mode
& DELETABLE
) == DELETABLE
;
157 boolean isSelectable
= (mode
& SELECTABLE
) == SELECTABLE
;
159 this.labelString
= (labelString
== null || labelString
.equals("")) ?
"" : labelString
+ " : ";
161 this.conversation
= conversation
;
163 if (isSelectable
&& formFactory
.getSelectionProvider() != null) {
164 selectionArbitrator
= formFactory
.createSelectionArbitrator(this);
167 createControls(getLayoutComposite(), SWT
.NULL
);
172 public EntitySelectionElement(CdmFormFactory formFactory
,
173 ConversationHolder conversation
, ICdmFormElement parentElement
, Class
<T
> clazz
,
174 String labelString
, T entity
, int mode
, int style
) {
175 this(formFactory
, conversation
, parentElement
, labelString
, entity
, mode
, style
);
179 private void createControls(Composite parent
, int style
) {
181 label
= formFactory
.createLabel(getLayoutComposite(), labelString
,
186 selectableComposite
= formFactory
.createComposite(getLayoutComposite());
196 selectableComposite
.setLayout(LayoutConstants
.LAYOUT(columns
, false));
197 selectableComposite
.setLayoutData(LayoutConstants
.FILL_HORIZONTALLY());
199 addControl(selectableComposite
);
201 text
= formFactory
.createText(selectableComposite
, null, SWT
.WRAP
);
202 text
.setEditable(false);
205 text
.setLayoutData(LayoutConstants
.FILL_HORIZONTALLY());
206 text
.setBackground(StoreUtil
207 .getColor(Resources
.COLOR_TEXT_DISABLED_BACKGROUND
));
209 button_selection
= formFactory
.createButton(selectableComposite
, null,
211 button_selection
.setImage(ImageResources
212 .getImage(ImageResources
.BROWSE_ICON
));
213 button_selection
.setToolTipText("Browse existing");
215 addControl(button_selection
);
216 button_selection
.addSelectionListener(this);
219 button_edit
= formFactory
.createButton(selectableComposite
, null,
221 button_edit
.setImage(ImageResources
222 .getImage(ImageResources
.EDIT_ICON
));
223 button_edit
.setToolTipText("Edit");
224 addControl(button_edit
);
225 button_edit
.addSelectionListener(new EditListener(this));
229 button_remove
= formFactory
.createButton(selectableComposite
, null,
231 button_remove
.setImage(ImageResources
232 .getImage(ImageResources
.TRASH_ICON
));
233 button_remove
.setToolTipText("Remove");
234 addControl(button_remove
);
235 button_remove
.addSelectionListener(new DeleteListener(this));
240 public void widgetSelected(SelectionEvent e
) {
241 T selection
= SelectionDialogFactory
.getSelectionFromDialog(clazz
, getShell(), getConversationHolder(), getEntity());
242 setSelectionInternal(selection
);
246 * Return the selected object
248 * @return a T object.
250 public T
getSelection() {
258 * eu.etaxonomy.taxeditor.forms.IEnableableFormElement#setEnabled(boolean)
262 public void setEnabled(boolean enabled
) {
263 button_selection
.setEnabled(enabled
);
265 updateButtonStates();
270 * @see eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement#isEnabled()
273 public boolean isEnabled() {
274 return button_selection
.isEnabled();
279 * setSelectionInternal
285 protected void setSelectionInternal(T selection
) {
286 if (selection
!= null && !selection
.equals(this.entity
)) {
287 setEntity(selection
);
288 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, null));
294 * Setter for the field <code>entity</code>.
300 public void setEntity(T selection
) {
301 this.entity
= selection
;
306 * Updates this elements view
308 protected void updateElement() {
309 String title
= CdmUtils
.Nz(getTitle());
310 text
.setText(title
); // title can be null
312 updateButtonStates();
316 public void updateFromWizard() {
318 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, null));
326 * @return a {@link java.lang.String} object.
328 protected String
getTitle() {
330 if(entity
instanceof IIdentifiableEntity
) {
331 return ((IIdentifiableEntity
) entity
).getTitleCache();
332 } else if(entity
instanceof Group
){
333 return ((Group
) entity
).getName();
334 } else if(entity
instanceof GrantedAuthority
){
335 return GrantedAuthorityLabelTextProvider
.getText(((GrantedAuthority
) entity
));
336 } else if(entity
instanceof User
){
337 return ((User
) entity
).getUsername();
338 } else if (entity
instanceof Primer
){
339 return ((Primer
) entity
).getLabel();
340 } else if (entity
instanceof Amplification
){
341 return ((Amplification
) entity
).getDescription();
350 public void setSelected(boolean selected
) {
351 setBackground(selected ? SELECTED
: getPersistentBackground());
357 * @see eu.etaxonomy.taxeditor.forms.IEntityElement#getEntity()
361 * Getter for the field <code>entity</code>.
364 * @return a T object.
367 public T
getEntity() {
374 * @see eu.etaxonomy.taxeditor.forms.section.cdmdetail.ISelectableElement#
375 * getSelectionArbitrator()
379 * Getter for the field <code>selectionArbitrator</code>.
382 * @return a {@link eu.etaxonomy.taxeditor.ui.element.SelectionArbitrator}
386 public SelectionArbitrator
getSelectionArbitrator() {
387 return selectionArbitrator
;
391 * Convenient access to current shell
393 * @return a {@link org.eclipse.swt.widgets.Shell} object.
395 public Shell
getShell() {
396 return getLayoutComposite().getShell();
401 public void setIrrelevant(boolean irrelevant
) {
402 String colorId
= irrelevant ? Resources
.COLOR_COMPOSITE_IRRELEVANT
403 : Resources
.COLOR_TEXT_DISABLED_BACKGROUND
;
405 Color color
= StoreUtil
.getColor(colorId
);
406 text
.setBackground(color
);
409 private class DeleteListener
extends SelectionAdapter
{
411 private final EntitySelectionElement
<T
> selectionElement
;
413 public DeleteListener(EntitySelectionElement
<T
> selectionElement
) {
414 this.selectionElement
= selectionElement
;
418 public void widgetSelected(SelectionEvent e
) {
420 firePropertyChangeEvent(new CdmPropertyChangeEvent(
421 selectionElement
, null));
425 private class EditListener
extends SelectionAdapter
{
427 private static final String TRANSIENT_EDITING_WARNING_TEXT
= "Warning: All changes for this element are directly reflected in the data base.\nThe \"Cancel\" button has no effect";
428 private static final String TRANSIENT_EDITING_WARNING_TITLE
= "CDM element not yet saved.";
429 private final EntitySelectionElement
<T
> selectionElement
;
431 public EditListener(EntitySelectionElement
<T
> selectionElement
) {
432 this.selectionElement
= selectionElement
;
437 public void widgetSelected(SelectionEvent e
) {
438 T originalEntity
= selectionElement
.getEntity();
439 T clonedEntity
= null;
440 IService
<T
> service
= null;
441 if(originalEntity
instanceof CdmBase
){
442 //get corresponding service
443 if(entity
instanceof Reference
<?
>){
444 service
= (IService
<T
>) CdmStore
.getService(IReferenceService
.class);
446 else if (entity
instanceof Team
|| entity
instanceof Person
|| entity
instanceof Institution
) {
447 service
= (IService
<T
>) CdmStore
.getService(IAgentService
.class);
449 else if (entity
instanceof NonViralName
) {
450 service
= (IService
<T
>) CdmStore
.getService(INameService
.class);
452 else if (entity
instanceof SpecimenOrObservationBase
) {
453 service
= (IService
<T
>) CdmStore
.getService(IOccurrenceService
.class);
455 else if (entity
instanceof Collection
) {
456 service
= (IService
<T
>) CdmStore
.getService(ICollectionService
.class);
458 else if (entity
instanceof User
) {
459 service
= (IService
<T
>) CdmStore
.getService(IUserService
.class);
461 else if (entity
instanceof Primer
) {
462 service
= (IService
<T
>) CdmStore
.getService(IPrimerService
.class);
464 else if (entity
instanceof Amplification
) {
465 service
= (IService
<T
>) CdmStore
.getService(IAmplificationService
.class);
467 //check if original already exists in data base. If not then do not clone and all changes will be persisted directly -> Warning to user.
468 if(service
!=null && service
.find(originalEntity
.getUuid())==null){
469 if(MessagingUtils
.confirmDialog(TRANSIENT_EDITING_WARNING_TITLE
, "["+originalEntity
.getClass().getSimpleName()+"]"+originalEntity
+ " has to be saved before it can be edited. Save now?")){
470 service
.save(originalEntity
);
471 AbstractUtility
.getActiveEditor().doSave(new NullProgressMonitor());
474 //transient CDM elements should not be edited to avoid merge conflicts
475 // when the elements are cascaded
482 clonedEntity
= (T
) ((CdmBase
) originalEntity
).clone();
483 } catch (CloneNotSupportedException e1
) {
484 MessagingUtils
.warningDialog(TRANSIENT_EDITING_WARNING_TITLE
, this, TRANSIENT_EDITING_WARNING_TEXT
);
489 if(clonedEntity
!=null){
490 selectionElement
.setEntity(clonedEntity
);
492 WizardDialog dialog
= new WizardDialog(selectionElement
.getShell(),
493 new EditFromSelectionWizard(selectionElement
));
494 if (dialog
.open() == IStatus
.OK
) {
495 if(service
!=null && clonedEntity
!=null){//check if cloning happened
496 T editedClonedEntity
= selectionElement
.getEntity();
497 editedClonedEntity
.setId(originalEntity
.getId());
498 editedClonedEntity
.setUuid(originalEntity
.getUuid());
500 //merge clone and original
501 service
.merge(editedClonedEntity
);
502 originalEntity
= service
.load(originalEntity
.getUuid());
505 selectionElement
.setEntity(originalEntity
);
506 selectionElement
.updateFromWizard();
508 //be sure to reset to original in all cases
509 selectionElement
.setEntity(originalEntity
);
516 public void widgetDefaultSelected(SelectionEvent e
) {
521 * getConversationHolder
524 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
528 public ConversationHolder
getConversationHolder() {
534 public void setBackground(Color color
) {
535 if(!label
.isDisposed()){
536 label
.setBackground(color
);
542 public void setLabel(String labelString
) {
544 label
.setText(labelString
);
550 * Getter for the field <code>label</code>.
553 * @return a {@link java.lang.String} object.
556 public String
getLabel() {
558 return label
.getText() + " : ";
565 public void update(CdmDataChangeMap changeEvents
) {
569 * @see eu.etaxonomy.taxeditor.ui.element.AbstractCdmFormElement#removeElements()
572 public void removeElements(){
573 super.removeElements();
574 LoginManager loginManager
= CdmStore
.getLoginManager();
575 loginManager
.addObserver(this);
579 public void update(Observable o
, Object arg
) {
580 if(o
instanceof LoginManager
){
581 updateButtonStates();
585 private void updateButtonStates() {
586 if(button_edit
!= null && !button_selection
.isDisposed()){
587 button_edit
.setEnabled(isEditable
&& button_selection
.isEnabled() && getEntity() != null && CdmStore
.currentAuthentiationHasPermission((CdmBase
) getEntity(), UPDATE
));