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 4ba3ed06fc
commit 285bedac9e
3 changed files with 74 additions and 33 deletions

View File

@ -58,44 +58,47 @@ public class XSSFHyperlink implements Hyperlink {
_ctHyperlink = ctHyperlink; _ctHyperlink = ctHyperlink;
_externalRel = hyperlinkRel; _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 (_externalRel == null) {
if (ctHyperlink.getLocation() != null) { // If it has a location, it's internal
_type = Hyperlink.LINK_DOCUMENT; if (ctHyperlink.getLocation() != null) {
_location = ctHyperlink.getLocation(); _type = Hyperlink.LINK_DOCUMENT;
} else { _location = ctHyperlink.getLocation();
// Otherwise it's somehow external, check } else if (ctHyperlink.getId() != null) {
// the relation to see how throw new IllegalStateException("The hyperlink for cell "
if (_externalRel == null) { + ctHyperlink.getRef() + " references relation "
if (ctHyperlink.getId() != null) { + ctHyperlink.getId() + ", but that didn't exist!");
throw new IllegalStateException("The hyperlink for cell " + ctHyperlink.getRef() + } else {
" references relation " + ctHyperlink.getId() + ", but that didn't exist!");
}
// hyperlink is internal and is not related to other parts // hyperlink is internal and is not related to other parts
_type = Hyperlink.LINK_DOCUMENT; _type = Hyperlink.LINK_DOCUMENT;
} else { }
URI target = _externalRel.getTargetURI(); } else {
_location = target.toString(); URI target = _externalRel.getTargetURI();
_location = target.toString();
// Try to figure out the type if (ctHyperlink.getLocation() != null) {
if (_location.startsWith("http://") || _location.startsWith("https://") // URI fragment
|| _location.startsWith("ftp://")) { _location += "#" + ctHyperlink.getLocation();
_type = Hyperlink.LINK_URL;
} else if (_location.startsWith("mailto:")) {
_type = Hyperlink.LINK_EMAIL;
} else {
_type = Hyperlink.LINK_FILE;
}
} }
// 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. * 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 * @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 * @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 * 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 * @param address - the address of this hyperlink
*/ */

View File

@ -17,12 +17,12 @@
package org.apache.poi.xssf.usermodel; package org.apache.poi.xssf.usermodel;
import java.io.IOException;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFHyperlink; import org.apache.poi.hssf.usermodel.HSSFHyperlink;
import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; 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.CreationHelper;
import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.usermodel.Row; 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.ss.util.CellReference;
import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples; 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 // 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()); // 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.