package com.gwt.ui.client.masterview; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; /** * * @author ibouakl * */ public class DataSource { public static final int DEFAULT_PAGE_SIZE = 10; protected int pageSize; protected int currentPageNumber; private boolean enabledPagination = true; protected String propertyToSort; protected String sortType = SortConstants.NO_SORTING; private int currentPageCount; public String getPropertyToSort() { return propertyToSort; } public void setPropertyToSort(String propertyToSort) { this.propertyToSort = propertyToSort; refreshDisplayData(); } public String getSortType() { return sortType; } public void setSortType(String sortType) { this.sortType = sortType; refreshDisplayData(); } /** * <p> * The list of dataSource listeners. * </p> */ @SuppressWarnings("unchecked") protected List dataSourceListeners = new ArrayList(); /** * <p> * The list of filters. * </p> */ @SuppressWarnings("unchecked") protected List filters = new ArrayList(); /** * <p> * Filtered, paged and sorted data - ready to be displayed. * </p> */ @SuppressWarnings("unchecked") protected List displayData = new ArrayList(); /** * <p> * Original data that is not affected by filters, sorting and pagination. * </p> */ @SuppressWarnings("unchecked") protected List initialData = new ArrayList(); /** * <p> * The mapper that can be used to get values of the bean's fields by names of these fields (it's used instead of reflection that is not * supported in GWT JRE). * </p> * <p/> * <p> * It's generated by MasterViewGenerator in compile-time based on the class of the beans that would be keeped in datasource. * </p> */ protected PropertyMapper propertyMapper; /** * <p> * Adds a datasource listener to a list of listeners. Later it will be notifyed then the data will change. * <p> * * @param dataSourceListener a listener to add. */ @SuppressWarnings("unchecked") public void addDataSourceListener(DataSourceListener dataSourceListener) { if (!dataSourceListeners.contains(dataSourceListener)) { dataSourceListeners.add(dataSourceListener); } } /** * <p> * Removes a datasource listener from the list of listeners. * </p> * * @param dataSourceListener a listener to remove. */ public void removeDataSourceListener(DataSourceListener dataSourceListener) { if (dataSourceListeners.contains(dataSourceListener)) { dataSourceListeners.remove(dataSourceListener); } } /** * Gets property mapper. The property mapper is the object that can be used to get values of the bean's fields by names of these fields * (it's used instead of reflection that is not supported in GWT JRE). * * @return */ public PropertyMapper getPropertyMapper() { return propertyMapper; } public void setPropertyMapper(PropertyMapper propertyMapper) { this.propertyMapper = propertyMapper; } public DataSource() { this.currentPageNumber = 0; this.pageSize = DEFAULT_PAGE_SIZE; } public DataSource(boolean enabledPagination) { this.enabledPagination = enabledPagination; this.currentPageNumber = 0; this.pageSize = DEFAULT_PAGE_SIZE; } @SuppressWarnings("unchecked") public DataSource(List data) { this.currentPageNumber = 0; this.pageSize = DEFAULT_PAGE_SIZE; setInitialData(data); /*setDisplayData(data);*/ } public void clearData() { initialData = null; } @SuppressWarnings("unchecked") public void addFilter(Filter filter) { if (!filters.contains(filter)) { filters.add(filter); } refreshDisplayData(); } public void removeFilter(Filter filter) { if (filters.contains(filter)) { filters.remove(filter); } refreshDisplayData(); } public void clearFilters(Filter filter) { filters.clear(); refreshDisplayData(); } public void clearFiltersByProperty(String propertyName) { for (int i = 0; i < filters.size(); i++) { if (!(filters.get(i) instanceof Filter)) { continue; } Filter filter = (Filter) filters.get(i); if (filter.getPropertyName().equals(propertyName)) { filters.remove(filter); } } refreshDisplayData(); } @SuppressWarnings("unchecked") public void setInitialData(List initialData) { this.initialData = initialData; refreshDisplayData(); } @SuppressWarnings("unchecked") public void setDisplayData(List displayData) { this.displayData = displayData; notifyDataSourceListeners(displayData.size(), initialData.size()); } @SuppressWarnings("unchecked") public List getDisplayData() { return displayData; } protected void notifyDataSourceListeners(int readItemsCount, int allItemsCount) { for (int i = 0; i < dataSourceListeners.size(); i++) { if (dataSourceListeners.get(i) instanceof DataSourceListener) { DataSourceListener dataSourceListener = (DataSourceListener) dataSourceListeners.get(i); dataSourceListener.onDataChanged(readItemsCount, allItemsCount); } } } /** * Filters the data with a list of assigned filtes. */ @SuppressWarnings("unchecked") protected List filterData(List dataToFilter) { List filteredData = new ArrayList(); for (int i = 0; i < getInitialData().size(); i++) { filteredData.add(getInitialData().get(i)); } for (int i = 0; i < filters.size(); i++) { Filter filter = (Filter) filters.get(i); Validator validator = ValidatorBuilder.buildFromFilterExpression(filter.getExpression()); List toBeRemovedObjects = new ArrayList(); for (int j = 0; j < filteredData.size(); j++) { Object objectToTest = filteredData.get(j); Object propertyValueToTest = propertyMapper.getProperty(objectToTest, filter.getPropertyName()); if (!validator.isValid(propertyValueToTest)) { toBeRemovedObjects.add(objectToTest); } } for (int j = 0; j < toBeRemovedObjects.size(); j++) { filteredData.remove(toBeRemovedObjects.get(j)); } } return filteredData; } @SuppressWarnings("unchecked") protected List sortData(List dataToSort) { if (sortType.equals(SortConstants.NO_SORTING)) { return dataToSort; } final Comparator comparator; Object propertyValue = propertyMapper.getProperty(initialData.get(0), getPropertyToSort()); if (propertyValue instanceof Date) { comparator = new Comparator() { @Override public int compare(Object o1, Object o2) { Date d1 = (Date) o1; Date d2 = (Date) o2; return d1.before(d2) ? -1 : 1; } }; } else if ((propertyValue instanceof Integer) || (propertyValue instanceof Long) || (propertyValue instanceof Byte) || (propertyValue instanceof Double) || (propertyValue instanceof Float)) { comparator = new Comparator() { @Override public int compare(Object o1, Object o2) { if (o1 instanceof Double) { return ((Double) o1).compareTo(((Double) o2)); } else if (o1 instanceof Long) { return ((Long) o1).compareTo(((Long) o2)); } else if (o1 instanceof Integer) { return ((Integer) o1).compareTo(((Integer) o2)); } else { return -1; } } }; } else { comparator = new Comparator() { @Override public int compare(Object o1, Object o2) { return o1.toString().toLowerCase().compareTo(o2.toString().toLowerCase()); } }; } Collections.sort(dataToSort, new Comparator() { public int compare(Object firstBean, Object secondBbean) { Object firstObject = propertyMapper.getProperty(firstBean, propertyToSort); Object secondObject = propertyMapper.getProperty(secondBbean, propertyToSort); return comparator.compare(firstObject, secondObject); } }); if (sortType.equals(SortConstants.SORT_DESC)) { Collections.reverse(dataToSort); } return dataToSort; } @SuppressWarnings("unchecked") protected List paginateData(List dataToPaginate) { int firstEntityNumber = getPageSize() * getCurrentPageNumber(); if (firstEntityNumber >= dataToPaginate.size()) { /*throw new EmptyDataSourceException("");*/ } int lastEntityNumber = firstEntityNumber + pageSize; if (lastEntityNumber >= dataToPaginate.size()) { lastEntityNumber = dataToPaginate.size(); } if (lastEntityNumber == firstEntityNumber) { /*throw new EmptyDataSourceException("");*/ } List resultData = new ArrayList(); for (int i = firstEntityNumber; i < lastEntityNumber; i++) { resultData.add(dataToPaginate.get(i)); } return resultData; } public int getPageCount() { return currentPageCount; } @SuppressWarnings("unchecked") public void refreshDisplayData() { if (initialData == null || initialData.isEmpty()) { return; } List dataToBeDisplayed = new ArrayList(); for (int i = 0; i < getInitialData().size(); i++) { dataToBeDisplayed.add(getInitialData().get(i)); } dataToBeDisplayed = filterData(dataToBeDisplayed); dataToBeDisplayed = sortData(dataToBeDisplayed); currentPageCount = dataToBeDisplayed.size() / getPageSize() + 1; adjustCurrentPage(); if (enabledPagination) { dataToBeDisplayed = paginateData(dataToBeDisplayed); } setDisplayData(dataToBeDisplayed); } @SuppressWarnings("unchecked") public List getInitialData() { return initialData; } public boolean isEmpty() { return initialData.isEmpty(); } public int getCurrentPageNumber() { return currentPageNumber; } public void setCurrentPageNumber(int currentPageNumber) { if (getInitialData() == null) { setCurrentPageNumber(getLastPageNumber()); } else if (currentPageNumber > getLastPageNumber()) { setCurrentPageNumber(getLastPageNumber()); } else { this.currentPageNumber = currentPageNumber; } refreshDisplayData(); } private int getLastPageNumber() { int lastPageNumber = getInitialData().size() / getPageSize(); return lastPageNumber; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; refreshDisplayData(); } public void toPreviousPage() { setCurrentPageNumber(getCurrentPageNumber() - 1); refreshDisplayData(); } public void toNextPage() { setCurrentPageNumber(getCurrentPageNumber() + 1); refreshDisplayData(); } public void toFirstPage() { setCurrentPageNumber(0); refreshDisplayData(); } public void toLastPage() { setCurrentPageNumber(getPageCount() - 1); refreshDisplayData(); } public void adjustCurrentPage() { if (getCurrentPageNumber() >= getPageCount()) { setCurrentPageNumber(getPageCount() - 1); } } }