Add support for ExHyperlink and ExHyperlinkAtom
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@497079 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
255bc5a9c3
commit
a2bc714fa3
148
src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlink.java
Normal file
148
src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlink.java
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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.hslf.record;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* This class represents the data of a link in the document.
|
||||
* @author Nick Burch
|
||||
*/
|
||||
public class ExHyperlink extends RecordContainer {
|
||||
private byte[] _header;
|
||||
private static long _type = 4055;
|
||||
|
||||
// Links to our more interesting children
|
||||
private ExHyperlinkAtom linkAtom;
|
||||
private CString linkDetailsA;
|
||||
private CString linkDetailsB;
|
||||
private Comment2000Atom commentAtom;
|
||||
|
||||
/**
|
||||
* Returns the ExHyperlinkAtom of this link
|
||||
*/
|
||||
public ExHyperlinkAtom getExHyperlinkAtom() { return linkAtom; }
|
||||
|
||||
/**
|
||||
* Returns the URL of the link.
|
||||
* TODO: Figure out which of detailsA or detailsB is the
|
||||
* one that always holds it
|
||||
*/
|
||||
public String getLinkURL() {
|
||||
return linkDetailsA.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URL of the link
|
||||
* TODO: Figure out if we should always set both
|
||||
*/
|
||||
public void setLinkURL(String url) {
|
||||
linkDetailsA.setText(url);
|
||||
linkDetailsB.setText(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link details (field A)
|
||||
*/
|
||||
public String _getDetailsA() {
|
||||
return linkDetailsA.getText();
|
||||
}
|
||||
/**
|
||||
* Get the link details (field B)
|
||||
*/
|
||||
public String _getDetailsB() {
|
||||
return linkDetailsB.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set things up, and find our more interesting children
|
||||
*/
|
||||
protected ExHyperlink(byte[] source, int start, int len) {
|
||||
// Grab the header
|
||||
_header = new byte[8];
|
||||
System.arraycopy(source,start,_header,0,8);
|
||||
|
||||
// Find our children
|
||||
_children = Record.findChildRecords(source,start+8,len-8);
|
||||
findInterestingChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through our child records, picking out the ones that are
|
||||
* interesting, and saving those for use by the easy helper
|
||||
* methods.
|
||||
*/
|
||||
private void findInterestingChildren() {
|
||||
// First child should be the ExHyperlinkAtom
|
||||
if(_children[0] instanceof ExHyperlinkAtom) {
|
||||
linkAtom = (ExHyperlinkAtom)_children[0];
|
||||
} else {
|
||||
throw new IllegalStateException("First child record wasn't a ExHyperlinkAtom, was of type " + _children[0].getRecordType());
|
||||
}
|
||||
|
||||
// Second child should be the first link details
|
||||
if(_children[1] instanceof CString) {
|
||||
linkDetailsA = (CString)_children[1];
|
||||
} else {
|
||||
throw new IllegalStateException("Second child record wasn't a CString, was of type " + _children[1].getRecordType());
|
||||
}
|
||||
// Third child should be the second link details
|
||||
if(_children[2] instanceof CString) {
|
||||
linkDetailsB = (CString)_children[2];
|
||||
} else {
|
||||
throw new IllegalStateException("Third child record wasn't a CString, was of type " + _children[2].getRecordType());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ExHyperlink, with blank fields
|
||||
*/
|
||||
public ExHyperlink() {
|
||||
_header = new byte[8];
|
||||
_children = new Record[3];
|
||||
|
||||
// Setup our header block
|
||||
_header[0] = 0x0f; // We are a container record
|
||||
LittleEndian.putShort(_header, 2, (short)_type);
|
||||
|
||||
// Setup our child records
|
||||
CString csa = new CString();
|
||||
CString csb = new CString();
|
||||
csa.setCount(0x00);
|
||||
csb.setCount(0x10);
|
||||
_children[0] = new ExHyperlinkAtom();
|
||||
_children[1] = csa;
|
||||
_children[2] = csb;
|
||||
findInterestingChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* We are of type 4055
|
||||
*/
|
||||
public long getRecordType() { return _type; }
|
||||
|
||||
/**
|
||||
* Write the contents of the record back, so it can be written
|
||||
* to disk
|
||||
*/
|
||||
public void writeOut(OutputStream out) throws IOException {
|
||||
writeOut(_header[0],_header[1],_type,_children,out);
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/* ====================================================================
|
||||
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.hslf.record;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.poi.hslf.util.SystemTimeUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* Tne atom that holds metadata on a specific Link in the document.
|
||||
* (The actual link is held in a sibling CString record)
|
||||
*
|
||||
* @author Nick Burch
|
||||
*/
|
||||
|
||||
public class ExHyperlinkAtom extends RecordAtom
|
||||
{
|
||||
/**
|
||||
* Record header.
|
||||
*/
|
||||
private byte[] _header;
|
||||
|
||||
/**
|
||||
* Record data.
|
||||
*/
|
||||
private byte[] _data;
|
||||
|
||||
/**
|
||||
* Constructs a brand new link related atom record.
|
||||
*/
|
||||
protected ExHyperlinkAtom() {
|
||||
_header = new byte[8];
|
||||
_data = new byte[4];
|
||||
|
||||
LittleEndian.putShort(_header, 2, (short)getRecordType());
|
||||
LittleEndian.putInt(_header, 4, _data.length);
|
||||
|
||||
// It is fine for the other values to be zero
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the link related atom record from its
|
||||
* source data.
|
||||
*
|
||||
* @param source the source data as a byte array.
|
||||
* @param start the start offset into the byte array.
|
||||
* @param len the length of the slice in the byte array.
|
||||
*/
|
||||
protected ExHyperlinkAtom(byte[] source, int start, int len) {
|
||||
// Get the header.
|
||||
_header = new byte[8];
|
||||
System.arraycopy(source,start,_header,0,8);
|
||||
|
||||
// Get the record data.
|
||||
_data = new byte[len-8];
|
||||
System.arraycopy(source,start+8,_data,0,len-8);
|
||||
|
||||
// Must be at least 4 bytes long
|
||||
if(_data.length < 4) {
|
||||
throw new IllegalArgumentException("The length of the data for a ExHyperlinkAtom must be at least 4 bytes, but was only " + _data.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the link number. This will match the one in the
|
||||
* InteractiveInfoAtom which uses the link.
|
||||
* @return the link number
|
||||
*/
|
||||
public int getNumber() {
|
||||
return LittleEndian.getInt(_data,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the link number
|
||||
* @param number the link number.
|
||||
*/
|
||||
public void setNumber(int number) {
|
||||
LittleEndian.putInt(_data,0,number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the record type.
|
||||
* @return the record type.
|
||||
*/
|
||||
public long getRecordType() { return RecordTypes.ExHyperlinkAtom.typeID; }
|
||||
|
||||
/**
|
||||
* Write the contents of the record back, so it can be written
|
||||
* to disk
|
||||
*
|
||||
* @param out the output stream to write to.
|
||||
* @throws IOException if an error occurs.
|
||||
*/
|
||||
public void writeOut(OutputStream out) throws IOException {
|
||||
out.write(_header);
|
||||
out.write(_data);
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ import org.apache.poi.util.LittleEndian;
|
||||
*/
|
||||
public class InteractiveInfo extends RecordContainer {
|
||||
private byte[] _header;
|
||||
private static long _type = RecordTypes.InteractiveInfo.typeID;
|
||||
private static long _type = 4082;
|
||||
|
||||
// Links to our more interesting children
|
||||
private InteractiveInfoAtom infoAtom;
|
||||
|
@ -107,8 +107,8 @@ public class RecordTypes {
|
||||
public static final Type BookmarkEntityAtom = new Type(4048,null);
|
||||
public static final Type ExLinkAtom = new Type(4049,null);
|
||||
public static final Type SrKinsokuAtom = new Type(4050,null);
|
||||
public static final Type ExHyperlinkAtom = new Type(4051,null);
|
||||
public static final Type ExHyperlink = new Type(4055,null);
|
||||
public static final Type ExHyperlinkAtom = new Type(4051,ExHyperlinkAtom.class);
|
||||
public static final Type ExHyperlink = new Type(4055,ExHyperlink.class);
|
||||
public static final Type SlideNumberMCAtom = new Type(4056,null);
|
||||
public static final Type HeadersFooters = new Type(4057,null);
|
||||
public static final Type HeadersFootersAtom = new Type(4058,null);
|
||||
|
Binary file not shown.
@ -0,0 +1,100 @@
|
||||
|
||||
/* ====================================================================
|
||||
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.hslf.record;
|
||||
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Tests that ExHyperlink works properly.
|
||||
*
|
||||
* @author Nick Burch (nick at torchbox dot com)
|
||||
*/
|
||||
public class TestExHyperlink extends TestCase {
|
||||
// From a real file
|
||||
private byte[] data_a = new byte[] {
|
||||
0x0F, 00, 0xD7-256, 0x0F, 0xA8-256, 00, 00, 00,
|
||||
|
||||
00, 00, 0xD3-256, 0x0F, 04, 00, 00, 00,
|
||||
03, 00, 00, 00,
|
||||
|
||||
00, 00, 0xBA-256, 0x0F, 0x46, 00, 00, 00,
|
||||
0x68, 00, 0x74, 00, 0x74, 00, 0x70, 00,
|
||||
0x3A, 00, 0x2F, 00, 0x2F, 00, 0x6A, 00,
|
||||
0x61, 00, 0x6B, 00, 0x61, 00, 0x72, 00,
|
||||
0x74, 00, 0x61, 00, 0x2E, 00, 0x61, 00,
|
||||
0x70, 00, 0x61, 00, 0x63, 00, 0x68, 00,
|
||||
0x65, 00, 0x2E, 00, 0x6F, 00, 0x72, 00,
|
||||
0x67, 00, 0x2F, 00, 0x70, 00, 0x6F, 00,
|
||||
0x69, 00, 0x2F, 00, 0x68, 00, 0x73, 00,
|
||||
0x73, 00, 0x66, 00, 0x2F, 00,
|
||||
|
||||
0x10, 00, 0xBA-256, 0x0F, 0x46, 00, 00, 00,
|
||||
0x68, 00, 0x74, 00, 0x74, 00, 0x70, 00,
|
||||
0x3A, 00, 0x2F, 00, 0x2F, 00, 0x6A, 00,
|
||||
0x61, 00, 0x6B, 00, 0x61, 00, 0x72, 00,
|
||||
0x74, 00, 0x61, 00, 0x2E, 00, 0x61, 00,
|
||||
0x70, 00, 0x61, 00, 0x63, 00, 0x68, 00,
|
||||
0x65, 00, 0x2E, 00, 0x6F, 00, 0x72, 00,
|
||||
0x67, 00, 0x2F, 00, 0x70, 00, 0x6F, 00,
|
||||
0x69, 00, 0x2F, 00, 0x68, 00, 0x73, 00,
|
||||
0x73, 00, 0x66, 00, 0x2F, 00
|
||||
};
|
||||
|
||||
public void testRecordType() throws Exception {
|
||||
ExHyperlink eh = new ExHyperlink(data_a, 0, data_a.length);
|
||||
assertEquals(4055l, eh.getRecordType());
|
||||
}
|
||||
|
||||
public void testNumber() throws Exception {
|
||||
ExHyperlink eh = new ExHyperlink(data_a, 0, data_a.length);
|
||||
assertEquals(3, eh.getExHyperlinkAtom().getNumber());
|
||||
}
|
||||
|
||||
public void testLinkURL() throws Exception {
|
||||
ExHyperlink eh = new ExHyperlink(data_a, 0, data_a.length);
|
||||
assertEquals("http://jakarta.apache.org/poi/hssf/", eh.getLinkURL());
|
||||
}
|
||||
public void testDetails() throws Exception {
|
||||
ExHyperlink eh = new ExHyperlink(data_a, 0, data_a.length);
|
||||
assertEquals("http://jakarta.apache.org/poi/hssf/", eh._getDetailsA());
|
||||
assertEquals("http://jakarta.apache.org/poi/hssf/", eh._getDetailsB());
|
||||
}
|
||||
|
||||
public void testWrite() throws Exception {
|
||||
ExHyperlink eh = new ExHyperlink(data_a, 0, data_a.length);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
eh.writeOut(baos);
|
||||
byte[] b = baos.toByteArray();
|
||||
|
||||
assertEquals(data_a.length, b.length);
|
||||
for(int i=0; i<data_a.length; i++) {
|
||||
assertEquals(data_a[i],b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void testRealFile() throws Exception {
|
||||
// TODO
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
|
||||
/* ====================================================================
|
||||
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.hslf.record;
|
||||
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Tests that InteractiveInfoAtom works properly.
|
||||
*
|
||||
* @author Nick Burch (nick at torchbox dot com)
|
||||
*/
|
||||
public class TestExHyperlinkAtom extends TestCase {
|
||||
// From a real file
|
||||
private byte[] data_a = new byte[] {
|
||||
00, 00, 0xD3-256, 0x0F, 04, 00, 00, 00,
|
||||
01, 00, 00, 00
|
||||
};
|
||||
private byte[] data_b = new byte[] {
|
||||
00, 00, 0xD3-256, 0x0F, 04, 00, 00, 00,
|
||||
04, 00, 00, 00
|
||||
};
|
||||
|
||||
public void testRecordType() throws Exception {
|
||||
ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length);
|
||||
assertEquals(4051l, eha.getRecordType());
|
||||
}
|
||||
|
||||
public void testGetNumber() throws Exception {
|
||||
ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length);
|
||||
ExHyperlinkAtom ehb = new ExHyperlinkAtom(data_b, 0, data_b.length);
|
||||
|
||||
assertEquals(1, eha.getNumber());
|
||||
assertEquals(4, ehb.getNumber());
|
||||
}
|
||||
|
||||
public void testWrite() throws Exception {
|
||||
ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
eha.writeOut(baos);
|
||||
byte[] b = baos.toByteArray();
|
||||
|
||||
assertEquals(data_a.length, b.length);
|
||||
for(int i=0; i<data_a.length; i++) {
|
||||
assertEquals(data_a[i],b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create A from scratch
|
||||
public void testCreate() throws Exception {
|
||||
ExHyperlinkAtom eha = new ExHyperlinkAtom();
|
||||
|
||||
// Set value
|
||||
eha.setNumber(1);
|
||||
|
||||
// Check it's now the same as a
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
eha.writeOut(baos);
|
||||
byte[] b = baos.toByteArray();
|
||||
|
||||
assertEquals(data_a.length, b.length);
|
||||
for(int i=0; i<data_a.length; i++) {
|
||||
assertEquals(data_a[i],b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to turn a into b
|
||||
public void testChange() throws Exception {
|
||||
ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length);
|
||||
|
||||
// Change the number
|
||||
eha.setNumber(4);
|
||||
|
||||
// Check bytes are now the same
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
eha.writeOut(baos);
|
||||
byte[] b = baos.toByteArray();
|
||||
|
||||
// Should now be the same
|
||||
assertEquals(data_b.length, b.length);
|
||||
for(int i=0; i<data_b.length; i++) {
|
||||
assertEquals(data_b[i],b[i]);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user