git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1144275 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_8_BETA4
@@ -513,6 +513,12 @@ public final class HWPFDocument extends HWPFDocumentCore | |||
_fib.setLcbPlcfsed(tableStream.getOffset() - tableOffset); | |||
tableOffset = tableStream.getOffset(); | |||
if ( _fieldsTables != null ) | |||
{ | |||
_fieldsTables.write( _fib, tableStream ); | |||
tableOffset = tableStream.getOffset(); | |||
} | |||
// write out the list tables | |||
if (_lt != null) | |||
{ |
@@ -19,14 +19,17 @@ | |||
package org.apache.poi.hwpf.model; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import org.apache.poi.hwpf.model.io.HWPFOutputStream; | |||
/** | |||
* This class provides access to all the fields Plex. | |||
* | |||
* @author Cedric Bosdonnat <cbosdonnat@novell.com> | |||
* | |||
* | |||
*/ | |||
public class FieldsTables | |||
{ | |||
@@ -62,75 +65,145 @@ public class FieldsTables | |||
// The size in bytes of the FLD data structure | |||
private static final int FLD_SIZE = 2; | |||
private HashMap<Integer, ArrayList<PlexOfField>> _tables; | |||
private HashMap<Integer, PlexOfCps> _tables; | |||
public FieldsTables(byte[] tableStream, FileInformationBlock fib) | |||
{ | |||
_tables = new HashMap<Integer, ArrayList<PlexOfField>>(); | |||
public FieldsTables( byte[] tableStream, FileInformationBlock fib ) | |||
{ | |||
_tables = new HashMap<Integer, PlexOfCps>(); | |||
for ( int i = PLCFFLDATN; i <= PLCFFLDTXBX; i++ ) | |||
{ | |||
_tables.put( Integer.valueOf( i ), readPLCF( tableStream, fib, i ) ); | |||
} | |||
} | |||
for (int i = PLCFFLDATN; i <= PLCFFLDTXBX; i++ ) | |||
private PlexOfCps readPLCF( byte[] tableStream, FileInformationBlock fib, | |||
int type ) | |||
{ | |||
_tables.put(i, readPLCF(tableStream, fib, i)); | |||
int start = 0; | |||
int length = 0; | |||
switch ( type ) | |||
{ | |||
case PLCFFLDATN: | |||
start = fib.getFcPlcffldAtn(); | |||
length = fib.getLcbPlcffldAtn(); | |||
break; | |||
case PLCFFLDEDN: | |||
start = fib.getFcPlcffldEdn(); | |||
length = fib.getLcbPlcffldEdn(); | |||
break; | |||
case PLCFFLDFTN: | |||
start = fib.getFcPlcffldFtn(); | |||
length = fib.getLcbPlcffldFtn(); | |||
break; | |||
case PLCFFLDHDR: | |||
start = fib.getFcPlcffldHdr(); | |||
length = fib.getLcbPlcffldHdr(); | |||
break; | |||
case PLCFFLDHDRTXBX: | |||
start = fib.getFcPlcffldHdrtxbx(); | |||
length = fib.getLcbPlcffldHdrtxbx(); | |||
break; | |||
case PLCFFLDMOM: | |||
start = fib.getFcPlcffldMom(); | |||
length = fib.getLcbPlcffldMom(); | |||
break; | |||
case PLCFFLDTXBX: | |||
start = fib.getFcPlcffldTxbx(); | |||
length = fib.getLcbPlcffldTxbx(); | |||
break; | |||
default: | |||
break; | |||
} | |||
if ( start <= 0 || length <= 0 ) | |||
return null; | |||
return new PlexOfCps( tableStream, start, length, FLD_SIZE ); | |||
} | |||
} | |||
public ArrayList<PlexOfField> getFieldsPLCF( int type ) | |||
{ | |||
return _tables.get(type); | |||
} | |||
private ArrayList<PlexOfField> readPLCF(byte[] tableStream, FileInformationBlock fib, int type) | |||
{ | |||
int start = 0; | |||
int length = 0; | |||
switch (type) | |||
public ArrayList<PlexOfField> getFieldsPLCF( int type ) | |||
{ | |||
case PLCFFLDATN: | |||
start = fib.getFcPlcffldAtn(); | |||
length = fib.getLcbPlcffldAtn(); | |||
break; | |||
case PLCFFLDEDN: | |||
start = fib.getFcPlcffldEdn(); | |||
length = fib.getLcbPlcffldEdn(); | |||
break; | |||
case PLCFFLDFTN: | |||
start = fib.getFcPlcffldFtn(); | |||
length = fib.getLcbPlcffldFtn(); | |||
break; | |||
case PLCFFLDHDR: | |||
start = fib.getFcPlcffldHdr(); | |||
length = fib.getLcbPlcffldHdr(); | |||
break; | |||
case PLCFFLDHDRTXBX: | |||
start = fib.getFcPlcffldHdrtxbx(); | |||
length = fib.getLcbPlcffldHdrtxbx(); | |||
break; | |||
case PLCFFLDMOM: | |||
start = fib.getFcPlcffldMom(); | |||
length = fib.getLcbPlcffldMom(); | |||
break; | |||
case PLCFFLDTXBX: | |||
start = fib.getFcPlcffldTxbx(); | |||
length = fib.getLcbPlcffldTxbx(); | |||
default: | |||
break; | |||
return toArrayList( _tables.get( Integer.valueOf( type ) ) ); | |||
} | |||
ArrayList<PlexOfField> fields = new ArrayList<PlexOfField>(); | |||
private static ArrayList<PlexOfField> toArrayList( PlexOfCps plexOfCps ) | |||
{ | |||
if ( plexOfCps == null ) | |||
return new ArrayList<PlexOfField>(); | |||
ArrayList<PlexOfField> fields = new ArrayList<PlexOfField>(); | |||
fields.ensureCapacity( plexOfCps.length() ); | |||
for ( int i = 0; i < plexOfCps.length(); i++ ) | |||
{ | |||
GenericPropertyNode propNode = plexOfCps.getProperty( i ); | |||
PlexOfField plex = new PlexOfField( propNode ); | |||
fields.add( plex ); | |||
} | |||
return fields; | |||
} | |||
if (start > 0 && length > 0) | |||
private int savePlex( PlexOfCps plexOfCps, int type, | |||
FileInformationBlock fib, HWPFOutputStream outputStream ) | |||
throws IOException | |||
{ | |||
PlexOfCps plcf = new PlexOfCps(tableStream, start, length, FLD_SIZE); | |||
fields.ensureCapacity(plcf.length()); | |||
for ( int i = 0; i < plcf.length(); i ++ ) { | |||
GenericPropertyNode propNode = plcf.getProperty( i ); | |||
PlexOfField plex = new PlexOfField( propNode.getStart(), propNode.getEnd(), propNode.getBytes() ); | |||
fields.add( plex ); | |||
} | |||
if ( plexOfCps == null || plexOfCps.length() == 0 ) | |||
return 0; | |||
byte[] data = plexOfCps.toByteArray(); | |||
int start = outputStream.getOffset(); | |||
int length = data.length; | |||
outputStream.write( data ); | |||
switch ( type ) | |||
{ | |||
case PLCFFLDATN: | |||
fib.setFcPlcffldAtn( start ); | |||
fib.setLcbPlcffldAtn( length ); | |||
break; | |||
case PLCFFLDEDN: | |||
fib.setFcPlcffldEdn( start ); | |||
fib.setLcbPlcffldEdn( length ); | |||
break; | |||
case PLCFFLDFTN: | |||
fib.setFcPlcffldFtn( start ); | |||
fib.setLcbPlcffldFtn( length ); | |||
break; | |||
case PLCFFLDHDR: | |||
fib.setFcPlcffldHdr( start ); | |||
fib.setLcbPlcffldHdr( length ); | |||
break; | |||
case PLCFFLDHDRTXBX: | |||
fib.setFcPlcffldHdrtxbx( start ); | |||
fib.setLcbPlcffldHdrtxbx( length ); | |||
break; | |||
case PLCFFLDMOM: | |||
fib.setFcPlcffldMom( start ); | |||
fib.setLcbPlcffldMom( length ); | |||
break; | |||
case PLCFFLDTXBX: | |||
fib.setFcPlcffldTxbx( start ); | |||
fib.setLcbPlcffldTxbx( length ); | |||
break; | |||
default: | |||
return 0; | |||
} | |||
return length; | |||
} | |||
return fields; | |||
} | |||
public void write( FileInformationBlock fib, HWPFOutputStream tableStream ) | |||
throws IOException | |||
{ | |||
for ( int i = PLCFFLDATN; i <= PLCFFLDTXBX; i++ ) | |||
{ | |||
PlexOfCps plexOfCps = _tables.get( Integer.valueOf( i ) ); | |||
savePlex( plexOfCps, i, fib, tableStream ); | |||
} | |||
} | |||
} |
@@ -472,6 +472,16 @@ public final class FileInformationBlock extends FIBAbstractType | |||
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDATN); | |||
} | |||
public void setFcPlcffldAtn( int offset ) | |||
{ | |||
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDATN, offset ); | |||
} | |||
public void setLcbPlcffldAtn( int size ) | |||
{ | |||
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDATN, size ); | |||
} | |||
public int getFcPlcffldEdn() | |||
{ | |||
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDEDN); | |||
@@ -482,6 +492,16 @@ public final class FileInformationBlock extends FIBAbstractType | |||
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDEDN); | |||
} | |||
public void setFcPlcffldEdn( int offset ) | |||
{ | |||
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDEDN, offset ); | |||
} | |||
public void setLcbPlcffldEdn( int size ) | |||
{ | |||
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDEDN, size ); | |||
} | |||
public int getFcPlcffldFtn() | |||
{ | |||
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDFTN); | |||
@@ -492,6 +512,16 @@ public final class FileInformationBlock extends FIBAbstractType | |||
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDFTN); | |||
} | |||
public void setFcPlcffldFtn( int offset ) | |||
{ | |||
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDFTN, offset ); | |||
} | |||
public void setLcbPlcffldFtn( int size ) | |||
{ | |||
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDFTN, size ); | |||
} | |||
public int getFcPlcffldHdr() | |||
{ | |||
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDHDR); | |||
@@ -502,6 +532,16 @@ public final class FileInformationBlock extends FIBAbstractType | |||
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDHDR); | |||
} | |||
public void setFcPlcffldHdr( int offset ) | |||
{ | |||
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDHDR, offset ); | |||
} | |||
public void setLcbPlcffldHdr( int size ) | |||
{ | |||
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDHDR, size ); | |||
} | |||
public int getFcPlcffldHdrtxbx() | |||
{ | |||
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDHDRTXBX); | |||
@@ -511,7 +551,17 @@ public final class FileInformationBlock extends FIBAbstractType | |||
{ | |||
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDHDRTXBX); | |||
} | |||
public void setFcPlcffldHdrtxbx( int offset ) | |||
{ | |||
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDHDRTXBX, offset ); | |||
} | |||
public void setLcbPlcffldHdrtxbx( int size ) | |||
{ | |||
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDHDRTXBX, size ); | |||
} | |||
public int getFcPlcffldMom() | |||
{ | |||
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDMOM); | |||
@@ -521,7 +571,17 @@ public final class FileInformationBlock extends FIBAbstractType | |||
{ | |||
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDMOM); | |||
} | |||
public void setFcPlcffldMom( int offset ) | |||
{ | |||
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDMOM, offset ); | |||
} | |||
public void setLcbPlcffldMom( int size ) | |||
{ | |||
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDMOM, size ); | |||
} | |||
public int getFcPlcffldTxbx() | |||
{ | |||
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDTXBX); | |||
@@ -532,6 +592,16 @@ public final class FileInformationBlock extends FIBAbstractType | |||
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDTXBX); | |||
} | |||
public void setFcPlcffldTxbx( int offset ) | |||
{ | |||
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDTXBX, offset ); | |||
} | |||
public void setLcbPlcffldTxbx( int size ) | |||
{ | |||
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDTXBX, size ); | |||
} | |||
public int getFcPlcspaMom() | |||
{ | |||
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCSPAMOM); |
@@ -25,37 +25,47 @@ import java.text.MessageFormat; | |||
* Structure describing the Plex for fields (contained plclfd* in the spec). | |||
* | |||
* @author Cedric Bosdonnat <cbosdonnat@novell.com> | |||
* | |||
* | |||
*/ | |||
public class PlexOfField | |||
public class PlexOfField | |||
{ | |||
private int fcStart; | |||
private int fcEnd; | |||
private FieldDescriptor fld; | |||
public PlexOfField( int fcStart, int fcEnd, byte[] data ) { | |||
this.fcStart = fcStart; | |||
this.fcEnd = fcEnd; | |||
fld = new FieldDescriptor( data ); | |||
} | |||
public int getFcStart() { | |||
return fcStart; | |||
} | |||
public int getFcEnd() { | |||
return fcEnd; | |||
} | |||
public FieldDescriptor getFld() { | |||
return fld; | |||
} | |||
private final PropertyNode<?> propertyNode; | |||
private final FieldDescriptor fld; | |||
@Deprecated | |||
public PlexOfField( int fcStart, int fcEnd, byte[] data ) | |||
{ | |||
propertyNode = new GenericPropertyNode( fcStart, fcEnd, data ); | |||
fld = new FieldDescriptor( data ); | |||
} | |||
public PlexOfField( PropertyNode<?> propertyNode ) | |||
{ | |||
this.propertyNode = propertyNode; | |||
fld = new FieldDescriptor( (byte[]) propertyNode._buf ); | |||
} | |||
public int getFcStart() | |||
{ | |||
return propertyNode.getStart(); | |||
} | |||
public int getFcEnd() | |||
{ | |||
return propertyNode.getEnd(); | |||
} | |||
public FieldDescriptor getFld() | |||
{ | |||
return fld; | |||
} | |||
public String toString() | |||
{ | |||
return MessageFormat.format( "[{0}, {1}) - FLD - 0x{2}; 0x{3}", fcStart, | |||
fcEnd, Integer.toHexString( 0xff & fld.getBoundaryType() ), | |||
return MessageFormat.format( "[{0}, {1}) - FLD - 0x{2}; 0x{3}", | |||
getFcStart(), getFcEnd(), | |||
Integer.toHexString( 0xff & fld.getBoundaryType() ), | |||
Integer.toHexString( 0xff & fld.getFlt() ) ); | |||
} | |||
} |
@@ -17,6 +17,8 @@ | |||
package org.apache.poi.hwpf.usermodel; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.List; | |||
@@ -552,10 +554,13 @@ public final class TestProblems extends HWPFTestCase { | |||
.getFieldsPLCF( FieldsTables.PLCFFLDMOM ); | |||
List<PlexOfField> actualFields = doc2.getFieldsTables() | |||
.getFieldsPLCF( FieldsTables.PLCFFLDMOM ); | |||
assertEquals( expectedFields.size(), actualFields.size() ); | |||
fixed("47286"); | |||
assertTableStructures( doc1.getRange(), doc2.getRange() ); | |||
// no, it still not fixed, need to figure what is the difference in | |||
// document | |||
// fixed( "47286" ); | |||
} | |||
catch ( AssertionFailedError exc ) | |||
{ | |||
@@ -746,6 +751,11 @@ public final class TestProblems extends HWPFTestCase { | |||
expected.text().replace( "\r", "\n" ).replaceAll( "\n\n", "\n" ), | |||
actual.text().replace( "\r", "\n" ).replaceAll( "\n\n", "\n" ) ); | |||
assertTableStructures( expected, actual ); | |||
} | |||
private static void assertTableStructures( Range expected, Range actual ) | |||
{ | |||
assertEquals( expected.numParagraphs(), actual.numParagraphs() ); | |||
for ( int p = 0; p < expected.numParagraphs(); p++ ) | |||
{ |