blob: a751a8792f43a2c96180bd10c71481b8f2aedc17 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.empire.jsf2.pageelements;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import javax.faces.event.ActionEvent;
import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.exceptions.NotSupportedException;
import org.apache.empire.exceptions.ObjectNotValidException;
import org.apache.empire.jsf2.pages.Page;
import org.apache.empire.jsf2.pages.PageElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class ListPageElement<T> extends PageElement
{
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(ListPageElement.class);
protected Class<T> beanClass;
protected List<T> items = null;
protected SelectionSet selectedItems = null;
public static class SelectionSet extends HashSet<String>
{
private static final long serialVersionUID = 1L;
private boolean singleSelection = false;
private boolean invertSelection = false;
public SelectionSet()
{
super();
}
public SelectionSet(int size)
{
super(size);
}
public boolean isSingleSelection()
{
return singleSelection;
}
public void setSingleSelection(boolean singleSelection)
{
this.singleSelection = singleSelection;
clear();
}
public boolean isInvertSelection()
{
return invertSelection;
}
public boolean set(String e)
{
clear();
return super.add(e);
}
@Override
public boolean add(String e)
{
if (singleSelection)
return false;
return super.add(e);
}
@Override
public boolean remove(Object o)
{
if (singleSelection)
return false;
return super.remove(o);
}
public void setInvertSelection(boolean invertSelection)
{
if (this.invertSelection==invertSelection)
return; // no change
// invert
this.invertSelection = invertSelection;
this.clear();
}
@Override
public boolean contains(Object item)
{
boolean exists = super.contains(item);
return (invertSelection ? !exists : exists);
}
}
/**
* Interface to uniquely identify a list item
* This will be used for selection and navigation
*/
public static interface ParameterizedItem {
public String getIdParam();
public void setIdParam(String idParam);
}
/**
* Abstract superclass to make a list item selectable
*/
public static abstract class SelectableItem implements Serializable
{
private static final long serialVersionUID = 1L;
private SelectionSet selectSet = null;
protected void setSelectMap(SelectionSet selectSet)
{
this.selectSet = selectSet;
}
public boolean isSelected()
{
String id = getIdParam();
return this.selectSet.contains(id);
}
public void setSelected(boolean selected)
{
String id = getIdParam();
if (selected != this.selectSet.isInvertSelection())
{
this.selectSet.add(id);
}
else
{
this.selectSet.remove(id);
}
}
public abstract String getIdParam();
}
/**
* This class holds information about the list view to display.
* This will be held on the session in order to maintain position and sorting when navigating back and forth.
*/
public static class ListTableInfo implements Serializable
{
private static final long serialVersionUID = 1L;
/** Pagination **/
/**
* position, starts with 0
*/
private int itemCount = -1;
private boolean valid = false;
private boolean modified = false;
/** Sorting **/
private String sortColumnName;
private boolean sortAscending = true;
private boolean sortOrderChanged = false;
/** Pagination **/
private int position = 0;
private int pageSize = 0;
public void init(int itemCount, int pageSize)
{
if (pageSize < 0)
{ // pageSize must not be negative!
throw new ObjectNotValidException(this);
}
this.itemCount = itemCount;
this.pageSize = pageSize;
this.position = 0;
this.valid = (itemCount >= 0);
this.modified = false;
}
public boolean isValid()
{
return this.valid;
}
public void setValid(boolean valid)
{
if (valid && (this.itemCount < 0))
{ // itemCount and position must not be negative!
throw new ObjectNotValidException(this);
}
this.valid = valid;
}
public boolean isModified()
{
return (this.valid && this.modified);
}
public void setModified(boolean modified)
{
this.modified = modified;
}
public int getItemCount()
{
return this.itemCount;
}
public int getPageSize()
{
return this.pageSize;
}
/*** sorting ***/
public String getSortColumnName()
{
return this.sortColumnName;
}
public void setSortColumnName(String column)
{
if (ObjectUtils.compareEqual(column, this.sortColumnName))
{
return;
}
// change value
this.sortColumnName = column;
this.position = 0;
this.modified = true;
this.sortOrderChanged = true;
}
public boolean getSortAscending()
{
return this.sortAscending;
}
public void setSortAscending(boolean sortAscending)
{
if (this.sortAscending == sortAscending)
{
return;
}
// change value
this.sortAscending = sortAscending;
this.modified = true;
this.sortOrderChanged = true;
}
public boolean isSortOrderChanged()
{
return this.sortOrderChanged;
}
public void setSortOrderChanged(boolean sortOrderChanged)
{
this.sortOrderChanged = sortOrderChanged;
}
/*** pagination ***/
public int getPosition()
{
return this.position;
}
public void setPosition(int position)
{
if (this.pageSize == 0)
{
throw new NotSupportedException(this, "setPosition");
}
if (position < 0)
{
position = 0;
}
if (position >= this.itemCount)
{
position = this.itemCount - 1;
}
if (this.position == position)
{
return;
}
// change value
this.position = position;
this.modified = true;
}
public boolean isAllowPagination()
{
return (this.pageSize > 0);
}
public boolean isHasNextPage()
{
if (isValid() && isAllowPagination())
{
return ((this.itemCount - (this.position + this.pageSize)) > 0);
}
return false;
}
public boolean isHasPrevPage()
{
return (isValid() && isAllowPagination() && this.position > 0);
}
/**
* set the next x entries
*/
public void nextPage(ActionEvent e)
{
if (!isAllowPagination())
{
throw new NotSupportedException(this, "nextPage");
}
// Check
if ((this.position + this.pageSize) > this.itemCount)
{
return; // Already on last page
}
// One page forward
this.position += this.pageSize;
this.modified = true;
}
/**
* set the prev x entries
*/
public void prevPage(ActionEvent e)
{
if (!isAllowPagination())
{
throw new NotSupportedException(this, "prevPage");
}
// Check
if (this.position == 0)
{
return; // Already on first page
}
// one page back
if (this.position > this.pageSize)
{
this.position -= this.pageSize;
}
else
{
this.position = 0;
}
// modified
this.modified = true;
}
public int getPageNumber()
{
if (!isAllowPagination())
{
return 1; // always first page
}
// Calc Page num
int pageNumber = new Double(Math.ceil(((double) this.position / this.pageSize))).intValue() + 1;
return pageNumber;
}
public int getPageCount()
{
if (!isAllowPagination())
{
return 1; // only one page
}
// Calc Page count
int pageCount = new Double(Math.ceil(((double) this.itemCount / this.pageSize))).intValue();
return pageCount;
}
}
public ListPageElement(Page page, Class<T> beanClass, String propertyName)
{
super(page, propertyName);
// set bean Class
this.beanClass = beanClass;
// selectable
if (ListPageElement.isSelectableItem(beanClass))
{
this.selectedItems = new SelectionSet();
}
}
private static <T> boolean isSelectableItem(Class<T> beanClass)
{
Class<?> superClass = beanClass.getSuperclass();
while (superClass != null)
{ // Check Superclass
if (superClass.equals(SelectableItem.class))
{
return true;
}
superClass = superClass.getSuperclass();
}
return false;
}
/** session scoped properties **/
public abstract ListTableInfo getTableInfo();
public List<T> getItems()
{
if (this.items == null)
{
ListPageElement.log.warn("Bean List has not been initialized!");
}
return this.items;
}
/**
* returns whether the item list has been loaded
* @return true if the item list has been loaded even it contains no items for false otherwise
*/
public final boolean isValid()
{
return (this.items != null);
}
/**
* returns true if the either the item list is not valid or if it contains no items
* @return true if the either the item list is not valid or if it contains no items
*/
public final boolean isEmpty()
{
return (this.items==null || this.items.size()==0);
}
/**
* returns whether the item list is valid and contains at least one item
* @return true if the item list contains one or more items or false otherwise
*/
public final boolean isNotEmpty()
{
return (this.items!=null && this.items.size()>0);
}
/**
* added as "isEmpty" is not accessible from EL.
* @return true if the either the item list is not valid or if it contains no items
*/
public final boolean isBlank()
{
return isEmpty();
}
/**
* returns the total item count of the entire list (not just the visible part)
* @return the total number of items in the list
*/
public int getItemCount()
{
return getTableInfo().getItemCount();
}
public void clearItems()
{
clearSelection();
this.items = null;
}
/*** Selection ***/
public void clearSelection()
{
if (this.selectedItems != null)
{
this.selectedItems.clear();
}
}
public boolean isHasSelection()
{
if (this.selectedItems==null)
return false;
// Has selected Items
return (selectedItems.size()>0 || selectedItems.isInvertSelection());
}
public int getSelectedItemCount()
{
if (this.selectedItems==null)
return 0;
// Item count
return this.selectedItems.size();
}
public List<T> getSelectedItems()
{
if (this.selectedItems==null)
throw new NotSupportedException(this, "getSelectedItems");
// find all items
List<T> selection = new ArrayList<T>(this.selectedItems.size());
for (T item : getItems())
{
if (((SelectableItem)item).isSelected())
selection.add(item);
}
return selection;
}
public boolean isInvertSelection()
{
if (this.selectedItems==null)
return false;
// Invert selection
return this.selectedItems.isInvertSelection();
}
public void setInvertSelection(boolean invertSelection)
{
if (this.selectedItems==null)
throw new NotSupportedException(this, "setInvertSelection");
// Invert
this.selectedItems.setInvertSelection(invertSelection);
}
public boolean isSingleSelection()
{
if (this.selectedItems==null)
return false;
// Invert selection
return this.selectedItems.isSingleSelection();
}
public void setSingleSelection(boolean singleSelection)
{
if (this.selectedItems==null)
throw new NotSupportedException(this, "setSingleSelection");
// Invert
this.selectedItems.setSingleSelection(singleSelection);
}
public void setSelection(SelectableItem item)
{
if (this.selectedItems==null)
throw new NotSupportedException(this, "setInvertSelection");
// Invert
if (item!=null)
this.selectedItems.set(item.getIdParam());
else
this.selectedItems.clear();
}
public void setSelection(SelectableItem[] items)
{
if (this.selectedItems==null)
throw new NotSupportedException(this, "setInvertSelection");
// Invert
this.selectedItems.clear();
for (SelectableItem item : items)
this.selectedItems.add(item.getIdParam());
}
protected void assignSelectionMap(List<?> items)
{
// Check selectable
if (this.selectedItems == null)
return;
// generate all
for (Object item : items)
{
if (item instanceof SelectableItem)
{
((SelectableItem) item).setSelectMap(this.selectedItems);
}
}
}
}