Java tutorial
/* * Copyright 2014 Matti Tahvonen. * * 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 org.vaadin.maddon; import com.vaadin.data.Container; import com.vaadin.data.Container.ItemSetChangeNotifier; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.util.AbstractContainer; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.apache.commons.beanutils.BeanComparator; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.beanutils.DynaProperty; import org.apache.commons.beanutils.WrapDynaBean; import org.apache.commons.beanutils.WrapDynaClass; import org.apache.commons.collections.comparators.ComparableComparator; import org.apache.commons.collections.comparators.ReverseComparator; import org.apache.commons.lang3.ClassUtils; /** * A replacement for BeanItemContainer from the core * <p> * The ListContainer is rather similar to the cores BeanItemContainer, but has * better typed API, much smaller memory overhead (practically no overhead if * data is given as List) and also otherwise better performance. * * @param <T> the type of beans in the backed list */ public class ListContainer<T> extends AbstractContainer implements Container.Indexed, Container.Sortable, ItemSetChangeNotifier { private List<T> backingList; public ListContainer(Collection<T> backingList) { setCollection(backingList); } public ListContainer(Class<T> type, Collection<T> backingList) { dynaClass = WrapDynaClass.createDynaClass(type); setCollection(backingList); } public final void setCollection(Collection<T> backingList1) { if (backingList1 instanceof List) { this.backingList = (List<T>) backingList1; } else { this.backingList = new ArrayList<T>(backingList1); } fireItemSetChange(); } public ListContainer(Class<T> type) { backingList = new ArrayList<T>(); dynaClass = WrapDynaClass.createDynaClass(type); } protected List<T> getBackingList() { return backingList; } private transient WrapDynaClass dynaClass; private WrapDynaClass getDynaClass() { if (dynaClass == null && !backingList.isEmpty()) { dynaClass = WrapDynaClass.createDynaClass(backingList.get(0).getClass()); } return dynaClass; } @Override public int indexOfId(Object itemId) { return backingList.indexOf(itemId); } public int indexOf(T bean) { return indexOfId(bean); } @Override public T getIdByIndex(int index) { return backingList.get(index); } @Override public List<T> getItemIds(int startIndex, int numberOfItems) { return backingList.subList(startIndex, startIndex + numberOfItems); } @Override public Object addItemAt(int index) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported yet."); } @Override public Item addItemAt(int index, Object newItemId) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported yet."); } @Override public T nextItemId(Object itemId) { int i = backingList.indexOf(itemId) + 1; if (backingList.size() == i) { return null; } return backingList.get(i); } @Override public T prevItemId(Object itemId) { int i = backingList.indexOf(itemId) - 1; if (i < 0) { return null; } return backingList.get(i); } @Override public T firstItemId() { return backingList.get(0); } @Override public T lastItemId() { return backingList.get(backingList.size() - 1); } @Override public boolean isFirstId(Object itemId) { return itemId.equals(firstItemId()); } @Override public boolean isLastId(Object itemId) { return itemId.equals(lastItemId()); } @Override public Object addItemAfter(Object previousItemId) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported yet."); } @Override public Item addItemAfter(Object previousItemId, Object newItemId) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported yet."); } @Override public Item getItem(Object itemId) { if (itemId == null) { return null; } return new DynaBeanItem<T>((T) itemId); } @Override public Collection<String> getContainerPropertyIds() { ArrayList<String> properties = new ArrayList<String>(); if (getDynaClass() != null) { for (DynaProperty db : getDynaClass().getDynaProperties()) { properties.add(db.getName()); } properties.remove("class"); } return properties; } @Override public Collection<?> getItemIds() { return backingList; } @Override public Property getContainerProperty(Object itemId, Object propertyId) { return getItem(itemId).getItemProperty(propertyId); } @Override public Class<?> getType(Object propertyId) { final Class<?> type = getDynaClass().getDynaProperty(propertyId.toString()).getType(); if (type.isPrimitive()) { // Vaadin can't handle primitive types in _all_ places, so use // wrappers instead. FieldGroup works, but e.g. Table in _editable_ // mode fails for some reason return ClassUtils.primitiveToWrapper(type); } return type; } @Override public int size() { return backingList.size(); } @Override public boolean containsId(Object itemId) { return backingList.contains((T) itemId); } @Override public Item addItem(Object itemId) throws UnsupportedOperationException { backingList.add((T) itemId); fireItemSetChange(); return getItem(itemId); } @Override public Object addItem() throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported yet."); } @Override public boolean removeItem(Object itemId) throws UnsupportedOperationException { final boolean remove = backingList.remove((T) itemId); if (remove) { fireItemSetChange(); } return remove; } @Override public boolean addContainerProperty(Object propertyId, Class<?> type, Object defaultValue) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported yet."); } @Override public boolean removeContainerProperty(Object propertyId) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported yet."); } @Override public boolean removeAllItems() throws UnsupportedOperationException { backingList.clear(); fireItemSetChange(); return true; } public ListContainer addAll(Collection<T> beans) { backingList.addAll(beans); fireItemSetChange(); return this; } @Override public void sort(Object[] propertyId, boolean[] ascending) { Comparator c = new ComparableComparator(); if (!ascending[0]) { c = new ReverseComparator(c); } BeanComparator<T> bc = new BeanComparator<T>(propertyId[0].toString(), c); Collections.sort(backingList, bc); } @Override public Collection<?> getSortableContainerPropertyIds() { ArrayList<String> properties = new ArrayList<String>(); for (DynaProperty db : getDynaClass().getDynaProperties()) { if (db.getType().isPrimitive() || Comparable.class.isAssignableFrom(db.getType())) { properties.add(db.getName()); } } properties.remove("class"); return properties; } public void addItemSetChangeListener(Container.ItemSetChangeListener listener) { super.addItemSetChangeListener(listener); } public void removeItemSetChangeListener(Container.ItemSetChangeListener listener) { super.removeItemSetChangeListener(listener); } public void addListener(Container.ItemSetChangeListener listener) { super.addListener(listener); } public void removeListener(Container.ItemSetChangeListener listener) { super.removeListener(listener); } public class DynaBeanItem<T> implements Item { private class DynaProperty implements Property { private final String propertyName; public DynaProperty(String property) { propertyName = property; } @Override public Object getValue() { return getDynaBean().get(propertyName); } @Override public void setValue(Object newValue) throws Property.ReadOnlyException { getDynaBean().set(propertyName, newValue); } @Override public Class getType() { return ListContainer.this.getType(propertyName); } @Override public boolean isReadOnly() { return getDynaClass().getPropertyDescriptor(propertyName).getWriteMethod() == null; } @Override public void setReadOnly(boolean newStatus) { throw new UnsupportedOperationException("Not supported yet."); } } private T bean; private transient DynaBean db; public DynaBeanItem(T bean) { this.bean = bean; } private DynaBean getDynaBean() { if (db == null) { db = new WrapDynaBean(bean); } return db; } @Override public Property getItemProperty(Object id) { return new DynaProperty(id.toString()); } @Override public Collection<String> getItemPropertyIds() { return ListContainer.this.getContainerPropertyIds(); } @Override public boolean addItemProperty(Object id, Property property) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported yet."); } @Override public boolean removeItemProperty(Object id) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported yet."); } } }