2 * Copyright (C) 2017 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.
9 package eu
.etaxonomy
.vaadin
.component
;
11 import java
.util
.Objects
;
12 import java
.util
.Optional
;
13 import java
.util
.UUID
;
15 import org
.vaadin
.viritin
.fields
.LazyComboBox
.FilterableCountProvider
;
16 import org
.vaadin
.viritin
.fields
.LazyComboBox
.FilterablePagingProvider
;
18 import com
.vaadin
.data
.Property
;
19 import com
.vaadin
.data
.Validator
.InvalidValueException
;
20 import com
.vaadin
.data
.fieldgroup
.FieldGroup
;
21 import com
.vaadin
.data
.util
.converter
.Converter
.ConversionException
;
22 import com
.vaadin
.server
.AbstractErrorMessage
.ContentMode
;
23 import com
.vaadin
.server
.ErrorMessage
.ErrorLevel
;
24 import com
.vaadin
.server
.UserError
;
25 import com
.vaadin
.ui
.Button
;
26 import com
.vaadin
.ui
.Button
.ClickListener
;
27 import com
.vaadin
.ui
.Component
;
28 import com
.vaadin
.ui
.CssLayout
;
29 import com
.vaadin
.ui
.Field
;
30 import com
.vaadin
.ui
.themes
.ValoTheme
;
32 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
33 import eu
.etaxonomy
.cdm
.model
.permission
.CRUD
;
34 import eu
.etaxonomy
.cdm
.service
.IFilterableStringRepresentationPagingProvider
;
35 import eu
.etaxonomy
.cdm
.service
.UserHelperAccess
;
36 import eu
.etaxonomy
.cdm
.vaadin
.component
.ButtonFactory
;
37 import eu
.etaxonomy
.cdm
.vaadin
.event
.NestedButtonStateUpdater
;
40 * By AM: Combobox (with buttons) for switching back and forth from a TextBox.
42 * @author a.kohlbecker
45 public class WeaklyRelatedEntityCombobox
<V
extends IdentifiableEntity
<?
>>
46 extends CompositeCustomField
<String
>
47 implements WeaklyRelatedEntityField
<V
>, ReloadableSelect
{
49 private static final long serialVersionUID
= 6277565876657520311L;
51 public static final String PRIMARY_STYLE
= "v-related-entity-combobox";
53 private Class
<V
> type
;
55 private CssLayout container
= new CssLayout();
57 private ReloadableLazyComboBox
<String
> lazySelect
;
59 private Button addButton
= ButtonFactory
.CREATE_NEW
.createButton();
60 private Button editButton
= ButtonFactory
.EDIT_ITEM
.createButton();
62 private WeaklyRelatedEntityButtonUpdater buttonUpdater
;
64 private IFilterableStringRepresentationPagingProvider
<UUID
> filterablePagingProvider
;
66 public WeaklyRelatedEntityCombobox(String caption
, Class
<V
> type
){
69 lazySelect
= new ReloadableLazyComboBox
<String
>(String
.class);
70 addStyledComponents(lazySelect
, addButton
, editButton
);
71 addSizedComponents(lazySelect
, container
);
72 buttonUpdater
= new WeaklyRelatedEntityButtonUpdater(this);
73 lazySelect
.addValueChangeListener(buttonUpdater
);
74 lazySelect
.setValidationVisible(true);
75 lazySelect
.addValueChangeListener(e
-> {
76 // update the itemContainer immediately so that the edit button acts on the chosen item
77 // TODO In contrast to ToOneRelatedEntityCombobox where getValue() is overwritten to call
78 // commitSelect() calling this method would most probably remove all strings which do not have a
79 // weakly related entity. Such behavior would be very unfriendly to users.
82 } catch (InvalidValueException ie
){
89 public void addValueChangeListener(ValueChangeListener valueChangeListener
){
90 super.addValueChangeListener(valueChangeListener
);
91 lazySelect
.addValueChangeListener(valueChangeListener
);
95 protected Component
initContent() {
96 container
.addComponents(lazySelect
, addButton
, editButton
);
97 setPrimaryStyleName(PRIMARY_STYLE
);
103 public Class
<String
> getType() {
108 protected void addDefaultStyles() {
109 container
.addStyleName(ValoTheme
.LAYOUT_COMPONENT_GROUP
);
113 public Optional
<FieldGroup
> getFieldGroup() {
114 return Optional
.empty();
117 public ReloadableLazyComboBox
<String
> getSelect() {
121 public void loadFrom(FilterablePagingProvider
<String
> filterablePagingProvider
, FilterableCountProvider filterableCountProvider
, int pageLength
) {
123 this.filterablePagingProvider
= (IFilterableStringRepresentationPagingProvider
<UUID
>) filterablePagingProvider
;
124 lazySelect
.loadFrom(filterablePagingProvider
, filterableCountProvider
, pageLength
);
125 buttonUpdater
.updateButtons(getValue());
129 * reload the selected entity from the persistent storage
132 public void reload() {
133 filterablePagingProvider
.clearIdCache();
134 getSelect().reload();
138 public void setAddButtonEnabled(boolean enabled
) {
139 addButton
.setEnabled(enabled
);
143 public void addClickListenerAddEntity(ClickListener listener
) {
144 addButton
.addClickListener(listener
);
148 public void setEditButtonEnabled(boolean enabled
) {
149 editButton
.setEnabled(enabled
);
153 public void addClickListenerEditEntity(ClickListener listener
) {
154 editButton
.addClickListener(listener
);
158 public void selectNewItem(String bean
){
162 public UUID
getIdForValue(){
163 return filterablePagingProvider
.idFor(getValue());
167 * sets the selection to the <code>newFieldValue</code> only if the value can
168 * be provided by the FilterablePagingProvider
171 public void setValue(String newFieldValue
) throws com
.vaadin
.data
.Property
.ReadOnlyException
, ConversionException
{
172 if(!Objects
.equals(newFieldValue
, lazySelect
.getValue())){
173 //if value changed...
174 if(contains(newFieldValue
)){
175 lazySelect
.setValue(newFieldValue
);
176 lazySelect
.markAsDirty();
177 }else if (lazySelect
.getValue() != null) {
178 //if new suggested value does not exist in the list,
179 //set the value of the combobox to null, if it it not yet null
180 lazySelect
.setValue(null);
181 lazySelect
.markAsDirty();
187 public String
getValue() {
188 return lazySelect
.getValue();
192 private boolean contains(String newFieldValue
) {
193 UUID id
= filterablePagingProvider
.idFor(newFieldValue
);
198 public boolean isValueInOptions(){
199 return lazySelect
.getOptions().contains(lazySelect
.getValue());
203 public void setPropertyDataSource(Property newDataSource
) {
204 lazySelect
.setPropertyDataSource(newDataSource
);
205 if(buttonUpdater
!= null){
206 buttonUpdater
.updateButtons(lazySelect
.getValue());
211 public Property
getPropertyDataSource() {
212 return lazySelect
.getPropertyDataSource();
216 public void setReadOnly(boolean readOnly
) {
217 super.setReadOnly(readOnly
);
218 setDeepReadOnly(readOnly
, getContent(), null);
219 if(buttonUpdater
!= null){
220 buttonUpdater
.updateButtons(lazySelect
.getValue());
225 public void setRequired(boolean required
) {
226 super.setRequired(required
);
227 lazySelect
.setRequired(required
);
231 public void setImmediate(boolean immediate
){
232 super.setImmediate(immediate
);
233 lazySelect
.setImmediate(immediate
);
237 public void updateButtons(){
238 buttonUpdater
.updateButtons(getValue());
242 public void commit() throws SourceException
, InvalidValueException
{
246 public void commitSelect() {
248 setComponentError(null);
250 } catch (InvalidValueException ex
){
251 UserError componentError
= new UserError(ex
.getHtmlMessage(), ContentMode
.HTML
, ErrorLevel
.ERROR
);
252 lazySelect
.setComponentError(componentError
);
260 * @deprecated NestedButtonStateUpdater should rather be instantiated in the RelatedEntityField instead of passing it as property
264 public void setNestedButtonStateUpdater(NestedButtonStateUpdater
<V
> buttonUpdater
) {
268 class WeaklyRelatedEntityButtonUpdater
implements NestedButtonStateUpdater
<String
> {
270 private static final long serialVersionUID
= 4472031263172275012L;
272 WeaklyRelatedEntityCombobox
<V
> toOneRelatedEntityField
;
274 public WeaklyRelatedEntityButtonUpdater(WeaklyRelatedEntityCombobox
<V
> toOneRelatedEntityField
){
275 this.toOneRelatedEntityField
= toOneRelatedEntityField
;
276 updateButtons(toOneRelatedEntityField
.getValue());
277 toOneRelatedEntityField
.setEditButtonEnabled(false);
281 public void valueChange(com
.vaadin
.data
.Property
.ValueChangeEvent event
) {
283 String value
= (String
)event
.getProperty().getValue();
284 updateButtons(value
);
288 public void updateButtons(String value
) {
291 if(value
!= null && filterablePagingProvider
!= null){
292 uuid
= filterablePagingProvider
.idFor(value
);
294 boolean userIsAllowedToUpdate
= uuid
!= null && UserHelperAccess
.userHelper().userHasPermission(type
, uuid
, CRUD
.UPDATE
);
295 boolean userIsAllowedToCreate
= UserHelperAccess
.userHelper().userHasPermission(type
, CRUD
.CREATE
);
296 boolean isReadOnlyField
= ((Field
)toOneRelatedEntityField
).isReadOnly();
298 toOneRelatedEntityField
.setAddButtonEnabled(!isReadOnlyField
&& userIsAllowedToCreate
);
299 toOneRelatedEntityField
.setEditButtonEnabled(!isReadOnlyField
&& userIsAllowedToUpdate
);