Author: nick
Date: Fri Oct 14 10:44:03 2016
New Revision: 1764863

URL: http://svn.apache.org/viewvc?rev=1764863&view=rev
Log:
#60255 When creating a XSSF drawing, find the next available document part, 
even if another type has pinched the next number

Modified:
    poi/trunk/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
    poi/trunk/src/ooxml/testcases/org/apache/poi/TestPOIXMLDocument.java
    
poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java

Modified: poi/trunk/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java?rev=1764863&r1=1764862&r2=1764863&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java Fri Oct 14 
10:44:03 2016
@@ -39,6 +39,7 @@ import org.apache.poi.openxml4j.opc.Targ
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
+import org.apache.poi.xssf.usermodel.XSSFRelation;
 
 /**
  * Represents an entry of a OOXML package.
@@ -537,6 +538,55 @@ public class POIXMLDocumentPart {
     public final POIXMLDocumentPart createRelationship(POIXMLRelation 
descriptor, POIXMLFactory factory, int idx){
         return createRelationship(descriptor, factory, idx, 
false).getDocumentPart();
     }
+    
+    /**
+     * Identifies the next available part number for a part of the given type,
+     *  if possible, otherwise -1 if none are available.
+     * The found (valid) index can then be safely given to
+     *  {@link #createRelationship(POIXMLRelation, POIXMLFactory, int)} or
+     *  {@link #createRelationship(POIXMLRelation, POIXMLFactory, int, 
boolean)}
+     *  without naming clashes.
+     * If parts with other types are already claiming a name for this 
relationship
+     *  type (eg a {@link XSSFRelation#CHART} using the drawing part namespace 
+     *  normally used by {@link XSSFRelation#DRAWINGS}), those will be 
considered
+     *  when finding the next spare number.
+     *
+     * @param descriptor The relationship type to find the part number for
+     * @param minIdx The minimum free index to assign, use -1 for any
+     * @return The next free part number, or -1 if none available
+     */
+    protected final int getNextPartNumber(POIXMLRelation descriptor, int 
minIdx) {
+        OPCPackage pkg = packagePart.getPackage();
+        
+        try {
+            if 
(descriptor.getDefaultFileName().equals(descriptor.getFileName(9999))) {
+                // Non-index based, check if default is free
+                PackagePartName ppName = 
PackagingURIHelper.createPartName(descriptor.getDefaultFileName());
+                if (pkg.containPart(ppName)) {
+                    // Default name already taken, not index based, nothing 
free
+                    return -1;
+                } else {
+                    // Default name free
+                    return 0;
+                }
+            }
+            
+            // Default to searching from 1, unless they asked for 0+
+            int idx = minIdx;
+            if (minIdx < 0) idx = 1;
+            while (idx < 1000) {
+                String name = descriptor.getFileName(idx);
+                if (!pkg.containPart(PackagingURIHelper.createPartName(name))) 
{
+                    return idx;
+                }
+                idx++;
+            }
+        } catch (InvalidFormatException e) {
+            // Give a general wrapped exception for the problem
+            throw new POIXMLException(e);
+        }
+        return -1;
+    }
 
     /**
      * Create a new child POIXMLDocumentPart

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java?rev=1764863&r1=1764862&r2=1764863&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java 
(original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java Fri 
Oct 14 10:44:03 2016
@@ -554,8 +554,9 @@ public class XSSFSheet extends POIXMLDoc
             return getDrawingPatriarch();
         }
         
-        //drawingNumber = #drawings.size() + 1
+        // Default drawingNumber = #drawings.size() + 1
         int drawingNumber = 
getPackagePart().getPackage().getPartsByContentType(XSSFRelation.DRAWINGS.getContentType()).size()
 + 1;
+        drawingNumber = getNextPartNumber(XSSFRelation.DRAWINGS, 
drawingNumber);
         RelationPart rp = createRelationship(XSSFRelation.DRAWINGS, 
XSSFFactory.getInstance(), drawingNumber, false);
         XSSFDrawing drawing = rp.getDocumentPart();
         String relId = rp.getRelationship().getId();

Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/TestPOIXMLDocument.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/TestPOIXMLDocument.java?rev=1764863&r1=1764862&r2=1764863&view=diff
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/TestPOIXMLDocument.java 
(original)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/TestPOIXMLDocument.java Fri 
Oct 14 10:44:03 2016
@@ -44,6 +44,8 @@ import org.apache.poi.util.PackageHelper
 import org.apache.poi.util.TempFile;
 import org.apache.poi.xslf.usermodel.XMLSlideShow;
 import org.apache.poi.xslf.usermodel.XSLFShape;
+import org.apache.poi.xssf.usermodel.XSSFRelation;
+import org.apache.poi.xwpf.usermodel.XWPFRelation;
 import org.junit.Test;
 
 /**
@@ -227,6 +229,39 @@ public final class TestPOIXMLDocument {
                doc.close();
         }
     }
+    
+    @Test
+    public void testGetNextPartNumber() throws Exception {
+        POIDataSamples pds = POIDataSamples.getDocumentInstance();
+        @SuppressWarnings("resource")
+        OPCPackage pkg = 
PackageHelper.open(pds.openResourceAsStream("WordWithAttachments.docx"));
+        OPCParser doc = new OPCParser(pkg);
+        try {
+            doc.parse(new TestFactory());
+            
+            // Non-indexed parts: Word is taken, Excel is not
+            assertEquals(-1, doc.getNextPartNumber(XWPFRelation.DOCUMENT, 0));
+            assertEquals(-1, doc.getNextPartNumber(XWPFRelation.DOCUMENT, -1));
+            assertEquals(-1, doc.getNextPartNumber(XWPFRelation.DOCUMENT, 99));
+            assertEquals(0, doc.getNextPartNumber(XSSFRelation.WORKBOOK, 0));
+            assertEquals(0, doc.getNextPartNumber(XSSFRelation.WORKBOOK, -1));
+            assertEquals(0, doc.getNextPartNumber(XSSFRelation.WORKBOOK, 99));
+            
+            // Indexed parts:
+            // Has 2 headers
+            assertEquals(0, doc.getNextPartNumber(XWPFRelation.HEADER, 0));
+            assertEquals(3, doc.getNextPartNumber(XWPFRelation.HEADER, -1));
+            assertEquals(3, doc.getNextPartNumber(XWPFRelation.HEADER, 1));
+            assertEquals(8, doc.getNextPartNumber(XWPFRelation.HEADER, 8));
+            
+            // Has no Excel Sheets
+            assertEquals(0, doc.getNextPartNumber(XSSFRelation.WORKSHEET, 0));
+            assertEquals(1, doc.getNextPartNumber(XSSFRelation.WORKSHEET, -1));
+            assertEquals(1, doc.getNextPartNumber(XSSFRelation.WORKSHEET, 1));
+        } finally {
+            doc.close();
+        }
+    }
 
     @Test
     public void testCommitNullPart() throws IOException, 
InvalidFormatException {

Modified: 
poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java?rev=1764863&r1=1764862&r2=1764863&view=diff
==============================================================================
--- 
poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java 
(original)
+++ 
poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java 
Fri Oct 14 10:44:03 2016
@@ -3128,4 +3128,47 @@ public final class TestXSSFBugs extends
         
         wb.close();
     }
+    
+    /**
+     * Other things, including charts, may end up taking drawing part
+     *  numbers. (Uses a test file hand-crafted with an extra non-drawing
+     *  part with a part number)
+     */
+    @Test
+    public void drawingNumbersAlreadyTaken_60255() throws Exception {
+        Workbook wb = 
XSSFTestDataSamples.openSampleWorkbook("60255_extra_drawingparts.xlsx");
+        assertEquals(4, wb.getNumberOfSheets());
+        
+        // Sheet 3 starts with a drawing
+        Sheet sheet = wb.getSheetAt(0);
+        assertNull(sheet.getDrawingPatriarch());
+        sheet = wb.getSheetAt(1);
+        assertNull(sheet.getDrawingPatriarch());
+        sheet = wb.getSheetAt(2);
+        assertNotNull(sheet.getDrawingPatriarch());
+        sheet = wb.getSheetAt(3);
+        assertNull(sheet.getDrawingPatriarch());
+        
+        // Add another sheet, and give it a drawing
+        sheet = wb.createSheet();
+        assertNull(sheet.getDrawingPatriarch());
+        sheet.createDrawingPatriarch();
+        assertNotNull(sheet.getDrawingPatriarch());
+        
+        // Save and check
+        wb = XSSFTestDataSamples.writeOutAndReadBack(wb);
+        assertEquals(5, wb.getNumberOfSheets());
+        
+        // Sheets 3 and 5 now
+        sheet = wb.getSheetAt(0);
+        assertNull(sheet.getDrawingPatriarch());
+        sheet = wb.getSheetAt(1);
+        assertNull(sheet.getDrawingPatriarch());
+        sheet = wb.getSheetAt(2);
+        assertNotNull(sheet.getDrawingPatriarch());
+        sheet = wb.getSheetAt(3);
+        assertNull(sheet.getDrawingPatriarch());
+        sheet = wb.getSheetAt(4);
+        assertNotNull(sheet.getDrawingPatriarch());
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@poi.apache.org
For additional commands, e-mail: commits-h...@poi.apache.org

Reply via email to