package org.vaadin.viritin.v7.grid;
import com.vaadin.v7.data.Item;
import com.vaadin.v7.data.Property;
import com.vaadin.v7.data.util.PropertyValueGenerator;
import java.util.ArrayList;
import org.vaadin.viritin.v7.ListContainer;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
*
* @author Shabak Nikolay (nikolay.shabak@gmail.com)
* @since 23.04.2016
* @param <T> the entity type listed in the consumer of the container, Vaadin Grid
*/
public class GeneratedPropertyListContainer<T> extends ListContainer<T> {
private static final long serialVersionUID = -8384723868776183241L;
private final Map<String, PropertyValueGenerator<?>> propertyGenerators = new HashMap();
protected final Class<T> type;
/**
* Property implementation for generated properties
* @param <T> property data type
*/
protected static class GeneratedProperty<T> implements Property<T> {
private static final long serialVersionUID = -538857801793925329L;
private final Item item;
private final Object itemId;
private final Object propertyId;
private final PropertyValueGenerator<T> generator;
GeneratedProperty(Item item, Object propertyId, Object itemId,
PropertyValueGenerator<T> generator) {
this.item = item;
this.itemId = itemId;
this.propertyId = propertyId;
this.generator = generator;
}
@Override
public T getValue() {
return generator.getValue(item, itemId, propertyId);
}
@Override
public void setValue(T newValue) throws ReadOnlyException {
throw new ReadOnlyException("Generated properties are read only");
}
@Override
public Class<? extends T> getType() {
return generator.getType();
}
@Override
public boolean isReadOnly() {
return true;
}
@Override
public void setReadOnly(boolean newStatus) {
if (newStatus) {
// No-op
return;
}
throw new UnsupportedOperationException(
"Generated properties are read only");
}
}
/**
* Item implementation for generated properties.
*/
protected class GeneratedPropertyItem implements Item {
private static final long serialVersionUID = 8231832690836075843L;
private final Item wrappedItem;
private final Object itemId;
protected GeneratedPropertyItem(Object itemId, Item item) {
this.itemId = itemId;
wrappedItem = item;
}
@Override
public Property getItemProperty(Object id) {
if (propertyGenerators.containsKey(id)) {
return createProperty(wrappedItem, id, itemId,
propertyGenerators.get(id));
}
return wrappedItem.getItemProperty(id);
}
@Override
public Collection<?> getItemPropertyIds() {
Set wrappedProperties = new HashSet<>(wrappedItem.getItemPropertyIds());
wrappedProperties.addAll(propertyGenerators.keySet());
return wrappedProperties;
}
@Override
public boolean addItemProperty(Object id, Property property)
throws UnsupportedOperationException {
throw new UnsupportedOperationException(
"GeneratedPropertyItem does not support adding properties");
}
@Override
public boolean removeItemProperty(Object id)
throws UnsupportedOperationException {
throw new UnsupportedOperationException(
"GeneratedPropertyItem does not support removing properties");
}
/**
* Tests if the given object is the same as the this object. Two Items
* from the same container with the same ID are equal.
*
* @param obj
* an object to compare with this object
* @return <code>true</code> if the given object is the same as this
* object, <code>false</code> if not
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null
|| !obj.getClass().equals(GeneratedPropertyItem.class)) {
return false;
}
final GeneratedPropertyItem li = (GeneratedPropertyItem) obj;
return getContainer() == li.getContainer()
&& itemId.equals(li.itemId);
}
@Override
public int hashCode() {
return itemId.hashCode();
}
private GeneratedPropertyListContainer getContainer() {
return GeneratedPropertyListContainer.this;
}
}
public GeneratedPropertyListContainer(Class<T> type) {
super(type);
this.type = type;
}
public GeneratedPropertyListContainer(Class<T> type, String... properties) {
super(type);
this.type = type;
setContainerPropertyIds(properties);
}
public void addGeneratedProperty(String propertyId, PropertyValueGenerator<?> generator) {
propertyGenerators.put(propertyId, generator);
fireContainerPropertySetChange();
}
/**
* @param <P> the presentation type, displays the generated value
* @param propertyId the property id for generated property
* @param presentationType the presentation type of the generated property
* @param generator the generator that creates the property value on demand
*/
public <P> void addGeneratedProperty(String propertyId,
Class<P> presentationType,
TypedPropertyValueGenerator.ValueGenerator<T, P> generator) {
TypedPropertyValueGenerator<T, P> lambdaPropertyValueGenerator =
new TypedPropertyValueGenerator<>(type, presentationType, generator);
propertyGenerators.put(propertyId, lambdaPropertyValueGenerator);
fireContainerPropertySetChange();
}
public void addGeneratedProperty(String propertyId,
StringPropertyValueGenerator.ValueGenerator<T> generator) {
StringPropertyValueGenerator<T> lambdaPropertyValueGenerator =
new StringPropertyValueGenerator<>(type, generator);
propertyGenerators.put(propertyId, lambdaPropertyValueGenerator);
fireContainerPropertySetChange();
}
@Override
public Class<?> getType(Object propertyId) {
if (propertyGenerators.containsKey(propertyId)) {
return propertyGenerators.get(propertyId).getType();
}
return super.getType(propertyId);
}
@Override
public Item getItem(Object itemId) {
if (itemId == null) {
return null;
}
Item item = super.getItem(itemId);
return createGeneratedPropertyItem(itemId, item);
}
@Override
public Collection<String> getContainerPropertyIds() {
// create returned list of propertyIds
ArrayList<String> properties = new ArrayList<>();
// add all propertyIds of the underlying ListContainer
properties.addAll(super.getContainerPropertyIds());
// add the propertyIds for all the given generators
properties.addAll(propertyGenerators.keySet());
return properties;
}
private <T> Property<T> createProperty(final Item item,
final Object propertyId, final Object itemId,
final PropertyValueGenerator<T> generator) {
return new GeneratedProperty<>(item, propertyId, itemId, generator);
}
private Item createGeneratedPropertyItem(final Object itemId,
final Item item) {
return new GeneratedPropertyItem(itemId, item);
}
}