001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.objecttools; 018 019import static java.util.Arrays.*; 020 021import java.lang.reflect.*; 022import java.util.*; 023import java.util.ArrayList; 024 025import org.apache.juneau.*; 026 027/** 028 * POJO model paginator. 029 * 030 * <p> 031 * This class is designed to extract sublists from arrays/collections of maps or beans. 032 * </p> 033 * 034 * <h5 class='section'>Example:</h5> 035 * <p class='bjava'> 036 * MyBean[] <jv>arrayOfBeans</jv> = ...; 037 * ObjectPaginator <jv>paginator</jv> = ObjectPaginator.<jsm>create</jsm>(); 038 * 039 * <jc>// Returns all rows from 100 to 110.</jc> 040 * List<MyBean> <jv>result</jv> = <jv>paginator</jv>.run(<jv>arrayOfBeans</jv>, 100, 10); 041 * </p> 042 * <p> 043 * The tool can be used against the following data types: 044 * </p> 045 * <ul> 046 * <li>Arrays/collections of maps or beans. 047 * </ul> 048 * 049 * <h5 class='section'>See Also:</h5><ul> 050 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ObjectTools">Object Tools</a> 051 052 * </ul> 053 */ 054public class ObjectPaginator implements ObjectTool<PageArgs> { 055 056 //----------------------------------------------------------------------------------------------------------------- 057 // Static 058 //----------------------------------------------------------------------------------------------------------------- 059 060 /** 061 * Static creator. 062 * @return A new {@link ObjectPaginator} object. 063 */ 064 public static ObjectPaginator create() { 065 return new ObjectPaginator(); 066 } 067 068 //----------------------------------------------------------------------------------------------------------------- 069 // Instance 070 //----------------------------------------------------------------------------------------------------------------- 071 072 /** 073 * Convenience method for executing the paginator. 074 * 075 * @param <R> The collection element type. 076 * @param input The input. Must be a collection or array of objects. 077 * @param pos The zero-index position to start from. 078 * @param limit The max number of entries to retrieve. 079 * @return A sublist of representing the entries from the position with the specified limit. 080 */ 081 @SuppressWarnings("unchecked") 082 public <R> List<R> run(Object input, int pos, int limit) { 083 BeanSession bs = BeanContext.DEFAULT_SESSION; 084 Object r = run(BeanContext.DEFAULT_SESSION, input, PageArgs.create(pos, limit)); 085 if (r instanceof List) 086 return (List<R>)r; 087 return bs.convertToType(r, List.class); 088 } 089 090 @Override /* ObjectTool */ 091 @SuppressWarnings({ "rawtypes", "unchecked" }) 092 public Object run(BeanSession session, Object input, PageArgs args) { 093 094 if (input == null) 095 return null; 096 097 ClassMeta type = session.getClassMetaForObject(input); 098 099 if (! type.isCollectionOrArray()) 100 return input; 101 102 int pos = args.getPosition(); 103 int limit = args.getLimit(); 104 105 if (type.isArray()) { 106 int size = Array.getLength(input); 107 int end = (limit+pos >= size) ? size : limit + pos; 108 pos = Math.min(pos, size); 109 ClassMeta<?> et = type.getElementType(); 110 if (! et.isPrimitive()) 111 return copyOfRange((Object[])input, pos, end); 112 if (et.is(boolean.class)) 113 return copyOfRange((boolean[])input, pos, end); 114 if (et.is(byte.class)) 115 return copyOfRange((byte[])input, pos, end); 116 if (et.is(char.class)) 117 return copyOfRange((char[])input, pos, end); 118 if (et.is(double.class)) 119 return copyOfRange((double[])input, pos, end); 120 if (et.is(float.class)) 121 return copyOfRange((float[])input, pos, end); 122 if (et.is(int.class)) 123 return copyOfRange((int[])input, pos, end); 124 if (et.is(long.class)) 125 return copyOfRange((long[])input, pos, end); 126 return copyOfRange((short[])input, pos, end); 127 } 128 129 List l = type.isList() ? (List)input : new ArrayList((Collection)input); 130 int end = (limit+pos >= l.size()) ? l.size() : limit + pos; 131 pos = Math.min(pos, l.size()); 132 return l.subList(pos, end); 133 } 134}