Files
HRMS/hrmsEjb/jxl/write/biff/HyperlinkRecord.java
2025-07-28 13:56:49 +05:30

559 lines
16 KiB
Java

package jxl.write.biff;
import common.Assert;
import common.Logger;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import jxl.CellType;
import jxl.Hyperlink;
import jxl.Range;
import jxl.Sheet;
import jxl.biff.CellReferenceHelper;
import jxl.biff.IntegerHelper;
import jxl.biff.SheetRangeImpl;
import jxl.biff.StringHelper;
import jxl.biff.Type;
import jxl.biff.WritableRecordData;
import jxl.write.Label;
import jxl.write.WritableCell;
import jxl.write.WritableSheet;
public class HyperlinkRecord extends WritableRecordData {
private static Logger logger = Logger.getLogger(HyperlinkRecord.class);
private int firstRow;
private int lastRow;
private int firstColumn;
private int lastColumn;
private URL url;
private File file;
private String location;
private String contents;
private LinkType linkType;
private byte[] data;
private Range range;
private WritableSheet sheet;
private boolean modified;
private static class LinkType {
private LinkType() {}
}
private static final LinkType urlLink = new LinkType();
private static final LinkType fileLink = new LinkType();
private static final LinkType uncLink = new LinkType();
private static final LinkType workbookLink = new LinkType();
private static final LinkType unknown = new LinkType();
protected HyperlinkRecord(Hyperlink h, WritableSheet s) {
super(Type.HLINK);
Assert.verify(h instanceof jxl.read.biff.HyperlinkRecord);
jxl.read.biff.HyperlinkRecord hl = (jxl.read.biff.HyperlinkRecord)h;
this.data = hl.getRecord().getData();
this.sheet = s;
this.firstRow = hl.getRow();
this.firstColumn = hl.getColumn();
this.lastRow = hl.getLastRow();
this.lastColumn = hl.getLastColumn();
this.range = (Range)new SheetRangeImpl((Sheet)s, this.firstColumn, this.firstRow, this.lastColumn, this.lastRow);
this.linkType = unknown;
if (hl.isFile()) {
this.linkType = fileLink;
this.file = hl.getFile();
} else if (hl.isURL()) {
this.linkType = urlLink;
this.url = hl.getURL();
} else if (hl.isLocation()) {
this.linkType = workbookLink;
this.location = hl.getLocation();
}
this.modified = false;
}
protected HyperlinkRecord(int col, int row, int lastcol, int lastrow, URL url, String desc) {
super(Type.HLINK);
this.firstColumn = col;
this.firstRow = row;
this.lastColumn = Math.max(this.firstColumn, lastcol);
this.lastRow = Math.max(this.firstRow, lastrow);
this.url = url;
this.contents = desc;
this.linkType = urlLink;
this.modified = true;
}
protected HyperlinkRecord(int col, int row, int lastcol, int lastrow, File file, String desc) {
super(Type.HLINK);
this.firstColumn = col;
this.firstRow = row;
this.lastColumn = Math.max(this.firstColumn, lastcol);
this.lastRow = Math.max(this.firstRow, lastrow);
this.contents = desc;
this.file = file;
if (file.getPath().startsWith("\\\\")) {
this.linkType = uncLink;
} else {
this.linkType = fileLink;
}
this.modified = true;
}
protected HyperlinkRecord(int col, int row, int lastcol, int lastrow, String desc, WritableSheet s, int destcol, int destrow, int lastdestcol, int lastdestrow) {
super(Type.HLINK);
this.firstColumn = col;
this.firstRow = row;
this.lastColumn = Math.max(this.firstColumn, lastcol);
this.lastRow = Math.max(this.firstRow, lastrow);
setLocation(s, destcol, destrow, lastdestcol, lastdestrow);
this.contents = desc;
this.linkType = workbookLink;
this.modified = true;
}
public boolean isFile() {
return (this.linkType == fileLink);
}
public boolean isUNC() {
return (this.linkType == uncLink);
}
public boolean isURL() {
return (this.linkType == urlLink);
}
public boolean isLocation() {
return (this.linkType == workbookLink);
}
public int getRow() {
return this.firstRow;
}
public int getColumn() {
return this.firstColumn;
}
public int getLastRow() {
return this.lastRow;
}
public int getLastColumn() {
return this.lastColumn;
}
public URL getURL() {
return this.url;
}
public File getFile() {
return this.file;
}
public byte[] getData() {
if (!this.modified)
return this.data;
byte[] commonData = new byte[32];
IntegerHelper.getTwoBytes(this.firstRow, commonData, 0);
IntegerHelper.getTwoBytes(this.lastRow, commonData, 2);
IntegerHelper.getTwoBytes(this.firstColumn, commonData, 4);
IntegerHelper.getTwoBytes(this.lastColumn, commonData, 6);
commonData[8] = -48;
commonData[9] = -55;
commonData[10] = -22;
commonData[11] = 121;
commonData[12] = -7;
commonData[13] = -70;
commonData[14] = -50;
commonData[15] = 17;
commonData[16] = -116;
commonData[17] = -126;
commonData[18] = 0;
commonData[19] = -86;
commonData[20] = 0;
commonData[21] = 75;
commonData[22] = -87;
commonData[23] = 11;
commonData[24] = 2;
commonData[25] = 0;
commonData[26] = 0;
commonData[27] = 0;
int optionFlags = 0;
if (isURL()) {
optionFlags = 3;
if (this.contents != null)
optionFlags |= 0x14;
} else if (isFile()) {
optionFlags = 3;
if (this.contents == null)
optionFlags |= 0x14;
} else if (isLocation()) {
optionFlags = 8;
} else if (isUNC()) {
optionFlags = 259;
}
IntegerHelper.getFourBytes(optionFlags, commonData, 28);
if (isURL()) {
this.data = getURLData(commonData);
} else if (isFile()) {
this.data = getFileData(commonData);
} else if (isLocation()) {
this.data = getLocationData(commonData);
} else if (isUNC()) {
this.data = getUNCData(commonData);
}
return this.data;
}
public String toString() {
if (isFile())
return this.file.toString();
if (isURL())
return this.url.toString();
if (isUNC())
return this.file.toString();
return "";
}
public Range getRange() {
return this.range;
}
public void setURL(URL url) {
this.linkType = urlLink;
this.file = null;
this.location = null;
this.contents = null;
this.url = url;
this.modified = true;
if (this.sheet == null)
return;
WritableCell wc = this.sheet.getWritableCell(this.firstColumn, this.firstRow);
Assert.verify((wc.getType() == CellType.LABEL));
Label l = (Label)wc;
l.setString(url.toString());
}
public void setFile(File file) {
this.linkType = fileLink;
this.url = null;
this.location = null;
this.contents = null;
this.file = file;
this.modified = true;
if (this.sheet == null)
return;
WritableCell wc = this.sheet.getWritableCell(this.firstColumn, this.firstRow);
Assert.verify((wc.getType() == CellType.LABEL));
Label l = (Label)wc;
l.setString(file.toString());
}
protected void setLocation(String desc, WritableSheet sheet, int destcol, int destrow, int lastdestcol, int lastdestrow) {
this.linkType = workbookLink;
this.url = null;
this.file = null;
this.modified = true;
this.contents = desc;
setLocation(sheet, destcol, destrow, lastdestcol, lastdestrow);
if (sheet == null)
return;
WritableCell wc = sheet.getWritableCell(this.firstColumn, this.firstRow);
Assert.verify((wc.getType() == CellType.LABEL));
Label l = (Label)wc;
l.setString(desc);
}
private void setLocation(WritableSheet sheet, int destcol, int destrow, int lastdestcol, int lastdestrow) {
StringBuffer sb = new StringBuffer();
sb.append('\'');
if (sheet.getName().indexOf('\'') == -1) {
sb.append(sheet.getName());
} else {
String sheetName = sheet.getName();
int pos = 0;
int nextPos = sheetName.indexOf('\'', pos);
while (nextPos != -1 && pos < sheetName.length()) {
sb.append(sheetName.substring(pos, nextPos));
sb.append("''");
pos = nextPos + 1;
nextPos = sheetName.indexOf('\'', pos);
}
sb.append(sheetName.substring(pos));
}
sb.append('\'');
sb.append('!');
lastdestcol = Math.max(destcol, lastdestcol);
lastdestrow = Math.max(destrow, lastdestrow);
CellReferenceHelper.getCellReference(destcol, destrow, sb);
sb.append(':');
CellReferenceHelper.getCellReference(lastdestcol, lastdestrow, sb);
this.location = sb.toString();
}
void insertRow(int r) {
Assert.verify((this.sheet != null && this.range != null));
if (r > this.lastRow)
return;
if (r <= this.firstRow) {
this.firstRow++;
this.modified = true;
}
if (r <= this.lastRow) {
this.lastRow++;
this.modified = true;
}
if (this.modified)
this.range = (Range)new SheetRangeImpl((Sheet)this.sheet, this.firstColumn, this.firstRow, this.lastColumn, this.lastRow);
}
void insertColumn(int c) {
Assert.verify((this.sheet != null && this.range != null));
if (c > this.lastColumn)
return;
if (c <= this.firstColumn) {
this.firstColumn++;
this.modified = true;
}
if (c <= this.lastColumn) {
this.lastColumn++;
this.modified = true;
}
if (this.modified)
this.range = (Range)new SheetRangeImpl((Sheet)this.sheet, this.firstColumn, this.firstRow, this.lastColumn, this.lastRow);
}
void removeRow(int r) {
Assert.verify((this.sheet != null && this.range != null));
if (r > this.lastRow)
return;
if (r < this.firstRow) {
this.firstRow--;
this.modified = true;
}
if (r < this.lastRow) {
this.lastRow--;
this.modified = true;
}
if (this.modified) {
Assert.verify((this.range != null));
this.range = (Range)new SheetRangeImpl((Sheet)this.sheet, this.firstColumn, this.firstRow, this.lastColumn, this.lastRow);
}
}
void removeColumn(int c) {
Assert.verify((this.sheet != null && this.range != null));
if (c > this.lastColumn)
return;
if (c < this.firstColumn) {
this.firstColumn--;
this.modified = true;
}
if (c < this.lastColumn) {
this.lastColumn--;
this.modified = true;
}
if (this.modified) {
Assert.verify((this.range != null));
this.range = (Range)new SheetRangeImpl((Sheet)this.sheet, this.firstColumn, this.firstRow, this.lastColumn, this.lastRow);
}
}
private byte[] getURLData(byte[] cd) {
String urlString = this.url.toString();
int dataLength = cd.length + 20 + (urlString.length() + 1) * 2;
if (this.contents != null)
dataLength += 4 + (this.contents.length() + 1) * 2;
byte[] d = new byte[dataLength];
System.arraycopy(cd, 0, d, 0, cd.length);
int urlPos = cd.length;
if (this.contents != null) {
IntegerHelper.getFourBytes(this.contents.length() + 1, d, urlPos);
StringHelper.getUnicodeBytes(this.contents, d, urlPos + 4);
urlPos += (this.contents.length() + 1) * 2 + 4;
}
d[urlPos] = -32;
d[urlPos + 1] = -55;
d[urlPos + 2] = -22;
d[urlPos + 3] = 121;
d[urlPos + 4] = -7;
d[urlPos + 5] = -70;
d[urlPos + 6] = -50;
d[urlPos + 7] = 17;
d[urlPos + 8] = -116;
d[urlPos + 9] = -126;
d[urlPos + 10] = 0;
d[urlPos + 11] = -86;
d[urlPos + 12] = 0;
d[urlPos + 13] = 75;
d[urlPos + 14] = -87;
d[urlPos + 15] = 11;
IntegerHelper.getFourBytes((urlString.length() + 1) * 2, d, urlPos + 16);
StringHelper.getUnicodeBytes(urlString, d, urlPos + 20);
return d;
}
private byte[] getUNCData(byte[] cd) {
String uncString = this.file.getPath();
byte[] d = new byte[cd.length + uncString.length() * 2 + 2 + 4];
System.arraycopy(cd, 0, d, 0, cd.length);
int urlPos = cd.length;
int length = uncString.length() + 1;
IntegerHelper.getFourBytes(length, d, urlPos);
StringHelper.getUnicodeBytes(uncString, d, urlPos + 4);
return d;
}
private byte[] getFileData(byte[] cd) {
ArrayList path = new ArrayList();
ArrayList shortFileName = new ArrayList();
path.add(this.file.getName());
shortFileName.add(getShortName(this.file.getName()));
File parent = this.file.getParentFile();
while (parent != null) {
path.add(parent.getName());
shortFileName.add(getShortName(parent.getName()));
parent = parent.getParentFile();
}
int upLevelCount = 0;
int pos = path.size() - 1;
boolean upDir = true;
while (upDir) {
String s = path.get(pos);
if (s.equals("..")) {
upLevelCount++;
path.remove(pos);
shortFileName.remove(pos);
} else {
upDir = false;
}
pos--;
}
StringBuffer filePathSB = new StringBuffer();
StringBuffer shortFilePathSB = new StringBuffer();
if (this.file.getPath().charAt(1) == ':') {
char driveLetter = this.file.getPath().charAt(0);
if (driveLetter != 'C' && driveLetter != 'c') {
filePathSB.append(driveLetter);
filePathSB.append(':');
shortFilePathSB.append(driveLetter);
shortFilePathSB.append(':');
}
}
for (int i = path.size() - 1; i >= 0; i--) {
filePathSB.append(path.get(i));
shortFilePathSB.append(shortFileName.get(i));
if (i != 0) {
filePathSB.append("\\");
shortFilePathSB.append("\\");
}
}
String filePath = filePathSB.toString();
String shortFilePath = shortFilePathSB.toString();
int dataLength = cd.length + 4 + (shortFilePath.length() + 1) * 2 + 16 + 2 + 4 + filePath.length() + 1 + 4 + 24;
if (this.contents != null)
dataLength += 4 + (this.contents.length() + 1) * 2;
byte[] d = new byte[dataLength];
System.arraycopy(cd, 0, d, 0, cd.length);
int filePos = cd.length;
if (this.contents != null) {
IntegerHelper.getFourBytes(this.contents.length() + 1, d, filePos);
StringHelper.getUnicodeBytes(this.contents, d, filePos + 4);
filePos += (this.contents.length() + 1) * 2 + 4;
}
int curPos = filePos;
IntegerHelper.getFourBytes(shortFilePath.length() + 1, d, curPos);
StringHelper.getUnicodeBytes(shortFilePath, d, curPos + 4);
curPos += 4 + (shortFilePath.length() + 1) * 2;
d[curPos] = 3;
d[curPos + 1] = 3;
d[curPos + 2] = 0;
d[curPos + 3] = 0;
d[curPos + 4] = 0;
d[curPos + 5] = 0;
d[curPos + 6] = 0;
d[curPos + 7] = 0;
d[curPos + 8] = -64;
d[curPos + 9] = 0;
d[curPos + 10] = 0;
d[curPos + 11] = 0;
d[curPos + 12] = 0;
d[curPos + 13] = 0;
d[curPos + 14] = 0;
d[curPos + 15] = 70;
curPos += 16;
IntegerHelper.getTwoBytes(upLevelCount, d, curPos);
curPos += 2;
IntegerHelper.getFourBytes(filePath.length() + 1, d, curPos);
curPos += 4;
StringHelper.getBytes(filePath, d, curPos);
curPos += filePath.length() + 1;
d[curPos] = -1;
d[curPos + 1] = -1;
d[curPos + 2] = -83;
d[curPos + 3] = -34;
return d;
}
private String getShortName(String s) {
int sep = s.indexOf('.');
String prefix = null;
String suffix = null;
if (sep == -1) {
prefix = s;
suffix = "";
} else {
prefix = s.substring(0, sep);
suffix = s.substring(sep + 1);
}
if (prefix.length() > 8) {
prefix = prefix.substring(0, 6) + "~" + (prefix.length() - 6);
prefix = prefix.substring(0, 8);
}
suffix = suffix.substring(0, Math.min(3, suffix.length()));
if (suffix.length() > 0)
return prefix + '.' + suffix;
return prefix;
}
private byte[] getLocationData(byte[] cd) {
byte[] d = new byte[cd.length + 4 + (this.location.length() + 1) * 2];
System.arraycopy(cd, 0, d, 0, cd.length);
int locPos = cd.length;
IntegerHelper.getFourBytes(this.location.length() + 1, d, locPos);
StringHelper.getUnicodeBytes(this.location, d, locPos + 4);
return d;
}
void initialize(WritableSheet s) {
this.sheet = s;
this.range = (Range)new SheetRangeImpl((Sheet)s, this.firstColumn, this.firstRow, this.lastColumn, this.lastRow);
}
String getContents() {
return this.contents;
}
protected void setContents(String desc) {
this.contents = desc;
this.modified = true;
}
}