bug 59775: correctly create XSSFHyperlinks when target is a URL containing a hash mark; patch contributed by Guillermo Alvarez

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1753013 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Javen O'Neal 2016-07-17 05:43:03 +00:00
parent 9f45341c9c
commit 6803dc89e0
3 changed files with 74 additions and 33 deletions

View 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();
// 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;
}
}
} 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 {
_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
*/

View File

@ -17,12 +17,12 @@
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();
}
}

Binary file not shown.