373 lines
12 KiB
Java
373 lines
12 KiB
Java
/* ====================================================================
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
this work for additional information regarding copyright ownership.
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
(the "License"); you may not use this file except in compliance with
|
|
the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
==================================================================== */
|
|
package org.apache.poi.xssf.usermodel;
|
|
|
|
import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
|
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
|
import org.apache.poi.ss.usermodel.Hyperlink;
|
|
import org.apache.poi.ss.util.CellReference;
|
|
import org.apache.poi.util.Internal;
|
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink;
|
|
|
|
/**
|
|
* XSSF Implementation of a Hyperlink.
|
|
* Note - unlike with HSSF, many kinds of hyperlink
|
|
* are largely stored as relations of the sheet
|
|
*/
|
|
public class XSSFHyperlink implements Hyperlink {
|
|
final private int _type;
|
|
final private PackageRelationship _externalRel;
|
|
final private CTHyperlink _ctHyperlink; //contains a reference to the cell where the hyperlink is anchored, getRef()
|
|
private String _location; //what the hyperlink refers to
|
|
|
|
/**
|
|
* Create a new XSSFHyperlink. This method is protected to be used only by XSSFCreationHelper
|
|
*
|
|
* @param type - the type of hyperlink to create, see {@link Hyperlink}
|
|
*/
|
|
protected XSSFHyperlink(int type) {
|
|
_type = type;
|
|
_ctHyperlink = CTHyperlink.Factory.newInstance();
|
|
_externalRel = null;
|
|
}
|
|
|
|
/**
|
|
* Create a XSSFHyperlink and initialize it from the supplied CTHyperlink bean and package relationship
|
|
*
|
|
* @param ctHyperlink the xml bean containing xml properties
|
|
* @param hyperlinkRel the relationship in the underlying OPC package which stores the actual link's address
|
|
*/
|
|
protected XSSFHyperlink(CTHyperlink ctHyperlink, PackageRelationship hyperlinkRel) {
|
|
_ctHyperlink = ctHyperlink;
|
|
_externalRel = hyperlinkRel;
|
|
|
|
// Figure out the Hyperlink type and destination
|
|
|
|
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 {
|
|
_type = Hyperlink.LINK_FILE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Create a new XSSFHyperlink. This method is for Internal use only.
|
|
* 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
|
|
*/
|
|
@Internal //FIXME: change to protected if/when SXSSFHyperlink class is created
|
|
public XSSFHyperlink(Hyperlink other) {
|
|
if (other instanceof XSSFHyperlink) {
|
|
XSSFHyperlink xlink = (XSSFHyperlink) other;
|
|
_type = xlink.getType();
|
|
_location = xlink._location;
|
|
_externalRel = xlink._externalRel;
|
|
_ctHyperlink = (CTHyperlink) xlink._ctHyperlink.copy();
|
|
}
|
|
else {
|
|
_type = other.getType();
|
|
_location = other.getAddress();
|
|
_externalRel = null;
|
|
_ctHyperlink = CTHyperlink.Factory.newInstance();
|
|
setCellReference(new CellReference(other.getFirstRow(), other.getFirstColumn()));
|
|
}
|
|
}
|
|
/**
|
|
* @return the underlying CTHyperlink object
|
|
*/
|
|
@Internal
|
|
public CTHyperlink getCTHyperlink() {
|
|
return _ctHyperlink;
|
|
}
|
|
|
|
/**
|
|
* Do we need to a relation too, to represent
|
|
* this hyperlink?
|
|
*/
|
|
public boolean needsRelationToo() {
|
|
return (_type != Hyperlink.LINK_DOCUMENT);
|
|
}
|
|
|
|
/**
|
|
* Generates the relation if required
|
|
*/
|
|
protected void generateRelationIfNeeded(PackagePart sheetPart) {
|
|
if (_externalRel == null && needsRelationToo()) {
|
|
// Generate the relation
|
|
PackageRelationship rel =
|
|
sheetPart.addExternalRelationship(_location, XSSFRelation.SHEET_HYPERLINKS.getRelation());
|
|
|
|
// Update the r:id
|
|
_ctHyperlink.setId(rel.getId());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the type of this hyperlink
|
|
*
|
|
* @return the type of this hyperlink
|
|
*/
|
|
@Override
|
|
public int getType() {
|
|
return _type;
|
|
}
|
|
|
|
/**
|
|
* Get the reference of the cell this applies to,
|
|
* es A55
|
|
*/
|
|
public String getCellRef() {
|
|
return _ctHyperlink.getRef();
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
@Override
|
|
public String getAddress() {
|
|
return _location;
|
|
}
|
|
|
|
/**
|
|
* Return text label for this hyperlink
|
|
*
|
|
* @return text to display
|
|
*/
|
|
@Override
|
|
public String getLabel() {
|
|
return _ctHyperlink.getDisplay();
|
|
}
|
|
|
|
/**
|
|
* Location within target. If target is a workbook (or this workbook) this shall refer to a
|
|
* sheet and cell or a defined name. Can also be an HTML anchor if target is HTML file.
|
|
*
|
|
* @return location
|
|
*/
|
|
public String getLocation() {
|
|
return _ctHyperlink.getLocation();
|
|
}
|
|
|
|
/**
|
|
* Sets text label for this hyperlink
|
|
*
|
|
* @param label text label for this hyperlink
|
|
*/
|
|
@Override
|
|
public void setLabel(String label) {
|
|
_ctHyperlink.setDisplay(label);
|
|
}
|
|
|
|
/**
|
|
* Location within target. If target is a workbook (or this workbook) this shall refer to a
|
|
* sheet and cell or a defined name. Can also be an HTML anchor if target is HTML file.
|
|
*
|
|
* @param location - string representing a location of this hyperlink
|
|
*/
|
|
public void setLocation(String location) {
|
|
_ctHyperlink.setLocation(location);
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
@Override
|
|
public void setAddress(String address) {
|
|
validate(address);
|
|
|
|
_location = address;
|
|
//we must set location for internal hyperlinks
|
|
if (_type == Hyperlink.LINK_DOCUMENT) {
|
|
setLocation(address);
|
|
}
|
|
}
|
|
|
|
private void validate(String address) {
|
|
switch (_type){
|
|
// email, path to file and url must be valid URIs
|
|
case Hyperlink.LINK_EMAIL:
|
|
case Hyperlink.LINK_FILE:
|
|
case Hyperlink.LINK_URL:
|
|
try {
|
|
new URI(address);
|
|
} catch (URISyntaxException x) {
|
|
IllegalArgumentException y = new IllegalArgumentException("Address of hyperlink must be a valid URI");
|
|
y.initCause(x);
|
|
throw y;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assigns this hyperlink to the given cell reference
|
|
*/
|
|
@Internal
|
|
public void setCellReference(String ref) {
|
|
_ctHyperlink.setRef(ref);
|
|
}
|
|
protected void setCellReference(CellReference ref) {
|
|
setCellReference(ref.formatAsString());
|
|
}
|
|
|
|
private CellReference buildCellReference() {
|
|
String ref = _ctHyperlink.getRef();
|
|
if (ref == null) {
|
|
ref = "A1";
|
|
}
|
|
return new CellReference(ref);
|
|
}
|
|
|
|
|
|
/**
|
|
* Return the column of the first cell that contains the hyperlink
|
|
*
|
|
* @return the 0-based column of the first cell that contains the hyperlink
|
|
*/
|
|
@Override
|
|
public int getFirstColumn() {
|
|
return buildCellReference().getCol();
|
|
}
|
|
|
|
|
|
/**
|
|
* Return the column of the last cell that contains the hyperlink
|
|
*
|
|
* @return the 0-based column of the last cell that contains the hyperlink
|
|
*/
|
|
@Override
|
|
public int getLastColumn() {
|
|
return buildCellReference().getCol();
|
|
}
|
|
|
|
/**
|
|
* Return the row of the first cell that contains the hyperlink
|
|
*
|
|
* @return the 0-based row of the cell that contains the hyperlink
|
|
*/
|
|
@Override
|
|
public int getFirstRow() {
|
|
return buildCellReference().getRow();
|
|
}
|
|
|
|
|
|
/**
|
|
* Return the row of the last cell that contains the hyperlink
|
|
*
|
|
* @return the 0-based row of the last cell that contains the hyperlink
|
|
*/
|
|
@Override
|
|
public int getLastRow() {
|
|
return buildCellReference().getRow();
|
|
}
|
|
|
|
/**
|
|
* Set the column of the first cell that contains the hyperlink
|
|
*
|
|
* @param col the 0-based column of the first cell that contains the hyperlink
|
|
*/
|
|
@Override
|
|
public void setFirstColumn(int col) {
|
|
setCellReference(new CellReference( getFirstRow(), col ));
|
|
}
|
|
|
|
/**
|
|
* Set the column of the last cell that contains the hyperlink.
|
|
* For XSSF, a Hyperlink may only reference one cell
|
|
*
|
|
* @param col the 0-based column of the last cell that contains the hyperlink
|
|
*/
|
|
@Override
|
|
public void setLastColumn(int col) {
|
|
setFirstColumn(col);
|
|
}
|
|
|
|
/**
|
|
* Set the row of the first cell that contains the hyperlink
|
|
*
|
|
* @param row the 0-based row of the first cell that contains the hyperlink
|
|
*/
|
|
@Override
|
|
public void setFirstRow(int row) {
|
|
setCellReference(new CellReference( row, getFirstColumn() ));
|
|
}
|
|
|
|
/**
|
|
* Set the row of the last cell that contains the hyperlink.
|
|
* For XSSF, a Hyperlink may only reference one cell
|
|
*
|
|
* @param row the 0-based row of the last cell that contains the hyperlink
|
|
*/
|
|
@Override
|
|
public void setLastRow(int row) {
|
|
setFirstRow(row);
|
|
}
|
|
|
|
/**
|
|
* @return additional text to help the user understand more about the hyperlink
|
|
*/
|
|
public String getTooltip() {
|
|
return _ctHyperlink.getTooltip();
|
|
}
|
|
|
|
/**
|
|
* @param text additional text to help the user understand more about the hyperlink
|
|
*/
|
|
public void setTooltip(String text) {
|
|
_ctHyperlink.setTooltip(text);
|
|
}
|
|
}
|