Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
package net.sf.jasperreports.engine.base;
import java.io.Serializable;
import java.util.Arrays;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.jasperreports.engine.JRConstants;
import net.sf.jasperreports.engine.JRPrintElement;
/**
* @author Lucian Chirita ([email protected])
*/
public class ElementsBlockList implements ElementStore, Serializable
{
private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID;
private static final Log log = LogFactory.getLog(ElementsBlockList.class);
private static final int INITIAL_SIZE = 3;
private static final int MAX_INCREMENT = 200;
private int blockCount;
private int[] offsets;
private ElementsBlock[] blocks;
private int size;
private transient int lastIndex = -1;
public ElementsBlockList(ElementsBlock block)
{
blocks = new ElementsBlock[INITIAL_SIZE];
offsets = new int[INITIAL_SIZE];
blockCount = 1;
blocks[0] = block;
offsets[0] = 0;
size = block.size();
}
@Override
public void updatePage(JRVirtualPrintPage page)
{
for (ElementsBlock block : blocks)
{
if (block != null)
{
block.updatePage(page);
}
}
}
public void addBlock(ElementsBlock block)
{
incrementBlocks();
blocks[blockCount] = block;
offsets[blockCount] = size;
size += block.size();
++blockCount;
}
protected void addBlock()
{
ElementsBlock block = new ElementsBlock(blocks[0].getContext(), blocks[0].getPage());
addBlock(block);
if (log.isDebugEnabled())
{
log.debug("created block " + block + " at offset " + size);
}
}
protected void incrementBlocks()
{
if (blockCount == blocks.length)
{
int newSize = Math.min((blockCount * 3) / 2 + 1, blockCount + MAX_INCREMENT);
ElementsBlock[] newBlocks = new ElementsBlock[newSize];
System.arraycopy(blocks, 0, newBlocks, 0, blockCount);
blocks = newBlocks;
int[] newOffsets = new int[newSize];
System.arraycopy(offsets, 0, newOffsets, 0, blockCount);
offsets = newOffsets;
}
}
public ElementsBlock[] getBlocks()
{
return Arrays.copyOf(blocks, blockCount);
}
@Override
public int size()
{
return size;
}
@Override
public JRPrintElement get(int index)
{
int blockIndex = blockIndex(index);
return blocks[blockIndex].get(index - offsets[blockIndex]);
}
@Override
public boolean add(JRPrintElement element)
{
// allow the last block to overflow.
if (!blocks[blockCount - 1].add(element, false))
{
// the last block overflowed, create a new one
addBlock();
// add the element to the new block
blocks[blockCount - 1].add(element, true);
}
++size;
return true;
}
@Override
public boolean add(int index, JRPrintElement element)
{
int blockIndex = blockIndex(index);
// only allow the last block to overflow.
// we're not moving elements across blocks when adding an element
// in the middle of a page.
// this can lead to bigger blocks, but the case is exotic.
boolean last = blockIndex == blockCount - 1;
if (last)
{
if (!blocks[blockIndex].add(index - offsets[blockIndex], element, false))
{
// the last block overflowed, create a new one
addBlock();
// add the element to the new block
blockIndex = blockCount - 1;
blocks[blockIndex].add(index - offsets[blockIndex], element, true);
}
}
else
{
blocks[blockIndex].add(index - offsets[blockIndex], element, true);
// increment offsets of subsequent blocks
for (int idx = blockIndex + 1; idx < blockCount; ++idx)
{
++offsets[blockIndex];
}
}
++size;
return true;
}
@Override
public JRPrintElement set(int index, JRPrintElement element)
{
int blockIndex = blockIndex(index);
return blocks[blockIndex].set(index - offsets[blockIndex], element);
}
@Override
public JRPrintElement remove(int index)
{
// FIXME removing elements from an existing block without moving elements
// across blocks. this can lead to small blocks if many elements are
// removed from a page, such as when we have a group with keep together.
int blockIndex = blockIndex(index);
ElementsBlock block = blocks[blockIndex];
JRPrintElement element = block.remove(index - offsets[blockIndex]);
// decrement offsets of subsequent blocks
if (blockIndex + 1 < blockCount)
{
for (int idx = blockIndex + 1; idx < blockCount; ++idx)
{
--offsets[idx];
}
}
// if the block was left empty and this is not the only block, get rid of it
if (blockCount > 1 && block.isEmpty())
{
// shift the remaining blocks
for (int idx = blockIndex + 1; idx < blockCount; ++idx)
{
blocks[idx - 1] = blocks[idx];
offsets[idx - 1] = offsets[idx];
}
--blockCount;
blocks[blockCount] = null;
offsets[blockCount] = 0;
}
--size;
return element;
}
@Override
public void dispose()
{
for (int idx = 0; idx < blockCount; ++idx)
{
blocks[idx].dispose();
}
}
protected int blockIndex(int index)
{
if (index < 0)
{
throw new IndexOutOfBoundsException("index: " + index);
}
// see if the index falls in the lastIndex block
if (lastIndex >= 0 && lastIndex < blockCount)
{
if (index >= offsets[lastIndex]
&& (lastIndex + 1 == blockCount
|| index < offsets[lastIndex + 1]))
{
return lastIndex;
}
}
int blockIndex = Arrays.binarySearch(offsets, 0, blockCount, index);
if (blockIndex < 0)
{
blockIndex = -blockIndex - 2;
}
// caching last index for fast serial access
lastIndex = blockIndex;
return blockIndex;
}
@Override
public JRVirtualPrintPage getPage()
{
return blocks[0].getPage();
}
}