/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* Copyright (c) 2013, MPL CodeInside http://codeinside.ru
*/
package ru.codeinside.gses.lazyquerycontainer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.vaadin.ui.Table;
import ru.codeinside.gses.webui.components.api.IRefresh;
import com.vaadin.data.Buffered;
import com.vaadin.data.Container;
import com.vaadin.data.Container.Indexed;
import com.vaadin.data.Container.ItemSetChangeNotifier;
import com.vaadin.data.Container.PropertySetChangeNotifier;
import com.vaadin.data.Container.Sortable;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
public class LazyQueryContainer implements Indexed, Sortable, ItemSetChangeNotifier, PropertySetChangeNotifier,
Buffered, IRefresh {
/**
* Java serialization UID.
*/
private static final long serialVersionUID = 1L;
/**
* QueryView where LazyQueryContainer delegates method calls to.
*/
private QueryView queryView;
/**
* List of registered ItemSetChangeListener.
*/
private List<ItemSetChangeListener> itemSetChangeListeners = new ArrayList<ItemSetChangeListener>();
/**
* List of registered PropertySetChangeListeners.
*/
private List<PropertySetChangeListener> propertySetChangeListeners = new ArrayList<PropertySetChangeListener>();
/**
* Constructs LazyQueryContainer with LazyQueryView and given queryFactory.
*
* @param queryFactory The query factory to be used.
* @param compositeItems True if items are wrapped to CompositeItems.
* @param batchSize The batch size to be used when loading data.
*/
public LazyQueryContainer(final QueryFactory queryFactory, final boolean compositeItems,
final int batchSize) {
this.queryView = new LazyQueryView(queryFactory, compositeItems, batchSize);
}
/**
* Constructs LazyQueryContainer with LazyQueryView and given queryFactory
* and queryDefinition.
*
* @param queryFactory The query factory to be used.
* @param queryDefinition The query definition to be used.
*/
public LazyQueryContainer(final QueryDefinition queryDefinition, final QueryFactory queryFactory) {
this.queryView = new LazyQueryView(queryDefinition, queryFactory);
}
/**
* Constructs LazyQueryContainer with the given QueryView. This constructor
* role is to enable use of custom view implementations.
*
* @param queryView The query view to be used.
*/
public LazyQueryContainer(final QueryView queryView) {
this.queryView = queryView;
}
/**
* Sets new sort state and refreshes container.
*
* @param sortPropertyIds The IDs of the properties participating in sort.
* @param ascendingStates The sort state of the properties participating in sort. True means ascending.
*/
public final void sort(final Object[] sortPropertyIds, final boolean[] ascendingStates) {
queryView.sort(sortPropertyIds, ascendingStates);
}
/**
* Lists of the property IDs queried.
*
* @return A list of property IDs queried.
*/
public final Collection<?> getContainerPropertyIds() {
return queryView.getQueryDefinition().getPropertyIds();
}
/**
* List of the property IDs which can be sorted.
*
* @return A list of the property IDs which can be sorted.
*/
public final Collection<?> getSortableContainerPropertyIds() {
return queryView.getQueryDefinition().getSortablePropertyIds();
}
/**
* Gets the property value class of the given property.
*
* @param propertyId If of the property of interest.
* @return The value class of the given property.
*/
public final Class<?> getType(final Object propertyId) {
return queryView.getQueryDefinition().getPropertyType(propertyId);
}
/**
* Adds a new property to the definition.
*
* @param propertyId Id of the property.
* @param type Value class of the property.
* @param defaultValue Default value of the property.
* @return always true.
*/
public final boolean addContainerProperty(final Object propertyId, final Class<?> type, final Object defaultValue) {
queryView.getQueryDefinition().addProperty(propertyId, type, defaultValue, true, false);
notifyPropertySetChanged();
return true;
}
/**
* Adds a new property to the definition.
*
* @param propertyId Id of the property.
* @param type Value class of the property.
* @param defaultValue Default value of the property.
* @param readOnly Read only state of the property.
* @param sortable Sortable state of the property.
* @return always true.
*/
public final boolean addContainerProperty(final Object propertyId, final Class<?> type, final Object defaultValue,
final boolean readOnly, final boolean sortable) {
queryView.getQueryDefinition().addProperty(propertyId, type, defaultValue, readOnly, sortable);
notifyPropertySetChanged();
return true;
}
/**
* Removes the given property from the definition.
*
* @param propertyId If of the property to be removed.
* @return always true.
*/
public final boolean removeContainerProperty(final Object propertyId) {
queryView.getQueryDefinition().removeProperty(propertyId);
notifyPropertySetChanged();
return true;
}
/**
* Number of items in the container.
*
* @return number of items.
*/
public final int size() {
return queryView.size();
}
/**
* Gets list of item indexes in the container.
*
* @return Collection of Integers.
*/
public final Collection<?> getItemIds() {
return new NaturalNumbersList(size());
}
/**
* Gets item at given index.
*
* @param itemId index of the item.
* @return Item at the given index.
*/
public final Item getItem(final Object itemId) {
return queryView.getItem((Integer) itemId);
}
/**
* Gets property of an item.
*
* @param itemId The index of the item.
* @param propertyId ID of the property.
* @return the property corresponding to given IDs.
*/
public final Property getContainerProperty(final Object itemId, final Object propertyId) {
return getItem(itemId).getItemProperty(propertyId);
}
/**
* Gets ID of given index.
* In other words returns the index itself.
*
* @param index The index of the item.
* @return the object ID i.e. index.
*/
public final Object getIdByIndex(final int index) {
return index;
}
/**
* Gets index of given ID.
* In other words returns the index itself.
*
* @param itemId the item ID.
* @return the index.
*/
public final int indexOfId(final Object itemId) {
return (Integer) itemId;
}
/**
* True if container contains the given index.
*
* @param itemId Item index.
* @return true if container contains the given index.
*/
public final boolean containsId(final Object itemId) {
if (itemId.getClass() == Integer.class) {
return size() > (Integer) itemId && (Integer) itemId >= 0;
} else {
return false;
}
}
/**
* Check if given index is first i.e. 0.
*
* @param itemId the object index.
* @return true if index is 0.
*/
public final boolean isFirstId(final Object itemId) {
if (itemId.getClass() == Integer.class) {
return (Integer) itemId == 0;
} else {
return false;
}
}
/**
* Check if given index is first i.e. size() - 1.
*
* @param itemId the object index.
* @return true if index is size() - 1.
*/
public final boolean isLastId(final Object itemId) {
if (itemId.getClass() == Integer.class) {
return (Integer) itemId == size() - 1;
} else {
return false;
}
}
/**
* @return first item ID i.e. 0.
*/
public final Object firstItemId() {
return 0;
}
/**
* @return last item ID i.e. size() - 1
*/
public final Object lastItemId() {
return size() - 1;
}
/**
* @param itemId the item index
* @return itemId + 1
*/
public final Object nextItemId(final Object itemId) {
return (Integer) itemId + 1;
}
/**
* @param itemId the item index
* @return itemId - 1
*/
public final Object prevItemId(final Object itemId) {
return (Integer) itemId - 1;
}
/**
* Not supported.
*
* @param index item index
* @return new item ID.
*/
public final Object addItemAt(final int index) {
throw new UnsupportedOperationException();
}
/**
* Not supported.
*
* @param previousItemId ID of previous item.
* @return new item ID.
*/
public final Object addItemAfter(final Object previousItemId) {
throw new UnsupportedOperationException();
}
/**
* Not supported.
*
* @param index item index
* @param newItemId ID of new item
* @return new Item
*/
public final Item addItemAt(final int index, final Object newItemId) {
throw new UnsupportedOperationException();
}
/**
* Not supported.
*
* @param previousItemId ID of previous item.
* @param newItemId ID of new item
* @return new Item
*/
public final Item addItemAfter(final Object previousItemId, final Object newItemId) {
throw new UnsupportedOperationException();
}
/**
* Not supported.
*
* @param itemId itemId
* @return new Item
*/
public final Item addItem(final Object itemId) {
throw new UnsupportedOperationException();
}
/**
* Constructs and adds new item.
*
* @return item index.
*/
public final Object addItem() {
Object itemId = queryView.addItem();
notifyItemSetChanged();
return itemId;
}
/**
* Removes Item at given index.
*
* @param itemId Item index.
* @return always true.
*/
public final boolean removeItem(final Object itemId) {
queryView.removeItem((Integer) itemId);
notifyItemSetChanged();
return true;
}
/**
* Removes all items.
*
* @return always true.
*/
public final boolean removeAllItems() {
queryView.removeAllItems();
refresh();
return true;
}
/**
* Adds ItemSetChangeListener.
*
* @param listener ItemSetChangeListener to be added.
*/
public final void addListener(final ItemSetChangeListener listener) {
itemSetChangeListeners.add(listener);
}
/**
* Removes ItemSetChangeListener.
*
* @param listener ItemSetChangeListener to be removed.
*/
public final void removeListener(final ItemSetChangeListener listener) {
itemSetChangeListeners.remove(listener);
}
/**
* Refreshes container.
*/
public final void refresh() {
queryView.refresh();
notifyItemSetChanged();
}
/**
* Notifies that item set has been changed.
*/
private void notifyItemSetChanged() {
try {
QueryItemSetChangeEvent event = new QueryItemSetChangeEvent(this);
for (ItemSetChangeListener listener : itemSetChangeListeners) {
listener.containerItemSetChange(event);
}
} catch (RuntimeException e) {
Throwable x = e;
while (x.getCause() != null) {
x = x.getCause();
}
if (x instanceof Table.CacheUpdateException) {
Throwable[] causes = ((Table.CacheUpdateException) x).getCauses();
for (Throwable cause : causes) {
cause.printStackTrace();
}
}
}
}
/**
* Adds PropertySetChangeListener.
*
* @param listener PropertySetChangeListener to be added.
*/
public final void addListener(final PropertySetChangeListener listener) {
propertySetChangeListeners.add(listener);
}
/**
* Removes PropertySetChangeListener.
*
* @param listener PropertySetChangeListener to be removed.
*/
public final void removeListener(final PropertySetChangeListener listener) {
propertySetChangeListeners.remove(listener);
}
/**
* Notifies that property set has been changed.
*/
private void notifyPropertySetChanged() {
QueryPropertySetChangeEvent event = new QueryPropertySetChangeEvent(this);
for (PropertySetChangeListener listener : propertySetChangeListeners) {
listener.containerPropertySetChange(event);
}
}
/**
* Private ItemSetChangeEvent implementation.
*
* @author Tommi Laukkanen
*/
private class QueryItemSetChangeEvent implements ItemSetChangeEvent {
/**
* Java serialization version UID.
*/
private static final long serialVersionUID = 1L;
/**
* The container where event occurred.
*/
private LazyQueryContainer container;
/**
* Constructor for setting the container.
*
* @param container the Contianer.
*/
public QueryItemSetChangeEvent(final LazyQueryContainer container) {
this.container = container;
}
/**
* Gets the container where event occurred.
*
* @return the Contianer.
*/
public Container getContainer() {
return container;
}
}
/**
* Private PropertySetChangeEvent implementation.
*
* @author Tommi Laukkanen
*/
private class QueryPropertySetChangeEvent implements PropertySetChangeEvent {
/**
* Java serialization version UID.
*/
private static final long serialVersionUID = 1L;
/**
* The container where event occurred.
*/
private LazyQueryContainer container;
/**
* Constructor for setting the container.
*
* @param container the Contianer.
*/
public QueryPropertySetChangeEvent(final LazyQueryContainer container) {
this.container = container;
}
/**
* Gets the container where event occurred.
*
* @return the Contianer.
*/
public Container getContainer() {
return container;
}
}
/**
* Commits changed and refreshes container.
*/
public final void commit() {
queryView.commit();
refresh();
}
/**
* Discards changes and refreshes container.
*/
public final void discard() {
queryView.discard();
refresh();
}
/**
* @return true if container contains uncommited modifications.
*/
public final boolean isModified() {
return queryView.isModified();
}
/**
* Is container in read through mode.
*
* @return always false.
*/
public final boolean isReadThrough() {
return false;
}
/**
* Is container in write through mode.
*
* @return always false.
*/
public final boolean isWriteThrough() {
return false;
}
/**
* Not supported.
*
* @param readThrough is container in read through mode.
*/
public final void setReadThrough(final boolean readThrough) {
throw new UnsupportedOperationException();
}
/**
* Not supported.
*
* @param writeThrough is container in write through mode.
*/
public final void setWriteThrough(final boolean writeThrough) {
throw new UnsupportedOperationException();
}
/**
* @return the queryView
*/
public final QueryView getQueryView() {
return queryView;
}
}