/* * Copyright 2002-2013 the original author or authors. * * 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.springframework.data.gemfire.function; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.apache.geode.cache.execute.ResultSender; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; /** * Sends collection results using a {@link ResultSender} in chunks determined by batchSize * * @author David Turanski * @since 1.3.0 */ class BatchingResultSender { private final int batchSize; private ResultSender<Object> resultSender; public BatchingResultSender(int batchSize, ResultSender<Object> resultSender) { Assert.notNull(resultSender, "resultSender cannot be null"); Assert.isTrue(batchSize >= 0, "batchSize must be >= 0"); this.batchSize = batchSize; this.resultSender = resultSender; } public void sendResults(Iterable<?> result) { if (batchSize == 0) { resultSender.lastResult(result); return; } List<Object> chunk = new ArrayList<Object>(batchSize); for (Iterator<?> it = result.iterator(); it.hasNext();) { if (chunk.size() < batchSize) { chunk.add(it.next()); } if (chunk.size() == batchSize || !it.hasNext()) { if (it.hasNext()) { resultSender.sendResult(chunk); } else { resultSender.lastResult(chunk); } chunk.clear(); } } } public void sendArrayResults(Object result) { if (batchSize == 0) { resultSender.lastResult(result); return; } Assert.isTrue(ObjectUtils.isArray(result)); int length = Array.getLength(result); for (int from =0; from < length; from += batchSize) { int to = Math.min(length,from + batchSize); Object chunk = copyOfRange(result,from, to); if (to == length -1) { resultSender.lastResult(chunk); } else { resultSender.sendResult(chunk); } } } /** * @param result * @param from * @param to * @return */ private Object copyOfRange(Object result, int from, int to) { Class<?> arrayClass = result.getClass(); int size = to - from; if (int[].class.isAssignableFrom(arrayClass)) { int[] array = new int[size]; for(int i = 0; i < size ; ++i){ array[i] = Array.getInt(result, from + i); } return array; } if (float[].class.isAssignableFrom(arrayClass)) { float[] array = new float[size]; for(int i = 0; i < size ; ++i){ array[i] = Array.getFloat(result, from + i); } return array; } if (double[].class.isAssignableFrom(arrayClass)) { double[] array = new double[size]; for(int i = 0; i < size ; ++i){ array[i] = Array.getDouble(result, from + i); } return array; } if (boolean[].class.isAssignableFrom(arrayClass)) { boolean[] array = new boolean[size]; for(int i = 0; i < size ; ++i){ array[i] = Array.getBoolean(result, from + i); } return array; } if (byte[].class.isAssignableFrom(arrayClass)) { byte[] array = new byte[size]; for(int i = 0; i < size ; ++i){ array[i] = Array.getByte(result, from + i); } return array; } if (short[].class.isAssignableFrom(arrayClass)) { short[] array = new short[size]; for(int i = 0; i < size ; ++i){ array[i] = Array.getShort(result, from + i); } return array; } if (long[].class.isAssignableFrom(arrayClass)) { long[] array = new long[size]; for(int i = 0; i < size ; ++i){ array[i] = Array.getLong(result, from + i); } return array; } if (char[].class.isAssignableFrom(arrayClass)) { char[] array = new char[size]; for(int i = 0; i < size ; ++i){ array[i] = Array.getChar(result, from + i); } return array; } return Arrays.copyOfRange((Object[])result, from, to); } }