]> source.dussan.org Git - poi.git/commitdiff
bug 58365: patch from Hannes Erven. Update CommentsTable to use CellAddress instead...
authorJaven O'Neal <onealj@apache.org>
Mon, 23 Nov 2015 12:29:45 +0000 (12:29 +0000)
committerJaven O'Neal <onealj@apache.org>
Mon, 23 Nov 2015 12:29:45 +0000 (12:29 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1715784 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java
src/ooxml/testcases/org/apache/poi/xssf/model/TestCommentsTable.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFComment.java

index 3cbc49dd507b8a9b55efa2b752274ad9ed4989ec..60d95a6d246d42a7807864068bcfe9a0bf701063 100644 (file)
@@ -23,10 +23,15 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
 
 import org.apache.poi.POIXMLDocumentPart;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.ss.usermodel.Comment;
+import org.apache.poi.ss.util.CellAddress;
+import org.apache.poi.util.Internal;
 import org.apache.poi.xssf.usermodel.XSSFComment;
 import org.apache.xmlbeans.XmlException;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
@@ -34,20 +39,26 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument;
 
+@Internal
 public class CommentsTable extends POIXMLDocumentPart {
+    public static final String DEFAULT_AUTHOR = "";
+    public static final int DEFAULT_AUTHOR_ID = 0;
+    /**
+     * Underlying XML Beans CTComment list.
+     */
     private CTComments comments;
     /**
      * XML Beans uses a list, which is very slow
      *  to search, so we wrap things with our own
      *  map for fast lookup.
      */
-    private Map<String, CTComment> commentRefs;
+    private Map<CellAddress, CTComment> commentRefs;
 
     public CommentsTable() {
         super();
         comments = CTComments.Factory.newInstance();
         comments.addNewCommentList();
-        comments.addNewAuthors().addAuthor("");
+        comments.addNewAuthors().addAuthor(DEFAULT_AUTHOR);
     }
 
     public CommentsTable(PackagePart part, PackageRelationship rel) throws IOException {
@@ -80,11 +91,22 @@ public class CommentsTable extends POIXMLDocumentPart {
     /**
      * Called after the reference is updated, so that
      *  we can reflect that in our cache
+     *  @deprecated 2015-11-23 (circa POI 3.14beta1). Use {@link #referenceUpdated(CellAddress, CTComment)} instead
      */
     public void referenceUpdated(String oldReference, CTComment comment) {
+       referenceUpdated(new CellAddress(oldReference), comment);
+    }
+    
+    /**
+     * Called after the reference is updated, so that
+     *  we can reflect that in our cache
+     *  @param oldReference the comment to remove from the commentRefs map
+     *  @param comment the comment to replace in the commentRefs map
+     */
+    public void referenceUpdated(CellAddress oldReference, CTComment comment) {
        if(commentRefs != null) {
           commentRefs.remove(oldReference);
-          commentRefs.put(comment.getRef(), comment);
+          commentRefs.put(new CellAddress(comment.getRef()), comment);
        }
     }
 
@@ -100,8 +122,8 @@ public class CommentsTable extends POIXMLDocumentPart {
         return comments.getAuthors().getAuthorArray((int)authorId);
     }
 
-    @SuppressWarnings("deprecation")
     public int findAuthor(String author) {
+        @SuppressWarnings("deprecation")
         String[] authorArray = comments.getAuthors().getAuthorArray();
         for (int i = 0 ; i < authorArray.length; i++) {
             if (authorArray[i].equals(author)) {
@@ -111,53 +133,144 @@ public class CommentsTable extends POIXMLDocumentPart {
         return addNewAuthor(author);
     }
 
+    /**
+     * Finds the cell comment at cellAddress, if one exists
+     *
+     * @param cellAddress the address of the cell to find a comment
+     * @return cell comment if one exists, otherwise returns null
+     * @deprecated 2015-11-23 (circa POI 3.14beta1). Use {@link #findCellComment(CellAddress)} instead
+     */
     public XSSFComment findCellComment(String cellRef) {
-        CTComment ct = getCTComment(cellRef);
+        return findCellComment(new CellAddress(cellRef));
+    }
+
+    /**
+     * Finds the cell comment at cellAddress, if one exists
+     *
+     * @param cellAddress the address of the cell to find a comment
+     * @return cell comment if one exists, otherwise returns null
+     */
+    public XSSFComment findCellComment(CellAddress cellAddress) {
+        CTComment ct = getCTComment(cellAddress);
         return ct == null ? null : new XSSFComment(this, ct, null);
     }
+    
 
-    @SuppressWarnings("deprecation") //YK: getXYZArray() array accessors are deprecated in xmlbeans with JDK 1.5 support
-    public CTComment getCTComment(String cellRef) {
+    /**
+     * Get the underlying CTComment xmlbean for a comment located at cellRef, if it exists
+     *
+     * @param cellRef the location of the cell comment
+     * @return CTComment xmlbean if comment exists, otherwise return null.
+     * @deprecated 2015-11-23 (circa POI 3.14beta1). Use {@link CommentsTable#getCTComment(CellAddress)} instead
+     */
+    @Internal
+    public CTComment getCTComment(String ref) {
+        return getCTComment(new CellAddress(ref));
+    }
+    
+    /**
+     * Get the underlying CTComment xmlbean for a comment located at cellRef, if it exists
+     *
+     * @param cellRef the location of the cell comment
+     * @return CTComment xmlbean if comment exists, otherwise return null.
+     */
+    @Internal
+    public CTComment getCTComment(CellAddress cellRef) {
         // Create the cache if needed
-        if(commentRefs == null) {
-           commentRefs = new HashMap<String, CTComment>();
-           for (CTComment comment : comments.getCommentList().getCommentArray()) {
-              commentRefs.put(comment.getRef(), comment);
-           }
-        }
+        prepareCTCommentCache();
 
         // Return the comment, or null if not known
         return commentRefs.get(cellRef);
     }
+    
+    /**
+     * Returns all cell comments on this sheet.
+     * @return A map of each Comment in this sheet, keyed on the cell address where
+     * the comment is located.
+     */
+    public Map<CellAddress, Comment> getCellComments(){
+        prepareCTCommentCache();
+        final TreeMap<CellAddress, Comment> map = new TreeMap<CellAddress, Comment>();
+        
+        for (final Entry<CellAddress, CTComment> e: commentRefs.entrySet()) {
+            map.put(e.getKey(), new XSSFComment(this, e.getValue(), null));
+        }
+        
+        return map;
+    }
 
     /**
-     * This method is deprecated and should not be used any more as
-     * it silently overwrites the comment in Cell A1 if present
-     * @deprecated Use {@link #newComment(String)} instead to explicitly set the cell reference to create for
+     * Refresh Map<CellAddress, CTComment> commentRefs cache,
+     * Calls that use the commentRefs cache will perform in O(1)
+     * time rather than O(n) lookup time for List<CTComment> comments.
      */
-    @Deprecated
-    public CTComment newComment() {
-        return newComment("A1");
+    @SuppressWarnings("deprecation") //YK: getXYZArray) array accessors are deprecated in xmlbeans with JDK 1.5 support
+    private void prepareCTCommentCache() {
+        // Create the cache if needed
+        if(commentRefs == null) {
+           commentRefs = new HashMap<CellAddress, CTComment>();
+           for (CTComment comment : comments.getCommentList().getCommentArray()) {
+              commentRefs.put(new CellAddress(comment.getRef()), comment);
+           }
+        }
     }
     
+    /**
+     * Create a new comment located at cell address
+     *
+     * @param ref the location to add the comment
+     * @return a new CTComment located at ref with default author
+     * @deprecated 2015-11-23 (circa POI 3.14beta1). Use {@link #newComment(CellAddress)} instead
+     */
+    @Internal
     public CTComment newComment(String ref) {
+        return newComment(new CellAddress(ref));
+    }
+    
+    /**
+     * Create a new comment located` at cell address
+     *
+     * @param ref the location to add the comment
+     * @return a new CTComment located at ref with default author
+     */
+    @Internal
+    public CTComment newComment(CellAddress ref) {
         CTComment ct = comments.getCommentList().addNewComment();
-        ct.setRef(ref);
-        ct.setAuthorId(0);
+        ct.setRef(ref.formatAsString());
+        ct.setAuthorId(DEFAULT_AUTHOR_ID);
         
         if(commentRefs != null) {
-           commentRefs.put(ct.getRef(), ct);
+           commentRefs.put(ref, ct);
         }
         return ct;
     }
-
+    
+    /**
+     * Remove the comment at cellRef location, if one exists
+     *
+     * @param cellRef the location of the comment to remove
+     * @return returns true if a comment was removed
+     * @deprecated 2015-11-23 (circa POI 3.14beta1). Use {@link #removeComment(CellAddress)} instead
+     */
     public boolean removeComment(String cellRef) {
+        return removeComment(new CellAddress(cellRef));
+    }
+
+    /**
+     * Remove the comment at cellRef location, if one exists
+     *
+     * @param cellRef the location of the comment to remove
+     * @return returns true if a comment was removed
+     */
+    public boolean removeComment(CellAddress cellRef) {
+        final String stringRef = cellRef.formatAsString();
         CTCommentList lst = comments.getCommentList();
         if(lst != null) {
+            @SuppressWarnings("deprecation") //YK: getXYZArray() array accessors are deprecated in xmlbeans with JDK 1.5 support
             CTComment[] commentArray = lst.getCommentArray();
             for (int i = 0; i < commentArray.length; i++) {
                 CTComment comment = commentArray[i];
-                if (cellRef.equals(comment.getRef())) {
+                if (stringRef.equals(comment.getRef())) {
                     lst.removeComment(i);
 
                     if(commentRefs != null) {
@@ -170,12 +283,25 @@ public class CommentsTable extends POIXMLDocumentPart {
         return false;
     }
 
+    /**
+     * Add a new author to the CommentsTable.
+     * This does not check if the author already exists.
+     *
+     * @param author the name of the comment author
+     * @return the index of the new author
+     */
     private int addNewAuthor(String author) {
         int index = comments.getAuthors().sizeOfAuthorArray();
         comments.getAuthors().insertAuthor(index, author);
         return index;
     }
 
+    /**
+     * Returns the underlying CTComments list xmlbean
+     *
+     * @return underlying comments list xmlbean
+     */
+    @Internal
     public CTComments getCTComments(){
         return comments;
     }
index 1ef9d19b4dcb605b0a3ed6fcc645242f29a05d52..6e88e4563c890666870e4f08ff1e02f50af02530 100644 (file)
@@ -34,6 +34,7 @@ import org.apache.poi.ss.usermodel.Drawing;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.xssf.XSSFTestDataSamples;
 import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
 import org.apache.poi.xssf.usermodel.XSSFRichTextString;
@@ -86,9 +87,9 @@ public class TestCommentsTable {
                comment1.setText(ctrst1);
 
                // test finding the right comment for a cell
-               assertSame(comment0, sheetComments.getCTComment("A1"));
-               assertSame(comment1, sheetComments.getCTComment("A2"));
-               assertNull(sheetComments.getCTComment("A3"));
+               assertSame(comment0, sheetComments.getCTComment(new CellAddress("A1")));
+               assertSame(comment1, sheetComments.getCTComment(new CellAddress("A2")));
+               assertNull(sheetComments.getCTComment(new CellAddress("A3")));
        }
 
 
@@ -210,33 +211,37 @@ public class TestCommentsTable {
 
        @Test
        public void removeComment() throws Exception {
+           final CellAddress addrA1 = new CellAddress("A1");
+        final CellAddress addrA2 = new CellAddress("A2");
+        final CellAddress addrA3 = new CellAddress("A3");
+           
         CommentsTable sheetComments = new CommentsTable();
-        CTComment a1 = sheetComments.newComment("A1");
-        CTComment a2 = sheetComments.newComment("A2");
-        CTComment a3 = sheetComments.newComment("A3");
+        CTComment a1 = sheetComments.newComment(addrA1);
+        CTComment a2 = sheetComments.newComment(addrA2);
+        CTComment a3 = sheetComments.newComment(addrA3);
 
-        assertSame(a1, sheetComments.getCTComment("A1"));
-        assertSame(a2, sheetComments.getCTComment("A2"));
-        assertSame(a3, sheetComments.getCTComment("A3"));
+        assertSame(a1, sheetComments.getCTComment(addrA1));
+        assertSame(a2, sheetComments.getCTComment(addrA2));
+        assertSame(a3, sheetComments.getCTComment(addrA3));
         assertEquals(3, sheetComments.getNumberOfComments());
 
-        assertTrue(sheetComments.removeComment("A1"));
+        assertTrue(sheetComments.removeComment(addrA1));
         assertEquals(2, sheetComments.getNumberOfComments());
-        assertNull(sheetComments.getCTComment("A1"));
-        assertSame(a2, sheetComments.getCTComment("A2"));
-        assertSame(a3, sheetComments.getCTComment("A3"));
+        assertNull(sheetComments.getCTComment(addrA1));
+        assertSame(a2, sheetComments.getCTComment(addrA2));
+        assertSame(a3, sheetComments.getCTComment(addrA3));
 
-        assertTrue(sheetComments.removeComment("A2"));
+        assertTrue(sheetComments.removeComment(addrA2));
         assertEquals(1, sheetComments.getNumberOfComments());
-        assertNull(sheetComments.getCTComment("A1"));
-        assertNull(sheetComments.getCTComment("A2"));
-        assertSame(a3, sheetComments.getCTComment("A3"));
+        assertNull(sheetComments.getCTComment(addrA1));
+        assertNull(sheetComments.getCTComment(addrA2));
+        assertSame(a3, sheetComments.getCTComment(addrA3));
 
-        assertTrue(sheetComments.removeComment("A3"));
+        assertTrue(sheetComments.removeComment(addrA3));
         assertEquals(0, sheetComments.getNumberOfComments());
-        assertNull(sheetComments.getCTComment("A1"));
-        assertNull(sheetComments.getCTComment("A2"));
-        assertNull(sheetComments.getCTComment("A3"));
+        assertNull(sheetComments.getCTComment(addrA1));
+        assertNull(sheetComments.getCTComment(addrA2));
+        assertNull(sheetComments.getCTComment(addrA3));
     }
 
        @Test
index 0687c4b323b552477026550bbcf10d6067c7e462..79a9c2122445fcae55627df3ee4ffb49e546f77c 100644 (file)
@@ -38,6 +38,7 @@ import org.apache.poi.ss.usermodel.RichTextString;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.xssf.XSSFITestDataProvider;
 import org.apache.poi.xssf.XSSFTestDataSamples;
@@ -73,7 +74,7 @@ public final class TestXSSFComment extends BaseTestCellComment  {
         assertEquals(1, sheetComments.getCTComments().getAuthors().sizeOfAuthorArray());
         assertEquals(1, sheetComments.getNumberOfAuthors());
 
-        CTComment ctComment = sheetComments.newComment("A1");
+        CTComment ctComment = sheetComments.newComment(CellAddress.A1);
         CTShape vmlShape = CTShape.Factory.newInstance();
 
         XSSFComment comment = new XSSFComment(sheetComments, ctComment, vmlShape);
@@ -88,7 +89,7 @@ public final class TestXSSFComment extends BaseTestCellComment  {
     public void getSetCol() {
         CommentsTable sheetComments = new CommentsTable();
         XSSFVMLDrawing vml = new XSSFVMLDrawing();
-        CTComment ctComment = sheetComments.newComment("A1");
+        CTComment ctComment = sheetComments.newComment(CellAddress.A1);
         CTShape vmlShape = vml.newCommentShape();
 
         XSSFComment comment = new XSSFComment(sheetComments, ctComment, vmlShape);
@@ -107,7 +108,7 @@ public final class TestXSSFComment extends BaseTestCellComment  {
     public void getSetRow() {
         CommentsTable sheetComments = new CommentsTable();
         XSSFVMLDrawing vml = new XSSFVMLDrawing();
-        CTComment ctComment = sheetComments.newComment("A1");
+        CTComment ctComment = sheetComments.newComment(CellAddress.A1);
         CTShape vmlShape = vml.newCommentShape();
 
         XSSFComment comment = new XSSFComment(sheetComments, ctComment, vmlShape);
@@ -179,7 +180,7 @@ public final class TestXSSFComment extends BaseTestCellComment  {
     @Test
     public void author() {
         CommentsTable sheetComments = new CommentsTable();
-        CTComment ctComment = sheetComments.newComment("A1");
+        CTComment ctComment = sheetComments.newComment(CellAddress.A1);
 
         assertEquals(1, sheetComments.getNumberOfAuthors());
         XSSFComment comment = new XSSFComment(sheetComments, ctComment, null);
@@ -230,8 +231,7 @@ public final class TestXSSFComment extends BaseTestCellComment  {
             }
 
             // create the comment in two different ways and verify that there is no difference
-            @SuppressWarnings("deprecation")
-            XSSFComment shape1 = new XSSFComment(comments, comments.newComment(), vmlShape1);
+            XSSFComment shape1 = new XSSFComment(comments, comments.newComment(CellAddress.A1), vmlShape1);
             shape1.setColumn(ca.getCol1());
             shape1.setRow(ca.getRow1());
 
@@ -243,7 +243,7 @@ public final class TestXSSFComment extends BaseTestCellComment  {
                 vmlShape2.getClientDataArray(0).setAnchorArray(0, position);
             }
             
-            String ref = new CellReference(ca.getRow1(), ca.getCol1()).formatAsString();
+            CellAddress ref = new CellAddress(ca.getRow1(), ca.getCol1());
             XSSFComment shape2 = new XSSFComment(comments, comments.newComment(ref), vmlShape2);
         
             assertEquals(shape1.getAuthor(), shape2.getAuthor());