aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/pdfbox/pdmodel/common
diff options
context:
space:
mode:
authortknall <tknall@7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c>2006-12-01 12:20:24 +0000
committertknall <tknall@7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c>2006-12-01 12:20:24 +0000
commit6025b6016517c6d898d8957d1d7e03ba71431912 (patch)
treeb15bd6fa5ffe9588a9bca3f2b8a7e358f83b6eba /src/main/java/org/pdfbox/pdmodel/common
parentd2c77e820ab4aba8235d71275755021347b3ad10 (diff)
downloadpdf-as-3-6025b6016517c6d898d8957d1d7e03ba71431912.tar.gz
pdf-as-3-6025b6016517c6d898d8957d1d7e03ba71431912.tar.bz2
pdf-as-3-6025b6016517c6d898d8957d1d7e03ba71431912.zip
Initial import of release 2.2.REL-2.2@923
git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@4 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c
Diffstat (limited to 'src/main/java/org/pdfbox/pdmodel/common')
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/COSArrayList.java643
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/COSDictionaryMap.java278
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/COSObjectable.java49
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/COSStreamArray.java304
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/DualCOSObjectable.java56
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/PDMatrix.java120
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/PDMemoryStream.java284
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/PDMetadata.java87
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/PDNameTreeNode.java337
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/PDNamedTextStream.java137
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/PDObjectStream.java151
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/PDRange.java146
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/PDRectangle.java295
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/PDStream.java538
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/PDTextStream.java180
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/filespecification/PDComplexFileSpecification.java326
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/filespecification/PDEmbeddedFile.java298
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/filespecification/PDFileSpecification.java83
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/filespecification/PDSimpleFileSpecification.java95
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/filespecification/package.html9
-rw-r--r--src/main/java/org/pdfbox/pdmodel/common/package.html9
21 files changed, 4425 insertions, 0 deletions
diff --git a/src/main/java/org/pdfbox/pdmodel/common/COSArrayList.java b/src/main/java/org/pdfbox/pdmodel/common/COSArrayList.java
new file mode 100644
index 0000000..bb3648a
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/COSArrayList.java
@@ -0,0 +1,643 @@
+/**
+ * Copyright (c) 2003-2004, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import org.pdfbox.cos.COSArray;
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSDictionary;
+import org.pdfbox.cos.COSInteger;
+import org.pdfbox.cos.COSFloat;
+import org.pdfbox.cos.COSString;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.cos.COSNull;
+import org.pdfbox.cos.COSNumber;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * This is an implementation of a List that will sync its contents to a COSArray.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.12 $
+ */
+public class COSArrayList implements List
+{
+ private COSArray array;
+ private List actual;
+
+ private COSDictionary parentDict;
+ private String dictKey;
+
+ /**
+ * Constructor.
+ *
+ * @param actualList The list of standard java objects
+ * @param cosArray The COS array object to sync to.
+ */
+ public COSArrayList( List actualList, COSArray cosArray )
+ {
+ actual = actualList;
+ array = cosArray;
+ }
+
+ /**
+ * This is a really special constructor. Sometimes the PDF spec says
+ * that a dictionary entry can either be a single item or an array of those
+ * items. But in the PDModel interface we really just want to always return
+ * a java.util.List. In the case were we get the list and never modify it
+ * we don't want to convert to COSArray and put one element, unless we append
+ * to the list. So here we are going to create this object with a single
+ * item instead of a list, but allow more items to be added and then converted
+ * to an array.
+ *
+ * @param actualObject The PDModel object.
+ * @param item The COS Model object.
+ * @param dictionary The dictionary that holds the item, and will hold the array if an item is added.
+ * @param dictionaryKey The key into the dictionary to set the item.
+ */
+ public COSArrayList( Object actualObject, COSBase item, COSDictionary dictionary, String dictionaryKey )
+ {
+ array = new COSArray();
+ array.add( item );
+ actual = new ArrayList();
+ actual.add( actualObject );
+
+ parentDict = dictionary;
+ dictKey = dictionaryKey;
+ }
+
+ /**
+ * @see List#size()
+ */
+ public int size()
+ {
+ return actual.size();
+ }
+
+ /**
+ * @see List#isEmpty()
+ */
+ public boolean isEmpty()
+ {
+ return actual.isEmpty();
+ }
+
+ /**
+ * @see List#contains( Object )
+ */
+ public boolean contains(Object o)
+ {
+ return actual.contains(o);
+ }
+
+ /**
+ * @see List#iterator()
+ */
+ public Iterator iterator()
+ {
+ return actual.iterator();
+ }
+
+ /**
+ * @see List#toArray()
+ */
+ public Object[] toArray()
+ {
+ return actual.toArray();
+ }
+
+ /**
+ * @see List#toArray( Object[] )
+ */
+ public Object[] toArray(Object[] a)
+ {
+ return actual.toArray(a);
+
+ }
+
+ /**
+ * @see List#add( Object )
+ */
+ public boolean add(Object o)
+ {
+ //when adding if there is a parentDict then change the item
+ //in the dictionary from a single item to an array.
+ if( parentDict != null )
+ {
+ parentDict.setItem( dictKey, array );
+ //clear the parent dict so it doesn't happen again, there might be
+ //a usecase for keeping the parentDict around but not now.
+ parentDict = null;
+ }
+ //string is a special case because we can't subclass to be COSObjectable
+ if( o instanceof String )
+ {
+ array.add( new COSString( (String)o ) );
+ }
+ else if( o instanceof DualCOSObjectable )
+ {
+ DualCOSObjectable dual = (DualCOSObjectable)o;
+ array.add( dual.getFirstCOSObject() );
+ array.add( dual.getSecondCOSObject() );
+ }
+ else
+ {
+ array.add( ((COSObjectable)o).getCOSObject() );
+ }
+ return actual.add(o);
+ }
+
+ /**
+ * @see List#remove( Object )
+ */
+ public boolean remove(Object o)
+ {
+ boolean retval = true;
+ int index = actual.indexOf( o );
+ if( index >= 0 )
+ {
+ actual.remove( index );
+ array.remove( index );
+ }
+ else
+ {
+ retval = false;
+ }
+ return retval;
+ }
+
+ /**
+ * @see List#containsAll( Collection )
+ */
+ public boolean containsAll(Collection c)
+ {
+ return actual.containsAll( c );
+ }
+
+ /**
+ * @see List#addAll( Collection )
+ */
+ public boolean addAll(Collection c)
+ {
+ //when adding if there is a parentDict then change the item
+ //in the dictionary from a single item to an array.
+ if( parentDict != null && c.size() > 0)
+ {
+ parentDict.setItem( dictKey, array );
+ //clear the parent dict so it doesn't happen again, there might be
+ //a usecase for keeping the parentDict around but not now.
+ parentDict = null;
+ }
+ array.addAll( toCOSObjectList( c ) );
+ return actual.addAll( c );
+ }
+
+ /**
+ * @see List#addAll( int, Collection )
+ */
+ public boolean addAll(int index, Collection c)
+ {
+ //when adding if there is a parentDict then change the item
+ //in the dictionary from a single item to an array.
+ if( parentDict != null && c.size() > 0)
+ {
+ parentDict.setItem( dictKey, array );
+ //clear the parent dict so it doesn't happen again, there might be
+ //a usecase for keeping the parentDict around but not now.
+ parentDict = null;
+ }
+
+ if( c.size() >0 && c.toArray()[0] instanceof DualCOSObjectable )
+ {
+ array.addAll( index*2, toCOSObjectList( c ) );
+ }
+ else
+ {
+ array.addAll( index, toCOSObjectList( c ) );
+ }
+ return actual.addAll( index, c );
+ }
+
+ /**
+ * This will take an array of COSNumbers and return a COSArrayList of
+ * java.lang.Integer values.
+ *
+ * @param intArray The existing integer Array.
+ *
+ * @return A list that is part of the core Java collections.
+ */
+ public static List convertIntegerCOSArrayToList( COSArray intArray )
+ {
+ List numbers = new ArrayList();
+ for( int i=0; i<intArray.size(); i++ )
+ {
+ numbers.add( new Integer( ((COSNumber)intArray.get( i )).intValue() ) );
+ }
+ return new COSArrayList( numbers, intArray );
+ }
+
+ /**
+ * This will take an array of COSNumbers and return a COSArrayList of
+ * java.lang.Float values.
+ *
+ * @param floatArray The existing float Array.
+ *
+ * @return The list of Float objects.
+ */
+ public static List convertFloatCOSArrayToList( COSArray floatArray )
+ {
+ List retval = null;
+ if( floatArray != null )
+ {
+ List numbers = new ArrayList();
+ for( int i=0; i<floatArray.size(); i++ )
+ {
+ numbers.add( new Float( ((COSNumber)floatArray.get( i )).floatValue() ) );
+ }
+ retval = new COSArrayList( numbers, floatArray );
+ }
+ return retval;
+ }
+
+ /**
+ * This will take an array of COSName and return a COSArrayList of
+ * java.lang.String values.
+ *
+ * @param nameArray The existing name Array.
+ *
+ * @return The list of String objects.
+ */
+ public static List convertCOSNameCOSArrayToList( COSArray nameArray )
+ {
+ List retval = null;
+ if( nameArray != null )
+ {
+ List names = new ArrayList();
+ for( int i=0; i<nameArray.size(); i++ )
+ {
+ names.add( ((COSName)nameArray.getObject( i )).getName() );
+ }
+ retval = new COSArrayList( names, nameArray );
+ }
+ return retval;
+ }
+
+ /**
+ * This will take an array of COSString and return a COSArrayList of
+ * java.lang.String values.
+ *
+ * @param stringArray The existing name Array.
+ *
+ * @return The list of String objects.
+ */
+ public static List convertCOSStringCOSArrayToList( COSArray stringArray )
+ {
+ List retval = null;
+ if( stringArray != null )
+ {
+ List string = new ArrayList();
+ for( int i=0; i<stringArray.size(); i++ )
+ {
+ string.add( ((COSString)stringArray.getObject( i )).getString() );
+ }
+ retval = new COSArrayList( string, stringArray );
+ }
+ return retval;
+ }
+
+ /**
+ * This will take an list of string objects and return a COSArray of COSName
+ * objects.
+ *
+ * @param strings A list of strings
+ *
+ * @return An array of COSName objects
+ */
+ public static COSArray convertStringListToCOSNameCOSArray( List strings )
+ {
+ COSArray retval = new COSArray();
+ for( int i=0; i<strings.size(); i++ )
+ {
+ Object next = strings.get( i );
+ if( next instanceof COSName )
+ {
+ retval.add( (COSName)next );
+ }
+ else
+ {
+ retval.add( COSName.getPDFName( (String)next ) );
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * This will take an list of string objects and return a COSArray of COSName
+ * objects.
+ *
+ * @param strings A list of strings
+ *
+ * @return An array of COSName objects
+ */
+ public static COSArray convertStringListToCOSStringCOSArray( List strings )
+ {
+ COSArray retval = new COSArray();
+ for( int i=0; i<strings.size(); i++ )
+ {
+ retval.add( new COSString( (String)strings.get( i ) ) );
+ }
+ return retval;
+ }
+
+ /**
+ * This will convert a list of COSObjectables to an
+ * array list of COSBase objects.
+ *
+ * @param cosObjectableList A list of COSObjectable.
+ *
+ * @return A list of COSBase.
+ */
+ public static COSArray converterToCOSArray( List cosObjectableList )
+ {
+ COSArray array = null;
+ if( cosObjectableList != null )
+ {
+ array = new COSArray();
+ Iterator iter = cosObjectableList.iterator();
+ while( iter.hasNext() )
+ {
+ Object next = iter.next();
+ if( next instanceof String )
+ {
+ array.add( new COSString( (String)next ) );
+ }
+ else if( next instanceof Integer || next instanceof Long )
+ {
+ array.add( new COSInteger( ((Number)next).longValue() ) );
+ }
+ else if( next instanceof Float || next instanceof Double )
+ {
+ array.add( new COSFloat( ((Number)next).floatValue() ) );
+ }
+ else if( next instanceof COSObjectable )
+ {
+ COSObjectable object = (COSObjectable)next;
+ array.add( object.getCOSObject() );
+ }
+ else if( next instanceof DualCOSObjectable )
+ {
+ DualCOSObjectable object = (DualCOSObjectable)next;
+ array.add( object.getFirstCOSObject() );
+ array.add( object.getSecondCOSObject() );
+ }
+ else if( next == null )
+ {
+ array.add( COSNull.NULL );
+ }
+ else
+ {
+ throw new RuntimeException( "Error: Don't know how to convert type to COSBase '" +
+ next.getClass().getName() + "'" );
+ }
+ }
+ }
+ return array;
+ }
+
+ private List toCOSObjectList( Collection list )
+ {
+ List cosObjects = new ArrayList();
+ Iterator iter = list.iterator();
+ while( iter.hasNext() )
+ {
+ Object next = iter.next();
+ if( next instanceof String )
+ {
+ cosObjects.add( new COSString( (String)next ) );
+ }
+ else if( next instanceof DualCOSObjectable )
+ {
+ DualCOSObjectable object = (DualCOSObjectable)next;
+ array.add( object.getFirstCOSObject() );
+ array.add( object.getSecondCOSObject() );
+ }
+ else
+ {
+ COSObjectable cos = (COSObjectable)next;
+ cosObjects.add( cos.getCOSObject() );
+ }
+ }
+ return cosObjects;
+ }
+
+ /**
+ * @see List#removeAll( Collection )
+ */
+ public boolean removeAll(Collection c)
+ {
+ array.removeAll( toCOSObjectList( c ) );
+ return actual.removeAll( c );
+ }
+
+ /**
+ * @see List#retainAll( Collection )
+ */
+ public boolean retainAll(Collection c)
+ {
+ array.retainAll( toCOSObjectList( c ) );
+ return actual.retainAll( c );
+ }
+
+ /**
+ * @see List#clear()
+ */
+ public void clear()
+ {
+ //when adding if there is a parentDict then change the item
+ //in the dictionary from a single item to an array.
+ if( parentDict != null )
+ {
+ parentDict.setItem( dictKey, (COSBase)null );
+ }
+ actual.clear();
+ array.clear();
+ }
+
+ /**
+ * @see List#equals( Object )
+ */
+ public boolean equals(Object o)
+ {
+ return actual.equals( o );
+ }
+
+ /**
+ * @see List#hashCode()
+ */
+ public int hashCode()
+ {
+ return actual.hashCode();
+ }
+
+ /**
+ * @see List#get( int )
+ */
+ public Object get(int index)
+ {
+ return actual.get( index );
+
+ }
+
+ /**
+ * @see List#set( int, Object )
+ */
+ public Object set(int index, Object element)
+ {
+ if( element instanceof String )
+ {
+ COSString item = new COSString( (String)element );
+ if( parentDict != null && index == 0 )
+ {
+ parentDict.setItem( dictKey, item );
+ }
+ array.set( index, item );
+ }
+ else if( element instanceof DualCOSObjectable )
+ {
+ DualCOSObjectable dual = (DualCOSObjectable)element;
+ array.set( index*2, dual.getFirstCOSObject() );
+ array.set( index*2+1, dual.getSecondCOSObject() );
+ }
+ else
+ {
+ if( parentDict != null && index == 0 )
+ {
+ parentDict.setItem( dictKey, ((COSObjectable)element).getCOSObject() );
+ }
+ array.set( index, ((COSObjectable)element).getCOSObject() );
+ }
+ return actual.set( index, element );
+ }
+
+ /**
+ * @see List#add( int, Object )
+ */
+ public void add(int index, Object element)
+ {
+ //when adding if there is a parentDict then change the item
+ //in the dictionary from a single item to an array.
+ if( parentDict != null )
+ {
+ parentDict.setItem( dictKey, array );
+ //clear the parent dict so it doesn't happen again, there might be
+ //a usecase for keeping the parentDict around but not now.
+ parentDict = null;
+ }
+ actual.add( index, element );
+ if( element instanceof String )
+ {
+ array.add( index, new COSString( (String)element ) );
+ }
+ else if( element instanceof DualCOSObjectable )
+ {
+ DualCOSObjectable dual = (DualCOSObjectable)element;
+ array.add( index*2, dual.getFirstCOSObject() );
+ array.add( index*2+1, dual.getSecondCOSObject() );
+ }
+ else
+ {
+ array.add( index, ((COSObjectable)element).getCOSObject() );
+ }
+ }
+
+ /**
+ * @see List#remove( int )
+ */
+ public Object remove(int index)
+ {
+ if( array.size() > index && array.get( index ) instanceof DualCOSObjectable )
+ {
+ //remove both objects
+ array.remove( index );
+ array.remove( index );
+ }
+ else
+ {
+ array.remove( index );
+ }
+ return actual.remove( index );
+ }
+
+ /**
+ * @see List#indexOf( Object )
+ */
+ public int indexOf(Object o)
+ {
+ return actual.indexOf( o );
+ }
+
+ /**
+ * @see List#lastIndexOf( Object )
+ */
+ public int lastIndexOf(Object o)
+ {
+ return actual.indexOf( o );
+
+ }
+
+ /**
+ * @see List#listIterator()
+ */
+ public ListIterator listIterator()
+ {
+ return actual.listIterator();
+ }
+
+ /**
+ * @see List#listIterator( int )
+ */
+ public ListIterator listIterator(int index)
+ {
+ return actual.listIterator( index );
+ }
+
+ /**
+ * @see List#subList( int, int )
+ */
+ public List subList(int fromIndex, int toIndex)
+ {
+ return actual.subList( fromIndex, toIndex );
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/COSDictionaryMap.java b/src/main/java/org/pdfbox/pdmodel/common/COSDictionaryMap.java
new file mode 100644
index 0000000..ca3821d
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/COSDictionaryMap.java
@@ -0,0 +1,278 @@
+/**
+ * Copyright (c) 2003-2004, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSBoolean;
+import org.pdfbox.cos.COSDictionary;
+import org.pdfbox.cos.COSFloat;
+import org.pdfbox.cos.COSInteger;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.cos.COSString;
+
+import java.io.IOException;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This is a Map that will automatically sync the contents to a COSDictionary.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.9 $
+ */
+public class COSDictionaryMap implements Map
+{
+ private COSDictionary map;
+ private Map actuals;
+
+ /**
+ * Constructor for this map.
+ *
+ * @param actualsMap The map with standard java objects as values.
+ * @param dicMap The map with COSBase objects as values.
+ */
+ public COSDictionaryMap( Map actualsMap, COSDictionary dicMap )
+ {
+ actuals = actualsMap;
+ map = dicMap;
+ }
+
+
+ /**
+ * @see java.util.Map#size()
+ */
+ public int size()
+ {
+ return map.size();
+ }
+
+ /**
+ * @see java.util.Map#isEmpty()
+ */
+ public boolean isEmpty()
+ {
+ return size() == 0;
+ }
+
+ /**
+ * @see java.util.Map#containsKey()
+ */
+ public boolean containsKey(Object key)
+ {
+ return map.keyList().contains( key );
+ }
+
+ /**
+ * @see java.util.Map#containsValue()
+ */
+ public boolean containsValue(Object value)
+ {
+ return actuals.containsValue( value );
+ }
+
+ /**
+ * @see java.util.Map#get()
+ */
+ public Object get(Object key)
+ {
+ return actuals.get( key );
+ }
+
+ /**
+ * @see java.util.Map#put()
+ */
+ public Object put(Object key, Object value)
+ {
+ COSObjectable object = (COSObjectable)value;
+
+ map.setItem( COSName.getPDFName( (String)key ), object.getCOSObject() );
+ return actuals.put( key, value );
+ }
+
+ /**
+ * @see java.util.Map#remove()
+ */
+ public Object remove(Object key)
+ {
+ map.removeItem( COSName.getPDFName( (String)key ) );
+ return actuals.remove( key );
+ }
+
+ /**
+ * @see java.util.Map#putAll()
+ */
+ public void putAll(Map t)
+ {
+ throw new RuntimeException( "Not yet implemented" );
+ }
+
+ /**
+ * @see java.util.Map#clear()
+ */
+ public void clear()
+ {
+ map.clear();
+ actuals.clear();
+ }
+
+ /**
+ * @see java.util.Map#keySet()
+ */
+ public Set keySet()
+ {
+ return actuals.keySet();
+ }
+
+ /**
+ * @see java.util.Map#values()
+ */
+ public Collection values()
+ {
+ return actuals.values();
+ }
+
+ /**
+ * @see java.util.Map#entrySet()
+ */
+ public Set entrySet()
+ {
+ throw new RuntimeException( "Not yet implemented" );
+ }
+
+ /**
+ * @see java.util.Map#equals()
+ */
+ public boolean equals(Object o)
+ {
+ boolean retval = false;
+ if( o instanceof COSDictionaryMap )
+ {
+ COSDictionaryMap other = (COSDictionaryMap)o;
+ retval = other.map.equals( this.map );
+ }
+ return retval;
+ }
+
+ /**
+ * This will get a string representation of this map.
+ *
+ * @return A human readable form of this map.
+ */
+ public String toString()
+ {
+ return actuals.toString();
+ }
+
+ /**
+ * @see java.util.Map#hashCode()
+ */
+ public int hashCode()
+ {
+ return map.hashCode();
+ }
+
+ /**
+ * This will take a map&lt;java.lang.String,org.pdfbox.pdmodel.COSObjectable&gt;
+ * and convert it into a COSDictionary&lt;COSName,COSBase&gt;.
+ *
+ * @param someMap A map containing COSObjectables
+ *
+ * @return A proper COSDictionary
+ */
+ public static COSDictionary convert( Map someMap )
+ {
+ Iterator iter = someMap.keySet().iterator();
+ COSDictionary dic = new COSDictionary();
+ while( iter.hasNext() )
+ {
+ String name = (String)iter.next();
+ COSObjectable object = (COSObjectable)someMap.get( name );
+ dic.setItem( COSName.getPDFName( name ), object.getCOSObject() );
+ }
+ return dic;
+ }
+
+ /**
+ * This will take a COS dictionary and convert it into COSDictionaryMap. All cos
+ * objects will be converted to their primitive form.
+ *
+ * @param map The COS mappings.
+ * @return A standard java map.
+ * @throws IOException If there is an error during the conversion.
+ */
+ public static COSDictionaryMap convertBasicTypesToMap( COSDictionary map ) throws IOException
+ {
+ COSDictionaryMap retval = null;
+ if( map != null )
+ {
+ Map actualMap = new HashMap();
+ Iterator keyIter = map.keyList().iterator();
+ while( keyIter.hasNext() )
+ {
+ COSName key = (COSName)keyIter.next();
+ COSBase cosObj = map.getDictionaryObject( key );
+ Object actualObject = null;
+ if( cosObj instanceof COSString )
+ {
+ actualObject = ((COSString)cosObj).getString();
+ }
+ else if( cosObj instanceof COSInteger )
+ {
+ actualObject = new Integer( ((COSInteger)cosObj).intValue() );
+ }
+ else if( cosObj instanceof COSName )
+ {
+ actualObject = ((COSName)cosObj).getName();
+ }
+ else if( cosObj instanceof COSFloat )
+ {
+ actualObject = new Float( ((COSInteger)cosObj).floatValue() );
+ }
+ else if( cosObj instanceof COSBoolean )
+ {
+ actualObject = ((COSBoolean)cosObj).getValue() ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else
+ {
+ throw new IOException( "Error:unknown type of object to convert:" + cosObj );
+ }
+ actualMap.put( key.getName(), actualObject );
+ }
+ retval = new COSDictionaryMap( actualMap, map );
+ }
+
+ return retval;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/COSObjectable.java b/src/main/java/org/pdfbox/pdmodel/common/COSObjectable.java
new file mode 100644
index 0000000..5bf7bfc
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/COSObjectable.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2003, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import org.pdfbox.cos.COSBase;
+
+/**
+ * This is an interface used to get/create the underlying COSObject.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.2 $
+ */
+public interface COSObjectable
+{
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject();
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/COSStreamArray.java b/src/main/java/org/pdfbox/pdmodel/common/COSStreamArray.java
new file mode 100644
index 0000000..87dbb6a
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/COSStreamArray.java
@@ -0,0 +1,304 @@
+/**
+ * Copyright (c) 2003-2004, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.io.SequenceInputStream;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+import org.pdfbox.cos.COSArray;
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSDictionary;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.cos.COSStream;
+import org.pdfbox.cos.ICOSVisitor;
+
+import org.pdfbox.exceptions.COSVisitorException;
+
+import org.pdfbox.pdfparser.PDFStreamParser;
+
+/**
+ * This will take an array of streams and sequence them together.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.7 $
+ */
+public class COSStreamArray extends COSStream
+{
+ private COSArray streams;
+
+ /**
+ * The first stream will be used to delegate some of the methods for this
+ * class.
+ */
+ private COSStream firstStream;
+
+ /**
+ * Constructor.
+ *
+ * @param array The array of COSStreams to concatenate together.
+ */
+ public COSStreamArray( COSArray array )
+ {
+ super( new COSDictionary(), null );
+ streams = array;
+ if( array.size() > 0 )
+ {
+ firstStream = (COSStream)array.getObject( 0 );
+ }
+ }
+ /**
+ * This will get the scratch file associated with this stream.
+ *
+ * @return The scratch file where this stream is being stored.
+ */
+ public RandomAccessFile getScratchFile()
+ {
+ return firstStream.getScratchFile();
+ }
+
+ /**
+ * This will get an object from this streams dictionary.
+ *
+ * @param key The key to the object.
+ *
+ * @return The dictionary object with the key or null if one does not exist.
+ */
+ public COSBase getItem( COSName key )
+ {
+ return firstStream.getItem( key );
+ }
+
+ /**
+ * This will get an object from this streams dictionary and dereference it
+ * if necessary.
+ *
+ * @param key The key to the object.
+ *
+ * @return The dictionary object with the key or null if one does not exist.
+ */
+ public COSBase getDictionaryObject( COSName key )
+ {
+ return firstStream.getDictionaryObject( key );
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ public String toString()
+ {
+ String result = "COSStream{}";
+ return result;
+ }
+
+ /**
+ * This will get all the tokens in the stream.
+ *
+ * @return All of the tokens in the stream.
+ *
+ * @throws IOException If there is an error parsing the stream.
+ */
+ public List getStreamTokens() throws IOException
+ {
+ List retval = null;
+ if( streams.size() > 0 )
+ {
+ PDFStreamParser parser = new PDFStreamParser( this );
+ parser.parse();
+ retval = parser.getTokens();
+ }
+ else
+ {
+ retval = new ArrayList();
+ }
+ return retval;
+ }
+
+ /**
+ * This will get the dictionary that is associated with this stream.
+ *
+ * @return the object that is associated with this stream.
+ */
+ public COSDictionary getDictionary()
+ {
+ return firstStream;
+ }
+
+ /**
+ * This will get the stream with all of the filters applied.
+ *
+ * @return the bytes of the physical (endoced) stream
+ *
+ * @throws IOException when encoding/decoding causes an exception
+ */
+ public InputStream getFilteredStream() throws IOException
+ {
+ throw new IOException( "Error: Not allowed to get filtered stream from array of streams." );
+ /**
+ Vector inputStreams = new Vector();
+ byte[] inbetweenStreamBytes = "\n".getBytes();
+
+ for( int i=0;i<streams.size(); i++ )
+ {
+ COSStream stream = (COSStream)streams.getObject( i );
+ }
+
+ return new SequenceInputStream( inputStreams.elements() );
+ **/
+ }
+
+ /**
+ * This will get the logical content stream with none of the filters.
+ *
+ * @return the bytes of the logical (decoded) stream
+ *
+ * @throws IOException when encoding/decoding causes an exception
+ */
+ public InputStream getUnfilteredStream() throws IOException
+ {
+ Vector inputStreams = new Vector();
+ byte[] inbetweenStreamBytes = "\n".getBytes();
+
+ for( int i=0;i<streams.size(); i++ )
+ {
+ COSStream stream = (COSStream)streams.getObject( i );
+ inputStreams.add( stream.getUnfilteredStream() );
+ //handle the case where there is no whitespace in the
+ //between streams in the contents array, without this
+ //it is possible that two operators will get concatenated
+ //together
+ inputStreams.add( new ByteArrayInputStream( inbetweenStreamBytes ) );
+ }
+
+ return new SequenceInputStream( inputStreams.elements() );
+ }
+
+ /**
+ * visitor pattern double dispatch method.
+ *
+ * @param visitor The object to notify when visiting this object.
+ * @return any object, depending on the visitor implementation, or null
+ * @throws COSVisitorException If an error occurs while visiting this object.
+ */
+ public Object accept(ICOSVisitor visitor) throws COSVisitorException
+ {
+ return streams.accept( visitor );
+ }
+
+
+ /**
+ * This will return the filters to apply to the byte stream
+ * the method will return.
+ * - null if no filters are to be applied
+ * - a COSName if one filter is to be applied
+ * - a COSArray containing COSNames if multiple filters are to be applied
+ *
+ * @return the COSBase object representing the filters
+ */
+ public COSBase getFilters()
+ {
+ return firstStream.getFilters();
+ }
+
+ /**
+ * This will create a new stream for which filtered byte should be
+ * written to. You probably don't want this but want to use the
+ * createUnfilteredStream, which is used to write raw bytes to.
+ *
+ * @return A stream that can be written to.
+ *
+ * @throws IOException If there is an error creating the stream.
+ */
+ public OutputStream createFilteredStream() throws IOException
+ {
+ return firstStream.createFilteredStream();
+ }
+
+ /**
+ * This will create a new stream for which filtered byte should be
+ * written to. You probably don't want this but want to use the
+ * createUnfilteredStream, which is used to write raw bytes to.
+ *
+ * @param expectedLength An entry where a length is expected.
+ *
+ * @return A stream that can be written to.
+ *
+ * @throws IOException If there is an error creating the stream.
+ */
+ public OutputStream createFilteredStream( COSBase expectedLength ) throws IOException
+ {
+ return firstStream.createFilteredStream( expectedLength );
+ }
+
+ /**
+ * set the filters to be applied to the stream.
+ *
+ * @param filters The filters to set on this stream.
+ *
+ * @throws IOException If there is an error clearing the old filters.
+ */
+ public void setFilters(COSBase filters) throws IOException
+ {
+ //should this be allowed? Should this
+ //propagate to all streams in the array?
+ firstStream.setFilters( filters );
+ }
+
+ /**
+ * This will create an output stream that can be written to.
+ *
+ * @return An output stream which raw data bytes should be written to.
+ *
+ * @throws IOException If there is an error creating the stream.
+ */
+ public OutputStream createUnfilteredStream() throws IOException
+ {
+ return firstStream.createUnfilteredStream();
+ }
+
+ /**
+ * Appends a new stream to the array that represents this object's stream.
+ *
+ * @param streamToAppend The stream to append.
+ */
+ public void appendStream(COSStream streamToAppend)
+ {
+ streams.add(streamToAppend);
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/DualCOSObjectable.java b/src/main/java/org/pdfbox/pdmodel/common/DualCOSObjectable.java
new file mode 100644
index 0000000..9c70d15
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/DualCOSObjectable.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2003, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import org.pdfbox.cos.COSBase;
+
+/**
+ * This is an interface to represent a PDModel object that holds two COS objects.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.1 $
+ */
+public interface DualCOSObjectable
+{
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getFirstCOSObject();
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getSecondCOSObject();
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDMatrix.java b/src/main/java/org/pdfbox/pdmodel/common/PDMatrix.java
new file mode 100644
index 0000000..ffee9e8
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/PDMatrix.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright (c) 2004, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import org.pdfbox.cos.COSArray;
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSFloat;
+import org.pdfbox.cos.COSNumber;
+
+/**
+ * This class will be used for matrix manipulation.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.2 $
+ */
+public class PDMatrix implements Cloneable, COSObjectable
+{
+ private COSArray matrix;
+
+ /**
+ * Constructor.
+ */
+ public PDMatrix()
+ {
+ matrix = new COSArray();
+ matrix.add( new COSFloat( 1.0f ) );
+ matrix.add( new COSFloat( 0.0f ) );
+ matrix.add( new COSFloat( 0.0f ) );
+ matrix.add( new COSFloat( 0.0f ) );
+ matrix.add( new COSFloat( 1.0f ) );
+ matrix.add( new COSFloat( 0.0f ) );
+ matrix.add( new COSFloat( 0.0f ) );
+ matrix.add( new COSFloat( 0.0f ) );
+ matrix.add( new COSFloat( 1.0f ) );
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param array The array that describes the matrix.
+ */
+ public PDMatrix( COSArray array )
+ {
+ matrix = array;
+ }
+
+ /**
+ * This will get the underlying array value.
+ *
+ * @return The cos object that this object wraps.
+ */
+ public COSArray getCOSArray()
+ {
+ return matrix;
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject()
+ {
+ return matrix;
+ }
+
+
+ /**
+ * This will get a matrix value at some point.
+ *
+ * @param row The row to get the value from.
+ * @param column The column to get the value from.
+ *
+ * @return The value at the row/column position.
+ */
+ public float getValue( int row, int column )
+ {
+ return ((COSNumber)matrix.get( row*3 + column )).floatValue();
+ }
+
+ /**
+ * This will set a value at a position.
+ *
+ * @param row The row to set the value at.
+ * @param column the column to set the value at.
+ * @param value The value to set at the position.
+ */
+ public void setValue( int row, int column, float value )
+ {
+ matrix.set( row*3+column, new COSFloat( value ) );
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDMemoryStream.java b/src/main/java/org/pdfbox/pdmodel/common/PDMemoryStream.java
new file mode 100644
index 0000000..61cbfbf
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/PDMemoryStream.java
@@ -0,0 +1,284 @@
+/**
+ * Copyright (c) 2005, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import java.util.List;
+
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSStream;
+
+import org.pdfbox.pdmodel.common.filespecification.PDFileSpecification;
+
+/**
+ * A PDStream represents a stream in a PDF document. Streams are tied to a single
+ * PDF document.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.1 $
+ */
+public class PDMemoryStream extends PDStream
+{
+ private byte[] data;
+
+ /**
+ * This will create a new PDStream object.
+ *
+ * @param buffer The data for this in memory stream.
+ */
+ public PDMemoryStream( byte[] buffer )
+ {
+ data = buffer;
+ }
+
+
+
+ /**
+ * If there are not compression filters on the current stream then this
+ * will add a compression filter, flate compression for example.
+ */
+ public void addCompression()
+ {
+ //no compression to add
+ }
+
+
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject()
+ {
+ throw new UnsupportedOperationException( "not supported for memory stream" );
+ }
+
+ /**
+ * This will get a stream that can be written to.
+ *
+ * @return An output stream to write data to.
+ *
+ * @throws IOException If an IO error occurs during writing.
+ */
+ public OutputStream createOutputStream() throws IOException
+ {
+ throw new UnsupportedOperationException( "not supported for memory stream" );
+ }
+
+ /**
+ * This will get a stream that can be read from.
+ *
+ * @return An input stream that can be read from.
+ *
+ * @throws IOException If an IO error occurs during reading.
+ */
+ public InputStream createInputStream() throws IOException
+ {
+ return new ByteArrayInputStream( data );
+ }
+
+ /**
+ * This will get a stream with some filters applied but not others. This is useful
+ * when doing images, ie filters = [flate,dct], we want to remove flate but leave dct
+ *
+ * @param stopFilters A list of filters to stop decoding at.
+ * @return A stream with decoded data.
+ * @throws IOException If there is an error processing the stream.
+ */
+ public InputStream getPartiallyFilteredStream( List stopFilters ) throws IOException
+ {
+ return createInputStream();
+ }
+
+ /**
+ * Get the cos stream associated with this object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSStream getStream()
+ {
+ throw new UnsupportedOperationException( "not supported for memory stream" );
+ }
+
+ /**
+ * This will get the length of the filtered/compressed stream. This is readonly in the
+ * PD Model and will be managed by this class.
+ *
+ * @return The length of the filtered stream.
+ */
+ public int getLength()
+ {
+ return data.length;
+ }
+
+ /**
+ * This will get the list of filters that are associated with this stream. Or
+ * null if there are none.
+ * @return A list of all encoding filters to apply to this stream.
+ */
+ public List getFilters()
+ {
+ return null;
+ }
+
+ /**
+ * This will set the filters that are part of this stream.
+ *
+ * @param filters The filters that are part of this stream.
+ */
+ public void setFilters( List filters )
+ {
+ throw new UnsupportedOperationException( "not supported for memory stream" );
+ }
+
+ /**
+ * Get the list of decode parameters. Each entry in the list will refer to
+ * an entry in the filters list.
+ *
+ * @return The list of decode parameters.
+ *
+ * @throws IOException if there is an error retrieving the parameters.
+ */
+ public List getDecodeParams() throws IOException
+ {
+ return null;
+ }
+
+ /**
+ * This will set the list of decode params.
+ *
+ * @param decodeParams The list of decode params.
+ */
+ public void setDecodeParams( List decodeParams )
+ {
+ //do nothing
+ }
+
+ /**
+ * This will get the file specification for this stream. This is only
+ * required for external files.
+ *
+ * @return The file specification.
+ */
+ public PDFileSpecification getFile()
+ {
+ return null;
+ }
+
+ /**
+ * Set the file specification.
+ * @param f The file specification.
+ */
+ public void setFile( PDFileSpecification f )
+ {
+ //do nothing.
+ }
+
+ /**
+ * This will get the list of filters that are associated with this stream. Or
+ * null if there are none.
+ * @return A list of all encoding filters to apply to this stream.
+ */
+ public List getFileFilters()
+ {
+ return null;
+ }
+
+ /**
+ * This will set the filters that are part of this stream.
+ *
+ * @param filters The filters that are part of this stream.
+ */
+ public void setFileFilters( List filters )
+ {
+ //do nothing.
+ }
+
+ /**
+ * Get the list of decode parameters. Each entry in the list will refer to
+ * an entry in the filters list.
+ *
+ * @return The list of decode parameters.
+ *
+ * @throws IOException if there is an error retrieving the parameters.
+ */
+ public List getFileDecodeParams() throws IOException
+ {
+ return null;
+ }
+
+ /**
+ * This will set the list of decode params.
+ *
+ * @param decodeParams The list of decode params.
+ */
+ public void setFileDecodeParams( List decodeParams )
+ {
+ //do nothing
+ }
+
+ /**
+ * This will copy the stream into a byte array.
+ *
+ * @return The byte array of the filteredStream
+ * @throws IOException When getFilteredStream did not work
+ */
+ public byte[] getByteArray() throws IOException
+ {
+ return data;
+ }
+
+ /**
+ * Get the metadata that is part of the document catalog. This will
+ * return null if there is no meta data for this object.
+ *
+ * @return The metadata for this object.
+ */
+ public PDMetadata getMetadata()
+ {
+ return null;
+ }
+
+ /**
+ * Set the metadata for this object. This can be null.
+ *
+ * @param meta The meta data for this object.
+ */
+ public void setMetadata( PDMetadata meta )
+ {
+ //do nothing
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDMetadata.java b/src/main/java/org/pdfbox/pdmodel/common/PDMetadata.java
new file mode 100644
index 0000000..77be580
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/PDMetadata.java
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2005, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.pdfbox.cos.COSStream;
+
+import org.pdfbox.pdmodel.PDDocument;
+
+/**
+ * This class represents metadata for various objects in a PDF document.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.1 $
+ */
+public class PDMetadata extends PDStream
+{
+
+ /**
+ * This will create a new PDMetadata object.
+ *
+ * @param document The document that the stream will be part of.
+ */
+ public PDMetadata( PDDocument document )
+ {
+ super( document );
+ getStream().setName( "Type", "Metadata" );
+ getStream().setName( "Subtype", "XML" );
+ }
+
+ /**
+ * Constructor. Reads all data from the input stream and embeds it into the
+ * document, this will close the InputStream.
+ *
+ * @param doc The document that will hold the stream.
+ * @param str The stream parameter.
+ * @param filtered True if the stream already has a filter applied.
+ * @throws IOException If there is an error creating the stream in the document.
+ */
+ public PDMetadata( PDDocument doc, InputStream str, boolean filtered ) throws IOException
+ {
+ super( doc, str, filtered );
+ getStream().setName( "Type", "Metadata" );
+ getStream().setName( "Subtype", "XML" );
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param str The stream parameter.
+ */
+ public PDMetadata( COSStream str )
+ {
+ super( str );
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDNameTreeNode.java b/src/main/java/org/pdfbox/pdmodel/common/PDNameTreeNode.java
new file mode 100644
index 0000000..4a79d10
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/PDNameTreeNode.java
@@ -0,0 +1,337 @@
+/**
+ * Copyright (c) 2004-2005, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.pdfbox.cos.COSArray;
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSDictionary;
+import org.pdfbox.cos.COSString;
+
+/**
+ * This class represends a PDF Name tree. See the PDF Reference 1.5 section 3.8.5
+ * for more details.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.3 $
+ */
+public class PDNameTreeNode implements COSObjectable
+{
+ private COSDictionary node;
+ private Class valueType = null;
+
+ /**
+ * Constructor.
+ *
+ * @param valueClass The PD Model type of object that is the value.
+ */
+ public PDNameTreeNode( Class valueClass )
+ {
+ node = new COSDictionary();
+ valueType = valueClass;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param dict The dictionary that holds the name information.
+ * @param valueClass The PD Model type of object that is the value.
+ */
+ public PDNameTreeNode( COSDictionary dict, Class valueClass )
+ {
+ node = dict;
+ valueType = valueClass;
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject()
+ {
+ return node;
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSDictionary getCOSDictionary()
+ {
+ return node;
+ }
+
+ /**
+ * Return the children of this node. This list will contain PDNameTreeNode objects.
+ *
+ * @return The list of children or null if there are no children.
+ */
+ public List getKids()
+ {
+
+ List retval = null;
+ COSArray kids = (COSArray)node.getDictionaryObject( "Kids" );
+ if( kids != null )
+ {
+ List pdObjects = new ArrayList();
+ for( int i=0; i<kids.size(); i++ )
+ {
+ pdObjects.add( createChildNode( (COSDictionary)kids.getObject(i) ) );
+ }
+ retval = new COSArrayList(pdObjects,kids);
+ }
+
+ return retval;
+ }
+
+ /**
+ * Set the children of this named tree.
+ *
+ * @param kids The children of this named tree.
+ */
+ public void setKids( List kids )
+ {
+ node.setItem( "Kids", COSArrayList.converterToCOSArray( kids ) );
+ }
+
+ /**
+ * The name to retrieve.
+ *
+ * @param name The name in the tree.
+ *
+ * @return The value of the name in the tree.
+ *
+ * @throws IOException If an there is a problem creating the destinations.
+ */
+ public Object getValue( String name ) throws IOException
+ {
+ Object retval = null;
+ Map names = getNames();
+ if( names != null )
+ {
+ retval = names.get( name );
+ }
+ else
+ {
+ List kids = getKids();
+ for( int i=0; i<kids.size() && retval == null; i++ )
+ {
+ PDNameTreeNode childNode = (PDNameTreeNode)kids.get( i );
+ if( childNode.getLowerLimit().compareTo( name ) <= 0 &&
+ childNode.getUpperLimit().compareTo( name ) >= 0 )
+ {
+ retval = childNode.getValue( name );
+ }
+ }
+ }
+ return retval;
+ }
+
+
+ /**
+ * This will return a map of names. The key will be a java.lang.String the value will
+ * depend on where this class is being used.
+ *
+ * @return A map of cos objects.
+ *
+ * @throws IOException If there is an error while creating the sub types.
+ */
+ public Map getNames() throws IOException
+ {
+ Map names = null;
+ COSArray namesArray = (COSArray)node.getDictionaryObject( "Names" );
+ if( namesArray != null )
+ {
+ names = new HashMap();
+ for( int i=0; i<namesArray.size(); i+=2 )
+ {
+ COSString key = (COSString)namesArray.getObject(i);
+ COSBase cosValue = namesArray.getObject( i+1 );
+ Object pdValue = convertCOSToPD( cosValue );
+
+ names.put( key.getString(), pdValue );
+ }
+ names = Collections.unmodifiableMap(names);
+ }
+
+ return names;
+ }
+
+ /**
+ * Method to convert the COS value in the name tree to the PD Model object. The
+ * default implementation will simply use reflection to create the correct object
+ * type. Subclasses can do whatever they want.
+ *
+ * @param base The COS object to convert.
+ * @return The converted PD Model object.
+ * @throws IOException If there is an error during creation.
+ */
+ protected Object convertCOSToPD( COSBase base ) throws IOException
+ {
+ Object retval = null;
+ try
+ {
+ Constructor ctor = valueType.getConstructor( new Class[] { base.getClass() } );
+ retval = ctor.newInstance( new Object[] { base } );
+ }
+ catch( Throwable t )
+ {
+ throw new IOException( "Error while trying to create value in named tree:" + t.getMessage());
+
+ }
+ return retval;
+ }
+
+ /**
+ * Create a child node object.
+ *
+ * @param dic The dictionary for the child node object to refer to.
+ * @return The new child node object.
+ */
+ protected PDNameTreeNode createChildNode( COSDictionary dic )
+ {
+ return new PDNameTreeNode(dic,valueType);
+ }
+
+ /**
+ * Set the names of for this node. The keys should be java.lang.String and the
+ * values must be a COSObjectable. This method will set the appropriate upper and lower
+ * limits based on the keys in the map.
+ *
+ * @param names The map of names to objects.
+ */
+ public void setNames( Map names )
+ {
+ if( names == null )
+ {
+ node.setItem( "Names", (COSObjectable)null );
+ node.setItem( "Limits", (COSObjectable)null);
+ }
+ else
+ {
+ List keys = new ArrayList( names.keySet() );
+ Collections.sort( keys );
+ COSArray array = new COSArray();
+ for( int i=0; i<keys.size(); i++ )
+ {
+ String key = (String)keys.get(i);
+ array.add( new COSString( key ) );
+ COSObjectable obj = (COSObjectable)names.get( key );
+ array.add( obj );
+ }
+ String lower = null;
+ String upper = null;
+ if( keys.size() > 0 )
+ {
+ lower = (String)keys.get( 0 );
+ upper = (String)keys.get( keys.size()-1 );
+ }
+ setUpperLimit( upper );
+ setLowerLimit( lower );
+ node.setItem( "Names", array );
+ }
+ }
+
+ /**
+ * Get the highest value for a key in the name map.
+ *
+ * @return The highest value for a key in the map.
+ */
+ public String getUpperLimit()
+ {
+ String retval = null;
+ COSArray arr = (COSArray)node.getDictionaryObject( "Limits" );
+ if( arr != null )
+ {
+ retval = arr.getString( 1 );
+ }
+ return retval;
+ }
+
+ /**
+ * Set the highest value for the key in the map.
+ *
+ * @param upper The new highest value for a key in the map.
+ */
+ private void setUpperLimit( String upper )
+ {
+ COSArray arr = (COSArray)node.getDictionaryObject( "Limits" );
+ if( arr == null )
+ {
+ arr = new COSArray();
+ arr.add( null );
+ arr.add( null );
+ }
+ arr.setString( 1, upper );
+ }
+
+ /**
+ * Get the lowest value for a key in the name map.
+ *
+ * @return The lowest value for a key in the map.
+ */
+ public String getLowerLimit()
+ {
+ String retval = null;
+ COSArray arr = (COSArray)node.getDictionaryObject( "Limits" );
+ if( arr != null )
+ {
+ retval = arr.getString( 0 );
+ }
+ return retval;
+ }
+
+ /**
+ * Set the lowest value for the key in the map.
+ *
+ * @param lower The new lowest value for a key in the map.
+ */
+ private void setLowerLimit( String lower )
+ {
+ COSArray arr = (COSArray)node.getDictionaryObject( "Limits" );
+ if( arr == null )
+ {
+ arr = new COSArray();
+ arr.add( null );
+ arr.add( null );
+ }
+ arr.setString( 0, lower );
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDNamedTextStream.java b/src/main/java/org/pdfbox/pdmodel/common/PDNamedTextStream.java
new file mode 100644
index 0000000..2321683
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/PDNamedTextStream.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright (c) 2004, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSName;
+
+/**
+ * A named text stream is a combination of a name and a PDTextStream object. This
+ * is used in name trees.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.2 $
+ */
+public class PDNamedTextStream implements DualCOSObjectable
+{
+ private COSName streamName;
+ private PDTextStream stream;
+
+ /**
+ * Constructor.
+ */
+ public PDNamedTextStream()
+ {
+ //default constructor
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the stream.
+ * @param str The stream.
+ */
+ public PDNamedTextStream( COSName name, COSBase str )
+ {
+ streamName = name;
+ stream = PDTextStream.createTextStream( str );
+ }
+
+ /**
+ * The name of the named text stream.
+ *
+ * @return The stream name.
+ */
+ public String getName()
+ {
+ String name = null;
+ if( streamName != null )
+ {
+ name = streamName.getName();
+ }
+ return name;
+ }
+
+ /**
+ * This will set the name of the named text stream.
+ *
+ * @param name The name of the named text stream.
+ */
+ public void setName( String name )
+ {
+ streamName = COSName.getPDFName( name );
+ }
+
+ /**
+ * This will get the stream.
+ *
+ * @return The stream associated with this name.
+ */
+ public PDTextStream getStream()
+ {
+ return stream;
+ }
+
+ /**
+ * This will set the stream.
+ *
+ * @param str The stream associated with this name.
+ */
+ public void setStream( PDTextStream str )
+ {
+ stream = str;
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getFirstCOSObject()
+ {
+ return streamName;
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getSecondCOSObject()
+ {
+ COSBase retval = null;
+ if( stream != null )
+ {
+ retval = stream.getCOSObject();
+ }
+ return retval;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDObjectStream.java b/src/main/java/org/pdfbox/pdmodel/common/PDObjectStream.java
new file mode 100644
index 0000000..3d31c1a
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/PDObjectStream.java
@@ -0,0 +1,151 @@
+/**
+ * Copyright (c) 2004-2005, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import org.pdfbox.cos.COSStream;
+
+import org.pdfbox.pdmodel.PDDocument;
+
+
+
+/**
+ * A PDStream represents a stream in a PDF document. Streams are tied to a single
+ * PDF document.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.2 $
+ */
+public class PDObjectStream extends PDStream
+{
+
+ /**
+ * Constructor.
+ *
+ * @param str The stream parameter.
+ */
+ public PDObjectStream( COSStream str )
+ {
+ super( str );
+ }
+
+ /**
+ * This will create a new PDStream object.
+ *
+ * @param document The document that the stream will be part of.
+ * @return A new stream object.
+ */
+ public static PDObjectStream createStream( PDDocument document )
+ {
+ COSStream cosStream = new COSStream( document.getDocument().getScratchFile() );
+ PDObjectStream strm = new PDObjectStream( cosStream );
+ strm.getStream().setName( "Type", "ObjStm" );
+ return strm;
+ }
+
+ /**
+ * Get the type of this object, should always return "ObjStm".
+ *
+ * @return The type of this object.
+ */
+ public String getType()
+ {
+ return getStream().getNameAsString( "Type" );
+ }
+
+ /**
+ * Get the number of compressed object.
+ *
+ * @return The number of compressed objects.
+ */
+ public int getNumberOfObjects()
+ {
+ return getStream().getInt( "N", 0 );
+ }
+
+ /**
+ * Set the number of objects.
+ *
+ * @param n The new number of objects.
+ */
+ public void setNumberOfObjects( int n )
+ {
+ getStream().setInt( "N", n );
+ }
+
+ /**
+ * The byte offset (in the decoded stream) of the first compressed object.
+ *
+ * @return The byte offset to the first object.
+ */
+ public int getFirstByteOffset()
+ {
+ return getStream().getInt( "First", 0 );
+ }
+
+ /**
+ * The byte offset (in the decoded stream) of the first compressed object.
+ *
+ * @param n The byte offset to the first object.
+ */
+ public void setFirstByteOffset( int n )
+ {
+ getStream().setInt( "First", n );
+ }
+
+ /**
+ * A reference to an object stream, of which the current object stream is
+ * considered an extension.
+ *
+ * @return The object that this stream is an extension.
+ */
+ public PDObjectStream getExtends()
+ {
+ PDObjectStream retval = null;
+ COSStream stream = (COSStream)getStream().getDictionaryObject( "Extends" );
+ if( stream != null )
+ {
+ retval = new PDObjectStream( stream );
+ }
+ return retval;
+
+ }
+
+ /**
+ * A reference to an object stream, of which the current object stream is
+ * considered an extension.
+ *
+ * @param stream The object stream extension.
+ */
+ public void setExtends( PDObjectStream stream )
+ {
+ getStream().setItem( "Extends", stream );
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDRange.java b/src/main/java/org/pdfbox/pdmodel/common/PDRange.java
new file mode 100644
index 0000000..2493d87
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/PDRange.java
@@ -0,0 +1,146 @@
+/**
+ * Copyright (c) 2004, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import org.pdfbox.cos.COSArray;
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSFloat;
+import org.pdfbox.cos.COSNumber;
+
+/**
+ * This class will be used to signify a range. a(min) <= a* <= a(max)
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.2 $
+ */
+public class PDRange implements COSObjectable
+{
+ private COSArray rangeArray;
+ private int startingIndex;
+
+ /**
+ * Constructor with an initial range of 0..1.
+ */
+ public PDRange()
+ {
+ rangeArray = new COSArray();
+ rangeArray.add( new COSFloat( 0.0f ) );
+ rangeArray.add( new COSFloat( 1.0f ) );
+ startingIndex = 0;
+ }
+
+ /**
+ * Constructor assumes a starting index of 0.
+ *
+ * @param range The array that describes the range.
+ */
+ public PDRange( COSArray range )
+ {
+ rangeArray = range;
+ }
+
+ /**
+ * Constructor with an index into an array. Because some arrays specify
+ * multiple ranges ie [ 0,1, 0,2, 2,3 ] It is convenient for this
+ * class to take an index into an array. So if you want this range to
+ * represent 0,2 in the above example then you would say <code>new PDRange( array, 2 )</code>.
+ *
+ * @param range The array that describes the index
+ * @param index The index into the array for the start of the range.
+ */
+ public PDRange( COSArray range, int index )
+ {
+ rangeArray = range;
+ startingIndex = index;
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject()
+ {
+ return rangeArray;
+ }
+
+ /**
+ * This will get the underlying array value.
+ *
+ * @return The cos object that this object wraps.
+ */
+ public COSArray getCOSArray()
+ {
+ return rangeArray;
+ }
+
+ /**
+ * This will get the minimum value of the range.
+ *
+ * @return The min value.
+ */
+ public float getMin()
+ {
+ COSNumber min = (COSNumber)rangeArray.getObject( startingIndex );
+ return min.floatValue();
+ }
+
+ /**
+ * This will set the minimum value for the range.
+ *
+ * @param min The new minimum for the range.
+ */
+ public void setMin( float min )
+ {
+ rangeArray.set( startingIndex, new COSFloat( min ) );
+ }
+
+ /**
+ * This will get the maximum value of the range.
+ *
+ * @return The max value.
+ */
+ public float getMax()
+ {
+ COSNumber max = (COSNumber)rangeArray.getObject( startingIndex+1 );
+ return max.floatValue();
+ }
+
+ /**
+ * This will set the maximum value for the range.
+ *
+ * @param max The new maximum for the range.
+ */
+ public void setMax( float max )
+ {
+ rangeArray.set( startingIndex+1, new COSFloat( max ) );
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDRectangle.java b/src/main/java/org/pdfbox/pdmodel/common/PDRectangle.java
new file mode 100644
index 0000000..b9f3267
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/PDRectangle.java
@@ -0,0 +1,295 @@
+/**
+ * Copyright (c) 2003-2005, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import org.pdfbox.cos.COSArray;
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSFloat;
+import org.pdfbox.cos.COSNumber;
+
+import org.pdfbox.util.BoundingBox;
+
+import java.awt.Dimension;
+
+/**
+ * This represents a rectangle in a PDF document.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.10 $
+ */
+public class PDRectangle implements COSObjectable
+{
+ private COSArray rectArray;
+
+ /**
+ * Constructor.
+ *
+ * Initializes to 0,0,0,0
+ */
+ public PDRectangle()
+ {
+ rectArray = new COSArray();
+ rectArray.add( new COSFloat( 0.0f ) );
+ rectArray.add( new COSFloat( 0.0f ) );
+ rectArray.add( new COSFloat( 0.0f ) );
+ rectArray.add( new COSFloat( 0.0f ) );
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param width The width of the rectangle.
+ * @param height The height of the rectangle.
+ */
+ public PDRectangle( float width, float height )
+ {
+ rectArray = new COSArray();
+ rectArray.add( new COSFloat( 0.0f ) );
+ rectArray.add( new COSFloat( 0.0f ) );
+ rectArray.add( new COSFloat( width ) );
+ rectArray.add( new COSFloat( height ) );
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param box The non PD bouding box.
+ */
+ public PDRectangle( BoundingBox box )
+ {
+ rectArray = new COSArray();
+ rectArray.add( new COSFloat( box.getLowerLeftX() ) );
+ rectArray.add( new COSFloat( box.getLowerLeftY() ) );
+ rectArray.add( new COSFloat( box.getUpperRightX() ) );
+ rectArray.add( new COSFloat( box.getUpperRightY() ) );
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param array An array of numbers as specified in the PDF Reference for a rectangle type.
+ */
+ public PDRectangle( COSArray array )
+ {
+ rectArray = array;
+ }
+
+ /**
+ * Method to determine if the x/y point is inside this rectangle.
+ * @param x The x-coordinate to test.
+ * @param y The y-coordinate to test.
+ * @return True if the point is inside this rectangle.
+ */
+ public boolean contains( float x, float y )
+ {
+ float llx = getLowerLeftX();
+ float urx = getUpperRightX();
+ float lly = getLowerLeftY();
+ float ury = getUpperRightY();
+ return x >= llx && x <= urx &&
+ y >= lly && y <= ury;
+ }
+
+ /**
+ * This will create a translated rectangle based off of this rectangle, such
+ * that the new rectangle retains the same dimensions(height/width), but the
+ * lower left x,y values are zero. <br />
+ * 100, 100, 400, 400 (llx, lly, urx, ury ) <br />
+ * will be translated to 0,0,300,300
+ *
+ * @return A new rectangle that has been translated back to the origin.
+ */
+ public PDRectangle createRetranslatedRectangle()
+ {
+ PDRectangle retval = new PDRectangle();
+ retval.setUpperRightX( getWidth() );
+ retval.setUpperRightY( getHeight() );
+ return retval;
+ }
+
+ /**
+ * This will get the underlying array for this rectangle.
+ *
+ * @return The cos array.
+ */
+ public COSArray getCOSArray()
+ {
+ return rectArray;
+ }
+
+ /**
+ * This will get the lower left x coordinate.
+ *
+ * @return The lower left x.
+ */
+ public float getLowerLeftX()
+ {
+ return ((COSNumber)rectArray.get(0)).floatValue();
+ }
+
+ /**
+ * This will set the lower left x coordinate.
+ *
+ * @param value The lower left x.
+ */
+ public void setLowerLeftX(float value)
+ {
+ rectArray.set(0, new COSFloat( value ) );
+ }
+
+ /**
+ * This will get the lower left y coordinate.
+ *
+ * @return The lower left y.
+ */
+ public float getLowerLeftY()
+ {
+ return ((COSNumber)rectArray.get(1)).floatValue();
+ }
+
+ /**
+ * This will set the lower left y coordinate.
+ *
+ * @param value The lower left y.
+ */
+ public void setLowerLeftY(float value)
+ {
+ rectArray.set(1, new COSFloat( value ) );
+ }
+
+ /**
+ * This will get the upper right x coordinate.
+ *
+ * @return The upper right x .
+ */
+ public float getUpperRightX()
+ {
+ return ((COSNumber)rectArray.get(2)).floatValue();
+ }
+
+ /**
+ * This will set the upper right x coordinate.
+ *
+ * @param value The upper right x .
+ */
+ public void setUpperRightX(float value)
+ {
+ rectArray.set(2, new COSFloat( value ) );
+ }
+
+ /**
+ * This will get the upper right y coordinate.
+ *
+ * @return The upper right y.
+ */
+ public float getUpperRightY()
+ {
+ return ((COSNumber)rectArray.get(3)).floatValue();
+ }
+
+ /**
+ * This will set the upper right y coordinate.
+ *
+ * @param value The upper right y.
+ */
+ public void setUpperRightY(float value)
+ {
+ rectArray.set(3, new COSFloat( value ) );
+ }
+
+ /**
+ * This will get the width of this rectangle as calculated by
+ * upperRightX - lowerLeftX.
+ *
+ * @return The width of this rectangle.
+ */
+ public float getWidth()
+ {
+ return getUpperRightX() - getLowerLeftX();
+ }
+
+ /**
+ * This will get the height of this rectangle as calculated by
+ * upperRightY - lowerLeftY.
+ *
+ * @return The height of this rectangle.
+ */
+ public float getHeight()
+ {
+ return getUpperRightY() - getLowerLeftY();
+ }
+
+ /**
+ * A convenience method to create a dimension object for AWT operations.
+ *
+ * @return A dimension that matches the width and height of this rectangle.
+ */
+ public Dimension createDimension()
+ {
+ return new Dimension( (int)getWidth(), (int)getHeight() );
+ }
+
+ /**
+ * This will move the rectangle the given relative amount.
+ *
+ * @param horizontalAmount positive values will move rectangle to the right, negative's to the left.
+ * @param verticalAmount positive values will move the rectangle up, negative's down.
+ */
+ public void move(float horizontalAmount, float verticalAmount)
+ {
+ setUpperRightX(getUpperRightX() + horizontalAmount);
+ setLowerLeftX(getLowerLeftX() + horizontalAmount);
+ setUpperRightY(getUpperRightY() + verticalAmount);
+ setLowerLeftY(getLowerLeftY() + verticalAmount);
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject()
+ {
+ return rectArray;
+ }
+
+
+ /**
+ * This will return a string representation of this rectangle.
+ *
+ * @return This object as a string.
+ */
+ public String toString()
+ {
+ return "[" + getLowerLeftX() + "," + getLowerLeftY() + "," +
+ getUpperRightX() + "," + getUpperRightY() +"]";
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDStream.java b/src/main/java/org/pdfbox/pdmodel/common/PDStream.java
new file mode 100644
index 0000000..74398b2
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/PDStream.java
@@ -0,0 +1,538 @@
+/**
+ * Copyright (c) 2004-2005, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.pdfbox.cos.COSArray;
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSDictionary;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.cos.COSStream;
+
+import org.pdfbox.filter.Filter;
+import org.pdfbox.filter.FilterManager;
+
+import org.pdfbox.pdmodel.PDDocument;
+
+import org.pdfbox.pdmodel.common.filespecification.PDFileSpecification;
+
+/**
+ * A PDStream represents a stream in a PDF document. Streams are tied to a single
+ * PDF document.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.14 $
+ */
+public class PDStream implements COSObjectable
+{
+ private COSStream stream;
+
+ /**
+ * This will create a new PDStream object.
+ */
+ protected PDStream()
+ {
+ //should only be called by PDMemoryStream
+ }
+
+ /**
+ * This will create a new PDStream object.
+ *
+ * @param document The document that the stream will be part of.
+ */
+ public PDStream( PDDocument document )
+ {
+ stream = new COSStream( document.getDocument().getScratchFile() );
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param str The stream parameter.
+ */
+ public PDStream( COSStream str )
+ {
+ stream = str;
+ }
+
+ /**
+ * Constructor. Reads all data from the input stream and embeds it into the
+ * document, this will close the InputStream.
+ *
+ * @param doc The document that will hold the stream.
+ * @param str The stream parameter.
+ * @throws IOException If there is an error creating the stream in the document.
+ */
+ public PDStream( PDDocument doc, InputStream str ) throws IOException
+ {
+ this( doc, str, false );
+ }
+
+ /**
+ * Constructor. Reads all data from the input stream and embeds it into the
+ * document, this will close the InputStream.
+ *
+ * @param doc The document that will hold the stream.
+ * @param str The stream parameter.
+ * @param filtered True if the stream already has a filter applied.
+ * @throws IOException If there is an error creating the stream in the document.
+ */
+ public PDStream( PDDocument doc, InputStream str, boolean filtered ) throws IOException
+ {
+ OutputStream output = null;
+ try
+ {
+ stream = new COSStream( doc.getDocument().getScratchFile() );
+ if( filtered )
+ {
+ output = stream.createFilteredStream();
+ }
+ else
+ {
+ output = stream.createUnfilteredStream();
+ }
+ byte[] buffer = new byte[ 1024 ];
+ int amountRead = -1;
+ while( (amountRead = str.read(buffer)) != -1 )
+ {
+ output.write( buffer, 0, amountRead );
+ }
+ }
+ finally
+ {
+ if( output != null )
+ {
+ output.close();
+ }
+ if( str != null )
+ {
+ str.close();
+ }
+ }
+ }
+
+ /**
+ * If there are not compression filters on the current stream then this
+ * will add a compression filter, flate compression for example.
+ */
+ public void addCompression()
+ {
+ List filters = getFilters();
+ if( filters == null )
+ {
+ filters = new ArrayList();
+ filters.add( COSName.FLATE_DECODE );
+ setFilters( filters );
+ }
+ }
+
+ /**
+ * Create a pd stream from either a regular COSStream on a COSArray of cos streams.
+ * @param base Either a COSStream or COSArray.
+ * @return A PDStream or null if base is null.
+ * @throws IOException If there is an error creating the PDStream.
+ */
+ public static PDStream createFromCOS( COSBase base ) throws IOException
+ {
+ PDStream retval = null;
+ if( base instanceof COSStream )
+ {
+ retval = new PDStream( (COSStream)base );
+ }
+ else if( base instanceof COSArray )
+ {
+ retval = new PDStream( new COSStreamArray( (COSArray)base ) );
+ }
+ else
+ {
+ if( base != null )
+ {
+ throw new IOException( "Contents are unknown type:" + base.getClass().getName() );
+ }
+ }
+ return retval;
+ }
+
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject()
+ {
+ return stream;
+ }
+
+ /**
+ * This will get a stream that can be written to.
+ *
+ * @return An output stream to write data to.
+ *
+ * @throws IOException If an IO error occurs during writing.
+ */
+ public OutputStream createOutputStream() throws IOException
+ {
+ return stream.createUnfilteredStream();
+ }
+
+ /**
+ * This will get a stream that can be read from.
+ *
+ * @return An input stream that can be read from.
+ *
+ * @throws IOException If an IO error occurs during reading.
+ */
+ public InputStream createInputStream() throws IOException
+ {
+ return stream.getUnfilteredStream();
+ }
+
+ /**
+ * This will get a stream with some filters applied but not others. This is useful
+ * when doing images, ie filters = [flate,dct], we want to remove flate but leave dct
+ *
+ * @param stopFilters A list of filters to stop decoding at.
+ * @return A stream with decoded data.
+ * @throws IOException If there is an error processing the stream.
+ */
+ public InputStream getPartiallyFilteredStream( List stopFilters ) throws IOException
+ {
+ FilterManager manager = stream.getFilterManager();
+ InputStream is = stream.getFilteredStream();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ List filters = getFilters();
+ Iterator iter = filters.iterator();
+ String nextFilter = null;
+ boolean done = false;
+ while( iter.hasNext() && !done )
+ {
+ os.reset();
+ nextFilter = (String)iter.next();
+ if( stopFilters.contains( nextFilter ) )
+ {
+ done = true;
+ }
+ else
+ {
+ Filter filter = manager.getFilter( COSName.getPDFName(nextFilter) );
+ filter.decode( is, os, stream );
+ is = new ByteArrayInputStream( os.toByteArray() );
+ }
+ }
+ return is;
+ }
+
+ /**
+ * Get the cos stream associated with this object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSStream getStream()
+ {
+ return stream;
+ }
+
+ /**
+ * This will get the length of the filtered/compressed stream. This is readonly in the
+ * PD Model and will be managed by this class.
+ *
+ * @return The length of the filtered stream.
+ */
+ public int getLength()
+ {
+ return stream.getInt( "Length", 0 );
+ }
+
+ /**
+ * This will get the list of filters that are associated with this stream. Or
+ * null if there are none.
+ * @return A list of all encoding filters to apply to this stream.
+ */
+ public List getFilters()
+ {
+ List retval = null;
+ COSBase filters = stream.getFilters();
+ if( filters instanceof COSName )
+ {
+ COSName name = (COSName)filters;
+ retval = new COSArrayList( name.getName(), name, stream, "Filter" );
+ }
+ else if( filters instanceof COSArray )
+ {
+ retval = COSArrayList.convertCOSNameCOSArrayToList( (COSArray)filters );
+ }
+ return retval;
+ }
+
+ /**
+ * This will set the filters that are part of this stream.
+ *
+ * @param filters The filters that are part of this stream.
+ */
+ public void setFilters( List filters )
+ {
+ COSBase obj = COSArrayList.convertStringListToCOSNameCOSArray( filters );
+ stream.setItem( "Filter", obj );
+ }
+
+ /**
+ * Get the list of decode parameters. Each entry in the list will refer to
+ * an entry in the filters list.
+ *
+ * @return The list of decode parameters.
+ *
+ * @throws IOException if there is an error retrieving the parameters.
+ */
+ public List getDecodeParams() throws IOException
+ {
+ List retval = null;
+
+ COSBase dp = stream.getDictionaryObject( "DecodeParms" );
+ if( dp == null )
+ {
+ //See PDF Ref 1.5 implementation note 7, the DP is sometimes used instead.
+ dp = stream.getDictionaryObject( "DP" );
+ }
+ if( dp instanceof COSDictionary )
+ {
+ Map map = COSDictionaryMap.convertBasicTypesToMap( (COSDictionary)dp );
+ retval = new COSArrayList(map, dp, stream, "DecodeParams" );
+ }
+ else if( dp instanceof COSArray )
+ {
+ COSArray array = (COSArray)dp;
+ List actuals = new ArrayList();
+ for( int i=0; i<array.size(); i++ )
+ {
+ actuals.add(
+ COSDictionaryMap.convertBasicTypesToMap(
+ (COSDictionary)array.getObject( i ) ) );
+ }
+ retval = new COSArrayList(actuals, array);
+ }
+
+ return retval;
+ }
+
+ /**
+ * This will set the list of decode params.
+ *
+ * @param decodeParams The list of decode params.
+ */
+ public void setDecodeParams( List decodeParams )
+ {
+ stream.setItem(
+ "DecodeParams", COSArrayList.converterToCOSArray( decodeParams ) );
+ }
+
+ /**
+ * This will get the file specification for this stream. This is only
+ * required for external files.
+ *
+ * @return The file specification.
+ */
+ public PDFileSpecification getFile()
+ {
+ COSBase f = stream.getDictionaryObject( "F" );
+ PDFileSpecification retval = PDFileSpecification.createFS( f );
+ return retval;
+ }
+
+ /**
+ * Set the file specification.
+ * @param f The file specification.
+ */
+ public void setFile( PDFileSpecification f )
+ {
+ stream.setItem( "F", f );
+ }
+
+ /**
+ * This will get the list of filters that are associated with this stream. Or
+ * null if there are none.
+ * @return A list of all encoding filters to apply to this stream.
+ */
+ public List getFileFilters()
+ {
+ List retval = null;
+ COSBase filters = stream.getDictionaryObject( "FFilter" );
+ if( filters instanceof COSName )
+ {
+ COSName name = (COSName)filters;
+ retval = new COSArrayList( name.getName(), name, stream, "FFilter" );
+ }
+ else if( filters instanceof COSArray )
+ {
+ retval = COSArrayList.convertCOSNameCOSArrayToList( (COSArray)filters );
+ }
+ return retval;
+ }
+
+ /**
+ * This will set the filters that are part of this stream.
+ *
+ * @param filters The filters that are part of this stream.
+ */
+ public void setFileFilters( List filters )
+ {
+ COSBase obj = COSArrayList.convertStringListToCOSNameCOSArray( filters );
+ stream.setItem( "FFilter", obj );
+ }
+
+ /**
+ * Get the list of decode parameters. Each entry in the list will refer to
+ * an entry in the filters list.
+ *
+ * @return The list of decode parameters.
+ *
+ * @throws IOException if there is an error retrieving the parameters.
+ */
+ public List getFileDecodeParams() throws IOException
+ {
+ List retval = null;
+
+ COSBase dp = stream.getDictionaryObject( "FDecodeParms" );
+ if( dp instanceof COSDictionary )
+ {
+ Map map = COSDictionaryMap.convertBasicTypesToMap( (COSDictionary)dp );
+ retval = new COSArrayList(map, dp, stream, "FDecodeParams" );
+ }
+ else if( dp instanceof COSArray )
+ {
+ COSArray array = (COSArray)dp;
+ List actuals = new ArrayList();
+ for( int i=0; i<array.size(); i++ )
+ {
+ actuals.add(
+ COSDictionaryMap.convertBasicTypesToMap(
+ (COSDictionary)array.getObject( i ) ) );
+ }
+ retval = new COSArrayList(actuals, array);
+ }
+
+ return retval;
+ }
+
+ /**
+ * This will set the list of decode params.
+ *
+ * @param decodeParams The list of decode params.
+ */
+ public void setFileDecodeParams( List decodeParams )
+ {
+ stream.setItem(
+ "FDecodeParams", COSArrayList.converterToCOSArray( decodeParams ) );
+ }
+
+ /**
+ * This will copy the stream into a byte array.
+ *
+ * @return The byte array of the filteredStream
+ * @throws IOException When getFilteredStream did not work
+ */
+ public byte[] getByteArray() throws IOException
+ {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ byte[] buf = new byte[1024];
+ InputStream is = null;
+ try
+ {
+ is = createInputStream();
+ int amountRead = -1;
+ while( (amountRead = is.read( buf )) != -1)
+ {
+ output.write( buf, 0, amountRead );
+ }
+ }
+ finally
+ {
+ if( is != null )
+ {
+ is.close();
+ }
+ }
+ return output.toByteArray();
+ }
+
+ /**
+ * A convenience method to get this stream as a string. Uses
+ * the default system encoding.
+ *
+ * @return a String representation of this (input) stream, with the
+ * platform default encoding.
+ *
+ * @throws IOException if there is an error while converting the stream
+ * to a string.
+ */
+ public String getInputStreamAsString() throws IOException
+ {
+ byte[] bStream = getByteArray();
+ return new String(bStream);
+ }
+
+ /**
+ * Get the metadata that is part of the document catalog. This will
+ * return null if there is no meta data for this object.
+ *
+ * @return The metadata for this object.
+ */
+ public PDMetadata getMetadata()
+ {
+ PDMetadata retval = null;
+ COSStream mdStream = (COSStream)stream.getDictionaryObject( "Metadata" );
+ if( mdStream != null )
+ {
+ retval = new PDMetadata( mdStream );
+ }
+ return retval;
+ }
+
+ /**
+ * Set the metadata for this object. This can be null.
+ *
+ * @param meta The meta data for this object.
+ */
+ public void setMetadata( PDMetadata meta )
+ {
+ stream.setItem( "Metadata", meta );
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDTextStream.java b/src/main/java/org/pdfbox/pdmodel/common/PDTextStream.java
new file mode 100644
index 0000000..c7c5ca1
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/PDTextStream.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright (c) 2004, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common;
+
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSStream;
+import org.pdfbox.cos.COSString;
+
+/**
+ * A PDTextStream class is used when the PDF specification supports either
+ * a string or a stream for the value of an object. This is usually when
+ * a value could be large or small, for example a JavaScript method. This
+ * class will help abstract that and give a single unified interface to
+ * those types of fields.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.2 $
+ */
+public class PDTextStream implements COSObjectable
+{
+ private COSString string;
+ private COSStream stream;
+
+ /**
+ * Constructor.
+ *
+ * @param str The string parameter.
+ */
+ public PDTextStream( COSString str )
+ {
+ string = str;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param str The string parameter.
+ */
+ public PDTextStream( String str )
+ {
+ string = new COSString( str );
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param str The stream parameter.
+ */
+ public PDTextStream( COSStream str )
+ {
+ stream = str;
+ }
+
+ /**
+ * This will create the text stream object. base must either be a string
+ * or a stream.
+ *
+ * @param base The COS text stream object.
+ *
+ * @return A PDTextStream that wraps the base object.
+ */
+ public static PDTextStream createTextStream( COSBase base )
+ {
+ PDTextStream retval = null;
+ if( base instanceof COSString )
+ {
+ retval = new PDTextStream( (COSString) base );
+ }
+ else if( base instanceof COSStream )
+ {
+ retval = new PDTextStream( (COSStream)base );
+ }
+ return retval;
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject()
+ {
+ COSBase retval = null;
+ if( string == null )
+ {
+ retval = stream;
+ }
+ else
+ {
+ retval = string;
+ }
+ return retval;
+ }
+
+ /**
+ * This will get this value as a string. If this is a stream then it
+ * will load the entire stream into memory, so you should only do this when
+ * the stream is a manageable size.
+ *
+ * @return This value as a string.
+ *
+ * @throws IOException If an IO error occurs while accessing the stream.
+ */
+ public String getAsString() throws IOException
+ {
+ String retval = null;
+ if( string != null )
+ {
+ retval = string.getString();
+ }
+ else
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] buffer = new byte[ 1024 ];
+ int amountRead = -1;
+ InputStream is = stream.getUnfilteredStream();
+ while( (amountRead = is.read( buffer ) ) != -1 )
+ {
+ out.write( buffer, 0, amountRead );
+ }
+ retval = new String( out.toByteArray() );
+ }
+ return retval;
+ }
+
+ /**
+ * This is the preferred way of getting data with this class as it uses
+ * a stream object.
+ *
+ * @return The stream object.
+ *
+ * @throws IOException If an IO error occurs while accessing the stream.
+ */
+ public InputStream getAsStream() throws IOException
+ {
+ InputStream retval = null;
+ if( string != null )
+ {
+ retval = new ByteArrayInputStream( string.getBytes() );
+ }
+ else
+ {
+ retval = stream.getUnfilteredStream();
+ }
+ return retval;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDComplexFileSpecification.java b/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDComplexFileSpecification.java
new file mode 100644
index 0000000..12618f1
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDComplexFileSpecification.java
@@ -0,0 +1,326 @@
+/**
+ * Copyright (c) 2004-2005, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common.filespecification;
+
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSDictionary;
+import org.pdfbox.cos.COSStream;
+
+/**
+ * This represents a file specification.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.3 $
+ */
+public class PDComplexFileSpecification extends PDFileSpecification
+{
+ private COSDictionary fs;
+
+ /**
+ * Default Constructor.
+ */
+ public PDComplexFileSpecification()
+ {
+ fs = new COSDictionary();
+ fs.setName( "Type", "Filespec" );
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param dict The dictionary that fulfils this file specification.
+ */
+ public PDComplexFileSpecification( COSDictionary dict )
+ {
+ fs = dict;
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject()
+ {
+ return fs;
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSDictionary getCOSDictionary()
+ {
+ return fs;
+ }
+
+ /**
+ * This will get the file name.
+ *
+ * @return The file name.
+ */
+ public String getFile()
+ {
+ return fs.getString( "F" );
+ }
+
+ /**
+ * This will set the file name.
+ *
+ * @param file The name of the file.
+ */
+ public void setFile( String file )
+ {
+ fs.setString( "F", file );
+ }
+
+ /**
+ * This will get the name representing a Dos file.
+ *
+ * @return The file name.
+ */
+ public String getFileDos()
+ {
+ return fs.getString( "DOS" );
+ }
+
+ /**
+ * This will set name representing a dos file.
+ *
+ * @param file The name of the file.
+ */
+ public void setFileDos( String file )
+ {
+ fs.setString( "DOS", file );
+ }
+
+ /**
+ * This will get the name representing a Mac file.
+ *
+ * @return The file name.
+ */
+ public String getFileMac()
+ {
+ return fs.getString( "Mac" );
+ }
+
+ /**
+ * This will set name representing a Mac file.
+ *
+ * @param file The name of the file.
+ */
+ public void setFileMac( String file )
+ {
+ fs.setString( "Mac", file );
+ }
+
+ /**
+ * This will get the name representing a Unix file.
+ *
+ * @return The file name.
+ */
+ public String getFileUnix()
+ {
+ return fs.getString( "Unix" );
+ }
+
+ /**
+ * This will set name representing a Unix file.
+ *
+ * @param file The name of the file.
+ */
+ public void setFileUnix( String file )
+ {
+ fs.setString( "Unix", file );
+ }
+
+ /**
+ * Tell if the underlying file is volatile and should not be cached by the
+ * reader application. Default: false
+ *
+ * @param fileIsVolatile The new value for the volatility of the file.
+ */
+ public void setVolatile( boolean fileIsVolatile )
+ {
+ fs.setBoolean( "V", fileIsVolatile );
+ }
+
+ /**
+ * Get if the file is volatile. Default: false
+ *
+ * @return True if the file is volatile attribute is set.
+ */
+ public boolean isVolatile()
+ {
+ return fs.getBoolean( "V", false );
+ }
+
+ /**
+ * Get the embedded file.
+ *
+ * @return The embedded file for this file spec.
+ */
+ public PDEmbeddedFile getEmbeddedFile()
+ {
+ PDEmbeddedFile file = null;
+ COSStream stream = (COSStream)fs.getObjectFromPath( "EF/F" );
+ if( stream != null )
+ {
+ file = new PDEmbeddedFile( stream );
+ }
+ return file;
+ }
+
+ /**
+ * Set the embedded file for this spec.
+ *
+ * @param file The file to be embedded.
+ */
+ public void setEmbeddedFile( PDEmbeddedFile file )
+ {
+ COSDictionary ef = (COSDictionary)fs.getDictionaryObject( "EF" );
+ if( ef == null && file != null )
+ {
+ ef = new COSDictionary();
+ fs.setItem( "EF", ef );
+ }
+ if( ef != null )
+ {
+ ef.setItem( "F", file );
+ }
+ }
+
+ /**
+ * Get the embedded dos file.
+ *
+ * @return The embedded file for this file spec.
+ */
+ public PDEmbeddedFile getEmbeddedFileDos()
+ {
+ PDEmbeddedFile file = null;
+ COSStream stream = (COSStream)fs.getObjectFromPath( "EF/DOS" );
+ if( stream != null )
+ {
+ file = new PDEmbeddedFile( stream );
+ }
+ return file;
+ }
+
+ /**
+ * Set the embedded dos file for this spec.
+ *
+ * @param file The dos file to be embedded.
+ */
+ public void setEmbeddedFileDos( PDEmbeddedFile file )
+ {
+ COSDictionary ef = (COSDictionary)fs.getDictionaryObject( "DOS" );
+ if( ef == null && file != null )
+ {
+ ef = new COSDictionary();
+ fs.setItem( "EF", ef );
+ }
+ if( ef != null )
+ {
+ ef.setItem( "DOS", file );
+ }
+ }
+
+ /**
+ * Get the embedded Mac file.
+ *
+ * @return The embedded file for this file spec.
+ */
+ public PDEmbeddedFile getEmbeddedFileMac()
+ {
+ PDEmbeddedFile file = null;
+ COSStream stream = (COSStream)fs.getObjectFromPath( "EF/Mac" );
+ if( stream != null )
+ {
+ file = new PDEmbeddedFile( stream );
+ }
+ return file;
+ }
+
+ /**
+ * Set the embedded Mac file for this spec.
+ *
+ * @param file The Mac file to be embedded.
+ */
+ public void setEmbeddedFileMac( PDEmbeddedFile file )
+ {
+ COSDictionary ef = (COSDictionary)fs.getDictionaryObject( "Mac" );
+ if( ef == null && file != null )
+ {
+ ef = new COSDictionary();
+ fs.setItem( "EF", ef );
+ }
+ if( ef != null )
+ {
+ ef.setItem( "Mac", file );
+ }
+ }
+
+ /**
+ * Get the embedded Unix file.
+ *
+ * @return The embedded file for this file spec.
+ */
+ public PDEmbeddedFile getEmbeddedFileUnix()
+ {
+ PDEmbeddedFile file = null;
+ COSStream stream = (COSStream)fs.getObjectFromPath( "EF/Unix" );
+ if( stream != null )
+ {
+ file = new PDEmbeddedFile( stream );
+ }
+ return file;
+ }
+
+ /**
+ * Set the embedded Unix file for this spec.
+ *
+ * @param file The Unix file to be embedded.
+ */
+ public void setEmbeddedFileUnix( PDEmbeddedFile file )
+ {
+ COSDictionary ef = (COSDictionary)fs.getDictionaryObject( "Unix" );
+ if( ef == null && file != null )
+ {
+ ef = new COSDictionary();
+ fs.setItem( "EF", ef );
+ }
+ if( ef != null )
+ {
+ ef.setItem( "Unix", file );
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDEmbeddedFile.java b/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDEmbeddedFile.java
new file mode 100644
index 0000000..1f4a288
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDEmbeddedFile.java
@@ -0,0 +1,298 @@
+/**
+ * Copyright (c) 2004, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common.filespecification;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+
+import org.pdfbox.cos.COSDictionary;
+import org.pdfbox.cos.COSStream;
+import org.pdfbox.pdmodel.PDDocument;
+import org.pdfbox.pdmodel.common.PDStream;
+
+/**
+ * This represents an embedded file in a file specification.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class PDEmbeddedFile extends PDStream
+{
+
+ /**
+ * @see PDStream#PDStream(PDDocument)
+ */
+ public PDEmbeddedFile( PDDocument document )
+ {
+ super( document );
+ getStream().setName( "Type", "EmbeddedFile" );
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param str The stream parameter.
+ */
+ public PDEmbeddedFile( COSStream str )
+ {
+ super( str );
+ }
+
+ /**
+ * @see PDStream#PDStream(PDDocument, InputStream )
+ */
+ public PDEmbeddedFile( PDDocument doc, InputStream str ) throws IOException
+ {
+ super( doc, str );
+ getStream().setName( "Type", "EmbeddedFile" );
+ }
+
+ /**
+ * @see PDStream#PDStream(PDDocument, InputStream, boolean)
+ */
+ public PDEmbeddedFile( PDDocument doc, InputStream str, boolean filtered ) throws IOException
+ {
+ super( doc, str, filtered );
+ getStream().setName( "Type", "EmbeddedFile" );
+ }
+
+ /**
+ * Set the subtype for this embedded file. This should be a mime type value. Optional.
+ *
+ * @param mimeType The mimeType for the file.
+ */
+ public void setSubtype( String mimeType )
+ {
+ getStream().setName( "Subtype", mimeType );
+ }
+
+ /**
+ * Get the subtype(mimetype) for the embedded file.
+ *
+ * @return The type of embedded file.
+ */
+ public String getSubtype()
+ {
+ return getStream().getNameAsString( "Subtype" );
+ }
+
+ /**
+ * Get the size of the embedded file.
+ *
+ * @return The size of the embedded file.
+ */
+ public int getSize()
+ {
+ return getStream().getEmbeddedInt( "Params", "Size" );
+ }
+
+ /**
+ * Set the size of the embedded file.
+ *
+ * @param size The size of the embedded file.
+ */
+ public void setSize( int size )
+ {
+ getStream().setEmbeddedInt( "Params", "Size", size );
+ }
+
+ /**
+ * Get the creation date of the embedded file.
+ *
+ * @return The Creation date.
+ * @throws IOException If there is an error while constructing the date.
+ */
+ public Calendar getCreationDate() throws IOException
+ {
+ return getStream().getEmbeddedDate( "Params", "CreationDate" );
+ }
+
+ /**
+ * Set the creation date.
+ *
+ * @param creation The new creation date.
+ */
+ public void setCreationDate( Calendar creation )
+ {
+ getStream().setEmbeddedDate( "Params", "CreationDate", creation );
+ }
+
+ /**
+ * Get the mod date of the embedded file.
+ *
+ * @return The mod date.
+ * @throws IOException If there is an error while constructing the date.
+ */
+ public Calendar getModDate() throws IOException
+ {
+ return getStream().getEmbeddedDate( "Params", "ModDate" );
+ }
+
+ /**
+ * Set the mod date.
+ *
+ * @param mod The new creation mod.
+ */
+ public void setModDate( Calendar mod )
+ {
+ getStream().setEmbeddedDate( "Params", "ModDate", mod );
+ }
+
+ /**
+ * Get the check sum of the embedded file.
+ *
+ * @return The check sum of the file.
+ */
+ public String getCheckSum()
+ {
+ return getStream().getEmbeddedString( "Params", "CheckSum" );
+ }
+
+ /**
+ * Set the check sum.
+ *
+ * @param checksum The checksum of the file.
+ */
+ public void setCheckSum( String checksum )
+ {
+ getStream().setEmbeddedString( "Params", "CheckSum", checksum );
+ }
+
+ /**
+ * Get the mac subtype.
+ *
+ * @return The mac subtype.
+ */
+ public String getMacSubtype()
+ {
+ String retval = null;
+ COSDictionary params = (COSDictionary)getStream().getDictionaryObject( "Params" );
+ if( params != null )
+ {
+ retval = params.getEmbeddedString( "Mac", "Subtype" );
+ }
+ return retval;
+ }
+
+ /**
+ * Set the mac subtype.
+ *
+ * @param macSubtype The mac subtype.
+ */
+ public void setMacSubtype( String macSubtype )
+ {
+ COSDictionary params = (COSDictionary)getStream().getDictionaryObject( "Params" );
+ if( params == null && macSubtype != null )
+ {
+ params = new COSDictionary();
+ getStream().setItem( "Params", params );
+ }
+ if( params != null )
+ {
+ params.setEmbeddedString( "Mac", "Subtype", macSubtype );
+ }
+ }
+
+ /**
+ * Get the mac Creator.
+ *
+ * @return The mac Creator.
+ */
+ public String getMacCreator()
+ {
+ String retval = null;
+ COSDictionary params = (COSDictionary)getStream().getDictionaryObject( "Params" );
+ if( params != null )
+ {
+ retval = params.getEmbeddedString( "Mac", "Creator" );
+ }
+ return retval;
+ }
+
+ /**
+ * Set the mac Creator.
+ *
+ * @param macCreator The mac Creator.
+ */
+ public void setMacCreator( String macCreator )
+ {
+ COSDictionary params = (COSDictionary)getStream().getDictionaryObject( "Params" );
+ if( params == null && macCreator != null )
+ {
+ params = new COSDictionary();
+ getStream().setItem( "Params", params );
+ }
+ if( params != null )
+ {
+ params.setEmbeddedString( "Mac", "Creator", macCreator );
+ }
+ }
+
+ /**
+ * Get the mac ResFork.
+ *
+ * @return The mac ResFork.
+ */
+ public String getMacResFork()
+ {
+ String retval = null;
+ COSDictionary params = (COSDictionary)getStream().getDictionaryObject( "Params" );
+ if( params != null )
+ {
+ retval = params.getEmbeddedString( "Mac", "ResFork" );
+ }
+ return retval;
+ }
+
+ /**
+ * Set the mac ResFork.
+ *
+ * @param macResFork The mac ResFork.
+ */
+ public void setMacResFork( String macResFork )
+ {
+ COSDictionary params = (COSDictionary)getStream().getDictionaryObject( "Params" );
+ if( params == null && macResFork != null )
+ {
+ params = new COSDictionary();
+ getStream().setItem( "Params", params );
+ }
+ if( params != null )
+ {
+ params.setEmbeddedString( "Mac", "ResFork", macResFork);
+ }
+ }
+
+
+
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDFileSpecification.java b/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDFileSpecification.java
new file mode 100644
index 0000000..2028247
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDFileSpecification.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) 2004, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common.filespecification;
+
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSDictionary;
+import org.pdfbox.cos.COSString;
+
+import org.pdfbox.pdmodel.common.COSObjectable;
+
+/**
+ * This represents a file specification.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.2 $
+ */
+public abstract class PDFileSpecification implements COSObjectable
+{
+
+ /**
+ * A file specfication can either be a COSString or a COSDictionary. This
+ * will create the file specification either way.
+ *
+ * @param base The cos object that describes the fs.
+ *
+ * @return The file specification for the COSBase object.
+ */
+ public static PDFileSpecification createFS( COSBase base )
+ {
+ PDFileSpecification retval = null;
+ if( base instanceof COSString )
+ {
+ retval = new PDSimpleFileSpecification( (COSString)base );
+ }
+ else if( base instanceof COSDictionary )
+ {
+ retval = new PDComplexFileSpecification( (COSDictionary)base );
+ }
+ return retval;
+ }
+
+ /**
+ * This will get the file name.
+ *
+ * @return The file name.
+ */
+ public abstract String getFile();
+
+ /**
+ * This will set the file name.
+ *
+ * @param file The name of the file.
+ */
+ public abstract void setFile( String file );
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDSimpleFileSpecification.java b/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDSimpleFileSpecification.java
new file mode 100644
index 0000000..b885a78
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/filespecification/PDSimpleFileSpecification.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright (c) 2004, www.pdfbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of pdfbox; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.pdfbox.org
+ *
+ */
+package org.pdfbox.pdmodel.common.filespecification;
+
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSString;
+
+/**
+ * A file specification that is just a string.
+ *
+ * @author blitchfield
+ * @version $Revision: 1.1 $
+ */
+public class PDSimpleFileSpecification extends PDFileSpecification
+{
+ private COSString file;
+
+ /**
+ * Constructor.
+ *
+ */
+ public PDSimpleFileSpecification()
+ {
+ file = new COSString( "" );
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param fileName The file that this spec represents.
+ */
+ public PDSimpleFileSpecification( COSString fileName )
+ {
+ file = fileName;
+ }
+
+ /**
+ * This will get the file name.
+ *
+ * @return The file name.
+ */
+ public String getFile()
+ {
+ return file.getString();
+ }
+
+ /**
+ * This will set the file name.
+ *
+ * @param fileName The name of the file.
+ */
+ public void setFile( String fileName )
+ {
+ file = new COSString( fileName );
+ }
+
+ /**
+ * Convert this standard java object to a COS object.
+ *
+ * @return The cos object that matches this Java object.
+ */
+ public COSBase getCOSObject()
+ {
+ return file;
+ }
+
+}
diff --git a/src/main/java/org/pdfbox/pdmodel/common/filespecification/package.html b/src/main/java/org/pdfbox/pdmodel/common/filespecification/package.html
new file mode 100644
index 0000000..ca87d22
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/filespecification/package.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+
+</head>
+<body>
+The file specification package defines classes that are used for the PDF File Specification logic.
+</body>
+</html>
diff --git a/src/main/java/org/pdfbox/pdmodel/common/package.html b/src/main/java/org/pdfbox/pdmodel/common/package.html
new file mode 100644
index 0000000..9d81599
--- /dev/null
+++ b/src/main/java/org/pdfbox/pdmodel/common/package.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+
+</head>
+<body>
+High level PD classes that are used throughout several packages are placed in the PDModel common package.
+</body>
+</html>