mirror of https://github.com/apache/poi.git
split BookmarksTables to internal and user-friendly API
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1148810 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
31624647c2
commit
d21d9d8fce
|
@ -38,7 +38,7 @@
|
|||
<action dev="poi-developers" type="fix">51481 - Fixed autofilters in HSSF to avoid warnings in Excel 2007</action>
|
||||
<action dev="poi-developers" type="fix">51533 - Avoid exception when changing name of a sheet containing shared formulas</action>
|
||||
<action dev="poi-developers" type="add">Support for appending images to existing drawings in HSSF</action>
|
||||
<action dev="poi-developers" type="fix">Added initial support for bookmarks in HWFP</action>
|
||||
<action dev="poi-developers" type="fix">Added initial support for bookmarks in HWPF</action>
|
||||
<action dev="poi-developers" type="fix">46250 - Fixed cloning worksheets with images</action>
|
||||
<action dev="poi-developers" type="fix">51524 - PapBinTable constructor is slow (regression)</action>
|
||||
<action dev="poi-developers" type="fix">51514 - allow HSSFObjectData to work with both POIFS and NPOIFS</action>
|
||||
|
|
|
@ -48,6 +48,8 @@ import org.apache.poi.hwpf.model.TextPiece;
|
|||
import org.apache.poi.hwpf.model.TextPieceTable;
|
||||
import org.apache.poi.hwpf.model.io.HWPFFileSystem;
|
||||
import org.apache.poi.hwpf.model.io.HWPFOutputStream;
|
||||
import org.apache.poi.hwpf.usermodel.Bookmarks;
|
||||
import org.apache.poi.hwpf.usermodel.BookmarksImpl;
|
||||
import org.apache.poi.hwpf.usermodel.HWPFList;
|
||||
import org.apache.poi.hwpf.usermodel.Range;
|
||||
import org.apache.poi.poifs.common.POIFSConstants;
|
||||
|
@ -102,9 +104,12 @@ public final class HWPFDocument extends HWPFDocumentCore
|
|||
/** Holds Office Art objects */
|
||||
protected ShapesTable _officeArts;
|
||||
|
||||
/** Holds the bookmarks */
|
||||
/** Holds the bookmarks tables */
|
||||
protected BookmarksTables _bookmarksTables;
|
||||
|
||||
|
||||
/** Holds the bookmarks */
|
||||
protected Bookmarks _bookmarks;
|
||||
|
||||
/** Holds the fields PLCFs */
|
||||
protected FieldsTables _fieldsTables;
|
||||
|
||||
|
@ -267,6 +272,7 @@ public final class HWPFDocument extends HWPFDocumentCore
|
|||
}
|
||||
|
||||
_bookmarksTables = new BookmarksTables( _tableStream, _fib );
|
||||
_bookmarks = new BookmarksImpl( _bookmarksTables );
|
||||
_fieldsTables = new FieldsTables(_tableStream, _fib);
|
||||
}
|
||||
|
||||
|
@ -444,12 +450,11 @@ public final class HWPFDocument extends HWPFDocumentCore
|
|||
}
|
||||
|
||||
/**
|
||||
* @return BookmarksTables object, that is able to extract bookmarks
|
||||
* descriptors from this document
|
||||
* @return user-friendly interface to access document bookmarks
|
||||
*/
|
||||
public BookmarksTables getBookmarksTables()
|
||||
public Bookmarks getBookmarks()
|
||||
{
|
||||
return _bookmarksTables;
|
||||
return _bookmarks;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,10 +1,25 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.apache.poi.hwpf.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.hwpf.model.io.HWPFOutputStream;
|
||||
import org.apache.poi.hwpf.usermodel.Bookmark;
|
||||
|
||||
public class BookmarksTables
|
||||
{
|
||||
|
@ -14,67 +29,55 @@ public class BookmarksTables
|
|||
|
||||
private String[] names = new String[0];
|
||||
|
||||
public BookmarksTables()
|
||||
{
|
||||
}
|
||||
|
||||
public BookmarksTables( byte[] tableStream, FileInformationBlock fib )
|
||||
{
|
||||
read( tableStream, fib );
|
||||
}
|
||||
|
||||
public Bookmark getBookmark( int index )
|
||||
{
|
||||
final GenericPropertyNode first = descriptorsFirst.getProperty( index );
|
||||
return new Bookmark()
|
||||
{
|
||||
public int getEnd()
|
||||
{
|
||||
int currentIndex = Arrays.asList(
|
||||
descriptorsFirst.toPropertiesArray() ).indexOf( first );
|
||||
if ( currentIndex >= descriptorsLim.length() )
|
||||
return first.getEnd();
|
||||
|
||||
GenericPropertyNode lim = descriptorsLim
|
||||
.getProperty( currentIndex );
|
||||
return lim.getStart();
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
int currentIndex = Arrays.asList(
|
||||
descriptorsFirst.toPropertiesArray() ).indexOf( first );
|
||||
if ( currentIndex >= names.length )
|
||||
return "";
|
||||
|
||||
return names[currentIndex];
|
||||
}
|
||||
|
||||
public int getStart()
|
||||
{
|
||||
return first.getStart();
|
||||
}
|
||||
|
||||
public void setName( String name )
|
||||
{
|
||||
int currentIndex = Arrays.asList(
|
||||
descriptorsFirst.toPropertiesArray() ).indexOf( first );
|
||||
if ( currentIndex < names.length )
|
||||
{
|
||||
String[] newNames = new String[currentIndex + 1];
|
||||
System.arraycopy( names, 0, newNames, 0, names.length );
|
||||
names = newNames;
|
||||
}
|
||||
names[currentIndex] = name;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int getBookmarksCount()
|
||||
{
|
||||
return descriptorsFirst.length();
|
||||
}
|
||||
|
||||
public GenericPropertyNode getDescriptorFirst( int index )
|
||||
throws IndexOutOfBoundsException
|
||||
{
|
||||
return descriptorsFirst.getProperty( index );
|
||||
}
|
||||
|
||||
public int getDescriptorFirstIndex( GenericPropertyNode descriptorFirst )
|
||||
{
|
||||
// TODO: very non-optimal
|
||||
return Arrays.asList( descriptorsFirst.toPropertiesArray() ).indexOf(
|
||||
descriptorFirst );
|
||||
}
|
||||
|
||||
public GenericPropertyNode getDescriptorLim( int index )
|
||||
throws IndexOutOfBoundsException
|
||||
{
|
||||
return descriptorsLim.getProperty( index );
|
||||
}
|
||||
|
||||
public int getDescriptorsFirstCount()
|
||||
{
|
||||
return descriptorsFirst.length();
|
||||
}
|
||||
|
||||
public int getDescriptorsLimCount()
|
||||
{
|
||||
return descriptorsLim.length();
|
||||
}
|
||||
|
||||
public String getName( int index ) throws ArrayIndexOutOfBoundsException
|
||||
{
|
||||
return names[index];
|
||||
}
|
||||
|
||||
public int getNamesCount()
|
||||
{
|
||||
return names.length;
|
||||
}
|
||||
|
||||
private void read( byte[] tableStream, FileInformationBlock fib )
|
||||
{
|
||||
int namesStart = fib.getFcSttbfbkmk();
|
||||
|
@ -97,6 +100,17 @@ public class BookmarksTables
|
|||
limDescriptorsLength, 0 );
|
||||
}
|
||||
|
||||
public void setName( int index, String name )
|
||||
{
|
||||
if ( index < names.length )
|
||||
{
|
||||
String[] newNames = new String[index + 1];
|
||||
System.arraycopy( names, 0, newNames, 0, names.length );
|
||||
names = newNames;
|
||||
}
|
||||
names[index] = name;
|
||||
}
|
||||
|
||||
public void writePlcfBkmkf( FileInformationBlock fib,
|
||||
HWPFOutputStream tableStream ) throws IOException
|
||||
{
|
||||
|
|
|
@ -35,9 +35,10 @@ import org.apache.poi.util.POILogger;
|
|||
public abstract class PropertyNode<T extends PropertyNode<T>> implements Comparable<T>, Cloneable
|
||||
{
|
||||
|
||||
static final class EndComparator implements Comparator<PropertyNode<?>>
|
||||
public static final class EndComparator implements
|
||||
Comparator<PropertyNode<?>>
|
||||
{
|
||||
static EndComparator instance = new EndComparator();
|
||||
public static EndComparator instance = new EndComparator();
|
||||
|
||||
public int compare( PropertyNode<?> o1, PropertyNode<?> o2 )
|
||||
{
|
||||
|
@ -48,9 +49,10 @@ public abstract class PropertyNode<T extends PropertyNode<T>> implements Compar
|
|||
}
|
||||
}
|
||||
|
||||
static final class StartComparator implements Comparator<PropertyNode<?>>
|
||||
public static final class StartComparator implements
|
||||
Comparator<PropertyNode<?>>
|
||||
{
|
||||
static StartComparator instance = new StartComparator();
|
||||
public static StartComparator instance = new StartComparator();
|
||||
|
||||
public int compare( PropertyNode<?> o1, PropertyNode<?> o2 )
|
||||
{
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.apache.poi.hwpf.usermodel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* User-friendly interface to access document bookmarks
|
||||
*
|
||||
* @author Sergey Vladimirov (vlsergey {at} gmail {dot} com)
|
||||
*/
|
||||
public interface Bookmarks
|
||||
{
|
||||
/**
|
||||
* @param index
|
||||
* bookmark document index
|
||||
* @return {@link Bookmark} with specified index
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if bookmark with specified index not present in document
|
||||
*/
|
||||
Bookmark getBookmark( int index ) throws IndexOutOfBoundsException;
|
||||
|
||||
/**
|
||||
* @return count of {@link Bookmark}s in document
|
||||
*/
|
||||
int getBookmarksCount();
|
||||
|
||||
/**
|
||||
* @return {@link Map} of bookmarks started in specified range, where key is
|
||||
* start position and value is sorted {@link List} of
|
||||
* {@link Bookmark}
|
||||
*/
|
||||
Map<Integer, List<Bookmark>> getBookmarksStartedBetween(
|
||||
int startInclusive, int endExclusive );
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.apache.poi.hwpf.usermodel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.hwpf.model.BookmarksTables;
|
||||
import org.apache.poi.hwpf.model.GenericPropertyNode;
|
||||
import org.apache.poi.hwpf.model.PropertyNode;
|
||||
|
||||
/**
|
||||
* Implementation of user-friendly interface for document bookmarks
|
||||
*
|
||||
* @author Sergey Vladimirov (vlsergey {at} gmail {doc} com)
|
||||
*/
|
||||
public class BookmarksImpl implements Bookmarks
|
||||
{
|
||||
|
||||
private final BookmarksTables bookmarksTables;
|
||||
|
||||
private Map<Integer, List<GenericPropertyNode>> sortedDescriptors = null;
|
||||
|
||||
private int[] sortedStartPositions = null;
|
||||
|
||||
public BookmarksImpl( BookmarksTables bookmarksTables )
|
||||
{
|
||||
this.bookmarksTables = bookmarksTables;
|
||||
}
|
||||
|
||||
private Bookmark getBookmark( final GenericPropertyNode first )
|
||||
{
|
||||
return new Bookmark()
|
||||
{
|
||||
public int getEnd()
|
||||
{
|
||||
int currentIndex = bookmarksTables
|
||||
.getDescriptorFirstIndex( first );
|
||||
try
|
||||
{
|
||||
GenericPropertyNode descriptorLim = bookmarksTables
|
||||
.getDescriptorLim( currentIndex );
|
||||
return descriptorLim.getStart();
|
||||
}
|
||||
catch ( IndexOutOfBoundsException exc )
|
||||
{
|
||||
return first.getEnd();
|
||||
}
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
int currentIndex = bookmarksTables
|
||||
.getDescriptorFirstIndex( first );
|
||||
try
|
||||
{
|
||||
return bookmarksTables.getName( currentIndex );
|
||||
}
|
||||
catch ( ArrayIndexOutOfBoundsException exc )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public int getStart()
|
||||
{
|
||||
return first.getStart();
|
||||
}
|
||||
|
||||
public void setName( String name )
|
||||
{
|
||||
int currentIndex = bookmarksTables
|
||||
.getDescriptorFirstIndex( first );
|
||||
bookmarksTables.setName( currentIndex, name );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Bookmark getBookmark( int index )
|
||||
{
|
||||
final GenericPropertyNode first = bookmarksTables
|
||||
.getDescriptorFirst( index );
|
||||
return getBookmark( first );
|
||||
}
|
||||
|
||||
public List<Bookmark> getBookmarksAt( int startCp )
|
||||
{
|
||||
updateSortedDescriptors();
|
||||
|
||||
List<GenericPropertyNode> nodes = sortedDescriptors.get( Integer
|
||||
.valueOf( startCp ) );
|
||||
if ( nodes == null || nodes.isEmpty() )
|
||||
return Collections.emptyList();
|
||||
|
||||
List<Bookmark> result = new ArrayList<Bookmark>( nodes.size() );
|
||||
for ( GenericPropertyNode node : nodes )
|
||||
{
|
||||
result.add( getBookmark( node ) );
|
||||
}
|
||||
return Collections.unmodifiableList( result );
|
||||
}
|
||||
|
||||
public int getBookmarksCount()
|
||||
{
|
||||
return bookmarksTables.getDescriptorsFirstCount();
|
||||
}
|
||||
|
||||
public Map<Integer, List<Bookmark>> getBookmarksStartedBetween(
|
||||
int startInclusive, int endExclusive )
|
||||
{
|
||||
updateSortedDescriptors();
|
||||
|
||||
int startLookupIndex = Arrays.binarySearch( this.sortedStartPositions,
|
||||
startInclusive );
|
||||
if ( startLookupIndex < 0 )
|
||||
startLookupIndex = -( startLookupIndex + 1 );
|
||||
int endLookupIndex = Arrays.binarySearch( this.sortedStartPositions,
|
||||
endExclusive );
|
||||
if ( endLookupIndex < 0 )
|
||||
endLookupIndex = -( endLookupIndex + 1 );
|
||||
|
||||
Map<Integer, List<Bookmark>> result = new LinkedHashMap<Integer, List<Bookmark>>();
|
||||
for ( int lookupIndex = startLookupIndex; lookupIndex < endLookupIndex; lookupIndex++ )
|
||||
{
|
||||
int s = sortedStartPositions[lookupIndex];
|
||||
List<Bookmark> startedAt = getBookmarksAt( s );
|
||||
if ( startedAt != null )
|
||||
result.put( Integer.valueOf( s ), startedAt );
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap( result );
|
||||
}
|
||||
|
||||
private void updateSortedDescriptors()
|
||||
{
|
||||
if ( sortedDescriptors != null )
|
||||
return;
|
||||
|
||||
Map<Integer, List<GenericPropertyNode>> result = new HashMap<Integer, List<GenericPropertyNode>>();
|
||||
for ( int b = 0; b < bookmarksTables.getDescriptorsFirstCount(); b++ )
|
||||
{
|
||||
GenericPropertyNode property = bookmarksTables
|
||||
.getDescriptorFirst( b );
|
||||
Integer positionKey = Integer.valueOf( property.getStart() );
|
||||
List<GenericPropertyNode> atPositionList = result.get( positionKey );
|
||||
if ( atPositionList == null )
|
||||
{
|
||||
atPositionList = new LinkedList<GenericPropertyNode>();
|
||||
result.put( positionKey, atPositionList );
|
||||
}
|
||||
atPositionList.add( property );
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
int[] indices = new int[result.size()];
|
||||
for ( Map.Entry<Integer, List<GenericPropertyNode>> entry : result
|
||||
.entrySet() )
|
||||
{
|
||||
indices[counter++] = entry.getKey().intValue();
|
||||
List<GenericPropertyNode> updated = new ArrayList<GenericPropertyNode>(
|
||||
entry.getValue() );
|
||||
Collections.sort( updated, PropertyNode.EndComparator.instance );
|
||||
entry.setValue( updated );
|
||||
}
|
||||
|
||||
this.sortedDescriptors = result;
|
||||
this.sortedStartPositions = indices;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,19 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.apache.poi.hwpf.model;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
@ -5,17 +21,24 @@ import junit.framework.TestCase;
|
|||
import org.apache.poi.hwpf.HWPFDocument;
|
||||
import org.apache.poi.hwpf.HWPFTestDataSamples;
|
||||
import org.apache.poi.hwpf.usermodel.Bookmark;
|
||||
import org.apache.poi.hwpf.usermodel.Bookmarks;
|
||||
|
||||
/**
|
||||
* Test cases for {@link BookmarksTables} and default implementation of
|
||||
* {@link Bookmarks}
|
||||
*
|
||||
* @author Sergey Vladimirov (vlsergey {at} gmail {dot} com)
|
||||
*/
|
||||
public class TestBookmarksTables extends TestCase
|
||||
{
|
||||
public void test()
|
||||
{
|
||||
HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "pageref.doc" );
|
||||
BookmarksTables bookmarksTables = doc.getBookmarksTables();
|
||||
Bookmarks bookmarks = doc.getBookmarks();
|
||||
|
||||
assertEquals( 1, bookmarksTables.getBookmarksCount() );
|
||||
assertEquals( 1, bookmarks.getBookmarksCount() );
|
||||
|
||||
Bookmark bookmark = bookmarksTables.getBookmark( 0 );
|
||||
Bookmark bookmark = bookmarks.getBookmark( 0 );
|
||||
assertEquals( "userref", bookmark.getName() );
|
||||
assertEquals( 27, bookmark.getStart() );
|
||||
assertEquals( 38, bookmark.getEnd() );
|
||||
|
|
Loading…
Reference in New Issue