001/*
002 * $Id: PdfObject.java 4784 2011-03-15 08:33:00Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text.pdf;
045import java.io.IOException;
046import java.io.OutputStream;
047
048/**
049 * <CODE>PdfObject</CODE> is the abstract superclass of all PDF objects.
050 * <P>
051 * PDF supports seven basic types of objects: Booleans, numbers, strings, names,
052 * arrays, dictionaries and streams. In addition, PDF provides a null object.
053 * Objects may be labeled so that they can be referred to by other objects.<BR>
054 * All these basic PDF objects are described in the 'Portable Document Format
055 * Reference Manual version 1.3' Chapter 4 (pages 37-54).
056 *
057 * @see         PdfNull
058 * @see         PdfBoolean
059 * @see         PdfNumber
060 * @see         PdfString
061 * @see         PdfName
062 * @see         PdfArray
063 * @see         PdfDictionary
064 * @see         PdfStream
065 * @see         PdfIndirectReference
066 */
067public abstract class PdfObject {
068
069    // CONSTANTS
070
071    /** A possible type of <CODE>PdfObject</CODE> */
072    public static final int BOOLEAN = 1;
073
074    /** A possible type of <CODE>PdfObject</CODE> */
075    public static final int NUMBER = 2;
076
077    /** A possible type of <CODE>PdfObject</CODE> */
078    public static final int STRING = 3;
079
080    /** A possible type of <CODE>PdfObject</CODE> */
081    public static final int NAME = 4;
082
083    /** A possible type of <CODE>PdfObject</CODE> */
084    public static final int ARRAY = 5;
085
086    /** A possible type of <CODE>PdfObject</CODE> */
087    public static final int DICTIONARY = 6;
088
089    /** A possible type of <CODE>PdfObject</CODE> */
090    public static final int STREAM = 7;
091
092    /** A possible type of <CODE>PdfObject</CODE> */
093    public static final int NULL = 8;
094
095    /** A possible type of <CODE>PdfObject</CODE> */
096    public static final int INDIRECT = 10;
097
098    /** An empty string used for the <CODE>PdfNull</CODE>-object and for an empty <CODE>PdfString</CODE>-object. */
099    public static final String NOTHING = "";
100
101    /**
102     * This is the default encoding to be used for converting Strings into
103     * bytes and vice versa. The default encoding is PdfDocEncoding.
104     */
105    public static final String TEXT_PDFDOCENCODING = "PDF";
106
107    /** This is the encoding to be used to output text in Unicode. */
108    public static final String TEXT_UNICODE = "UnicodeBig";
109
110    // CLASS VARIABLES
111
112    /** The content of this <CODE>PdfObject</CODE> */
113    protected byte[] bytes;
114
115    /** The type of this <CODE>PdfObject</CODE> */
116    protected int type;
117
118    /** Holds the indirect reference. */
119    protected PRIndirectReference indRef;
120
121    // CONSTRUCTORS
122
123    /**
124     * Constructs a <CODE>PdfObject</CODE> of a certain <VAR>type</VAR>
125     * without any <VAR>content</VAR>.
126     *
127     * @param type    type of the new <CODE>PdfObject</CODE>
128     */
129    protected PdfObject(int type) {
130        this.type = type;
131    }
132
133    /**
134     * Constructs a <CODE>PdfObject</CODE> of a certain <VAR>type</VAR>
135     * with a certain <VAR>content</VAR>.
136     *
137     * @param type     type of the new <CODE>PdfObject</CODE>
138     * @param content  content of the new <CODE>PdfObject</CODE> as a
139     *   <CODE>String</CODE>.
140     */
141    protected PdfObject(int type, String content) {
142        this.type = type;
143        bytes = PdfEncodings.convertToBytes(content, null);
144    }
145
146    /**
147     * Constructs a <CODE>PdfObject</CODE> of a certain <VAR>type</VAR>
148     * with a certain <VAR>content</VAR>.
149     *
150     * @param type   type of the new <CODE>PdfObject</CODE>
151     * @param bytes  content of the new <CODE>PdfObject</CODE> as an array of
152     *   <CODE>byte</CODE>.
153     */
154    protected PdfObject(int type, byte[] bytes) {
155        this.bytes = bytes;
156        this.type = type;
157    }
158
159    // methods dealing with the content of this object
160
161    /**
162     * Writes the PDF representation of this <CODE>PdfObject</CODE> as an
163     * array of <CODE>byte</CODE>s to the writer.
164     * 
165     * @param writer for backwards compatibility
166     * @param os     The <CODE>OutputStream</CODE> to write the bytes to.
167     * @throws IOException
168     */
169    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
170        if (bytes != null)
171            os.write(bytes);
172    }
173
174    /**
175     * Returns the <CODE>String</CODE>-representation of this
176     * <CODE>PdfObject</CODE>.
177     *
178     * @return    a <CODE>String</CODE>
179     */
180    public String toString() {
181        if (bytes == null)
182            return super.toString();
183        return PdfEncodings.convertToString(bytes, null);
184    }
185
186    /**
187     * Gets the presentation of this object in a byte array
188     * 
189     * @return a byte array
190     */
191    public byte[] getBytes() {
192        return bytes;
193    }
194
195    /**
196     * Whether this object can be contained in an object stream.
197     * 
198     * PdfObjects of type STREAM OR INDIRECT can not be contained in an
199     * object stream.
200     * 
201     * @return <CODE>true</CODE> if this object can be in an object stream.
202     *   Otherwise <CODE>false</CODE>
203     */
204    public boolean canBeInObjStm() {
205        switch (type) {
206            case NULL:
207            case BOOLEAN:
208            case NUMBER:
209            case STRING:
210            case NAME:
211            case ARRAY:
212            case DICTIONARY:
213                return true;
214            case STREAM:
215            case INDIRECT:
216            default:
217                return false;
218        }
219    }
220
221    /**
222     * Returns the length of the PDF representation of the <CODE>PdfObject</CODE>.
223     * <P>
224     * In some cases, namely for <CODE>PdfString</CODE> and <CODE>PdfStream</CODE>,
225     * this method differs from the method <CODE>length</CODE> because <CODE>length</CODE>
226     * returns the length of the actual content of the <CODE>PdfObject</CODE>.</P>
227     * <P>
228     * Remark: the actual content of an object is in most cases identical to its representation.
229     * The following statement is always true: length() &gt;= pdfLength().</P>
230     *
231     * @return          a length
232     */
233//    public int pdfLength() {
234//        return toPdf(null).length;
235//    }
236
237    /**
238     * Returns the length of the actual content of the <CODE>PdfObject</CODE>.
239     * <P>
240     * In some cases, namely for <CODE>PdfString</CODE> and <CODE>PdfStream</CODE>,
241     * this method differs from the method <CODE>pdfLength</CODE> because <CODE>pdfLength</CODE>
242     * returns the length of the PDF representation of the object, not of the actual content
243     * as does the method <CODE>length</CODE>.</P>
244     * <P>
245     * Remark: the actual content of an object is in some cases identical to its representation.
246     * The following statement is always true: length() &gt;= pdfLength().</P>
247     *
248     * @return The length as <CODE>int</CODE>
249     */
250    public int length() {
251        return toString().length();
252    }
253
254    /**
255     * Changes the content of this <CODE>PdfObject</CODE>.
256     *
257     * @param content    the new content of this <CODE>PdfObject</CODE>
258     */
259    protected void setContent(String content) {
260        bytes = PdfEncodings.convertToBytes(content, null);
261    }
262
263    // methods dealing with the type of this object
264
265    /**
266     * Returns the type of this <CODE>PdfObject</CODE>.
267     * 
268     * May be either of:
269     * - <VAR>NULL</VAR>: A <CODE>PdfNull</CODE>
270     * - <VAR>BOOLEAN</VAR>: A <CODE>PdfBoolean</CODE>
271     * - <VAR>NUMBER</VAR>: A <CODE>PdfNumber</CODE>
272     * - <VAR>STRING</VAR>: A <CODE>PdfString</CODE>
273     * - <VAR>NAME</VAR>: A <CODE>PdfName</CODE>
274     * - <VAR>ARRAY</VAR>: A <CODE>PdfArray</CODE>
275     * - <VAR>DICTIONARY</VAR>: A <CODE>PdfDictionary</CODE>
276     * - <VAR>STREAM</VAR>: A <CODE>PdfStream</CODE>
277     * - <VAR>INDIRECT</VAR>: ><CODE>PdfIndirectObject</CODE>
278     *
279     * @return The type
280     */
281    public int type() {
282        return type;
283    }
284
285    /**
286     * Checks if this <CODE>PdfObject</CODE> is of the type
287     * <CODE>PdfNull</CODE>.
288     *
289     * @return <CODE>true</CODE> or <CODE>false</CODE>
290     */
291    public boolean isNull() {
292        return (type == NULL);
293    }
294
295    /**
296     * Checks if this <CODE>PdfObject</CODE> is of the type
297     * <CODE>PdfBoolean</CODE>.
298     *
299     * @return <CODE>true</CODE> or <CODE>false</CODE>
300     */
301    public boolean isBoolean() {
302        return (type == BOOLEAN);
303    }
304
305    /**
306     * Checks if this <CODE>PdfObject</CODE> is of the type
307     * <CODE>PdfNumber</CODE>.
308     *
309     * @return <CODE>true</CODE> or <CODE>false</CODE>
310     */
311    public boolean isNumber() {
312        return (type == NUMBER);
313    }
314
315    /**
316     * Checks if this <CODE>PdfObject</CODE> is of the type
317     * <CODE>PdfString</CODE>.
318     *
319     * @return <CODE>true</CODE> or <CODE>false</CODE>
320     */
321    public boolean isString() {
322        return (type == STRING);
323    }
324
325    /**
326     * Checks if this <CODE>PdfObject</CODE> is of the type
327     * <CODE>PdfName</CODE>.
328     *
329     * @return <CODE>true</CODE> or <CODE>false</CODE>
330     */
331    public boolean isName() {
332        return (type == NAME);
333    }
334
335    /**
336     * Checks if this <CODE>PdfObject</CODE> is of the type
337     * <CODE>PdfArray</CODE>.
338     *
339     * @return <CODE>true</CODE> or <CODE>false</CODE>
340     */
341    public boolean isArray() {
342        return (type == ARRAY);
343    }
344
345    /**
346     * Checks if this <CODE>PdfObject</CODE> is of the type
347     * <CODE>PdfDictionary</CODE>.
348     *
349     * @return <CODE>true</CODE> or <CODE>false</CODE>
350     */
351    public boolean isDictionary() {
352        return (type == DICTIONARY);
353    }
354
355    /**
356     * Checks if this <CODE>PdfObject</CODE> is of the type
357     * <CODE>PdfStream</CODE>.
358     *
359     * @return <CODE>true</CODE> or <CODE>false</CODE>
360     */
361    public boolean isStream() {
362        return (type == STREAM);
363    }
364
365    /**
366     * Checks if this <CODE>PdfObject</CODE> is of the type
367     * <CODE>PdfIndirectObject</CODE>.
368     * 
369     * @return <CODE>true</CODE> if this is an indirect object,
370     *   otherwise <CODE>false</CODE>
371     */
372    public boolean isIndirect() {
373        return (type == INDIRECT);
374    }
375
376    /**
377     * Get the indirect reference
378     * 
379     * @return A <CODE>PdfIndirectReference</CODE>
380     */
381    public PRIndirectReference getIndRef() {
382        return indRef;
383    }
384
385    /**
386     * Set the indirect reference
387     * 
388     * @param indRef New value as a <CODE>PdfIndirectReference</CODE>
389     */
390    public void setIndRef(PRIndirectReference indRef) {
391        this.indRef = indRef;
392    }
393}