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 * Static creator. 057 * @return A new {@link ObjectPaginator} object. 058 */ 059 public static ObjectPaginator create() { 060 return new ObjectPaginator(); 061 } 062 063 @Override /* Overridden from ObjectTool */ 064 @SuppressWarnings({ "rawtypes", "unchecked" }) 065 public Object run(BeanSession session, Object input, PageArgs args) { 066 067 if (input == null) 068 return null; 069 070 var type = session.getClassMetaForObject(input); 071 072 if (! type.isCollectionOrArray()) 073 return input; 074 075 int pos = args.getPosition(); 076 int limit = args.getLimit(); 077 078 if (type.isArray()) { 079 var size = Array.getLength(input); 080 var end = (limit + pos >= size) ? size : limit + pos; 081 pos = Math.min(pos, size); 082 var et = type.getElementType(); 083 if (! et.isPrimitive()) 084 return copyOfRange((Object[])input, pos, end); 085 if (et.is(boolean.class)) 086 return copyOfRange((boolean[])input, pos, end); 087 if (et.is(byte.class)) 088 return copyOfRange((byte[])input, pos, end); 089 if (et.is(char.class)) 090 return copyOfRange((char[])input, pos, end); 091 if (et.is(double.class)) 092 return copyOfRange((double[])input, pos, end); 093 if (et.is(float.class)) 094 return copyOfRange((float[])input, pos, end); 095 if (et.is(int.class)) 096 return copyOfRange((int[])input, pos, end); 097 if (et.is(long.class)) 098 return copyOfRange((long[])input, pos, end); 099 return copyOfRange((short[])input, pos, end); 100 } 101 102 var l = type.isList() ? (List)input : new ArrayList((Collection)input); 103 var end = (limit + pos >= l.size()) ? l.size() : limit + pos; 104 pos = Math.min(pos, l.size()); 105 return l.subList(pos, end); 106 } 107 108 /** 109 * Convenience method for executing the paginator. 110 * 111 * @param <R> The collection element type. 112 * @param input The input. Must be a collection or array of objects. 113 * @param pos The zero-index position to start from. 114 * @param limit The max number of entries to retrieve. 115 * @return A sublist of representing the entries from the position with the specified limit. 116 */ 117 @SuppressWarnings("unchecked") 118 public <R> List<R> run(Object input, int pos, int limit) { 119 var bs = BeanContext.DEFAULT_SESSION; 120 var r = run(BeanContext.DEFAULT_SESSION, input, PageArgs.create(pos, limit)); 121 if (r instanceof List r2) 122 return r2; 123 return bs.convertToType(r, List.class); 124 } 125}