]> source.dussan.org Git - poi.git/commitdiff
bug 59775: correctly create XSSFHyperlinks when target is a URL containing a hash...
authorJaven O'Neal <onealj@apache.org>
Sun, 17 Jul 2016 05:43:03 +0000 (05:43 +0000)
committerJaven O'Neal <onealj@apache.org>
Sun, 17 Jul 2016 05:43:03 +0000 (05:43 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1753013 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java
test-data/spreadsheet/59775.xlsx [new file with mode: 0644]

index 4b70d50e258a8223afd264ff15ffcf15037eaf57..b0c9a92f35bc70b0b846593c7c223b860cf6d75c 100644 (file)
@@ -58,44 +58,47 @@ public class XSSFHyperlink implements Hyperlink {
         _ctHyperlink = ctHyperlink;
         _externalRel = hyperlinkRel;
 
-        // Figure out the Hyperlink type and distination
+        // Figure out the Hyperlink type and destination
 
-        // If it has a location, it's internal
-        if (ctHyperlink.getLocation() != null) {
-            _type = Hyperlink.LINK_DOCUMENT;
-            _location = ctHyperlink.getLocation();
-        } else {
-            // Otherwise it's somehow external, check
-            //  the relation to see how
-            if (_externalRel == null) {
-                if (ctHyperlink.getId() != null) {
-                    throw new IllegalStateException("The hyperlink for cell " + ctHyperlink.getRef() +
-                            " references relation " + ctHyperlink.getId() + ", but that didn't exist!");
-                }
+        if (_externalRel == null) {
+            // If it has a location, it's internal
+            if (ctHyperlink.getLocation() != null) {
+                _type = Hyperlink.LINK_DOCUMENT;
+                _location = ctHyperlink.getLocation();
+            } else if (ctHyperlink.getId() != null) {
+                throw new IllegalStateException("The hyperlink for cell "
+                        + ctHyperlink.getRef() + " references relation "
+                        + ctHyperlink.getId() + ", but that didn't exist!");
+            } else {
                 // hyperlink is internal and is not related to other parts
                 _type = Hyperlink.LINK_DOCUMENT;
+            }
+        } else {
+            URI target = _externalRel.getTargetURI();
+            _location = target.toString();
+            if (ctHyperlink.getLocation() != null) {
+                // URI fragment
+                _location += "#" + ctHyperlink.getLocation();
+            }
+
+            // Try to figure out the type
+               if (_location.startsWith("http://") || _location.startsWith("https://")
+                    || _location.startsWith("ftp://")) {
+                _type = Hyperlink.LINK_URL;
+            } else if (_location.startsWith("mailto:")) {
+                _type = Hyperlink.LINK_EMAIL;
             } else {
-                URI target = _externalRel.getTargetURI();
-                _location = target.toString();
-
-                // Try to figure out the type
-                if (_location.startsWith("http://") || _location.startsWith("https://")
-                        || _location.startsWith("ftp://")) {
-                    _type = Hyperlink.LINK_URL;
-                } else if (_location.startsWith("mailto:")) {
-                    _type = Hyperlink.LINK_EMAIL;
-                } else {
-                    _type = Hyperlink.LINK_FILE;
-                }
+                _type = Hyperlink.LINK_FILE;
             }
+        }
 
+     }
 
-        }
-    }
-    
     /**
      * Create a new XSSFHyperlink. This method is for Internal use only.
-     * XSSFHyperlinks can be created by XSSFCreationHelper.
+     * XSSFHyperlinks can be created by {@link XSSFCreationHelper}.
+     * See the <a href="https://poi.apache.org/spreadsheet/quick-guide.html#Hyperlinks">spreadsheet quick-guide</a>
+     * for an example.
      *
      * @param other the hyperlink to copy
      */
@@ -165,7 +168,8 @@ public class XSSFHyperlink implements Hyperlink {
     }
 
     /**
-     * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file
+     * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file.
+     * The is the hyperlink target.
      *
      * @return the address of this hyperlink
      */
@@ -216,6 +220,7 @@ public class XSSFHyperlink implements Hyperlink {
 
     /**
      * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file
+     * This is the hyperlink target.
      *
      * @param address - the address of this hyperlink
      */
index d5e3df294ef8f616549efdfe00c55f7df96c8fc9..ec68569b73c5fe67721235ed2bcf6c522d0be0d2 100644 (file)
 
 package org.apache.poi.xssf.usermodel;
 
-import java.io.IOException;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
+import java.io.IOException;
+
 import org.apache.poi.hssf.usermodel.HSSFHyperlink;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
 import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
@@ -31,6 +31,7 @@ import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.CreationHelper;
 import org.apache.poi.ss.usermodel.Hyperlink;
 import org.apache.poi.ss.usermodel.Row;
+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;
@@ -292,4 +293,39 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
         // Are HSSFHyperlink.label and XSSFHyperlink.tooltip the same? If so, perhaps one of these needs renamed for a consistent Hyperlink interface
         // assertEquals("label", xlink.getTooltip());
     }
+    
+    /* bug 59775: XSSFHyperlink has wrong type if it contains a location (CTHyperlink#getLocation)
+     * URLs with a hash mark (#) are still URL hyperlinks, not document links
+     */
+    @Test
+    public void testURLsWithHashMark() throws IOException {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("59775.xlsx");
+        XSSFSheet sh = wb.getSheetAt(0);
+        CellAddress A2 = new CellAddress("A2");
+        CellAddress A3 = new CellAddress("A3");
+        CellAddress A4 = new CellAddress("A4");
+        CellAddress A7 = new CellAddress("A7");
+        
+        XSSFHyperlink link = sh.getHyperlink(A2);
+        assertEquals("address", "A2", link.getCellRef());
+        assertEquals("link type", Hyperlink.LINK_URL, link.getType());
+        assertEquals("link target", "http://twitter.com/#!/apacheorg", link.getAddress());
+        
+        link = sh.getHyperlink(A3);
+        assertEquals("address", "A3", link.getCellRef());
+        assertEquals("link type", Hyperlink.LINK_URL, link.getType());
+        assertEquals("link target", "http://www.bailii.org/databases.html#ie", link.getAddress());
+        
+        link = sh.getHyperlink(A4);
+        assertEquals("address", "A4", link.getCellRef());
+        assertEquals("link type", Hyperlink.LINK_URL, link.getType());
+        assertEquals("link target", "https://en.wikipedia.org/wiki/Apache_POI#See_also", link.getAddress());
+        
+        link = sh.getHyperlink(A7);
+        assertEquals("address", "A7", link.getCellRef());
+        assertEquals("link type", Hyperlink.LINK_DOCUMENT, link.getType());
+        assertEquals("link target", "Sheet1", link.getAddress());
+        
+        wb.close();
+    }
 }
diff --git a/test-data/spreadsheet/59775.xlsx b/test-data/spreadsheet/59775.xlsx
new file mode 100644 (file)
index 0000000..03238bd
Binary files /dev/null and b/test-data/spreadsheet/59775.xlsx differ