Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.pdfbox.cos; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.Map.Entry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.pdfbox.io.IOUtils; import org.apache.pdfbox.pdmodel.common.COSObjectable; import org.apache.pdfbox.util.DateConverter; import org.apache.pdfbox.util.SmallMap; /** * This class represents a dictionary where name/value pairs reside. * * @author Ben Litchfield * */ public class COSDictionary extends COSBase implements COSUpdateInfo { /** * Log instance. */ private static final Log LOG = LogFactory.getLog(COSDictionary.class); private static final String PATH_SEPARATOR = "/"; private boolean needToBeUpdated; /** * The name-value pairs of this dictionary. The pairs are kept in the order they were added to the dictionary. */ protected Map<COSName, COSBase> items = new SmallMap<>(); /** * Constructor. */ public COSDictionary() { // default constructor } /** * Copy Constructor. This will make a shallow copy of this dictionary. * * @param dict The dictionary to copy. */ public COSDictionary(COSDictionary dict) { items.putAll(dict.items); } /** * @see java.util.Map#containsValue(java.lang.Object) * * @param value The value to find in the map. * * @return true if the map contains this value. */ public boolean containsValue(Object value) { boolean contains = items.containsValue(value); if (!contains && value instanceof COSObject) { contains = items.containsValue(((COSObject) value).getObject()); } return contains; } /** * Search in the map for the value that matches the parameter and return the first key that maps to that value. * * @param value The value to search for in the map. * @return The key for the value in the map or null if it does not exist. */ public COSName getKeyForValue(Object value) { for (Map.Entry<COSName, COSBase> entry : items.entrySet()) { Object nextValue = entry.getValue(); if (nextValue.equals(value) || (nextValue instanceof COSObject && ((COSObject) nextValue).getObject().equals(value))) { return entry.getKey(); } } return null; } /** * This will return the number of elements in this dictionary. * * @return The number of elements in the dictionary. */ public int size() { return items.size(); } /** * This will clear all items in the map. */ public void clear() { items.clear(); } /** * This will get an object from this dictionary. If the object is a reference then it will dereference it and get it * from the document. If the object is COSNull then null will be returned. * * @param key The key to the object that we are getting. * * @return The object that matches the key. */ public COSBase getDictionaryObject(String key) { return getDictionaryObject(COSName.getPDFName(key)); } /** * This is a special case of getDictionaryObject that takes multiple keys, it will handle the situation where * multiple keys could get the same value, ie if either CS or ColorSpace is used to get the colorspace. This will * get an object from this dictionary. If the object is a reference then it will dereference it and get it from the * document. If the object is COSNull then null will be returned. * * @param firstKey The first key to try. * @param secondKey The second key to try. * * @return The object that matches the key. */ public COSBase getDictionaryObject(COSName firstKey, COSName secondKey) { COSBase retval = getDictionaryObject(firstKey); if (retval == null && secondKey != null) { retval = getDictionaryObject(secondKey); } return retval; } /** * This will get an object from this dictionary. If the object is a reference then it will dereference it and get it * from the document. If the object is COSNull then null will be returned. * * @param key The key to the object that we are getting. * * @return The object that matches the key. */ public COSBase getDictionaryObject(COSName key) { COSBase retval = items.get(key); if (retval instanceof COSObject) { retval = ((COSObject) retval).getObject(); } if (retval instanceof COSNull) { retval = null; } return retval; } /** * This will set an item in the dictionary. If value is null then the result will be the same as removeItem( key ). * * @param key The key to the dictionary object. * @param value The value to the dictionary object. */ public void setItem(COSName key, COSBase value) { if (value == null) { removeItem(key); } else { items.put(key, value); } } /** * This will set an item in the dictionary. If value is null then the result will be the same as removeItem( key ). * * @param key The key to the dictionary object. * @param value The value to the dictionary object. */ public void setItem(COSName key, COSObjectable value) { COSBase base = null; if (value != null) { base = value.getCOSObject(); } setItem(key, base); } /** * This will set an item in the dictionary. If value is null then the result will be the same as removeItem( key ). * * @param key The key to the dictionary object. * @param value The value to the dictionary object. */ public void setItem(String key, COSObjectable value) { setItem(COSName.getPDFName(key), value); } /** * This will set an item in the dictionary. * * @param key The key to the dictionary object. * @param value The value to the dictionary object. */ public void setBoolean(String key, boolean value) { setItem(COSName.getPDFName(key), COSBoolean.getBoolean(value)); } /** * This will set an item in the dictionary. * * @param key The key to the dictionary object. * @param value The value to the dictionary object. */ public void setBoolean(COSName key, boolean value) { setItem(key, COSBoolean.getBoolean(value)); } /** * This will set an item in the dictionary. If value is null then the result will be the same as removeItem( key ). * * @param key The key to the dictionary object. * @param value The value to the dictionary object. */ public void setItem(String key, COSBase value) { setItem(COSName.getPDFName(key), value); } /** * This is a convenience method that will convert the value to a COSName object. If it is null then the object will * be removed. * * @param key The key to the object, * @param value The string value for the name. */ public void setName(String key, String value) { setName(COSName.getPDFName(key), value); } /** * This is a convenience method that will convert the value to a COSName object. If it is null then the object will * be removed. * * @param key The key to the object, * @param value The string value for the name. */ public void setName(COSName key, String value) { COSName name = null; if (value != null) { name = COSName.getPDFName(value); } setItem(key, name); } /** * Set the value of a date entry in the dictionary. * * @param key The key to the date value. * @param date The date value. */ public void setDate(String key, Calendar date) { setDate(COSName.getPDFName(key), date); } /** * Set the date object. * * @param key The key to the date. * @param date The date to set. */ public void setDate(COSName key, Calendar date) { setString(key, DateConverter.toString(date)); } /** * Set the value of a date entry in the dictionary. * * @param embedded The embedded dictionary. * @param key The key to the date value. * @param date The date value. */ public void setEmbeddedDate(String embedded, String key, Calendar date) { setEmbeddedDate(embedded, COSName.getPDFName(key), date); } /** * Set the date object. * * @param embedded The embedded dictionary. * @param key The key to the date. * @param date The date to set. */ public void setEmbeddedDate(String embedded, COSName key, Calendar date) { COSDictionary dic = (COSDictionary) getDictionaryObject(embedded); if (dic == null && date != null) { dic = new COSDictionary(); setItem(embedded, dic); } if (dic != null) { dic.setDate(key, date); } } /** * This is a convenience method that will convert the value to a COSString object. If it is null then the object * will be removed. * * @param key The key to the object, * @param value The string value for the name. */ public void setString(String key, String value) { setString(COSName.getPDFName(key), value); } /** * This is a convenience method that will convert the value to a COSString object. If it is null then the object * will be removed. * * @param key The key to the object, * @param value The string value for the name. */ public void setString(COSName key, String value) { COSString name = null; if (value != null) { name = new COSString(value); } setItem(key, name); } /** * This is a convenience method that will convert the value to a COSString object. If it is null then the object * will be removed. * * @param embedded The embedded dictionary to set the item in. * @param key The key to the object, * @param value The string value for the name. */ public void setEmbeddedString(String embedded, String key, String value) { setEmbeddedString(embedded, COSName.getPDFName(key), value); } /** * This is a convenience method that will convert the value to a COSString object. If it is null then the object * will be removed. * * @param embedded The embedded dictionary to set the item in. * @param key The key to the object, * @param value The string value for the name. */ public void setEmbeddedString(String embedded, COSName key, String value) { COSDictionary dic = (COSDictionary) getDictionaryObject(embedded); if (dic == null && value != null) { dic = new COSDictionary(); setItem(embedded, dic); } if (dic != null) { dic.setString(key, value); } } /** * This is a convenience method that will convert the value to a COSInteger object. * * @param key The key to the object, * @param value The int value for the name. */ public void setInt(String key, int value) { setInt(COSName.getPDFName(key), value); } /** * This is a convenience method that will convert the value to a COSInteger object. * * @param key The key to the object, * @param value The int value for the name. */ public void setInt(COSName key, int value) { setItem(key, COSInteger.get(value)); } /** * This is a convenience method that will convert the value to a COSInteger object. * * @param key The key to the object, * @param value The int value for the name. */ public void setLong(String key, long value) { setLong(COSName.getPDFName(key), value); } /** * This is a convenience method that will convert the value to a COSInteger object. * * @param key The key to the object, * @param value The int value for the name. */ public void setLong(COSName key, long value) { COSInteger intVal = COSInteger.get(value); setItem(key, intVal); } /** * This is a convenience method that will convert the value to a COSInteger object. * * @param embeddedDictionary The embedded dictionary. * @param key The key to the object, * @param value The int value for the name. */ public void setEmbeddedInt(String embeddedDictionary, String key, int value) { setEmbeddedInt(embeddedDictionary, COSName.getPDFName(key), value); } /** * This is a convenience method that will convert the value to a COSInteger object. * * @param embeddedDictionary The embedded dictionary. * @param key The key to the object, * @param value The int value for the name. */ public void setEmbeddedInt(String embeddedDictionary, COSName key, int value) { COSDictionary embedded = (COSDictionary) getDictionaryObject(embeddedDictionary); if (embedded == null) { embedded = new COSDictionary(); setItem(embeddedDictionary, embedded); } embedded.setInt(key, value); } /** * This is a convenience method that will convert the value to a COSFloat object. * * @param key The key to the object, * @param value The int value for the name. */ public void setFloat(String key, float value) { setFloat(COSName.getPDFName(key), value); } /** * This is a convenience method that will convert the value to a COSFloat object. * * @param key The key to the object, * @param value The int value for the name. */ public void setFloat(COSName key, float value) { COSFloat fltVal = new COSFloat(value); setItem(key, fltVal); } /** * Sets the given boolean value at bitPos in the flags. * * @param field The COSName of the field to set the value into. * @param bitFlag the bit position to set the value in. * @param value the value the bit position should have. */ public void setFlag(COSName field, int bitFlag, boolean value) { int currentFlags = getInt(field, 0); if (value) { currentFlags = currentFlags | bitFlag; } else { currentFlags &= ~bitFlag; } setInt(field, currentFlags); } /** * This is a convenience method that will get the dictionary object that is expected to be a name. Null is returned * if the entry does not exist in the dictionary. * * @param key The key to the item in the dictionary. * @return The COS name. */ public COSName getCOSName(COSName key) { COSBase name = getDictionaryObject(key); if (name instanceof COSName) { return (COSName) name; } return null; } /** * This is a convenience method that will get the dictionary object that is expected to be a COSObject. Null is * returned if the entry does not exist in the dictionary. * * @param key The key to the item in the dictionary. * @return The COSObject. */ public COSObject getCOSObject(COSName key) { COSBase object = getItem(key); if (object instanceof COSObject) { return (COSObject) object; } return null; } /** * This is a convenience method that will get the dictionary object that is expected to be a COSDictionary. Null is * returned if the entry does not exist in the dictionary. * * @param key The key to the item in the dictionary. * @return The COSDictionary. */ public COSDictionary getCOSDictionary(COSName key) { COSBase dictionary = getDictionaryObject(key); if (dictionary instanceof COSDictionary) { return (COSDictionary) dictionary; } return null; } /** * This is a convenience method that will get the dictionary object that is expected to be a * COSStream. Null is returned if the entry does not exist in the dictionary. * * @param key The key to the item in the dictionary. * @return The COSStream. */ public COSStream getCOSStream(COSName key) { COSBase base = getDictionaryObject(key); if (base instanceof COSStream) { return (COSStream) base; } return null; } /** * This is a convenience method that will get the dictionary object that is expected to be a COSArray. Null is * returned if the entry does not exist in the dictionary. * * @param key The key to the item in the dictionary. * @return The COSArray. */ public COSArray getCOSArray(COSName key) { COSBase array = getDictionaryObject(key); if (array instanceof COSArray) { return (COSArray) array; } return null; } /** * This is a convenience method that will get the dictionary object that is expected to be a name. Default is * returned if the entry does not exist in the dictionary. * * @param key The key to the item in the dictionary. * @param defaultValue The value to return if the dictionary item is null. * @return The COS name. */ public COSName getCOSName(COSName key, COSName defaultValue) { COSBase name = getDictionaryObject(key); if (name instanceof COSName) { return (COSName) name; } return defaultValue; } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. Null is returned if the entry does not exist in the dictionary. * * @param key The key to the item in the dictionary. * @return The name converted to a string. */ public String getNameAsString(String key) { return getNameAsString(COSName.getPDFName(key)); } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. Null is returned if the entry does not exist in the dictionary. * * @param key The key to the item in the dictionary. * @return The name converted to a string. */ public String getNameAsString(COSName key) { String retval = null; COSBase name = getDictionaryObject(key); if (name instanceof COSName) { retval = ((COSName) name).getName(); } else if (name instanceof COSString) { retval = ((COSString) name).getString(); } return retval; } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. * * @param key The key to the item in the dictionary. * @param defaultValue The value to return if the dictionary item is null. * @return The name converted to a string. */ public String getNameAsString(String key, String defaultValue) { return getNameAsString(COSName.getPDFName(key), defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. * * @param key The key to the item in the dictionary. * @param defaultValue The value to return if the dictionary item is null. * @return The name converted to a string. */ public String getNameAsString(COSName key, String defaultValue) { String retval = getNameAsString(key); if (retval == null) { retval = defaultValue; } return retval; } /** * This is a convenience method that will get the dictionary object that is expected to be a * string. Null is returned if the entry does not exist in the dictionary. * * @param key The key to the item in the dictionary. * @return The name converted to a string. */ public String getString(String key) { return getString(COSName.getPDFName(key)); } /** * This is a convenience method that will get the dictionary object that is expected to be a * string. Null is returned if the entry does not exist in the dictionary. * * @param key The key to the item in the dictionary. * @return The name converted to a string. */ public String getString(COSName key) { String retval = null; COSBase value = getDictionaryObject(key); if (value instanceof COSString) { retval = ((COSString) value).getString(); } return retval; } /** * This is a convenience method that will get the dictionary object that is expected to be a * string. * * @param key The key to the item in the dictionary. * @param defaultValue The default value to return. * @return The name converted to a string. */ public String getString(String key, String defaultValue) { return getString(COSName.getPDFName(key), defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be a * string. * * @param key The key to the item in the dictionary. * @param defaultValue The default value to return. * @return The name converted to a string. */ public String getString(COSName key, String defaultValue) { String retval = getString(key); if (retval == null) { retval = defaultValue; } return retval; } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. Null is returned if the entry does not exist in the dictionary. * * @param embedded The embedded dictionary. * @param key The key to the item in the dictionary. * @return The name converted to a string. */ public String getEmbeddedString(String embedded, String key) { return getEmbeddedString(embedded, COSName.getPDFName(key), null); } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. Null is returned if the entry does not exist in the dictionary. * * @param embedded The embedded dictionary. * @param key The key to the item in the dictionary. * @return The name converted to a string. */ public String getEmbeddedString(String embedded, COSName key) { return getEmbeddedString(embedded, key, null); } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. * * @param embedded The embedded dictionary. * @param key The key to the item in the dictionary. * @param defaultValue The default value to return. * @return The name converted to a string. */ public String getEmbeddedString(String embedded, String key, String defaultValue) { return getEmbeddedString(embedded, COSName.getPDFName(key), defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. * * @param embedded The embedded dictionary. * @param key The key to the item in the dictionary. * @param defaultValue The default value to return. * @return The name converted to a string. */ public String getEmbeddedString(String embedded, COSName key, String defaultValue) { String retval = defaultValue; COSBase base = getDictionaryObject(embedded); if (base instanceof COSDictionary) { retval = ((COSDictionary) base).getString(key, defaultValue); } return retval; } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. Null is returned if the entry does not exist in the dictionary or if the date was invalid. * * @param key The key to the item in the dictionary. * @return The name converted to a date. */ public Calendar getDate(String key) { return getDate(COSName.getPDFName(key)); } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. Null is returned if the entry does not exist in the dictionary or if the date was invalid. * * @param key The key to the item in the dictionary. * @return The name converted to a date. */ public Calendar getDate(COSName key) { COSBase base = getDictionaryObject(key); if (base instanceof COSString) { return DateConverter.toCalendar((COSString) base); } return null; } /** * This is a convenience method that will get the dictionary object that is expected to be a date. * * @param key The key to the item in the dictionary. * @param defaultValue The default value to return if the entry does not exist in the dictionary or if the date was invalid. * @return The name converted to a date. */ public Calendar getDate(String key, Calendar defaultValue) { return getDate(COSName.getPDFName(key), defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be a date. * * @param key The key to the item in the dictionary. * @param defaultValue The default value to return if the entry does not exist in the dictionary or if the date was invalid. * @return The name converted to a date. */ public Calendar getDate(COSName key, Calendar defaultValue) { Calendar retval = getDate(key); if (retval == null) { retval = defaultValue; } return retval; } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. Null is returned if the entry does not exist in the dictionary. * * @param embedded The embedded dictionary to get. * @param key The key to the item in the dictionary. * @return The name converted to a string. */ public Calendar getEmbeddedDate(String embedded, String key) { return getEmbeddedDate(embedded, COSName.getPDFName(key), null); } /** * This is a convenience method that will get the dictionary object that is expected to be a name and convert it to * a string. Null is returned if the entry does not exist in the dictionary. * * @param embedded The embedded dictionary to get. * @param key The key to the item in the dictionary. * @return The name converted to a string. */ public Calendar getEmbeddedDate(String embedded, COSName key) { return getEmbeddedDate(embedded, key, null); } /** * This is a convenience method that will get the dictionary object that is expected to be a date. * * @param embedded The embedded dictionary to get. * @param key The key to the item in the dictionary. * @param defaultValue The default value to return if the entry does not exist in the dictionary or if the date was invalid. * @return The name converted to a string. */ public Calendar getEmbeddedDate(String embedded, String key, Calendar defaultValue) { return getEmbeddedDate(embedded, COSName.getPDFName(key), defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be a date. * * @param embedded The embedded dictionary to get. * @param key The key to the item in the dictionary. * @param defaultValue The default value to return if the entry does not exist in the dictionary or if the date was invalid. * @return The name converted to a string. */ public Calendar getEmbeddedDate(String embedded, COSName key, Calendar defaultValue) { Calendar retval = defaultValue; COSDictionary eDic = (COSDictionary) getDictionaryObject(embedded); if (eDic != null) { retval = eDic.getDate(key, defaultValue); } return retval; } /** * This is a convenience method that will get the dictionary object that is expected to be a cos boolean and convert * it to a primitive boolean. * * @param key The key to the item in the dictionary. * @param defaultValue The value returned if the entry is null. * * @return The value converted to a boolean. */ public boolean getBoolean(String key, boolean defaultValue) { return getBoolean(COSName.getPDFName(key), defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be a COSBoolean and convert * it to a primitive boolean. * * @param key The key to the item in the dictionary. * @param defaultValue The value returned if the entry is null. * * @return The entry converted to a boolean. */ public boolean getBoolean(COSName key, boolean defaultValue) { return getBoolean(key, null, defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be a COSBoolean and convert * it to a primitive boolean. * * @param firstKey The first key to the item in the dictionary. * @param secondKey The second key to the item in the dictionary. * @param defaultValue The value returned if the entry is null. * * @return The entry converted to a boolean. */ public boolean getBoolean(COSName firstKey, COSName secondKey, boolean defaultValue) { boolean retval = defaultValue; COSBase bool = getDictionaryObject(firstKey, secondKey); if (bool instanceof COSBoolean) { retval = ((COSBoolean) bool).getValue(); } return retval; } /** * Get an integer from an embedded dictionary. Useful for 1-1 mappings. default:-1 * * @param embeddedDictionary The name of the embedded dictionary. * @param key The key in the embedded dictionary. * * @return The value of the embedded integer. */ public int getEmbeddedInt(String embeddedDictionary, String key) { return getEmbeddedInt(embeddedDictionary, COSName.getPDFName(key)); } /** * Get an integer from an embedded dictionary. Useful for 1-1 mappings. default:-1 * * @param embeddedDictionary The name of the embedded dictionary. * @param key The key in the embedded dictionary. * * @return The value of the embedded integer. */ public int getEmbeddedInt(String embeddedDictionary, COSName key) { return getEmbeddedInt(embeddedDictionary, key, -1); } /** * Get an integer from an embedded dictionary. Useful for 1-1 mappings. * * @param embeddedDictionary The name of the embedded dictionary. * @param key The key in the embedded dictionary. * @param defaultValue The value if there is no embedded dictionary or it does not contain the key. * * @return The value of the embedded integer. */ public int getEmbeddedInt(String embeddedDictionary, String key, int defaultValue) { return getEmbeddedInt(embeddedDictionary, COSName.getPDFName(key), defaultValue); } /** * Get an integer from an embedded dictionary. Useful for 1-1 mappings. * * @param embeddedDictionary The name of the embedded dictionary. * @param key The key in the embedded dictionary. * @param defaultValue The value if there is no embedded dictionary or it does not contain the key. * * @return The value of the embedded integer. */ public int getEmbeddedInt(String embeddedDictionary, COSName key, int defaultValue) { int retval = defaultValue; COSDictionary embedded = (COSDictionary) getDictionaryObject(embeddedDictionary); if (embedded != null) { retval = embedded.getInt(key, defaultValue); } return retval; } /** * This is a convenience method that will get the dictionary object that is expected to be an int. -1 is returned if * there is no value. * * @param key The key to the item in the dictionary. * @return The integer value. */ public int getInt(String key) { return getInt(COSName.getPDFName(key), -1); } /** * This is a convenience method that will get the dictionary object that is expected to be an int. -1 is returned if * there is no value. * * @param key The key to the item in the dictionary. * @return The integer value.. */ public int getInt(COSName key) { return getInt(key, -1); } /** * This is a convenience method that will get the dictionary object that is expected to be an integer. If the * dictionary value is null then the default value will be returned. * * @param key The key to the item in the dictionary. * @param defaultValue The value to return if the dictionary item is null. * @return The integer value. */ public int getInt(String key, int defaultValue) { return getInt(COSName.getPDFName(key), defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be an integer. If the * dictionary value is null then the defaultvalue will be returned. * * @param key The key to the item in the dictionary. * @param defaultValue The value to return if the dictionary item is null. * @return The integer value. */ public int getInt(COSName key, int defaultValue) { return getInt(key, null, defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be an integer. If the * dictionary value is null then the default value -1 will be returned. * * @param firstKey The first key to the item in the dictionary. * @param secondKey The second key to the item in the dictionary. * @return The integer value. */ public int getInt(COSName firstKey, COSName secondKey) { return getInt(firstKey, secondKey, -1); } /** * This is a convenience method that will get the dictionary object that is expected to be an integer. If the * dictionary value is null then the default value will be returned. * * @param firstKey The first key to the item in the dictionary. * @param secondKey The second key to the item in the dictionary. * @param defaultValue The value to return if the dictionary item is null. * @return The integer value. */ public int getInt(COSName firstKey, COSName secondKey, int defaultValue) { int retval = defaultValue; COSBase obj = getDictionaryObject(firstKey, secondKey); if (obj instanceof COSNumber) { retval = ((COSNumber) obj).intValue(); } return retval; } /** * This is a convenience method that will get the dictionary object that is expected to be an long. -1 is returned * if there is no value. * * @param key The key to the item in the dictionary. * * @return The long value. */ public long getLong(String key) { return getLong(COSName.getPDFName(key), -1L); } /** * This is a convenience method that will get the dictionary object that is expected to be an long. -1 is returned * if there is no value. * * @param key The key to the item in the dictionary. * @return The long value. */ public long getLong(COSName key) { return getLong(key, -1L); } /** * This is a convenience method that will get the dictionary object that is expected to be an integer. If the * dictionary value is null then the default value will be returned. * * @param key The key to the item in the dictionary. * @param defaultValue The value to return if the dictionary item is null. * @return The integer value. */ public long getLong(String key, long defaultValue) { return getLong(COSName.getPDFName(key), defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be an integer. If the * dictionary value is null then the default value will be returned. * * @param key The key to the item in the dictionary. * @param defaultValue The value to return if the dictionary item is null. * @return The integer value. */ public long getLong(COSName key, long defaultValue) { long retval = defaultValue; COSBase obj = getDictionaryObject(key); if (obj instanceof COSNumber) { retval = ((COSNumber) obj).longValue(); } return retval; } /** * This is a convenience method that will get the dictionary object that is expected to be an float. -1 is returned * if there is no value. * * @param key The key to the item in the dictionary. * @return The float value. */ public float getFloat(String key) { return getFloat(COSName.getPDFName(key), -1); } /** * This is a convenience method that will get the dictionary object that is expected to be an float. -1 is returned * if there is no value. * * @param key The key to the item in the dictionary. * @return The float value. */ public float getFloat(COSName key) { return getFloat(key, -1); } /** * This is a convenience method that will get the dictionary object that is expected to be a float. If the * dictionary value is null then the default value will be returned. * * @param key The key to the item in the dictionary. * @param defaultValue The value to return if the dictionary item is null. * @return The float value. */ public float getFloat(String key, float defaultValue) { return getFloat(COSName.getPDFName(key), defaultValue); } /** * This is a convenience method that will get the dictionary object that is expected to be an float. If the * dictionary value is null then the default value will be returned. * * @param key The key to the item in the dictionary. * @param defaultValue The value to return if the dictionary item is null. * @return The float value. */ public float getFloat(COSName key, float defaultValue) { float retval = defaultValue; COSBase obj = getDictionaryObject(key); if (obj instanceof COSNumber) { retval = ((COSNumber) obj).floatValue(); } return retval; } /** * Gets the boolean value from the flags at the given bit position. * * @param field The COSName of the field to get the flag from. * @param bitFlag the bitPosition to get the value from. * * @return true if the number at bitPos is '1' */ public boolean getFlag(COSName field, int bitFlag) { int ff = getInt(field, 0); return (ff & bitFlag) == bitFlag; } /** * This will remove an item for the dictionary. This will do nothing of the object does not exist. * * @param key The key to the item to remove from the dictionary. */ public void removeItem(COSName key) { items.remove(key); } /** * This will do a lookup into the dictionary. * * @param key The key to the object. * * @return The item that matches the key. */ public COSBase getItem(COSName key) { return items.get(key); } /** * This will do a lookup into the dictionary. * * @param key The key to the object. * * @return The item that matches the key. */ public COSBase getItem(String key) { return getItem(COSName.getPDFName(key)); } /** * This is a special case of getItem that takes multiple keys, it will handle the situation * where multiple keys could get the same value, ie if either CS or ColorSpace is used to get * the colorspace. This will get an object from this dictionary. * * @param firstKey The first key to try. * @param secondKey The second key to try. * * @return The object that matches the key. */ public COSBase getItem(COSName firstKey, COSName secondKey) { COSBase retval = getItem(firstKey); if (retval == null && secondKey != null) { retval = getItem(secondKey); } return retval; } /** * Returns the names of the entries in this dictionary. The returned set is in the order the entries were added to * the dictionary. * * @since Apache PDFBox 1.1.0 * @return names of the entries in this dictionary */ public Set<COSName> keySet() { return items.keySet(); } /** * Returns the name-value entries in this dictionary. The returned set is in the order the entries were added to the * dictionary. * * @since Apache PDFBox 1.1.0 * @return name-value entries in this dictionary */ public Set<Map.Entry<COSName, COSBase>> entrySet() { return items.entrySet(); } /** * This will get all of the values for the dictionary. * * @return All the values for the dictionary. */ public Collection<COSBase> getValues() { return items.values(); } /** * visitor pattern double dispatch method. * * @param visitor The object to notify when visiting this object. * @return The object that the visitor returns. * * @throws IOException If there is an error visiting this object. */ @Override public Object accept(ICOSVisitor visitor) throws IOException { return visitor.visitFromDictionary(this); } @Override public boolean isNeedToBeUpdated() { return needToBeUpdated; } @Override public void setNeedToBeUpdated(boolean flag) { needToBeUpdated = flag; } /** * This will add all of the dictionaries keys/values to this dictionary. * Only called when adding keys to a trailer that already exists. * * @param dic The dictionaries to get the keys from. */ public void addAll(COSDictionary dic) { for (Map.Entry<COSName, COSBase> entry : dic.entrySet()) { /* * If we're at a second trailer, we have a linearized pdf file, meaning that the first Size entry represents * all of the objects so we don't need to grab the second. */ if (!COSName.SIZE.equals(entry.getKey()) || !items.containsKey(COSName.SIZE)) { setItem(entry.getKey(), entry.getValue()); } } } /** * @see java.util.Map#containsKey(Object) * * @param name The key to find in the map. * @return true if the map contains this key. */ public boolean containsKey(COSName name) { return this.items.containsKey(name); } /** * @see java.util.Map#containsKey(Object) * * @param name The key to find in the map. * @return true if the map contains this key. */ public boolean containsKey(String name) { return containsKey(COSName.getPDFName(name)); } /** * Nice method, gives you every object you want Arrays works properly too. Try "P/Annots/[k]/Rect" where k means the * index of the Annots array. * * @param objPath the relative path to the object. * @return the object */ public COSBase getObjectFromPath(String objPath) { String[] path = objPath.split(PATH_SEPARATOR); COSBase retval = this; for (String pathString : path) { if (retval instanceof COSArray) { int idx = Integer.parseInt(pathString.replaceAll("\\[", "").replaceAll("\\]", "")); retval = ((COSArray) retval).getObject(idx); } else if (retval instanceof COSDictionary) { retval = ((COSDictionary) retval).getDictionaryObject(pathString); } } return retval; } /** * Returns an unmodifiable view of this dictionary. * * @return an unmodifiable view of this dictionary */ public COSDictionary asUnmodifiableDictionary() { return new UnmodifiableCOSDictionary(this); } /** * {@inheritDoc} */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof COSDictionary)) { return false; } COSDictionary toBeCompared = (COSDictionary) o; if (toBeCompared.size() != size()) { return false; } Iterator<Entry<COSName, COSBase>> iter = entrySet().iterator(); while (iter.hasNext()) { Entry<COSName, COSBase> entry = iter.next(); COSName key = entry.getKey(); COSBase value = entry.getValue(); if (value == null && !(toBeCompared.getItem(key) == null && toBeCompared.containsKey(key))) { return false; } else if (!value.equals(toBeCompared.getItem(key))) { return false; } } return true; } /** * {@inheritDoc} */ @Override public int hashCode() { return Objects.hash(items, needToBeUpdated); } /** * {@inheritDoc} */ @Override public String toString() { try { return getDictionaryString(this, new ArrayList<>()); } catch (IOException e) { LOG.debug("An exception occurred trying - returning error message instead", e); return "COSDictionary{" + e.getMessage() + "}"; } } private static String getDictionaryString(COSBase base, List<COSBase> objs) throws IOException { if (base == null) { return "null"; } if (objs.contains(base)) { // avoid endless recursion return String.valueOf(base.hashCode()); } objs.add(base); if (base instanceof COSDictionary) { StringBuilder sb = new StringBuilder(); sb.append("COSDictionary{"); for (Map.Entry<COSName, COSBase> x : ((COSDictionary) base).entrySet()) { sb.append(x.getKey()); sb.append(":"); sb.append(getDictionaryString(x.getValue(), objs)); sb.append(";"); } sb.append("}"); if (base instanceof COSStream) { try (InputStream stream = ((COSStream) base).createRawInputStream()) { byte[] b = IOUtils.toByteArray(stream); sb.append("COSStream{").append(Arrays.hashCode(b)).append("}"); } } return sb.toString(); } if (base instanceof COSArray) { StringBuilder sb = new StringBuilder(); sb.append("COSArray{"); for (COSBase x : ((COSArray) base).toList()) { sb.append(getDictionaryString(x, objs)); sb.append(";"); } sb.append("}"); return sb.toString(); } if (base instanceof COSObject) { COSObject obj = (COSObject) base; return "COSObject{" + getDictionaryString(obj.getObject(), objs) + "}"; } return base.toString(); } }