/*
* Copyright 2008 Fedora Commons, Inc.
*
* 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.mulgara.resolver.distributed.remote;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.rmi.RemoteException;
import java.util.Collection;
import java.util.Iterator;
import org.apache.log4j.Logger;
import org.mulgara.util.Rmi;
/**
* Implements the remote pager by iterating on a list and moving pages of elements over RMI.
* @param <E> The elements of the paged list.
*
* @created 2007-04-23
* @author <a href="mailto:gearon@users.sourceforge.net">Paula Gearon</a>
* @copyright © 2007 <a href="http://www.fedora-commons.org/">Fedora Commons</a>
*/
public class RemotePagerImpl<E extends Serializable> implements RemotePager<E> {
/** Logger. */
protected static final Logger logger = Logger.getLogger(RemotePagerImpl.class.getName());
/** The type of the wrapped class. Used for creating pages of elements in arrays. */
private Class<E> type;
/** Stored size of the wrapped collection. */
private final int size;
/** The objects to page over RMI. */
private Collection<E> collection;
/** Internal iterator for the collection. */
private Iterator<E> iter;
/** The latest page of data. */
private E[] currentPage;
/** The size of a data page. */
private final int pageSize = Config.getPageSize();
/**
* Creates a new remote paging object.
* @param type The java.lang.Class of the elements to be paged.
* @param collection The data to be paged.
* @throws RemoteException If the data cannot be sent over RMI.
*/
@SuppressWarnings("unchecked")
public RemotePagerImpl(Class<E> type, Collection<E> collection) throws RemoteException {
this.type = type;
this.collection = collection;
size = collection.size();
iter = null;
currentPage = (E[])Array.newInstance(type, pageSize);
Rmi.export(this);
}
/**
* Gets the number of items in the underlying data.
*/
public int size() {
return size;
}
/**
* Gets the first page of data as an array with length equal to the size of the page.
* @return an array of elements.
*/
public E[] firstPage() throws RemoteException {
iter = collection.iterator();
return fillPage();
}
/**
* Gets the next page of data as an array with length equal to the size of the page.
* @return an array of elements.
*/
public E[] nextPage() throws RemoteException {
return fillPage();
}
/**
* Populates the current page with elements from the underlying collection.
* @return The current page.
*/
private E[] fillPage() {
logger.trace("Filling page");
for (int i = 0; i < pageSize; i++) {
if (!iter.hasNext()) return truncatePage(i);
currentPage[i] = iter.next();
}
return currentPage;
}
/**
* Reduces the size of an array if there are fewer valid elements than the length of the array.
* @param The size of the array.
* @return A new current page.
*/
@SuppressWarnings("unchecked")
private E[] truncatePage(int offset) {
if (offset == 0) return null;
logger.trace("Building array of type: " + type +", with length: " + offset);
E[] result = (E[])Array.newInstance(type, offset);
System.arraycopy(currentPage, 0, result, 0, offset);
return result;
}
}