|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- /* ====================================================================
- 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.common.usermodel.HyperlinkType;
- 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 HyperlinkType _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
- * {@link XSSFCreationHelper#createHyperlink(HyperlinkType)}.
- *
- * @param type - the type of hyperlink to create
- */
- protected XSSFHyperlink(HyperlinkType 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 = HyperlinkType.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 = HyperlinkType.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 = HyperlinkType.URL;
- } else if (_location.startsWith("mailto:")) {
- _type = HyperlinkType.EMAIL;
- } else {
- _type = HyperlinkType.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 != HyperlinkType.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 HyperlinkType getType() {
- return _type;
- }
-
- /**
- * Get the address of the cell this hyperlink applies to, e.g. 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 == HyperlinkType.DOCUMENT) {
- setLocation(address);
- }
- }
-
- @SuppressWarnings("fall-through")
- private void validate(String address) {
- switch (_type) {
- // email, path to file and url must be valid URIs
- case EMAIL:
- case FILE:
- case URL:
- try {
- new URI(address);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException("Address of hyperlink must be a valid URI", e);
- }
- break;
- case DOCUMENT:
- // currently not evaluating anything.
- break;
- default:
- throw new IllegalStateException("Invalid Hyperlink type: " + _type);
- }
- }
-
- /**
- * Assigns this hyperlink to the given cell reference
- */
- @Internal
- public void setCellReference(String ref) {
- _ctHyperlink.setRef(ref);
- }
- @Internal
- public 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);
- }
- }
|