com.holonplatform.vaadin.internal.components.MultiSelectField Maven / Gradle / Ivy
/*
* Copyright 2016-2017 Axioma srl.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.holonplatform.vaadin.internal.components;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import com.holonplatform.core.datastore.DataTarget;
import com.holonplatform.core.datastore.Datastore;
import com.holonplatform.core.internal.utils.ObjectUtils;
import com.holonplatform.core.property.PathProperty;
import com.holonplatform.core.property.Property;
import com.holonplatform.core.property.PropertyBox;
import com.holonplatform.core.property.PropertySet;
import com.holonplatform.core.query.QueryConfigurationProvider;
import com.holonplatform.vaadin.components.Field;
import com.holonplatform.vaadin.components.MultiSelect;
import com.holonplatform.vaadin.components.builders.BaseSelectInputBuilder.RenderingMode;
import com.holonplatform.vaadin.components.builders.BaseSelectModeMultiPropertySelectInputBuilder.OptionsModeMultiPropertySelectInputBuilder;
import com.holonplatform.vaadin.components.builders.BaseSelectModeMultiPropertySelectInputBuilder.SelectModeMultiPropertySelectInputBuilder;
import com.holonplatform.vaadin.components.builders.BaseSelectModeMultiSelectInputBuilder.OptionsModeMultiSelectInputBuilder;
import com.holonplatform.vaadin.components.builders.BaseSelectModeMultiSelectInputBuilder.SelectModeMultiSelectInputBuilder;
import com.holonplatform.vaadin.components.builders.MultiPropertySelectInputBuilder;
import com.holonplatform.vaadin.components.builders.MultiPropertySelectInputBuilder.GenericMultiPropertySelectInputBuilder;
import com.holonplatform.vaadin.components.builders.MultiSelectInputBuilder;
import com.holonplatform.vaadin.components.builders.MultiSelectInputBuilder.GenericMultiSelectInputBuilder;
import com.holonplatform.vaadin.data.ItemConverter;
import com.holonplatform.vaadin.data.ItemDataProvider;
import com.holonplatform.vaadin.internal.components.builders.AbstractSelectFieldBuilder;
import com.holonplatform.vaadin.internal.data.PropertyItemIdentifier;
import com.vaadin.data.Converter;
import com.vaadin.data.HasDataProvider;
import com.vaadin.data.provider.DataProvider;
import com.vaadin.data.provider.Query;
import com.vaadin.event.selection.MultiSelectionEvent;
import com.vaadin.server.SerializableFunction;
import com.vaadin.server.SerializablePredicate;
import com.vaadin.ui.AbstractMultiSelect;
import com.vaadin.ui.CheckBoxGroup;
import com.vaadin.ui.ComboBox.CaptionFilter;
import com.vaadin.ui.ListSelect;
/**
* Default multiple select {@link Field} implementation.
*
* @param Field type
*
* @since 5.0.0
*/
public class MultiSelectField
extends AbstractSelectField, T, ITEM, Set- , AbstractMultiSelect
- > implements MultiSelect
{
private static final long serialVersionUID = -7662977233168084151L;
/**
* Constructor
* @param type Selection value type
* @param renderingMode Rendering mode
*/
@SuppressWarnings("unchecked")
public MultiSelectField(Class extends T> type, RenderingMode renderingMode) {
super((Class extends Set>) (Class>) Set.class, renderingMode);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.AbstractCustomField#buildInternalField(java.lang.Class)
*/
@Override
protected AbstractMultiSelect- buildInternalField(Class extends Set
> type) {
RenderingMode mode = getRenderingMode();
if (mode == null) {
mode = RenderingMode.OPTIONS;
}
if (mode == RenderingMode.OPTIONS) {
final CheckBoxGroup- field = new CheckBoxGroup<>();
field.setItemCaptionGenerator(i -> generateItemCaption(i));
field.setItemIconGenerator(i -> generateItemIcon(i));
field.setItemDescriptionGenerator(i -> generateItemDescription(i));
field.addSelectionListener(e -> fireSelectionListeners(buildSelectionEvent(e)));
return field;
}
final ListSelect
- field = new ListSelect<>();
field.setItemCaptionGenerator(i -> generateItemCaption(i));
field.addSelectionListener(e -> fireSelectionListeners(buildSelectionEvent(e)));
return field;
}
protected SelectionEvent
buildSelectionEvent(MultiSelectionEvent- event) {
return new DefaultSelectionEvent<>(fromInternalValue(event.getAllSelectedItems()), event.isUserOriginated());
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.AbstractCustomField#fromInternalValue(java.lang.Object)
*/
@Override
protected Set
fromInternalValue(Set- value) {
if (value != null) {
final Set
set = new HashSet<>(value.size());
value.forEach(v -> set.add(toSelection(v)));
return set;
}
return null;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.AbstractCustomField#toInternalValue(java.lang.Object)
*/
@Override
protected Set- toInternalValue(Set
value) {
if (value != null) {
final Set- set = new HashSet<>(value.size());
value.forEach(v -> set.add(toItem(v)));
return set;
}
return null;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.AbstractSelectField#setItems(java.util.Collection)
*/
@Override
public void setItems(Collection
- items) {
getInternalField().setItems(items);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.AbstractSelectField#setDataProvider(com.vaadin.data.provider.
* DataProvider)
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void setDataProvider(DataProvider
- dataProvider) {
if (getInternalField() instanceof HasDataProvider) {
((HasDataProvider) getInternalField()).setDataProvider(dataProvider);
}
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.AbstractSelectField#setDataProvider(com.vaadin.data.provider.
* DataProvider, com.vaadin.server.SerializableFunction)
*/
@Override
public void setDataProvider(DataProvider
- dataProvider, SerializableFunction
filterConverter) {
setDataProvider(dataProvider);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.AbstractSelectField#setItems(java.util.Collection,
* com.vaadin.ui.ComboBox.CaptionFilter)
*/
@Override
public void setItems(Collection- items, CaptionFilter filter) {
setItems(items);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.AbstractSelectField#getDataProvider()
*/
@Override
public Optional
> getDataProvider() {
return Optional.ofNullable(getInternalField().getDataProvider());
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.Selectable#getSelectedItems()
*/
@Override
public Set getSelectedItems() {
final Set value = getValue();
return (value != null) ? Collections.unmodifiableSet(value) : Collections.emptySet();
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.Selectable#deselectAll()
*/
@Override
public void deselectAll() {
clear();
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.MultiSelect#select(java.lang.Iterable)
*/
@SuppressWarnings("unchecked")
@Override
public void select(Iterable items) {
ObjectUtils.argumentNotNull(items, "Items to select must be not null");
final Set set = new HashSet<>();
items.forEach(i -> {
ObjectUtils.argumentNotNull(i, "Items to select must be not null");
set.add(i);
});
Set- toSelect = toInternalValue(set);
getInternalField().select((ITEM[]) toSelect.toArray());
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.MultiSelect#deselect(java.lang.Iterable)
*/
@SuppressWarnings("unchecked")
@Override
public void deselect(Iterable
items) {
ObjectUtils.argumentNotNull(items, "Items to deselect must be not null");
final Set set = new HashSet<>();
items.forEach(i -> {
if (i != null) {
set.add(i);
}
});
Set- toDeselect = toInternalValue(set);
getInternalField().deselect((ITEM[]) toDeselect.toArray());
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.MultiSelect#selectAll()
*/
@Override
public void selectAll() {
getDataProvider().ifPresent(dp -> {
Stream
- allItemsStream = dp.fetch(new Query<>());
LinkedHashSet
- allItems = new LinkedHashSet<>();
allItemsStream.forEach(allItems::add);
getInternalField().setValue(allItems);
});
}
public void setRows(int rows) {
if (getInternalField() instanceof ListSelect) {
((ListSelect>) getInternalField()).setRows(rows);
}
}
public void setHtmlContentAllowed(boolean htmlContentAllowed) {
if (getInternalField() instanceof CheckBoxGroup) {
((CheckBoxGroup>) getInternalField()).setHtmlContentAllowed(htmlContentAllowed);
}
}
@SuppressWarnings("unchecked")
public void setItemEnabledProvider(SerializablePredicate
itemEnabledProvider) {
if (getInternalField() instanceof CheckBoxGroup) {
((CheckBoxGroup) getInternalField()).setItemEnabledProvider(itemEnabledProvider);
}
}
// Builder
/**
* Base {@link MultiSelect} builder.
* @param Selection type
*/
public static abstract class Builder>
extends AbstractSelectFieldBuilder, MultiSelect, T, T, MultiSelectField, B>
implements MultiSelectInputBuilder {
/**
* Constructor
* @param type Selection value type
* @param renderingMode Rendering mode
*/
public Builder(Class extends T> type, RenderingMode renderingMode) {
super(new MultiSelectField<>(type, renderingMode));
getInstance().setItemConverter(Converter.identity());
}
/*
* (non-Javadoc)
* @see
* com.holonplatform.vaadin.components.builders.MultiSelectFieldBuilder#dataSource(com.holonplatform.vaadin.
* data.ItemDataProvider)
*/
@Override
public B dataSource(ItemDataProvider dataProvider) {
ObjectUtils.argumentNotNull(dataProvider, "Item data provider must be not null");
this.itemDataProvider = dataProvider;
return builder();
}
/*
* (non-Javadoc)
* @see
* com.holonplatform.vaadin.components.builders.SelectItemDataSourceBuilder#dataSource(com.vaadin.data.provider.
* DataProvider)
*/
@Override
public B dataSource(DataProvider dataProvider) {
this.dataProvider = dataProvider;
return builder();
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.builders.SelectFieldBuilder#items(java.lang.Iterable)
*/
@Override
public B items(Iterable items) {
ObjectUtils.argumentNotNull(items, "Items must be not null");
this.items.clear();
items.forEach(i -> this.items.add(i));
return builder();
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.builders.SelectFieldBuilder#addItem(java.lang.Object)
*/
@Override
public B addItem(T item) {
ObjectUtils.argumentNotNull(item, "Item must be not null");
this.items.add(item);
return builder();
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.builders.AbstractSelectFieldBuilder#buildSelect(com.
* holonframework.vaadin.internal.components.AbstractSelectField)
*/
@Override
protected MultiSelect buildSelect(MultiSelectField instance) {
return instance;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.builders.AbstractSelectFieldBuilder#buildSelectAsField(com.
* holonplatform.vaadin.internal.components.AbstractSelectField)
*/
@Override
protected Field> buildSelectAsField(MultiSelectField instance) {
return instance;
}
}
public static class GenericBuilder extends Builder>
implements GenericMultiSelectInputBuilder {
public GenericBuilder(Class extends T> type, RenderingMode renderingMode) {
super(type, renderingMode);
}
@Override
protected GenericMultiSelectInputBuilder builder() {
return this;
}
}
public static class SelectModeBuilder extends Builder>
implements SelectModeMultiSelectInputBuilder {
public SelectModeBuilder(Class extends T> type) {
super(type, RenderingMode.SELECT);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.builders.BaseSelectModeMultiSelectInputBuilder.
* SelectModeMultiSelectInputBuilder#rows(int)
*/
@Override
public SelectModeMultiSelectInputBuilder rows(int rows) {
getInstance().setRows(rows);
return this;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.builders.AbstractComponentConfigurator#builder()
*/
@Override
protected SelectModeMultiSelectInputBuilder builder() {
return this;
}
}
public static class OptionsModeBuilder extends Builder>
implements OptionsModeMultiSelectInputBuilder {
public OptionsModeBuilder(Class extends T> type) {
super(type, RenderingMode.OPTIONS);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.builders.BaseSelectModeMultiSelectInputBuilder.
* OptionsModeMultiSelectInputBuilder#htmlContentAllowed(boolean)
*/
@Override
public OptionsModeMultiSelectInputBuilder htmlContentAllowed(boolean htmlContentAllowed) {
getInstance().setHtmlContentAllowed(htmlContentAllowed);
return this;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.builders.BaseSelectModeMultiSelectInputBuilder.
* OptionsModeMultiSelectInputBuilder#itemEnabledProvider(com.vaadin.server.SerializablePredicate)
*/
@Override
public OptionsModeMultiSelectInputBuilder itemEnabledProvider(SerializablePredicate itemEnabledProvider) {
ObjectUtils.argumentNotNull(itemEnabledProvider, "ItemEnabledProvider must be not null");
getInstance().setItemEnabledProvider(itemEnabledProvider);
return this;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.builders.AbstractComponentConfigurator#builder()
*/
@Override
protected OptionsModeMultiSelectInputBuilder builder() {
return this;
}
}
// Property
/**
* Base {@link MultiSelect} builder with {@link Property} data source support.
* @param Selection type
*/
public static abstract class PropertyBuilder> extends
AbstractSelectFieldBuilder, MultiSelect, T, PropertyBox, MultiSelectField, B>
implements MultiPropertySelectInputBuilder {
private final Property selectProperty;
/**
* Constructor
* @param selectProperty Selection (and identifier) property
* @param renderingMode Rendering mode
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public PropertyBuilder(Property selectProperty, RenderingMode renderingMode) {
super(new MultiSelectField<>(selectProperty.getType(), renderingMode));
this.selectProperty = selectProperty;
itemIdentifier = new PropertyItemIdentifier(selectProperty);
// use the selection property as item caption by default
getInstance().setItemCaptionGenerator(value -> String.valueOf(value.getValue(selectProperty)));
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.builders.PropertySelectInputBuilder#itemConverter(com.holonplatform.
* vaadin.data.ItemConverter)
*/
@Override
public B itemConverter(ItemConverter itemConverter) {
getInstance().setItemConverter(new ReversiblePropertyBoxConverter<>(selectProperty, itemConverter));
return builder();
}
/*
* (non-Javadoc)
* @see
* com.holonplatform.vaadin.components.builders.PropertySelectFieldBuilder#dataSource(com.holonplatform.vaadin
* .data.ItemDataProvider)
*/
@Override
public B dataSource(ItemDataProvider dataProvider) {
ObjectUtils.argumentNotNull(dataProvider, "ItemDataProvider must be not null");
this.itemDataProvider = dataProvider;
return builder();
}
/*
* (non-Javadoc)
* @see
* com.holonplatform.vaadin.components.builders.PropertySelectInputBuilder#dataSource(com.holonplatform.core.
* datastore.Datastore, com.holonplatform.core.datastore.DataTarget, java.lang.Iterable,
* com.holonplatform.core.query.QueryConfigurationProvider[])
*/
@SuppressWarnings("rawtypes")
@Override
public B dataSource(Datastore datastore, DataTarget> dataTarget, Iterable
properties,
QueryConfigurationProvider... queryConfigurationProviders) {
MultiPropertySelectInputBuilder.super.dataSource(datastore, dataTarget, properties,
queryConfigurationProviders);
setupItemConverter(datastore, dataTarget, properties);
return builder();
}
/*
* (non-Javadoc)
* @see
* com.holonplatform.vaadin.components.builders.PropertySelectInputBuilder#dataSource(com.holonplatform.core.
* datastore.Datastore, com.holonplatform.core.datastore.DataTarget, com.holonplatform.core.property.Property[])
*/
@Override
public B dataSource(Datastore datastore, DataTarget> dataTarget, Property>... properties) {
MultiPropertySelectInputBuilder.super.dataSource(datastore, dataTarget, properties);
setupItemConverter(datastore, dataTarget, PropertySet.of(properties));
return builder();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
protected
> void setupItemConverter(Datastore datastore, DataTarget> dataTarget,
Iterable
properties) {
if (selectProperty != null && PathProperty.class.isAssignableFrom(selectProperty.getClass())
&& !getInstance().getItemConverter().isPresent()) {
itemConverter(value -> {
if (value != null) {
return datastore.query().target(dataTarget).filter(((PathProperty) selectProperty).eq(value))
.findOne(properties).orElse(null);
}
return null;
});
}
}
/*
* (non-Javadoc)
* @see
* com.holonplatform.vaadin.internal.components.builders.AbstractSelectFieldBuilder#preSetup(com.holonplatform.
* vaadin.internal.components.AbstractSelectField)
*/
@Override
protected void preSetup(MultiSelectField instance) {
if (!instance.getItemConverter().isPresent()) {
instance.setItemConverter(new DefaultPropertyBoxConverter<>(selectProperty));
}
super.preSetup(instance);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.builders.AbstractSelectFieldBuilder#buildSelect(com.
* holonframework.vaadin.internal.components.AbstractSelectField)
*/
@Override
protected MultiSelect buildSelect(MultiSelectField instance) {
return instance;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.builders.AbstractSelectFieldBuilder#buildSelectAsField(com.
* holonplatform.vaadin.internal.components.AbstractSelectField)
*/
@Override
protected Field> buildSelectAsField(MultiSelectField instance) {
return instance;
}
}
public static class GenericPropertyBuilder extends PropertyBuilder>
implements GenericMultiPropertySelectInputBuilder {
public GenericPropertyBuilder(Property selectProperty, RenderingMode renderingMode) {
super(selectProperty, renderingMode);
}
@Override
protected GenericMultiPropertySelectInputBuilder builder() {
return this;
}
}
public static class SelectModePropertyBuilder
extends PropertyBuilder>
implements SelectModeMultiPropertySelectInputBuilder {
public SelectModePropertyBuilder(Property selectProperty) {
super(selectProperty, RenderingMode.SELECT);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.builders.BaseSelectModeMultiPropertySelectInputBuilder.
* SelectModeMultiPropertySelectInputBuilder#rows(int)
*/
@Override
public SelectModeMultiPropertySelectInputBuilder rows(int rows) {
getInstance().setRows(rows);
return this;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.builders.AbstractComponentConfigurator#builder()
*/
@Override
protected SelectModeMultiPropertySelectInputBuilder builder() {
return this;
}
}
public static class OptionsModePropertyBuilder
extends PropertyBuilder>
implements OptionsModeMultiPropertySelectInputBuilder {
public OptionsModePropertyBuilder(Property selectProperty) {
super(selectProperty, RenderingMode.OPTIONS);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.builders.BaseSelectModeMultiPropertySelectInputBuilder.
* OptionsModeMultiPropertySelectInputBuilder#htmlContentAllowed(boolean)
*/
@Override
public OptionsModeMultiPropertySelectInputBuilder htmlContentAllowed(boolean htmlContentAllowed) {
getInstance().setHtmlContentAllowed(htmlContentAllowed);
return this;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.components.builders.BaseSelectModeMultiPropertySelectInputBuilder.
* OptionsModeMultiPropertySelectInputBuilder#itemEnabledProvider(com.vaadin.server.SerializablePredicate)
*/
@Override
public OptionsModeMultiPropertySelectInputBuilder itemEnabledProvider(
SerializablePredicate itemEnabledProvider) {
ObjectUtils.argumentNotNull(itemEnabledProvider, "ItemEnabledProvider must be not null");
getInstance().setItemEnabledProvider(itemEnabledProvider);
return this;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.internal.components.builders.AbstractComponentConfigurator#builder()
*/
@Override
protected OptionsModeMultiPropertySelectInputBuilder builder() {
return this;
}
}
}