]> source.dussan.org Git - poi.git/commitdiff
split BookmarksTables to internal and user-friendly API
authorSergey Vladimirov <sergey@apache.org>
Wed, 20 Jul 2011 15:03:43 +0000 (15:03 +0000)
committerSergey Vladimirov <sergey@apache.org>
Wed, 20 Jul 2011 15:03:43 +0000 (15:03 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1148810 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java
src/scratchpad/src/org/apache/poi/hwpf/model/BookmarksTables.java
src/scratchpad/src/org/apache/poi/hwpf/model/PropertyNode.java
src/scratchpad/src/org/apache/poi/hwpf/usermodel/Bookmarks.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/usermodel/BookmarksImpl.java [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hwpf/model/TestBookmarksTables.java

index 6019d3c14c5d90768786fc23eadcb850a7105a27..82000db2998d37a89af6fd0ebf40e249778b5549 100644 (file)
@@ -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>
index b8a2cd5f8b6e65a52968c1328512feefbea2b3cb..cc1b28ce0d011606b217924e12d2645ad02f0431 100644 (file)
@@ -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;
     }
 
   /**
index 2dd19d42d92f4fa9515b5f8dce75864d8b0269ee..ead86a60d3d9732088c576b0a1a266ec4a01c044 100644 (file)
@@ -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 BookmarksTables( byte[] tableStream, FileInformationBlock fib )
+    public int getBookmarksCount()
     {
-        read( tableStream, fib );
+        return descriptorsFirst.length();
     }
 
-    public Bookmark getBookmark( int index )
+    public GenericPropertyNode getDescriptorFirst( int index )
+            throws IndexOutOfBoundsException
     {
-        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;
-            }
-        };
+        return descriptorsFirst.getProperty( index );
     }
 
-    public int getBookmarksCount()
+    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
     {
index 78f4b35bf488be83a5a38610b0b6cf82da800403..ed6c2ac3851bb4a9d02b4e734e50ae7873c0821d 100644 (file)
@@ -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 )
         {
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Bookmarks.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Bookmarks.java
new file mode 100644 (file)
index 0000000..636746b
--- /dev/null
@@ -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 );
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/BookmarksImpl.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/BookmarksImpl.java
new file mode 100644 (file)
index 0000000..40b4064
--- /dev/null
@@ -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;
+    }
+}
index 7b0b9b0f7671111c812af04d07fd6e4d41c3698e..ced953c7f38fa51eca35bdd29e2632ae52f3923d 100644 (file)
@@ -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() );