in poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/CHPBinTable.java [118:304]
public void rebuild( ComplexFileTable complexFileTable )
{
long start = currentTimeMillis();
if ( complexFileTable != null )
{
SprmBuffer[] sprmBuffers = complexFileTable.getGrpprls();
// adding CHPX from fast-saved SPRMs
for ( TextPiece textPiece : complexFileTable.getTextPieceTable()
.getTextPieces() )
{
PropertyModifier prm = textPiece.getPieceDescriptor().getPrm();
if ( !prm.isComplex() )
continue;
int igrpprl = prm.getIgrpprl();
if ( igrpprl < 0 || igrpprl >= sprmBuffers.length )
{
LOG.atWarn().log("{}'s PRM references to unknown grpprl", textPiece);
continue;
}
boolean hasChp = false;
SprmBuffer sprmBuffer = sprmBuffers[igrpprl];
for ( SprmIterator iterator = sprmBuffer.iterator(); iterator
.hasNext(); )
{
SprmOperation sprmOperation = iterator.next();
if ( sprmOperation.getType() == SprmOperation.TYPE_CHP )
{
hasChp = true;
break;
}
}
if ( hasChp )
{
SprmBuffer newSprmBuffer = sprmBuffer.copy();
CHPX chpx = new CHPX( textPiece.getStart(),
textPiece.getEnd(), newSprmBuffer );
_textRuns.add( chpx );
}
}
LOG.atDebug().log("Merged with CHPX from complex file table in {} ms ({} elements in total)", box(currentTimeMillis() - start),box(_textRuns.size()));
start = currentTimeMillis();
}
List<CHPX> oldChpxSortedByStartPos = new ArrayList<>(_textRuns);
oldChpxSortedByStartPos.sort(PropertyNode.StartComparator);
LOG.atDebug().log("CHPX sorted by start position in {} ms", box(currentTimeMillis() - start));
start = currentTimeMillis();
final Map<CHPX, Integer> chpxToFileOrder = new IdentityHashMap<>();
{
int counter = 0;
for ( CHPX chpx : _textRuns )
{
chpxToFileOrder.put( chpx, Integer.valueOf( counter++ ) );
}
}
final Comparator<CHPX> chpxFileOrderComparator = (o1, o2) -> {
Integer i1 = chpxToFileOrder.get( o1 );
Integer i2 = chpxToFileOrder.get( o2 );
return i1.compareTo( i2 );
};
LOG.atDebug().log("CHPX's order map created in {} ms", box(currentTimeMillis() - start));
start = currentTimeMillis();
List<Integer> textRunsBoundariesList;
{
Set<Integer> textRunsBoundariesSet = new HashSet<>();
for ( CHPX chpx : _textRuns )
{
textRunsBoundariesSet.add( Integer.valueOf( chpx.getStart() ) );
textRunsBoundariesSet.add( Integer.valueOf( chpx.getEnd() ) );
}
textRunsBoundariesSet.remove( Integer.valueOf( 0 ) );
textRunsBoundariesList = new ArrayList<>(
textRunsBoundariesSet);
Collections.sort( textRunsBoundariesList );
}
LOG.atDebug().log("Texts CHPX boundaries collected in {} ms", box(currentTimeMillis() - start));
start = currentTimeMillis();
List<CHPX> newChpxs = new LinkedList<>();
int lastTextRunStart = 0;
for ( Integer objBoundary : textRunsBoundariesList )
{
final int boundary = objBoundary.intValue();
final int startInclusive = lastTextRunStart;
lastTextRunStart = boundary;
int startPosition = binarySearch( oldChpxSortedByStartPos, boundary );
startPosition = Math.abs( startPosition );
while ( startPosition >= oldChpxSortedByStartPos.size() )
startPosition--;
while ( startPosition > 0
&& oldChpxSortedByStartPos.get( startPosition ).getStart() >= boundary )
startPosition--;
List<CHPX> chpxs = new LinkedList<>();
for ( int c = startPosition; c < oldChpxSortedByStartPos.size(); c++ )
{
CHPX chpx = oldChpxSortedByStartPos.get( c );
if ( boundary < chpx.getStart() )
break;
int left = Math.max( startInclusive, chpx.getStart() );
int right = Math.min(boundary, chpx.getEnd() );
if ( left < right )
{
chpxs.add( chpx );
}
}
if ( chpxs.isEmpty() )
{
LOG.atWarn().log("Text piece [{}; {}) has no CHPX. Creating new one.", box(startInclusive),box(boundary));
// create it manually
CHPX chpx = new CHPX( startInclusive, boundary,
new SprmBuffer( 0 ) );
newChpxs.add( chpx );
continue;
}
if ( chpxs.size() == 1 )
{
// can we reuse existing?
CHPX existing = chpxs.get( 0 );
if ( existing.getStart() == startInclusive
&& existing.getEnd() == boundary)
{
newChpxs.add( existing );
continue;
}
}
chpxs.sort(chpxFileOrderComparator);
SprmBuffer sprmBuffer = new SprmBuffer( 0 );
for ( CHPX chpx : chpxs )
{
sprmBuffer.append( chpx.getGrpprl(), 0 );
}
CHPX newChpx = new CHPX( startInclusive, boundary, sprmBuffer );
newChpxs.add( newChpx );
continue;
}
this._textRuns = new ArrayList<>(newChpxs);
LOG.atDebug().log("CHPX rebuilt in {} ms ({} elements)", box(currentTimeMillis() - start),box(_textRuns.size()));
start = currentTimeMillis();
CHPX previous = null;
for ( Iterator<CHPX> iterator = _textRuns.iterator(); iterator
.hasNext(); )
{
CHPX current = iterator.next();
if ( previous == null )
{
previous = current;
continue;
}
if ( previous.getEnd() == current.getStart()
&& Arrays
.equals( previous.getGrpprl(), current.getGrpprl() ) )
{
previous.setEnd( current.getEnd() );
iterator.remove();
continue;
}
previous = current;
}
LOG.atDebug().log("CHPX compacted in {} ms ({} elements)", box(currentTimeMillis() - start),box(_textRuns.size()));
}