/*
 * 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: AbstractAFPObject.java 1296496 2012-03-02 22:19:46Z gadams $ */

package org.apache.fop.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.afp.Streamable;
import org.apache.fop.afp.util.BinaryUtils;

This is the base class for all data stream objects. Page objects are responsible for building and generating the binary datastream in an AFP format.
/** * This is the base class for all data stream objects. Page objects are * responsible for building and generating the binary datastream in an * AFP format. */
public abstract class AbstractAFPObject implements Streamable {
Static logging instance
/** Static logging instance */
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; private static final byte[] SF_HEADER = new byte[] { 0x5A, // Structured field identifier 0x00, // Length byte 1 0x10, // Length byte 2 SF_CLASS, // Structured field id byte 1 (byte) 0x00, // Structured field id byte 2 (byte) 0x00, // Structured field id byte 3 0x00, // Flags 0x00, // Reserved 0x00, // Reserved };
Length of bytes of a Structured Field Header
/** Length of bytes of a Structured Field Header */
protected static final int SF_HEADER_LENGTH = SF_HEADER.length;
Copies the template structured field data array to the given byte array
Params:
  • data – the structured field data byte array
  • type – the type code
  • category – the category code
/** * Copies the template structured field data array to the given byte array * * @param data the structured field data byte array * @param type the type code * @param category the category code */
protected void copySF(byte[] data, byte type, byte category) { copySF(data, SF_CLASS, type, category); }
Copies the template structured field data array to the given byte array
Params:
  • data – the structured field data byte array
  • clazz – the class code
  • type – the type code
  • category – the category code
/** * Copies the template structured field data array to the given byte array * * @param data the structured field data byte array * @param clazz the class code * @param type the type code * @param category the category code */
protected static void copySF(byte[] data, byte clazz, byte type, byte category) { System.arraycopy(SF_HEADER, 0, data, 0, SF_HEADER_LENGTH); data[3] = clazz; data[4] = type; data[5] = category; }
Writes a collection of Streamable to the AFP Datastream.
Params:
  • objects – a list of AFPObjects
  • os – The stream to write to
Type parameters:
  • <S> – Streamable view of an AFPObject
Throws:
  • IOException – an I/O exception of some sort has occurred.
/** * Writes a collection of Streamable to the AFP Datastream. * * @param objects a list of AFPObjects * @param <S> Streamable view of an AFPObject * @param os The stream to write to * @throws java.io.IOException an I/O exception of some sort has occurred. */
protected <S extends Streamable> void writeObjects(Collection<S> objects, OutputStream os) throws IOException { if (objects != null) { Iterator<S> it = objects.iterator(); while (it.hasNext()) { Streamable s = it.next(); s.writeToStream(os); it.remove(); // once written, immediately remove the object } } }
Writes data chunks to a given outputstream
Params:
  • data – the data byte array
  • dataHeader – the header data
  • lengthOffset – offset of length field in data chunk
  • maxChunkLength – the maximum chunk length
  • os – the outputstream to write to
Throws:
  • IOException – thrown if an I/O exception of some sort has occurred.
/** * Writes data chunks to a given outputstream * * @param data the data byte array * @param dataHeader the header data * @param lengthOffset offset of length field in data chunk * @param maxChunkLength the maximum chunk length * @param os the outputstream to write to * @throws IOException thrown if an I/O exception of some sort has occurred. */
protected static void writeChunksToStream(byte[] data, byte[] dataHeader, int lengthOffset, int maxChunkLength, OutputStream os) throws IOException { int dataLength = data.length; int numFullChunks = dataLength / maxChunkLength; int lastChunkLength = dataLength % maxChunkLength; int headerLen = dataHeader.length - lengthOffset; // length field is just before data so do not include in data length if (headerLen == 2) { headerLen = 0; } byte[] len; int off = 0; if (numFullChunks > 0) { // write out full data chunks len = BinaryUtils.convert(headerLen + maxChunkLength, 2); dataHeader[lengthOffset] = len[0]; // Length byte 1 dataHeader[lengthOffset + 1] = len[1]; // Length byte 2 for (int i = 0; i < numFullChunks; i++, off += maxChunkLength) { os.write(dataHeader); os.write(data, off, maxChunkLength); } } if (lastChunkLength > 0) { // write last data chunk len = BinaryUtils.convert(headerLen + lastChunkLength, 2); dataHeader[lengthOffset] = len[0]; // Length byte 1 dataHeader[lengthOffset + 1] = len[1]; // Length byte 2 os.write(dataHeader); os.write(data, off, lastChunkLength); } }
Truncates the string as necessary
Params:
  • str – a character string
  • maxLength – the maximum length allowed for the string
Returns:a possibly truncated string
/** * Truncates the string as necessary * * @param str a character string * @param maxLength the maximum length allowed for the string * @return a possibly truncated string */
protected static String truncate(String str, int maxLength) { if (str.length() > maxLength) { str = str.substring(0, maxLength); LOG.warn("truncated character string '" + str + "', longer than " + maxLength + " chars"); } return str; }
structured field type codes
/** structured field type codes */
public interface Type {
Attribute
/** Attribute */
byte ATTRIBUTE = (byte)0xA0;
Copy Count
/** Copy Count */
byte COPY_COUNT = (byte)0xA2;
Descriptor
/** Descriptor */
byte DESCRIPTOR = (byte)0xA6;
Control
/** Control */
byte CONTROL = (byte)0xA7;
Begin
/** Begin */
byte BEGIN = (byte)0xA8;
End
/** End */
byte END = (byte)0xA9;
Map
/** Map */
byte MAP = (byte)0xAB;
Position
/** Position */
byte POSITION = (byte)0xAC;
Process
/** Process */
byte PROCESS = (byte)0xAD;
Include
/** Include */
byte INCLUDE = (byte)0xAF;
Table
/** Table */
byte TABLE = (byte)0xB0;
Migration
/** Migration */
byte MIGRATION = (byte)0xB1;
Variable
/** Variable */
byte VARIABLE = (byte)0xB2;
Link
/** Link */
byte LINK = (byte)0xB4;
Data
/** Data */
byte DATA = (byte)0xEE; }
structured field category codes
/** structured field category codes */
public interface Category {
Page Segment
/** Page Segment */
byte PAGE_SEGMENT = (byte)0x5F;
Object Area
/** Object Area */
byte OBJECT_AREA = (byte)0x6B;
Color Attribute Table
/** Color Attribute Table */
byte COLOR_ATTRIBUTE_TABLE = (byte)0x77;
IM Image
/** IM Image */
byte IM_IMAGE = (byte)0x7B;
Medium
/** Medium */
byte MEDIUM = (byte)0x88;
Coded Font
/** Coded Font */
byte CODED_FONT = (byte)0x8A;
Process Element
/** Process Element */
byte PROCESS_ELEMENT = (byte)0x90;
Object Container
/** Object Container */
byte OBJECT_CONTAINER = (byte)0x92;
Presentation Text
/** Presentation Text */
byte PRESENTATION_TEXT = (byte)0x9B;
Index
/** Index */
byte INDEX = (byte)0xA7;
Document
/** Document */
byte DOCUMENT = (byte)0xA8;
Page Group
/** Page Group */
byte PAGE_GROUP = (byte)0xAD;
Page
/** Page */
byte PAGE = (byte)0xAF;
Graphics
/** Graphics */
byte GRAPHICS = (byte)0xBB;
Data Resource
/** Data Resource */
byte DATA_RESOURCE = (byte)0xC3;
Document Environment Group (DEG)
/** Document Environment Group (DEG) */
byte DOCUMENT_ENVIRONMENT_GROUP = (byte)0xC4;
Resource Group
/** Resource Group */
byte RESOURCE_GROUP = (byte)0xC6;
Object Environment Group (OEG)
/** Object Environment Group (OEG) */
byte OBJECT_ENVIRONMENT_GROUP = (byte)0xC7;
Active Environment Group (AEG)
/** Active Environment Group (AEG) */
byte ACTIVE_ENVIRONMENT_GROUP = (byte)0xC9;
Medium Map
/** Medium Map */
byte MEDIUM_MAP = (byte)0xCC;
Form Map
/** Form Map */
byte FORM_MAP = (byte)0xCD;
Name Resource
/** Name Resource */
byte NAME_RESOURCE = (byte)0xCE;
Page Overlay
/** Page Overlay */
byte PAGE_OVERLAY = (byte)0xD8;
Resource Environment Group (REG)
/** Resource Environment Group (REG) */
byte RESOURCE_ENVIROMENT_GROUP = (byte)0xD9;
Overlay
/** Overlay */
byte OVERLAY = (byte)0xDF;
Data Suppression
/** Data Suppression */
byte DATA_SUPRESSION = (byte)0xEA;
Bar Code
/** Bar Code */
byte BARCODE = (byte)0xEB;
No Operation
/** No Operation */
byte NO_OPERATION = (byte)0xEE;
Image
/** Image */
byte IMAGE = (byte)0xFB; } }