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:
Nick Burch 2007-01-17 16:59:45 +00:00
parent 255bc5a9c3
commit a2bc714fa3
7 changed files with 474 additions and 3 deletions

View 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);
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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
}
}

View File

@ -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]);
}
}
}