123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- /*
- * 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.parser;
-
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.DataInputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.text.DecimalFormat;
-
- /**
- * Represents an unparsed (generic) AFP structured field.
- */
- public final class UnparsedStructuredField {
-
- private final Introducer introducer;
- private final byte[] extData;
- private final byte[] data;
-
- /**
- *
- * @param Structured field introducer
- * @param data Structured field data
- * @param extData Structured field extension data
- */
- UnparsedStructuredField(Introducer introducer,
- byte[] data, byte[] extData) {
- this.introducer = introducer;
- this.data = data;
- if (extData != null) {
- this.extData = extData;
- } else {
- this.extData = null;
- }
- }
-
- @Override
- public String toString() {
- StringBuffer sb = new StringBuffer("Structured Field: ");
- sb.append(Integer.toHexString(getSfTypeID()).toUpperCase());
- sb.append(", len=");
- sb.append(new DecimalFormat("00000").format(getSfLength()));
- sb.append(" ").append(getTypeCodeAsString());
- sb.append(" ").append(getCategoryCodeAsString());
- if (isSfiExtensionPresent()) {
- sb.append(", SFI extension present");
- }
- if (isSfiSegmentedData()) {
- sb.append(", segmented data");
- }
- if (isSfiPaddingPresent()) {
- sb.append(", with padding");
- }
- return sb.toString();
- }
-
-
- /**
- * Returns type code function name for this field.
- * @return the type code function name
- */
- private String getTypeCodeAsString() {
- switch (getSfTypeCode() & 0xFF) {
- case 0xA0: return "Attribute";
- case 0xA2: return "CopyCount";
- case 0xA6: return "Descriptor";
- case 0xA7: return "Control";
- case 0xA8: return "Begin";
- case 0xA9: return "End";
- case 0xAB: return "Map";
- case 0xAC: return "Position";
- case 0xAD: return "Process";
- case 0xAF: return "Include";
- case 0xB0: return "Table";
- case 0xB1: return "Migration";
- case 0xB2: return "Variable";
- case 0xB4: return "Link";
- case 0xEE: return "Data";
- default: return "Unknown:" + Integer.toHexString(getSfTypeCode()).toUpperCase();
- }
- }
-
- /**
- * Returns category code function name for this field.
- * @return the category code function name
- */
- private String getCategoryCodeAsString() {
- switch (getSfCategoryCode() & 0xFF) {
- case 0x5F: return "Page Segment";
- case 0x6B: return "Object Area";
- case 0x77: return "Color Attribute Table";
- case 0x7B: return "IM Image";
- case 0x88: return "Medium";
- case 0x89: return "Font";
- case 0x8A: return "Coded Font";
- case 0x90: return "Process Element";
- case 0x92: return "Object Container";
- case 0x9B: return "Presentation Text";
- case 0xA7: return "Index";
- case 0xA8: return "Document";
- case 0xAD: return "Page Group";
- case 0xAF: return "Page";
- case 0xBB: return "Graphics";
- case 0xC3: return "Data Resource";
- case 0xC4: return "Document Environment Group (DEG)";
- case 0xC6: return "Resource Group";
- case 0xC7: return "Object Environment Group (OEG)";
- case 0xC9: return "Active Environment Group (AEG)";
- case 0xCC: return "Medium Map";
- case 0xCD: return "Form Map";
- case 0xCE: return "Name Resource";
- case 0xD8: return "Page Overlay";
- case 0xD9: return "Resource Environment Group (REG)";
- case 0xDF: return "Overlay";
- case 0xEA: return "Data Supression";
- case 0xEB: return "Bar Code";
- case 0xEE: return "No Operation";
- case 0xFB: return "Image";
- default: return "Unknown:" + Integer.toHexString(getSfTypeCode()).toUpperCase();
- }
- }
-
- /**
- * Returns the structured field's length.
- * @return the field length
- */
- public short getSfLength() {
- return introducer.length;
- }
-
- /**
- * Returns the structured field's identifier.
- * @return the field identifier
- */
- public int getSfTypeID() {
- return ((getSfClassCode() & 0xFF) << 16)
- | ((getSfTypeCode() & 0xFF) << 8)
- | (getSfCategoryCode() & 0xFF);
- }
-
- /**
- * Returns the structured field's class code.
- * @return the field class code
- */
- public byte getSfClassCode() {
- return introducer.classCode;
- }
-
- /**
- * Returns the structured field's type code.
- * @return the type code
- */
- public byte getSfTypeCode() {
- return introducer.typeCode;
- }
-
- /**
- * Returns the structured field's category code.
- * @return the sfCategoryCode
- */
- public byte getSfCategoryCode() {
- return introducer.categoryCode;
- }
-
- /**
- * Indicates whether an field introducer extension is present.
- * @return true if an field introducer extension is present
- */
- public boolean isSfiExtensionPresent() {
- return introducer.extensionPresent && (this.extData != null);
- }
-
- /**
- * Indicates whether segmented data is present.
- * @return true if the data is segmented
- */
- public boolean isSfiSegmentedData() {
- return introducer.segmentedData;
- }
-
- /**
- * Indicates whether the data is padded.
- * @return true if the data is padded
- */
- public boolean isSfiPaddingPresent() {
- return introducer.paddingPresent;
- }
-
- /**
- * Returns the length of the extension if present.
- * @return the length of the extension (or 0 if no extension is present)
- */
- public short getExtLength() {
- return (extData != null) ? (short)(extData.length + 1) : 0;
-
- }
-
- /**
- * Returns the extension data if present.
- * @return the extension data (or null if no extension is present)
- */
- byte[] getExtData() {
- if (this.extData == null) {
- return new byte[0];
- }
- byte[] rtn = new byte[this.extData.length];
- System.arraycopy(this.extData, 0, rtn, 0, rtn.length);
- return rtn;
- }
-
- /**
- * Returns the structured field's payload.
- * @return the field's data
- */
- public byte[] getData() {
- if (this.data == null) {
- return new byte[0];
- }
- byte[] rtn = new byte[this.data.length];
- System.arraycopy(this.data, 0, rtn, 0, rtn.length);
- return rtn;
- }
-
- //For unit testing
- byte[] getIntroducerData() {
- return introducer.getIntroducerData();
- }
-
- /**
- * Returns the complete structured field as a byte array.
- * @return the complete field data
- */
- public byte[] getCompleteFieldAsBytes() {
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream(getSfLength());
- try {
- writeTo(baos);
- } catch (IOException ioe) {
- //nop
- }
- return baos.toByteArray();
-
- }
-
- /**
- * Writes this structured field to the given {@link OutputStream}.
- * @param out the output stream
- * @throws IOException if an I/O error occurs
- */
- public void writeTo(OutputStream out) throws IOException {
- out.write(introducer.introducerData);
- if (isSfiExtensionPresent()) {
- out.write(this.extData.length + 1);
- out.write(this.extData);
- }
- out.write(this.data);
- }
-
- static final class Introducer {
-
- private final short length;
- private final byte classCode;
- private final byte typeCode;
- private final byte categoryCode;
- private final boolean extensionPresent;
- private final boolean segmentedData;
- private final boolean paddingPresent;
- private final byte[] introducerData;
-
- Introducer(byte[] introducerData) throws IOException {
-
- this.introducerData = introducerData;
-
- // Parse the introducer; the 8 bytes have already been read from the stream just
- // before, so we parse the introducer from the byte array
- DataInputStream iis = new DataInputStream(
- new ByteArrayInputStream(introducerData));
-
- length = iis.readShort();
-
- classCode = iis.readByte();
- typeCode = iis.readByte();
- categoryCode = iis.readByte();
-
- //Flags
- byte f = iis.readByte();
-
- extensionPresent = (f & 0x01) != 0;
- segmentedData = (f & 0x04) != 0;
- paddingPresent = (f & 0x10) != 0;
-
- }
-
-
- public short getLength() {
- return length;
- }
-
- public byte getClassCode() {
- return classCode;
- }
-
- public byte getTypeCode() {
- return typeCode;
- }
-
- public byte getCategoryCode() {
- return categoryCode;
- }
-
- public boolean isExtensionPresent() {
- return extensionPresent;
- }
-
-
- public boolean isSegmentedData() {
- return segmentedData;
- }
-
- public boolean isPaddingPresent() {
- return paddingPresent;
- }
-
- public byte[] getIntroducerData() {
- byte[] rtn = new byte[introducerData.length];
- System.arraycopy(introducerData, 0, rtn, 0, rtn.length);
- return rtn;
- }
- }
-
- }
|