git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1151452 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_1rc1old
public abstract class AbstractAFPObject implements Streamable { | public abstract class AbstractAFPObject implements Streamable { | ||||
/** Static logging instance */ | /** Static logging instance */ | ||||
protected static final Log LOG = LogFactory.getLog("org.apache.xmlgraphics.afp.modca"); | |||||
protected static final Log LOG = LogFactory.getLog(AbstractAFPObject.class); | |||||
/** the structured field class id */ | /** the structured field class id */ | ||||
protected static final byte SF_CLASS = (byte)0xD3; | protected static final byte SF_CLASS = (byte)0xD3; | ||||
/** the structure field header */ | |||||
static final byte[] SF_HEADER = new byte[] { | |||||
private static final byte[] SF_HEADER = new byte[] { | |||||
0x5A, // Structured field identifier | 0x5A, // Structured field identifier | ||||
0x00, // Length byte 1 | 0x00, // Length byte 1 | ||||
0x10, // Length byte 2 | 0x10, // Length byte 2 | ||||
0x00, // Reserved | 0x00, // Reserved | ||||
}; | }; | ||||
protected static final int SF_HEADER_LENGTH = SF_HEADER.length; | |||||
/** | /** | ||||
* Copies the template structured field data array to the given byte array | * Copies the template structured field data array to the given byte array | ||||
* | * | ||||
* @param os The stream to write to | * @param os The stream to write to | ||||
* @throws java.io.IOException an I/O exception of some sort has occurred. | * @throws java.io.IOException an I/O exception of some sort has occurred. | ||||
*/ | */ | ||||
protected void writeObjects(Collection/*<Streamable>*/ objects, OutputStream os) | |||||
throws IOException { | |||||
if (objects != null && objects.size() > 0) { | |||||
Iterator it = objects.iterator(); | |||||
protected <S extends Streamable> void writeObjects(Collection<S> objects, OutputStream os) | |||||
throws IOException { | |||||
if (objects != null) { | |||||
Iterator<S> it = objects.iterator(); | |||||
while (it.hasNext()) { | while (it.hasNext()) { | ||||
Object object = it.next(); | |||||
if (object instanceof Streamable) { | |||||
((Streamable)object).writeToStream(os); | |||||
it.remove(); // once written, immediately remove the object | |||||
} | |||||
Streamable s = it.next(); | |||||
s.writeToStream(os); | |||||
it.remove(); // once written, immediately remove the object | |||||
} | } | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Reads data chunks from an InputStream | |||||
* and then formats them with a structured header to a given OutputStream | |||||
* | |||||
* @param dataHeader the header data | |||||
* @param lengthOffset offset of length field in data chunk | |||||
* @param maxChunkLength the maximum chunk length | |||||
* @param inputStream the InputStream to read from | |||||
* @param outputStream the OutputStream to write to | |||||
* @throws IOException thrown if an I/O exception of some sort has occurred. | |||||
*/ | |||||
protected static void copyChunks(byte[] dataHeader, int lengthOffset, | |||||
int maxChunkLength, InputStream inputStream, OutputStream outputStream) | |||||
throws IOException { | |||||
int headerLen = dataHeader.length - lengthOffset; | |||||
// length field is just before data so do not include in data length | |||||
if (headerLen == 2) { | |||||
headerLen = 0; | |||||
} | |||||
byte[] data = new byte[maxChunkLength]; | |||||
int numBytesRead = 0; | |||||
while ((numBytesRead = inputStream.read(data, 0, maxChunkLength)) > 0) { | |||||
byte[] len = BinaryUtils.convert(headerLen + numBytesRead, 2); | |||||
dataHeader[lengthOffset] = len[0]; // Length byte 1 | |||||
dataHeader[lengthOffset + 1] = len[1]; // Length byte 2 | |||||
outputStream.write(dataHeader); | |||||
outputStream.write(data, 0, numBytesRead); | |||||
} | |||||
} | |||||
/** | /** | ||||
* Writes data chunks to a given outputstream | * Writes data chunks to a given outputstream | ||||
* | * | ||||
* @param maxLength the maximum length allowed for the string | * @param maxLength the maximum length allowed for the string | ||||
* @return a possibly truncated string | * @return a possibly truncated string | ||||
*/ | */ | ||||
protected String truncate(String str, int maxLength) { | |||||
protected static String truncate(String str, int maxLength) { | |||||
if (str.length() > maxLength) { | if (str.length() > maxLength) { | ||||
str = str.substring(0, maxLength); | str = str.substring(0, maxLength); | ||||
LOG.warn("truncated character string '" | LOG.warn("truncated character string '" |
return nameBytes; | return nameBytes; | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | |||||
protected void copySF(byte[] data, byte type, byte category) { | protected void copySF(byte[] data, byte type, byte category) { | ||||
super.copySF(data, type, category); | super.copySF(data, type, category); | ||||
byte[] nameData = getNameBytes(); | byte[] nameData = getNameBytes(); |
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.Iterator; | |||||
import java.util.List; | import java.util.List; | ||||
import org.apache.fop.afp.modca.Registry.ObjectType; | import org.apache.fop.afp.modca.Registry.ObjectType; | ||||
/** | /** | ||||
* A MODCA structured object base class providing support for Triplets | * A MODCA structured object base class providing support for Triplets | ||||
*/ | */ | ||||
public class AbstractTripletStructuredObject extends AbstractStructuredObject { | |||||
public abstract class AbstractTripletStructuredObject extends AbstractStructuredObject { | |||||
/** list of object triplets */ | /** list of object triplets */ | ||||
protected List/*<Triplet>*/ triplets = new java.util.ArrayList/*<Triplet>*/(); | |||||
protected List<AbstractTriplet> triplets = new java.util.ArrayList<AbstractTriplet>(); | |||||
/** | /** | ||||
* Returns the triplet data length | * Returns the triplet data length | ||||
*/ | */ | ||||
protected int getTripletDataLength() { | protected int getTripletDataLength() { | ||||
int dataLength = 0; | int dataLength = 0; | ||||
if (hasTriplets()) { | |||||
Iterator it = triplets.iterator(); | |||||
while (it.hasNext()) { | |||||
AbstractTriplet triplet = (AbstractTriplet)it.next(); | |||||
dataLength += triplet.getDataLength(); | |||||
} | |||||
for (Triplet triplet : triplets) { | |||||
dataLength += triplet.getDataLength(); | |||||
} | } | ||||
return dataLength; | return dataLength; | ||||
} | } | ||||
* @param tripletId the triplet identifier | * @param tripletId the triplet identifier | ||||
*/ | */ | ||||
private AbstractTriplet getTriplet(byte tripletId) { | private AbstractTriplet getTriplet(byte tripletId) { | ||||
Iterator it = getTriplets().iterator(); | |||||
while (it.hasNext()) { | |||||
AbstractTriplet triplet = (AbstractTriplet)it.next(); | |||||
if (triplet.getId() == tripletId) { | |||||
return triplet; | |||||
for (AbstractTriplet trip : triplets) { | |||||
if (trip.getId() == tripletId) { | |||||
return trip; | |||||
} | } | ||||
} | } | ||||
return null; | return null; | ||||
* | * | ||||
* @param triplet the triplet to add | * @param triplet the triplet to add | ||||
*/ | */ | ||||
protected void addTriplet(Triplet triplet) { | |||||
protected void addTriplet(AbstractTriplet triplet) { | |||||
triplets.add(triplet); | triplets.add(triplet); | ||||
} | } | ||||
* | * | ||||
* @param tripletCollection a collection of triplets | * @param tripletCollection a collection of triplets | ||||
*/ | */ | ||||
public void addTriplets(Collection/*<Triplet>*/ tripletCollection) { | |||||
public void addTriplets(Collection<AbstractTriplet> tripletCollection) { | |||||
if (tripletCollection != null) { | if (tripletCollection != null) { | ||||
triplets.addAll(tripletCollection); | triplets.addAll(tripletCollection); | ||||
} | } | ||||
} | } | ||||
/** @return the triplet list pertaining to this resource */ | /** @return the triplet list pertaining to this resource */ | ||||
protected List/*<Triplet>*/ getTriplets() { | |||||
protected List<AbstractTriplet> getTriplets() { | |||||
return triplets; | return triplets; | ||||
} | } | ||||
/** the object referenced is of type image */ | /** the object referenced is of type image */ | ||||
public static final byte TYPE_IMAGE = (byte)0xFB; | public static final byte TYPE_IMAGE = (byte)0xFB; | ||||
/** the object type referenced (default is other) */ | /** the object type referenced (default is other) */ | ||||
private byte objectType = TYPE_OTHER; | private byte objectType = TYPE_OTHER; | ||||
private int yoaOset = 0; | private int yoaOset = 0; | ||||
/** the orientation of the referenced object */ | /** the orientation of the referenced object */ | ||||
private int oaOrent = 0; | |||||
private ObjectAreaRotation oaOrent = ObjectAreaRotation.RIGHT_HANDED_0; | |||||
/** the X-axis origin defined in the object */ | /** the X-axis origin defined in the object */ | ||||
private int xocaOset = -1; | private int xocaOset = -1; | ||||
* The orientation (0,90, 180, 270) | * The orientation (0,90, 180, 270) | ||||
*/ | */ | ||||
public void setObjectAreaOrientation(int orientation) { | public void setObjectAreaOrientation(int orientation) { | ||||
if (orientation == 0 || orientation == 90 || orientation == 180 | |||||
|| orientation == 270) { | |||||
this.oaOrent = orientation; | |||||
} else { | |||||
throw new IllegalArgumentException( | |||||
"The orientation must be one of the values 0, 90, 180, 270"); | |||||
} | |||||
this.oaOrent = ObjectAreaRotation.objectAreaRotationFor(orientation); | |||||
} | } | ||||
/** | /** | ||||
data[17] = 0x00; // reserved | data[17] = 0x00; // reserved | ||||
data[18] = objectType; | data[18] = objectType; | ||||
//XoaOset (object area) | |||||
if (xoaOset > -1) { | |||||
byte[] x = BinaryUtils.convert(xoaOset, 3); | |||||
data[19] = x[0]; | |||||
data[20] = x[1]; | |||||
data[21] = x[2]; | |||||
} else { | |||||
data[19] = (byte)0xFF; | |||||
data[20] = (byte)0xFF; | |||||
data[21] = (byte)0xFF; | |||||
} | |||||
writeOsetTo(data, 19, xoaOset); | |||||
// YoaOset (object area) | |||||
if (yoaOset > -1) { | |||||
byte[] y = BinaryUtils.convert(yoaOset, 3); | |||||
data[22] = y[0]; | |||||
data[23] = y[1]; | |||||
data[24] = y[2]; | |||||
} else { | |||||
data[22] = (byte)0xFF; | |||||
data[23] = (byte)0xFF; | |||||
data[24] = (byte)0xFF; | |||||
} | |||||
writeOsetTo(data, 22, yoaOset); | |||||
// XoaOrent/YoaOrent | |||||
switch (oaOrent) { | |||||
case -1: // use x/y axis orientation defined in object | |||||
data[25] = (byte)0xFF; // x axis rotation | |||||
data[26] = (byte)0xFF; // | |||||
data[27] = (byte)0xFF; // y axis rotation | |||||
data[28] = (byte)0xFF; | |||||
break; | |||||
case 90: | |||||
data[25] = 0x2D; | |||||
data[26] = 0x00; | |||||
data[27] = 0x5A; | |||||
data[28] = 0x00; | |||||
break; | |||||
case 180: | |||||
data[25] = 0x5A; | |||||
data[25] = 0x00; | |||||
data[27] = (byte)0x87; | |||||
data[28] = 0x00; | |||||
break; | |||||
case 270: | |||||
data[25] = (byte)0x87; | |||||
data[26] = 0x00; | |||||
data[27] = 0x00; | |||||
data[28] = 0x00; | |||||
break; | |||||
default: // 0 degrees | |||||
data[25] = 0x00; | |||||
data[26] = 0x00; | |||||
data[27] = 0x2D; | |||||
data[28] = 0x00; | |||||
break; | |||||
} | |||||
oaOrent.writeTo(data, 25); | |||||
// XocaOset (object content) | |||||
if (xocaOset > -1) { | |||||
byte[] x = BinaryUtils.convert(xocaOset, 3); | |||||
data[29] = x[0]; | |||||
data[30] = x[1]; | |||||
data[31] = x[2]; | |||||
} else { | |||||
data[29] = (byte)0xFF; | |||||
data[30] = (byte)0xFF; | |||||
data[31] = (byte)0xFF; | |||||
} | |||||
writeOsetTo(data, 29, xocaOset); | |||||
writeOsetTo(data, 32, yocaOset); | |||||
// YocaOset (object content) | |||||
if (yocaOset > -1) { | |||||
byte[] y = BinaryUtils.convert(yocaOset, 3); | |||||
data[32] = y[0]; | |||||
data[33] = y[1]; | |||||
data[34] = y[2]; | |||||
} else { | |||||
data[32] = (byte)0xFF; | |||||
data[33] = (byte)0xFF; | |||||
data[34] = (byte)0xFF; | |||||
} | |||||
// RefCSys (Reference coordinate system) | // RefCSys (Reference coordinate system) | ||||
data[35] = 0x01; // Page or overlay coordinate system | data[35] = 0x01; // Page or overlay coordinate system | ||||
writeTriplets(os); | writeTriplets(os); | ||||
} | } | ||||
private static void writeOsetTo(byte[] out, int offset, int oset) { | |||||
if (oset > -1) { | |||||
byte[] y = BinaryUtils.convert(oset, 3); | |||||
out[offset] = y[0]; | |||||
out[offset + 1] = y[1]; | |||||
out[offset + 2] = y[2]; | |||||
} else { | |||||
out[offset] = (byte)0xFF; | |||||
out[offset + 1] = (byte)0xFF; | |||||
out[offset + 2] = (byte)0xFF; | |||||
} | |||||
} | |||||
private String getObjectTypeName() { | private String getObjectTypeName() { | ||||
String objectTypeName = null; | String objectTypeName = null; | ||||
if (objectType == TYPE_PAGE_SEGMENT) { | if (objectType == TYPE_PAGE_SEGMENT) { | ||||
addTriplet(new MeasurementUnitsTriplet(xRes, xRes)); | addTriplet(new MeasurementUnitsTriplet(xRes, xRes)); | ||||
} | } | ||||
} | |||||
/** | |||||
* Represents the 4 bytes that specify the area rotation reference coordinate system | |||||
* | |||||
*/ | |||||
private enum ObjectAreaRotation { | |||||
RIGHT_HANDED_0(Rotation.ROTATION_0, Rotation.ROTATION_90), | |||||
RIGHT_HANDED_90(Rotation.ROTATION_90, Rotation.ROTATION_180), | |||||
RIGHT_HANDED_180(Rotation.ROTATION_180, Rotation.ROTATION_270), | |||||
RIGHT_HANDED_270(Rotation.ROTATION_270, Rotation.ROTATION_0); | |||||
/** | |||||
* The object area’s X-axis rotation from the X axis of the reference coordinate system | |||||
*/ | |||||
private final Rotation xoaOrent; | |||||
/** | |||||
* The object area’s Y-axis rotation from the Y axis of the reference coordinate system | |||||
*/ | |||||
private final Rotation yoaOrent; | |||||
public void writeTo(byte[] out, int offset) { | |||||
xoaOrent.writeTo(out, offset); | |||||
yoaOrent.writeTo(out, offset + 2); | |||||
} | |||||
ObjectAreaRotation(Rotation xoaOrent, Rotation yoaOrent) { | |||||
this.xoaOrent = xoaOrent; | |||||
this.yoaOrent = yoaOrent; | |||||
} | |||||
private static ObjectAreaRotation objectAreaRotationFor(int orientation) { | |||||
switch (orientation) { | |||||
case 0: return RIGHT_HANDED_0; | |||||
case 90: return RIGHT_HANDED_90; | |||||
case 180: return RIGHT_HANDED_180; | |||||
case 270: return RIGHT_HANDED_270; | |||||
default: throw new IllegalArgumentException( | |||||
"The orientation must be one of the values 0, 90, 180, 270"); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Represents a rotation value | |||||
* | |||||
*/ | |||||
private enum Rotation { | |||||
ROTATION_0(0), | |||||
ROTATION_90(0x2D), | |||||
ROTATION_180(0x5A), | |||||
ROTATION_270(0x87); | |||||
private final byte firstByte; | |||||
public void writeTo(byte[] out, int offset) { | |||||
out[offset] = firstByte; | |||||
out[offset + 1] = (byte)0; | |||||
} | |||||
Rotation(int firstByte) { | |||||
this.firstByte = (byte) firstByte; | |||||
} | |||||
} | |||||
} |
setAttributeValue(value); | setAttributeValue(value); | ||||
setAttributeQualifier(tleID, 1); | setAttributeQualifier(tleID, 1); | ||||
byte[] data = new byte[SF_HEADER.length]; | |||||
byte[] data = new byte[SF_HEADER_LENGTH]; | |||||
copySF(data, Type.ATTRIBUTE, Category.PROCESS_ELEMENT); | copySF(data, Type.ATTRIBUTE, Category.PROCESS_ELEMENT); | ||||
int tripletDataLength = getTripletDataLength(); | int tripletDataLength = getTripletDataLength(); |
import org.apache.fop.image.loader.batik.ImageLoaderTestCase; | import org.apache.fop.image.loader.batik.ImageLoaderTestCase; | ||||
import org.apache.fop.image.loader.batik.ImagePreloaderTestCase; | import org.apache.fop.image.loader.batik.ImagePreloaderTestCase; | ||||
import org.apache.fop.intermediate.IFMimickingTestCase; | import org.apache.fop.intermediate.IFMimickingTestCase; | ||||
import org.apache.fop.render.afp.AFPTestSuite; | |||||
import org.apache.fop.render.extensions.prepress.PageBoundariesTest; | import org.apache.fop.render.extensions.prepress.PageBoundariesTest; | ||||
import org.apache.fop.render.extensions.prepress.PageScaleTest; | import org.apache.fop.render.extensions.prepress.PageScaleTest; | ||||
import org.apache.fop.render.pdf.PDFAConformanceTestCase; | import org.apache.fop.render.pdf.PDFAConformanceTestCase; | ||||
//$JUnit-BEGIN$ | //$JUnit-BEGIN$ | ||||
suite.addTest(BasicDriverTestSuite.suite()); | suite.addTest(BasicDriverTestSuite.suite()); | ||||
suite.addTest(UtilityCodeTestSuite.suite()); | suite.addTest(UtilityCodeTestSuite.suite()); | ||||
suite.addTest(org.apache.fop.afp.AFPTestSuite.suite()); | |||||
suite.addTest(new TestSuite(PDFAConformanceTestCase.class)); | suite.addTest(new TestSuite(PDFAConformanceTestCase.class)); | ||||
suite.addTest(new TestSuite(PDFEncodingTestCase.class)); | suite.addTest(new TestSuite(PDFEncodingTestCase.class)); | ||||
suite.addTest(new TestSuite(PDFCMapTestCase.class)); | suite.addTest(new TestSuite(PDFCMapTestCase.class)); | ||||
suite.addTest(new TestSuite(PDFsRGBSettingsTestCase.class)); | suite.addTest(new TestSuite(PDFsRGBSettingsTestCase.class)); | ||||
suite.addTest(new TestSuite(DejaVuLGCSerifTest.class)); | suite.addTest(new TestSuite(DejaVuLGCSerifTest.class)); | ||||
suite.addTest(new TestSuite(MODCAParserTestCase.class)); | suite.addTest(new TestSuite(MODCAParserTestCase.class)); | ||||
suite.addTest(AFPTestSuite.suite()); | |||||
suite.addTest(org.apache.fop.render.afp.AFPTestSuite.suite()); | |||||
suite.addTest(PSTestSuite.suite()); | suite.addTest(PSTestSuite.suite()); | ||||
suite.addTest(RichTextFormatTestSuite.suite()); | suite.addTest(RichTextFormatTestSuite.suite()); | ||||
suite.addTest(new TestSuite(ImageLoaderTestCase.class)); | suite.addTest(new TestSuite(ImageLoaderTestCase.class)); |
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.afp; | |||||
import junit.framework.Test; | |||||
import junit.framework.TestSuite; | |||||
import org.apache.fop.afp.modca.AbstractStructuredObjectTestCase; | |||||
import org.apache.fop.afp.modca.AbstractTripletStructuredObjectTestCase; | |||||
import org.apache.fop.afp.modca.IncludeObjectTestCase; | |||||
/** | |||||
* Test suite for FOP's AFP classes. | |||||
*/ | |||||
public class AFPTestSuite { | |||||
/** | |||||
* Builds the test suite | |||||
* @return the test suite | |||||
*/ | |||||
public static Test suite() { | |||||
TestSuite suite = new TestSuite("Test suite for FOP's AFP classes"); | |||||
//$JUnit-BEGIN$ | |||||
suite.addTest(new TestSuite(IncludeObjectTestCase.class)); | |||||
//$JUnit-END$ | |||||
return suite; | |||||
} | |||||
} |
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.afp.modca; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.IOException; | |||||
import java.io.OutputStream; | |||||
import java.util.ArrayList; | |||||
import java.util.Arrays; | |||||
import java.util.List; | |||||
import junit.framework.TestCase; | |||||
import org.apache.fop.afp.Streamable; | |||||
/** | |||||
* Tests the {@link AbstractAFPObject} class. | |||||
*/ | |||||
public abstract class AbstractAFPObjectTestCase<S extends AbstractAFPObject> | |||||
extends TestCase { | |||||
private S sut; | |||||
protected final S getSut() { | |||||
return sut; | |||||
} | |||||
protected final void setSut(S sut) { | |||||
if ( this.sut == null) { | |||||
this.sut = sut; | |||||
} | |||||
} | |||||
private byte[] header = new byte[] { | |||||
0x5A, // Structured field identifier | |||||
0x00, // Length byte 1 | |||||
0x10, // Length byte 2 | |||||
0x00, // Structured field id byte 1 | |||||
0x00, // Structured field id byte 2 | |||||
0x00, // Structured field id byte 3 | |||||
0x00, // Flags | |||||
0x00, // Reserved | |||||
0x00 // Reserved | |||||
}; | |||||
public void testCopySFStatic() { | |||||
byte[] actual = new byte[9]; | |||||
Arrays.fill(actual, (byte)-1); | |||||
S.copySF(actual, (byte)0, (byte)0, (byte)0); | |||||
assertTrue(Arrays.equals(actual, header)); | |||||
byte[] expected2 = new byte[9]; | |||||
System.arraycopy(header, 0, expected2, 0, header.length); | |||||
final byte clazz = (byte) 0x01; | |||||
final byte type = (byte) 0x02; | |||||
final byte catagory = (byte) 0x03; | |||||
expected2[3] = clazz; | |||||
expected2[4] = type; | |||||
expected2[5] = catagory; | |||||
AbstractAFPObject.copySF(actual, clazz, type, catagory); | |||||
assertTrue(Arrays.equals(actual, expected2)); | |||||
} | |||||
public void testCopySF() { | |||||
byte[] expected = new byte[9]; | |||||
S.copySF(expected, (byte) 0xD3, (byte)0, (byte)0); | |||||
byte[] actual = new byte[9]; | |||||
Arrays.fill(actual, (byte)-1); | |||||
getSut().copySF(actual, (byte)0, (byte)0); | |||||
assertTrue(Arrays.equals(actual, expected)); | |||||
byte[] expected2 = new byte[9]; | |||||
System.arraycopy(expected, 0, expected2, 0, expected.length); | |||||
final byte type = (byte)1; | |||||
final byte catagory = (byte)2; | |||||
expected2[4] = type; | |||||
expected2[5] = catagory; | |||||
getSut().copySF(actual, type, catagory); | |||||
assertTrue(Arrays.equals(actual, expected2)); | |||||
} | |||||
/** | |||||
* | |||||
*/ | |||||
public void testwriteObjects() { | |||||
final byte[][] expected = {{(byte)0, (byte)1}, {(byte)2, (byte)3}, {(byte)4, (byte)5}}; | |||||
List<Streamable> objects = new ArrayList<Streamable>() { | |||||
{ | |||||
add(StreamableObject.instance(expected[0])); | |||||
add(StreamableObject.instance(expected[1])); | |||||
add(StreamableObject.instance(expected[2])); | |||||
} }; | |||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
try { | |||||
getSut().writeObjects(objects, baos); | |||||
} catch (IOException e) { | |||||
fail(); | |||||
} | |||||
byte[] actual = baos.toByteArray(); | |||||
int index = 0; | |||||
for (int i = 0; i < expected.length; i++) { | |||||
for (int j = 0; j < expected[i].length; j++) { | |||||
assertTrue("" + index, actual[index] == expected[i][j]); | |||||
index++; | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* | |||||
*/ | |||||
public void testTruncate() { | |||||
String expected = "abc"; | |||||
assertTrue(AbstractAFPObject.truncate(expected, 4) == expected); | |||||
assertTrue(AbstractAFPObject.truncate(expected, 3) == expected); | |||||
assertEquals(AbstractAFPObject.truncate(expected + "d", 3), expected); | |||||
assertEquals(AbstractAFPObject.truncate(expected, 0), ""); | |||||
try { | |||||
assertTrue(AbstractAFPObject.truncate(null, 4) == null); | |||||
fail(); | |||||
} catch (NullPointerException e) { | |||||
// PASS | |||||
} | |||||
} | |||||
/** | |||||
* | |||||
*/ | |||||
public void testWriteChunksToStream() throws IOException { | |||||
final byte[] data = new byte[256]; | |||||
int counter = 0; | |||||
for (int i = 0; i < data.length; i++) { | |||||
data[i] = (byte) counter++; | |||||
} | |||||
byte[] header = new byte[9]; | |||||
// Test when chunk size % data.length == 0 | |||||
testWithGivenChunkSize(data, header, 16); | |||||
// test when chunk size % data.length != 0 | |||||
testWithGivenChunkSize(data, header, 10); | |||||
// test with an odd number... | |||||
testWithGivenChunkSize(data, header, 13); | |||||
} | |||||
private void testWithGivenChunkSize(byte[] data, byte[] header, int chunkSize) | |||||
throws IOException { | |||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
S.writeChunksToStream(data, header, 0, chunkSize, baos); | |||||
byte[] testData = baos.toByteArray(); | |||||
int numberOfFullDataChunks = data.length / chunkSize; | |||||
int lastChunkSize = data.length % chunkSize; | |||||
int lengthOfTestData = numberOfFullDataChunks * (chunkSize + header.length); | |||||
lengthOfTestData += lastChunkSize == 0 ? 0 : header.length + lastChunkSize; | |||||
putLengthInHeader(header, chunkSize); | |||||
assertEquals(lengthOfTestData, testData.length); | |||||
int testIndex = 0; | |||||
int expectedIndex = 0; | |||||
for (int i = 0; i < numberOfFullDataChunks; i++) { | |||||
checkHeaderAndData(header, data, testData, expectedIndex, testIndex, chunkSize); | |||||
expectedIndex += chunkSize + header.length; | |||||
testIndex += chunkSize; | |||||
} | |||||
putLengthInHeader(header, lastChunkSize); | |||||
// check last chunk | |||||
if (lastChunkSize != 0) { | |||||
checkHeaderAndData(header, data, testData, expectedIndex, testIndex, lastChunkSize); | |||||
} | |||||
} | |||||
private void putLengthInHeader(byte[] header, int chunkSize) { | |||||
header[0] = 0; | |||||
header[1] = (byte) (chunkSize + header.length); | |||||
} | |||||
private void checkHeaderAndData(byte[] header, byte[] data, byte[] testData, int expectedIndex, | |||||
int testIndex, int chunkSize) { | |||||
for (int i = 0; i < header.length; i++) { | |||||
assertEquals(testData[expectedIndex++], header[i]); | |||||
} | |||||
for (int i = 0; i < chunkSize; i++) { | |||||
assertEquals(testData[expectedIndex++], data[i + testIndex]); | |||||
} | |||||
} | |||||
/** | |||||
* | |||||
*/ | |||||
private static class StreamableObject implements Streamable { | |||||
private byte[] bytes; | |||||
StreamableObject(byte[] bytes) { | |||||
this.bytes = new byte[bytes.length]; | |||||
System.arraycopy(bytes, 0, this.bytes, 0, bytes.length); | |||||
} | |||||
private static Streamable instance(byte[] bytes) { | |||||
return new StreamableObject(bytes); | |||||
} | |||||
public void writeToStream(OutputStream os) throws IOException { | |||||
os.write(bytes); | |||||
} | |||||
} | |||||
} |
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.afp.modca; | |||||
import java.util.Arrays; | |||||
/** | |||||
* Tests the {@linkplain AbstractAFPObject} class. | |||||
*/ | |||||
public abstract class AbstractNamedAFPObjectTestCase<S extends AbstractNamedAFPObject> | |||||
extends AbstractAFPObjectTestCase<S> { | |||||
public void testCopySF() { | |||||
final S sut = getSut(); | |||||
byte[] expected = new byte[17]; | |||||
S.copySF(expected, (byte) 0xD3, (byte)0, (byte)0); | |||||
byte[] nameData = sut.getNameBytes(); | |||||
System.arraycopy(nameData, 0, expected, 9, nameData.length); | |||||
byte[] actual = new byte[17]; | |||||
Arrays.fill(actual, (byte)-1); | |||||
getSut().copySF(actual, (byte)0, (byte)0); | |||||
assertTrue(Arrays.equals(actual, expected)); | |||||
byte[] expected2 = new byte[17]; | |||||
System.arraycopy(expected, 0, expected2, 0, expected.length); | |||||
System.arraycopy(nameData, 0, expected, 9, nameData.length); | |||||
final byte type = (byte)1; | |||||
final byte catagory = (byte)2; | |||||
expected2[4] = type; | |||||
expected2[5] = catagory; | |||||
getSut().copySF(actual, type, catagory); | |||||
assertTrue(Arrays.equals(actual, expected2)); | |||||
} | |||||
} |
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.afp.modca; | |||||
import java.io.IOException; | |||||
public abstract class AbstractStructuredObjectTestCase<S extends AbstractStructuredObject> extends AbstractAFPObjectTestCase<S> { | |||||
/** | |||||
* Test writeStart() - test that the contract is maintained with | |||||
* {@link AbstractStructuredObject}. | |||||
* | |||||
* @throws IOException | |||||
*/ | |||||
public void testwriteStart() throws IOException { | |||||
} | |||||
/** | |||||
* Test writeEnd() - test that the contract is maintained with {@link AbstractStructuredObject}. | |||||
* | |||||
* @throws IOException | |||||
*/ | |||||
public void testWriteEnd() throws IOException { | |||||
} | |||||
/** | |||||
* Test writeContent() - test that the contract is maintained with | |||||
* {@link AbstractStructuredObject}. | |||||
* | |||||
* @throws IOException | |||||
*/ | |||||
public void testWriteContent() throws IOException { | |||||
} | |||||
/** | |||||
* Test writeToStream() - test that the contract is maintained with | |||||
* {@link AbstractStructuredObject}. | |||||
* | |||||
* @throws IOException | |||||
*/ | |||||
public void testWriteToStream() throws IOException { | |||||
testwriteStart(); | |||||
testWriteEnd(); | |||||
testWriteContent(); | |||||
} | |||||
} |
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.afp.modca; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.IOException; | |||||
import java.util.ArrayList; | |||||
import java.util.Arrays; | |||||
import java.util.Collections; | |||||
import java.util.List; | |||||
import org.apache.fop.afp.modca.triplets.AbstractTriplet; | |||||
import org.apache.fop.afp.modca.triplets.AttributeQualifierTriplet; | |||||
import org.apache.fop.afp.modca.triplets.CommentTriplet; | |||||
import org.apache.fop.afp.modca.triplets.ObjectAreaSizeTriplet; | |||||
import org.apache.fop.afp.modca.triplets.Triplet; | |||||
/** | |||||
* Test {@link AbstractTripletStructuredObject} | |||||
*/ | |||||
public abstract class AbstractTripletStructuredObjectTestCase<S extends AbstractTripletStructuredObject> | |||||
extends AbstractStructuredObjectTestCase<AbstractTripletStructuredObject> { | |||||
private static final List<AbstractTriplet> TRIPLETS; | |||||
static { | |||||
List<AbstractTriplet> triplets = new ArrayList<AbstractTriplet>(); | |||||
triplets.add(new CommentTriplet((byte) 0x01, "test comment")); | |||||
triplets.add(new AttributeQualifierTriplet(1, 1)); | |||||
triplets.add(new ObjectAreaSizeTriplet(10, 20)); | |||||
TRIPLETS = Collections.unmodifiableList(triplets); | |||||
} | |||||
private AbstractTripletStructuredObject emptyStructuredObject | |||||
= new AbstractTripletStructuredObject() { }; | |||||
@Override | |||||
public void setUp() throws Exception { | |||||
super.setUp(); | |||||
AbstractTripletStructuredObject sut = getSut(); | |||||
for (AbstractTriplet triplet : TRIPLETS) { | |||||
sut.addTriplet(triplet); | |||||
} | |||||
} | |||||
/** | |||||
* Test getTripletLength() - ensure a sum of all enclosing object lengths is returned. | |||||
*/ | |||||
public void testGetTripletLength() { | |||||
int dataLength = 0; | |||||
for (Triplet t : TRIPLETS) { | |||||
dataLength += t.getDataLength(); | |||||
} | |||||
assertEquals(dataLength, getSut().getTripletDataLength()); | |||||
assertEquals(0, emptyStructuredObject.getTripletDataLength()); | |||||
} | |||||
/** | |||||
* Test hasTriplets() | |||||
*/ | |||||
public void testHasTriplets() { | |||||
assertTrue(getSut().hasTriplets()); | |||||
assertFalse(emptyStructuredObject.hasTriplets()); | |||||
} | |||||
/** | |||||
* Test writeTriplets() - Ensure the triplets are written properly. | |||||
* | |||||
* @throws IOException - | |||||
*/ | |||||
public void testWriteObjects() throws IOException { | |||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
for (AbstractTriplet triplet : TRIPLETS) { | |||||
triplet.writeToStream(baos); | |||||
} | |||||
byte[] expected = baos.toByteArray(); | |||||
baos.reset(); | |||||
getSut().writeTriplets(baos); | |||||
assertTrue(Arrays.equals(expected, baos.toByteArray())); | |||||
baos.reset(); | |||||
// Ensure it doesn't die if no data has been added | |||||
emptyStructuredObject.writeTriplets(baos); | |||||
byte[] emptyArray = baos.toByteArray(); | |||||
assertTrue(Arrays.equals(emptyArray, new byte[0])); | |||||
} | |||||
/** | |||||
* Test hasTriplet() - ensure both positive and negative values are returned. | |||||
*/ | |||||
public void testHasTriplet() { | |||||
for (AbstractTriplet triplet : TRIPLETS) { | |||||
assertTrue(getSut().hasTriplet(triplet.getId())); | |||||
assertFalse(emptyStructuredObject.hasTriplet(triplet.getId())); | |||||
} | |||||
CommentTriplet notInSystem = new CommentTriplet((byte) 0x30, "This should return false"); | |||||
assertFalse(getSut().hasTriplet(notInSystem.getId())); | |||||
} | |||||
/** | |||||
* Test addTriplet() - mostly tested above, but check boundary cases | |||||
*/ | |||||
public void testAddTriplet() { | |||||
// ensure null doesn't kill it... not sure what else to test | |||||
getSut().addTriplet(null); | |||||
} | |||||
/** | |||||
* Test addTriplets() - ensure all triplets are added. | |||||
*/ | |||||
public void testAddTriplets() { | |||||
// Tested on empty object | |||||
List<AbstractTriplet> expectedList = TRIPLETS; | |||||
emptyStructuredObject.addTriplets(expectedList); | |||||
// checks equals() on each member of both lists | |||||
assertEquals(expectedList, emptyStructuredObject.getTriplets()); | |||||
// Add a list to an already populated list | |||||
getSut().addTriplets(expectedList); | |||||
List<AbstractTriplet> newExpected = new ArrayList<AbstractTriplet>(expectedList); | |||||
newExpected.addAll(expectedList); | |||||
assertEquals(newExpected, getSut().getTriplets()); | |||||
// Ensure null doesn't throw exception | |||||
emptyStructuredObject.addTriplets(null); | |||||
} | |||||
} |
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id:$ */ | |||||
package org.apache.fop.afp.modca; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.IOException; | |||||
import java.util.Arrays; | |||||
import org.apache.fop.afp.util.BinaryUtils; | |||||
/** | |||||
* Test {@link IncludeObject} | |||||
*/ | |||||
public class IncludeObjectTestCase extends AbstractNamedAFPObjectTestCase<IncludeObject> { | |||||
@Override | |||||
public void setUp() throws Exception { | |||||
setSut(new IncludeObject("8__chars")); | |||||
super.setUp(); | |||||
} | |||||
/** | |||||
* Test writeToStream() | |||||
* @throws IOException - | |||||
*/ | |||||
public void testWriteToStream() throws IOException { | |||||
final IncludeObject sut = getSut(); | |||||
byte[] expected = defaultIncludeObjectBytes(sut.getTripletDataLength(), sut.getNameBytes()); | |||||
testWriteToStreamHelper(sut, expected); | |||||
} | |||||
/** | |||||
* Test writeToStream() - the orientation of the referenced object is a right- | |||||
* handed with a 180 x-axis | |||||
* @throws IOException - | |||||
*/ | |||||
public void testWriteToStreamForOrientation() throws IOException { | |||||
final IncludeObject sut = getSut(); | |||||
byte[] expected = defaultIncludeObjectBytes(sut.getTripletDataLength(), sut.getNameBytes()); | |||||
expected[25] = (byte)0x5A; | |||||
expected[26] = (byte)0x00; | |||||
expected[27] = (byte)0x87; | |||||
expected[28] = (byte)0x00; | |||||
sut.setObjectAreaOrientation(180); | |||||
testWriteToStreamHelper(sut, expected); | |||||
} | |||||
private void testWriteToStreamHelper(IncludeObject sut, byte[] expected) throws IOException { | |||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
sut.writeToStream(baos); | |||||
byte[] actual = baos.toByteArray(); | |||||
assertTrue(Arrays.equals(actual, expected)); | |||||
} | |||||
private byte[] defaultIncludeObjectBytes(int tripletDataLength, byte[] nameData) { | |||||
byte[] expected = new byte[36]; | |||||
byte[] header = new byte[] { | |||||
0x5A, // Structured field identifier | |||||
0x00, // Length byte 1 | |||||
0x10, // Length byte 2 | |||||
(byte)0xD3, // Structured field id byte 1 | |||||
(byte)0xAF, // Structured field id byte 2 - type 'input' | |||||
(byte)0xC3, // Structured field id byte 3 - category 'data resource' | |||||
0x00, // Flags | |||||
0x00, // Reserved | |||||
0x00, // Reserved | |||||
}; | |||||
System.arraycopy(header, 0, expected, 0, header.length); | |||||
byte[] lengthBytes = BinaryUtils.convert(35 + tripletDataLength, 2); //Ignore first byte | |||||
expected[1] = lengthBytes[0]; | |||||
expected[2] = lengthBytes[1]; | |||||
System.arraycopy(nameData, 0, expected, 9, nameData.length); | |||||
expected[18] = (byte)0x92; // object type 'other' | |||||
expected[27] = (byte)0x2D; // orientation of the reference object | |||||
writeOsetTo(expected, 29, -1); // the X-axis origin defined in the object | |||||
writeOsetTo(expected, 32, -1); // the Y-axis origin defined in the object | |||||
expected[35] = 0x01; // Page or overlay coordinate system | |||||
return expected; | |||||
} | |||||
private static void writeOsetTo(byte[] out, int offset, int oset) { | |||||
if (oset > -1) { | |||||
byte[] y = BinaryUtils.convert(oset, 3); | |||||
out[offset] = y[0]; | |||||
out[offset + 1] = y[1]; | |||||
out[offset + 2] = y[2]; | |||||
} else { | |||||
out[offset] = (byte)0xFF; | |||||
out[offset + 1] = (byte)0xFF; | |||||
out[offset + 2] = (byte)0xFF; | |||||
} | |||||
} | |||||
} |