com.holonplatform.vaadin7.internal.data.container.DefaultItemDataSourceContainer 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.vaadin7.internal.data.container;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.WeakHashMap;
import java.util.stream.Collectors;
import com.holonplatform.core.ParameterSet;
import com.holonplatform.core.Path;
import com.holonplatform.core.exceptions.DataAccessException;
import com.holonplatform.core.internal.DefaultParameterSet;
import com.holonplatform.core.internal.utils.ConversionUtils;
import com.holonplatform.core.internal.utils.ObjectUtils;
import com.holonplatform.core.query.QueryConfigurationProvider;
import com.holonplatform.core.query.QueryFilter;
import com.holonplatform.core.query.QuerySort;
import com.holonplatform.core.query.QuerySort.SortDirection;
import com.holonplatform.vaadin7.Registration;
import com.holonplatform.vaadin7.data.ItemDataProvider;
import com.holonplatform.vaadin7.data.ItemIdentifierProvider;
import com.holonplatform.vaadin7.data.ItemDataSource.Configuration;
import com.holonplatform.vaadin7.data.container.ItemAdapter;
import com.holonplatform.vaadin7.data.container.ItemDataSourceContainer;
import com.holonplatform.vaadin7.internal.data.DefaultItemSort;
import com.holonplatform.vaadin7.internal.data.DefaultItemStore;
import com.holonplatform.vaadin7.internal.data.ItemStore;
import com.holonplatform.vaadin7.internal.data.ItemStore.ItemActionListener;
import com.vaadin.data.Container;
import com.vaadin.data.ContainerHelpers;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.data.util.filter.UnsupportedFilterException;
/**
* Default {@link ItemDataSourceContainer} implementation.
*
* @param - Item type
* @param
Item property type
*
* @since 5.0.0
*/
public class DefaultItemDataSourceContainer-
implements ItemDataSourceContainer
- , Configuration
, ItemActionListener- {
private static final long serialVersionUID = 5690427592609021861L;
/**
* Auto refresh
*/
private boolean autoRefresh = true;
/**
* Property ids
*/
private List
propertyIds = new LinkedList<>();
/**
* Property types
*/
private final Map> propertyTypes = new HashMap<>();
/**
* Property default values
*/
private Map defaultValues;
/**
* Read-only properties
*/
private Collection readOnlyPropertyIds = new LinkedList<>();
/**
* Sortable properties
*/
private final Collection sortablePropertyIds = new LinkedList<>();
/**
* Item sorts
*/
private final List> itemSorts = new LinkedList<>();
/**
* Item store
*/
private ItemStore- itemStore;
/**
* Item data provider
*/
private ItemDataProvider
- dataProvider;
/**
* Item adapter
*/
private ItemAdapter
- itemAdapter;
/**
* Item identifier provider
*/
private ItemIdentifierProvider
- itemIdentifierProvider;
/**
* Item commit handler
*/
private CommitHandler
- commitHandler;
/**
* List of registered ItemSetChangeListener
*/
private List
itemSetChangeListeners;
/**
* List of registered PropertySetChangeListeners
*/
private List propertySetChangeListeners;
/**
* Container filters
*/
private List containerFilters;
/**
* Buffered by default
*/
private boolean buffered = true;
/**
* Additional QueryConfigurationProviders
*/
private List queryConfigurationProviders;
/**
* Fixed query filter: if not null, it will always be added to query filters
*/
private QueryFilter fixedFilter;
/**
* Fixed query sort: if not null, it will always be added to query sorts
*/
private QuerySort fixedSort;
/**
* Default query sort: if no other sort is provided, this sort will be used
*/
private QuerySort defaultSort;
/**
* {@link PropertySortGenerator}s bound to properties
*/
private Map> propertySortGenerators;
/**
* Query parameters
*/
private final DefaultParameterSet queryParameters = new DefaultParameterSet();
/**
* ValueChangeListeners to track item property modifications
*/
private final Map- itemPropertyValueChangeListeners = new WeakHashMap<>(8);
/**
* Constructor.
* @param dataProvider {@link ItemDataProvider} to be used as items data source
* @param itemIdentifierProvider Item identifier provider
* @param itemAdapter Item adapter
* @param batchSize Batch size
*/
public DefaultItemDataSourceContainer(ItemDataProvider
- dataProvider,
ItemIdentifierProvider
- itemIdentifierProvider, ItemAdapter
- itemAdapter, int batchSize) {
this();
this.dataProvider = dataProvider;
this.itemIdentifierProvider = itemIdentifierProvider;
this.itemAdapter = itemAdapter;
init(batchSize);
}
/**
* Constructor which do not perform internal initialization. The container initialization must be performed later
* using the init method.
*/
protected DefaultItemDataSourceContainer() {
super();
// include container filters
addQueryConfigurationProvider(new QueryConfigurationProvider() {
@Override
public QueryFilter getQueryFilter() {
// Container filters
return ContainerUtils.convertContainerFilters(getConfiguration(), getContainerFilters()).orElse(null);
}
});
}
/**
* Init the data source container, configuring the internal {@link ItemStore}.
* @param batchSize batch size
*/
protected void init(int batchSize) {
this.itemStore = new DefaultItemStore<>(this, new ContainerItemDataProvider<>(
getDataProvider().orElseThrow(
() -> new IllegalStateException("Invalid data source configuration: missing ItemDataProvider")),
this,
getItemAdapter().orElseThrow(
() -> new IllegalStateException("Invalid data source configuration: missing ItemAdapter"))),
getItemIdentifierProvider().map(i -> new ContainerItemIdentifierProvider<>(i,
getItemAdapter().orElseThrow(() -> new IllegalStateException(
"Invalid data source configuration: missing ItemAdapter")),
this)).orElse(null),
batchSize, determineMaxCacheSize(batchSize));
this.itemStore.setFreezed(!isAutoRefresh());
this.itemStore.addItemActionListener(this);
}
/**
* Get the items store.
* @return the items store, empty if not setted
*/
protected Optional
> getItemStore() {
return Optional.ofNullable(itemStore);
}
/**
* Get the items store.
* @return the items store
* @throws IllegalStateException If the items store is not available
*/
protected ItemStore- requireItemStore() {
return getItemStore()
.orElseThrow(() -> new IllegalStateException("Missing ItemStore: check container configuration"));
}
/**
* Get the item adapter.
* @return the item adapter, empty if not setted
*/
protected Optional
> getItemAdapter() {
return Optional.ofNullable(itemAdapter);
}
/**
* Get the item adapter.
* @return the item adapter
* @throws IllegalStateException If the item adapter is not available
*/
protected ItemAdapter- requireItemAdapter() {
return getItemAdapter()
.orElseThrow(() -> new IllegalStateException("Missing ItemAdapter: check container configuration"));
}
/**
* Set the item adapter
* @param itemAdapter the item adapter to set
*/
public void setItemAdapter(ItemAdapter
- itemAdapter) {
this.itemAdapter = itemAdapter;
}
/**
* Get the {@link ItemIdentifierProvider}.
* @return the item identifier provider
*/
protected Optional
> getItemIdentifierProvider() {
return Optional.ofNullable(itemIdentifierProvider);
}
/**
* Set the {@link ItemIdentifierProvider}.
* @param Item id type
* @param itemIdentifierProvider the item identifier provider to set
*/
public void setItemIdentifierProvider(ItemIdentifierProvider- itemIdentifierProvider) {
this.itemIdentifierProvider = itemIdentifierProvider;
}
/**
* Get the item data provider.
* @return the item data provider
*/
public Optional
> getDataProvider() {
return Optional.ofNullable(dataProvider);
}
/**
* Set the item data provider.
* @param dataProvider the item data provider to set
*/
public void setDataProvider(ItemDataProvider- dataProvider) {
this.dataProvider = dataProvider;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.ItemDataSource#getConfiguration()
*/
@Override
public Configuration
getConfiguration() {
return this;
}
/**
* Calculate max item store cache size using batch size, if positive or default
*
* @param batchSize Batch size
* @return Item store max cache size
*/
protected int determineMaxCacheSize(int batchSize) {
if (batchSize > 0) {
return batchSize * 10;
} else {
return ItemStore.DEFAULT_MAX_CACHE_SIZE;
}
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.querycontainer.ItemQueryContainer# setMaxCacheSize(int)
*/
@Override
public void setMaxCacheSize(int maxCacheSize) {
getItemStore().ifPresent(s -> {
s.setMaxCacheSize(maxCacheSize);
});
}
/**
* Gets whether auto refresh is enabled.
* @return whether auto refresh is enabled
*/
protected boolean isAutoRefresh() {
return autoRefresh;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.querycontainer.ItemQueryContainer#setAutoRefresh( boolean)
*/
@Override
public void setAutoRefresh(boolean autoRefresh) {
this.autoRefresh = autoRefresh;
// if auto refresh not enabled, freeze the item store
getItemStore().ifPresent(i -> i.setFreezed(!autoRefresh));
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.ItemDataSource.Configuration#getProperties()
*/
@Override
public Iterable getProperties() {
return propertyIds;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.querycontainer.ItemQueryDefinition# isPropertyReadOnly(java.lang.Object)
*/
@Override
public boolean isPropertyReadOnly(Object propertyId) {
return (propertyId != null && readOnlyPropertyIds.contains(propertyId));
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.querycontainer.ItemQueryDefinition# isPropertySortable(java.lang.Object)
*/
@Override
public boolean isPropertySortable(Object propertyId) {
return (propertyId != null && sortablePropertyIds.contains(propertyId));
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.querycontainer.ItemQueryDefinition# getPropertyDefaultValue(java.lang.Object)
*/
@Override
public Object getPropertyDefaultValue(Object propertyId) {
if (defaultValues != null && propertyId != null) {
return defaultValues.get(propertyId);
}
return null;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.querycontainer.ItemQueryContainer# addContainerProperty(java.lang.Object,
* java.lang.Class, boolean, boolean, java.lang.Object)
*/
@Override
public boolean addContainerProperty(PROPERTY propertyId, Class type, boolean readOnly, boolean sortable,
T defaultValue) {
if (propertyId != null) {
// remove any previous property with same id
if (propertyIds.contains(propertyId)) {
propertyIds.remove(propertyId);
}
propertyIds.add(propertyId);
Class> pt = (type != null) ? type : Object.class;
propertyTypes.put(propertyId, pt);
if (readOnly) {
readOnlyPropertyIds.add(propertyId);
}
if (sortable) {
sortablePropertyIds.add(propertyId);
}
if (defaultValue != null) {
if (defaultValues == null) {
defaultValues = new HashMap<>();
}
defaultValues.put(propertyId, defaultValue);
}
// event
notifyPropertySetChanged();
return true;
}
return false;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.querycontainer.ItemQueryContainer# addContainerProperty(java.lang.Object,
* java.lang.Class, boolean, boolean)
*/
@Override
public boolean addContainerProperty(PROPERTY propertyId, Class> type, boolean readOnly, boolean sortable) {
return addContainerProperty(propertyId, type, readOnly, sortable, null);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.querycontainer.ItemQueryContainer# setPropertySortable(java.lang.Object, boolean)
*/
@Override
public void setPropertySortable(PROPERTY propertyId, boolean sortable) {
if (propertyId != null) {
if (sortable) {
if (!sortablePropertyIds.contains(propertyId)) {
sortablePropertyIds.add(propertyId);
}
} else {
sortablePropertyIds.remove(propertyId);
}
}
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.querycontainer.ItemQueryContainer# setPropertyReadOnly(java.lang.Object, boolean)
*/
@Override
public void setPropertyReadOnly(PROPERTY propertyId, boolean readOnly) {
if (propertyId != null) {
if (readOnly) {
if (!readOnlyPropertyIds.contains(propertyId)) {
readOnlyPropertyIds.add(propertyId);
}
} else {
readOnlyPropertyIds.remove(propertyId);
}
}
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.querycontainer.ItemQueryContainer# setPropertyDefaultValue(java.lang.Object,
* java.lang.Object)
*/
@Override
public void setPropertyDefaultValue(PROPERTY propertyId, Object defaultValue) {
if (propertyId != null) {
if (defaultValues == null) {
defaultValues = new HashMap<>();
}
defaultValues.put(propertyId, defaultValue);
}
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.querycontainer.ItemQueryContainer#refresh()
*/
@Override
public void refresh() throws DataAccessException {
requireItemStore().reset(true, false);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.querycontainer.ItemQueryContainer#clear()
*/
@Override
public void clear() {
requireItemStore().reset(true, !isAutoRefresh());
}
/*
* Container
*/
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#getContainerPropertyIds()
*/
@Override
public Collection> getContainerPropertyIds() {
return ConversionUtils.iterableAsList(getProperties());
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#getItemIds()
*/
@Override
public Collection> getItemIds() {
return requireItemStore().getItemIds();
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#getContainerProperty(java.lang.Object, java.lang.Object)
*/
@SuppressWarnings("rawtypes")
@Override
public Property getContainerProperty(Object itemId, Object propertyId) {
final Item item = getItem(itemId);
if (item != null) {
return item.getItemProperty(propertyId);
}
return null;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#addContainerProperty(java.lang.Object, java.lang.Class, java.lang.Object)
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public boolean addContainerProperty(Object propertyId, Class type, Object defaultValue)
throws UnsupportedOperationException {
try {
return addContainerProperty((PROPERTY) propertyId, type, false, false, defaultValue);
} catch (Exception e) {
throw new UnsupportedFilterException(e);
}
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#removeContainerProperty(java.lang.Object)
*/
@Override
public boolean removeContainerProperty(Object propertyId) throws UnsupportedOperationException {
if (propertyId != null && propertyIds.contains(propertyId)) {
propertyIds.remove(propertyId);
if (readOnlyPropertyIds.contains(propertyId)) {
readOnlyPropertyIds.remove(propertyId);
}
if (sortablePropertyIds.contains(propertyId)) {
sortablePropertyIds.remove(propertyId);
}
if (defaultValues != null && defaultValues.containsKey(propertyId)) {
defaultValues.remove(propertyId);
}
// event
notifyPropertySetChanged();
return true;
}
return false;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#getType(java.lang.Object)
*/
@Override
public Class> getType(Object propertyId) {
if (propertyId != null) {
return propertyTypes.get(propertyId);
}
return null;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.ItemDataSource.Configuration#getPropertyType(java.lang.Object)
*/
@Override
public Class> getPropertyType(PROPERTY property) {
return getType(property);
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#size()
*/
@Override
public int size() {
return requireItemStore().size();
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#getItem(java.lang.Object)
*/
@Override
public Item getItem(Object itemId) {
if (itemId != null) {
int index = requireItemStore().indexOfItem(itemId);
if (index > -1) {
return requireItemStore().getItem(index);
}
}
return null;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#containsId(java.lang.Object)
*/
@Override
public boolean containsId(Object itemId) {
return requireItemStore().containsItem(itemId);
}
/**
* Get the commit handler
* @return the commit handler
*/
public Optional> getCommitHandler() {
return Optional.ofNullable(commitHandler);
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.container.ItemQueryContainer#setCommitHandler(com.holonplatform.vaadin.data.
* ItemDataSource.CommitHandler)
*/
@Override
public void setCommitHandler(CommitHandler- commitHandler) {
this.commitHandler = commitHandler;
}
/*
* (non-Javadoc)
* @see
* com.holonplatform.vaadin.data.container.ItemDataSourceContainer#addQueryConfigurationProvider(com.holonplatform.
* core.query.QueryConfigurationProvider)
*/
@Override
public Registration addQueryConfigurationProvider(QueryConfigurationProvider queryConfigurationProvider) {
ObjectUtils.argumentNotNull(queryConfigurationProvider, "QueryConfigurationProvider must be not null");
if (queryConfigurationProviders == null) {
queryConfigurationProviders = new LinkedList<>();
}
if (!queryConfigurationProviders.contains(queryConfigurationProvider)) {
queryConfigurationProviders.add(queryConfigurationProvider);
// reset store
resetStorePreservingFreezeState();
}
return () -> {
queryConfigurationProviders.remove(queryConfigurationProvider);
// reset store
resetStorePreservingFreezeState();
};
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.querycontainer.ItemQueryContainer#setFixedQueryFilter(com.holonplatform.core.query.
* QueryFilter)
*/
@Override
public void setFixedFilter(QueryFilter filter) {
this.fixedFilter = filter;
// reset store
resetStorePreservingFreezeState();
}
@Override
public void setFixedSort(QuerySort sort) {
this.fixedSort = sort;
// reset store
resetStorePreservingFreezeState();
}
@Override
public void setDefaultSort(QuerySort sort) {
this.defaultSort = sort;
// reset store
resetStorePreservingFreezeState();
}
@Override
public void addQueryParameter(String name, Object value) {
queryParameters.addParameter(name, value);
// reset store
resetStorePreservingFreezeState();
}
@Override
public void removeQueryParameter(String name) {
queryParameters.removeParameter(name);
// reset store
resetStorePreservingFreezeState();
}
@Override
public void setPropertySortGenerator(PROPERTY property, PropertySortGenerator
propertySortGenerator) {
ObjectUtils.argumentNotNull(property, "Property must be not null");
ObjectUtils.argumentNotNull(propertySortGenerator, "PropertySortGenerator must be not null");
if (propertySortGenerators == null) {
propertySortGenerators = new HashMap<>(4);
}
propertySortGenerators.put(property, propertySortGenerator);
}
/**
* Get the {@link PropertySortGenerator} bound to given property, if any
* @param property Property
* @return PropertySortGenerator, or null
if not available
*/
protected PropertySortGenerator getPropertySortGenerator(PROPERTY property) {
if (propertySortGenerators != null) {
return propertySortGenerators.get(property);
}
return null;
}
/**
* Additional QueryConfigurationProvider
* @return QueryConfigurationProviders, or null
if none
*/
public List getQueryConfigurationProviders() {
return queryConfigurationProviders;
}
/**
* Fixed query filter
* @return Fixed filter, or null
if not setted
*/
public QueryFilter getFixedFilter() {
return fixedFilter;
}
/**
* Fixed query sort
* @return Fixed sort, or null
if not setted
*/
public QuerySort getFixedSort() {
return fixedSort;
}
/**
* Default query sort
* @return Default sort, or null
if not setted
*/
public QuerySort getDefaultSort() {
return defaultSort;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.ItemDataSource#sort(com.holonplatform.vaadin.data.ItemDataSource.ItemSort[])
*/
@SuppressWarnings("unchecked")
@Override
public void sort(ItemSort... sorts) {
List> itemSorts = (sorts == null) ? null : Arrays.asList(sorts);
setItemSorts(itemSorts);
// refresh
refresh();
}
/**
* Get current item sorts.
* @return current item sorts
*/
protected List> getItemSorts() {
return itemSorts;
}
/**
* Set the item sort directives.
* @param sorts Item sorts
*/
public void setItemSorts(List> sorts) {
itemSorts.clear();
if (sorts != null) {
sorts.forEach(s -> itemSorts.add(s));
}
}
/*
* (non-Javadoc)
* @see com.holonplatform.core.query.QueryConfigurationProvider#getQueryFilter()
*/
@Override
public QueryFilter getQueryFilter() {
final LinkedList filters = new LinkedList<>();
// fixed
QueryFilter fixed = getFixedFilter();
if (fixed != null) {
filters.add(fixed);
}
// externally provided
if (getQueryConfigurationProviders() != null) {
for (QueryConfigurationProvider provider : getQueryConfigurationProviders()) {
QueryFilter filter = provider.getQueryFilter();
if (filter != null) {
filters.add(filter);
}
}
}
// return overall filter
return QueryFilter.allOf(filters).orElse(null);
}
/*
* (non-Javadoc)
* @see com.holonplatform.core.query.QueryConfigurationProvider#getQuerySort()
*/
@Override
public QuerySort getQuerySort() {
LinkedList sorts = new LinkedList<>();
// sorts
List> itemSorts = getItemSorts();
if (!itemSorts.isEmpty()) {
// item sorts
for (ItemSort itemSort : itemSorts) {
// sort property
PROPERTY sortId = itemSort.getProperty();
// check delegate
PropertySortGenerator generator = getPropertySortGenerator(sortId);
if (generator != null) {
QuerySort sort = generator.getQuerySort(sortId, itemSort.isAscending());
if (sort != null) {
sorts.add(sort);
}
} else {
getPropertyPath(sortId, getProperties()).ifPresent(p -> {
sorts.add(QuerySort.of(p,
itemSort.isAscending() ? SortDirection.ASCENDING : SortDirection.DESCENDING));
});
}
}
} else {
// externally provided
if (getQueryConfigurationProviders() != null) {
for (QueryConfigurationProvider provider : getQueryConfigurationProviders()) {
QuerySort sort = provider.getQuerySort();
if (sort != null) {
sorts.add(sort);
}
}
}
}
// default sort
if (sorts.isEmpty()) {
QuerySort dft = getDefaultSort();
if (dft != null) {
sorts.add(dft);
}
}
// fixed
QuerySort fixed = getFixedSort();
if (fixed != null) {
sorts.add(fixed);
}
if (!sorts.isEmpty()) {
if (sorts.size() == 1) {
return sorts.getFirst();
}
return QuerySort.of(sorts);
}
return null;
}
/*
* (non-Javadoc)
* @see com.holonplatform.core.query.QueryConfigurationProvider#getQueryParameters()
*/
@Override
public ParameterSet getQueryParameters() {
return queryParameters;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.ItemDataSource#getId(java.lang.Object)
*/
@Override
public Object getId(ITEM item) {
if (item != null) {
return requireItemStore().getItemId(requireItemAdapter().adapt(this, item));
}
return null;
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.ItemDataSource#get(java.lang.Object)
*/
@Override
public Optional- get(Object itemId) {
ObjectUtils.argumentNotNull(itemId, "Item id must be not null");
int index = requireItemStore().indexOfItem(itemId);
if (index > -1) {
Item item = requireItemStore().getItem(index);
if (item != null) {
return Optional.ofNullable(requireItemAdapter().restore(this, item));
}
}
return Optional.empty();
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.ItemDataSource#add(java.lang.Object)
*/
@Override
public Object add(ITEM item) {
ObjectUtils.argumentNotNull(item, "Item to add must be not null");
return requireItemStore().addItem(requireItemAdapter().adapt(this, item));
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.ItemDataSource#update(java.lang.Object)
*/
@Override
public void update(ITEM item) {
ObjectUtils.argumentNotNull(item, "Item to update must be not null");
requireItemStore().setItemModified(requireItemAdapter().adapt(this, item));
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.ItemDataSource#remove(java.lang.Object)
*/
@Override
public boolean remove(ITEM item) {
ObjectUtils.argumentNotNull(item, "Item to remove must be not null");
return requireItemStore().removeItem(requireItemAdapter().adapt(this, item));
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.ItemDataSource#refresh(java.lang.Object)
*/
@Override
public void refresh(ITEM item) {
ObjectUtils.argumentNotNull(item, "Item to refresh must be not null");
requireItemStore().refreshItem(requireItemAdapter().adapt(this, item));
}
/*
* (non-Javadoc)
* @see com.holonplatform.vaadin.data.container.ItemDataSourceContainer#refreshItem(java.lang.Object)
*/
@Override
public void refreshItem(Object itemId) {
ObjectUtils.argumentNotNull(itemId, "Item id to refresh must be not null");
requireItemStore().refreshItem(getItem(itemId));
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#addItem(java.lang.Object)
*/
@Override
public Item addItem(Object itemId) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#addItem()
*/
@Override
public Object addItem() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container#removeItem(java.lang.Object)
*/
@Override
public boolean removeItem(Object itemId) throws UnsupportedOperationException {
if (itemId != null) {
int idx = requireItemStore().indexOfItem(itemId);
if (idx > -1) {
requireItemStore().removeItem(idx);
notifyItemSetChanged(new ItemRemovedEvent(this, itemId, idx));
return true;
}
}
return false;
}
/*
* Container.Indexed
*/
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Indexed#indexOfId(java.lang.Object)
*/
@Override
public int indexOfId(Object itemId) {
if (itemId != null) {
return requireItemStore().indexOfItem(itemId);
}
return -1;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Indexed#getIdByIndex(int)
*/
@Override
public Object getIdByIndex(int index) {
return requireItemStore().getItemIds().get(index);
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Indexed#getItemIds(int, int)
*/
@Override
public List> getItemIds(int startIndex, int numberOfItems) {
return ContainerHelpers.getItemIdsUsingGetIdByIndex(startIndex, numberOfItems, this);
}
/*
* Container.Ordered
*/
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object)
*/
@Override
public Object nextItemId(Object itemId) {
List> ids = requireItemStore().getItemIds();
int currentIndex = ids.indexOf(itemId);
if (currentIndex < 0 || currentIndex == (ids.size() - 1)) {
return null;
}
return ids.get(currentIndex + 1);
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object)
*/
@Override
public Object prevItemId(Object itemId) {
List> ids = requireItemStore().getItemIds();
int currentIndex = ids.indexOf(itemId);
if (currentIndex <= 0) {
return null;
}
return ids.get(currentIndex - 1);
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Ordered#firstItemId()
*/
@Override
public Object firstItemId() {
List> ids = requireItemStore().getItemIds();
if (!ids.isEmpty()) {
return ids.get(0);
}
return null;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Ordered#lastItemId()
*/
@Override
public Object lastItemId() {
List> ids = requireItemStore().getItemIds();
if (!ids.isEmpty()) {
return ids.get(ids.size() - 1);
}
return null;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object)
*/
@Override
public boolean isFirstId(Object itemId) {
return requireItemStore().indexOfItem(itemId) == 0;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object)
*/
@Override
public boolean isLastId(Object itemId) {
return requireItemStore().indexOfItem(itemId) == (size() - 1);
}
/*
* Container.Buffered
*/
/*
* (non-Javadoc)
* @see com.vaadin.data.Buffered#commit()
*/
@Override
public void commit() throws SourceException, InvalidValueException {
final CommitHandler
- handler = getCommitHandler()
.orElseThrow(() -> new IllegalStateException("Missing CommitHandler"));
List
- added = requireItemStore().getAddedItems().stream().map(i -> requireItemAdapter().restore(this, i))
.collect(Collectors.toList());
List
- modified = requireItemStore().getModifiedItems().stream()
.map(i -> requireItemAdapter().restore(this, i)).collect(Collectors.toList());
List
- removed = requireItemStore().getRemovedItems().stream()
.map(i -> requireItemAdapter().restore(this, i)).collect(Collectors.toList());
if (!added.isEmpty() || !modified.isEmpty() || !removed.isEmpty()) {
final List
- addedItemReversed = new ArrayList<>(added);
Collections.reverse(addedItemReversed);
handler.commit(addedItemReversed, modified, removed);
// reset items store
requireItemStore().reset(false, false);
}
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Buffered#discard()
*/
@Override
public void discard() throws SourceException {
requireItemStore().discard();
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Buffered#setBuffered(boolean)
*/
@Override
public void setBuffered(boolean buffered) {
this.buffered = buffered;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Buffered#isBuffered()
*/
@Override
public boolean isBuffered() {
return buffered;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Buffered#isModified()
*/
@Override
public boolean isModified() {
return requireItemStore().isModified();
}
@Override
public void onItemAction(Item item, Object itemId, Item previous, ItemAction action) {
// setup property value change listeners
if (action == ItemAction.LOADED) {
if (previous != null) {
ItemPropertyValueChangeListener listener = itemPropertyValueChangeListeners.get(item);
if (listener != null) {
listener.detach();
}
}
itemPropertyValueChangeListeners.put(item, new ItemPropertyValueChangeListener(item, requireItemStore()));
} else if (action == ItemAction.SET_CHANGED) {
for (ItemPropertyValueChangeListener listener : itemPropertyValueChangeListeners.values()) {
listener.detach();
}
itemPropertyValueChangeListeners.clear();
} else if (action == ItemAction.REFRESHED) {
if (previous != null) {
ItemPropertyValueChangeListener listener = itemPropertyValueChangeListeners.get(previous);
if (listener != null) {
listener.detach();
itemPropertyValueChangeListeners.remove(previous);
}
itemPropertyValueChangeListeners.put(item,
new ItemPropertyValueChangeListener(item, requireItemStore()));
}
} else if (action == ItemAction.ADDED) {
// noop
} else if (action == ItemAction.REMOVED) {
ItemPropertyValueChangeListener listener = itemPropertyValueChangeListeners.get(item);
if (listener != null) {
listener.detach();
}
}
// notify item set changed
if (action == ItemAction.ADDED || action == ItemAction.REMOVED || action == ItemAction.REFRESHED
|| action == ItemAction.SET_CHANGED) {
ItemSetChangeEvent event = null;
if (action == ItemAction.ADDED) {
event = new ItemAddedEvent(this, itemId);
} else if (action == ItemAction.REMOVED) {
event = new ItemRemovedEvent(this, itemId, indexOfId(itemId));
}
notifyItemSetChanged(event);
}
// if not buffered, invoke commit
if (!isBuffered()
&& (action == ItemAction.ADDED || action == ItemAction.REMOVED || action == ItemAction.MODIFIED)) {
commit();
}
}
/*
* Container.Filterable
*/
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Filterable#addContainerFilter(com.vaadin.data. Container.Filter)
*/
@Override
public void addContainerFilter(Filter filter) throws UnsupportedFilterException {
if (filter != null) {
if (containerFilters == null) {
containerFilters = new LinkedList<>();
}
containerFilters.add(filter);
// reset store
resetStorePreservingFreezeState();
}
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Filterable#removeContainerFilter(com.vaadin.data. Container.Filter)
*/
@Override
public void removeContainerFilter(Filter filter) {
if (filter != null && containerFilters != null) {
containerFilters.remove(filter);
// reset store
resetStorePreservingFreezeState();
}
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Filterable#removeAllContainerFilters()
*/
@Override
public void removeAllContainerFilters() {
containerFilters = null;
// reset store
resetStorePreservingFreezeState();
}
/**
* Reset item store content preserving the freezed state
*/
protected void resetStorePreservingFreezeState() {
getItemStore().ifPresent(i -> {
boolean freezed = i.isFreezed();
try {
i.reset(false, false);
} finally {
i.setFreezed(freezed);
}
});
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Filterable#getContainerFilters()
*/
@Override
public Collection
getContainerFilters() {
if (containerFilters != null) {
return containerFilters;
}
return Collections.emptyList();
}
/*
* Container.Sortable
*/
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Sortable#sort(java.lang.Object[], boolean[])
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void sort(Object[] propertyId, boolean[] ascending) {
ItemSort[] itemSorts = null;
if (propertyId != null && propertyId.length > 0) {
itemSorts = new ItemSort[propertyId.length];
for (int i = 0; i < propertyId.length; i++) {
itemSorts[i] = new DefaultItemSort(propertyId[i], ascending[i]);
}
}
sort(itemSorts);
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds()
*/
@Override
public Collection> getSortableContainerPropertyIds() {
return sortablePropertyIds;
}
/*
* Container.ItemSetChangeNotifier
*/
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.ItemSetChangeNotifier#addItemSetChangeListener(
* com.vaadin.data.Container.ItemSetChangeListener)
*/
@Override
public void addItemSetChangeListener(ItemSetChangeListener listener) {
if (listener != null) {
if (itemSetChangeListeners == null) {
itemSetChangeListeners = new LinkedList<>();
}
if (!itemSetChangeListeners.contains(listener)) {
itemSetChangeListeners.add(listener);
}
}
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.ItemSetChangeNotifier#addListener(com.vaadin.data
* .Container.ItemSetChangeListener)
*/
@Override
public void addListener(ItemSetChangeListener listener) {
addItemSetChangeListener(listener);
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.ItemSetChangeNotifier#removeItemSetChangeListener
* (com.vaadin.data.Container.ItemSetChangeListener)
*/
@Override
public void removeItemSetChangeListener(ItemSetChangeListener listener) {
if (listener != null && itemSetChangeListeners != null) {
itemSetChangeListeners.remove(listener);
}
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.ItemSetChangeNotifier#removeListener(com.vaadin.
* data.Container.ItemSetChangeListener)
*/
@Override
public void removeListener(ItemSetChangeListener listener) {
removeItemSetChangeListener(listener);
}
/**
* Notifies that item set has been changed.
* @param event Item set change event
*/
@SuppressWarnings("serial")
protected void notifyItemSetChanged(ItemSetChangeEvent event) {
if (itemSetChangeListeners != null) {
ItemSetChangeEvent evt = (event != null) ? event : new ItemSetChangeEvent() {
@Override
public Container getContainer() {
return DefaultItemDataSourceContainer.this;
}
};
for (ItemSetChangeListener listener : itemSetChangeListeners) {
listener.containerItemSetChange(evt);
}
}
}
/**
* Event to notify an item was added to container
*
* Added items will be always inserted at index 0 in this container.
*
*/
@SuppressWarnings({ "rawtypes", "serial" })
protected static final class ItemAddedEvent implements ItemAddEvent {
private final DefaultItemDataSourceContainer container;
private final Object itemId;
public ItemAddedEvent(DefaultItemDataSourceContainer container, Object itemId) {
super();
this.container = container;
this.itemId = itemId;
}
@Override
public Container getContainer() {
return container;
}
@Override
public Object getFirstItemId() {
return itemId;
}
@Override
public int getFirstIndex() {
return 0;
}
@Override
public int getAddedItemsCount() {
return 1;
}
}
/**
* Event to notify an item was removed from container
*/
@SuppressWarnings({ "rawtypes", "serial" })
protected static final class ItemRemovedEvent implements ItemRemoveEvent {
private final DefaultItemDataSourceContainer container;
private final Object itemId;
private final int itemIndex;
public ItemRemovedEvent(DefaultItemDataSourceContainer container, Object itemId, int itemIndex) {
super();
this.container = container;
this.itemId = itemId;
this.itemIndex = itemIndex;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.ItemSetChangeEvent#getContainer()
*/
@Override
public Container getContainer() {
return container;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Indexed.ItemRemoveEvent#getFirstItemId()
*/
@Override
public Object getFirstItemId() {
return itemId;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Indexed.ItemRemoveEvent#getFirstIndex()
*/
@Override
public int getFirstIndex() {
return itemIndex;
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.Indexed.ItemRemoveEvent#getRemovedItemsCount()
*/
@Override
public int getRemovedItemsCount() {
return 1;
}
}
/*
* Container.PropertySetChangeNotifier
*/
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.PropertySetChangeNotifier# addPropertySetChangeListener(com.vaadin.data.Container.
* PropertySetChangeListener)
*/
@Override
public void addPropertySetChangeListener(PropertySetChangeListener listener) {
if (listener != null) {
if (propertySetChangeListeners == null) {
propertySetChangeListeners = new LinkedList<>();
}
if (!propertySetChangeListeners.contains(listener)) {
propertySetChangeListeners.add(listener);
}
}
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.PropertySetChangeNotifier#addListener(com.vaadin.
* data.Container.PropertySetChangeListener)
*/
@Deprecated
@Override
public void addListener(PropertySetChangeListener listener) {
addPropertySetChangeListener(listener);
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.PropertySetChangeNotifier#
* removePropertySetChangeListener(com.vaadin.data.Container. PropertySetChangeListener)
*/
@Override
public void removePropertySetChangeListener(PropertySetChangeListener listener) {
if (listener != null && propertySetChangeListeners != null) {
propertySetChangeListeners.remove(listener);
}
}
/*
* (non-Javadoc)
* @see com.vaadin.data.Container.PropertySetChangeNotifier#removeListener(com.
* vaadin.data.Container.PropertySetChangeListener)
*/
@Deprecated
@Override
public void removeListener(PropertySetChangeListener listener) {
removePropertySetChangeListener(listener);
}
/**
* Notifies that property set has been changed.
*/
@SuppressWarnings("serial")
protected void notifyPropertySetChanged() {
if (propertySetChangeListeners != null) {
PropertySetChangeEvent event = new PropertySetChangeEvent() {
@Override
public Container getContainer() {
return DefaultItemDataSourceContainer.this;
}
};
for (PropertySetChangeListener listener : propertySetChangeListeners) {
listener.containerPropertySetChange(event);
}
}
}
/*
* Unsupported
*/
/**
* Not supported
*/
@Override
public boolean removeAllItems() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* Not supported
*
* @param index Index
* @return Added item
* @throws UnsupportedOperationException This operation is not supported by this container
*/
@Override
public Object addItemAt(int index) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* Not supported
*
* @param index index Index
* @param newItemId New item id
* @return Added item
* @throws UnsupportedOperationException This operation is not supported by this container
*/
@Override
public Item addItemAt(int index, Object newItemId) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* Not supported
*
* @param previousItemId Previous id
* @return Added item id
* @throws UnsupportedOperationException This operation is not supported by this container
*/
@Override
public Object addItemAfter(Object previousItemId) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* Not supported
*
* @param previousItemId Previous id
* @param newItemId New id
* @return Added item
* @throws UnsupportedOperationException This operation is not supported by this container
*/
@Override
public Item addItemAfter(Object previousItemId, Object newItemId) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
private static Optional> getPropertyPath(Object propertyId, Iterable> properties) {
if (propertyId != null) {
if (propertyId instanceof Path) {
return Optional.of((Path>) propertyId);
} else {
Path> property = getPathByName(propertyId.toString(), properties);
if (property != null) {
return Optional.of(property);
}
}
}
return Optional.empty();
}
private static Path> getPathByName(String propertyName, Iterable> properties) {
if (propertyName != null && properties != null) {
for (Object property : properties) {
if (String.class.isAssignableFrom(property.getClass()) && propertyName.equals(property)) {
return Path.of(propertyName, Object.class);
}
if (property instanceof Path && propertyName.equals(((Path>) property).getName())) {
return (Path>) property;
}
}
}
return null;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy