}
PDDocumentInformation destInfo = destination.getDocumentInformation();
PDDocumentInformation srcInfo = source.getDocumentInformation();
destInfo.getDictionary().mergeInto(srcInfo.getDictionary());
PDDocumentCatalog destCatalog = destination.getDocumentCatalog();
PDDocumentCatalog srcCatalog = source.getDocumentCatalog();
// use the highest version number for the resulting pdf
float destVersion = destination.getDocument().getVersion();
float srcVersion = source.getDocument().getVersion();
if (destVersion < srcVersion)
{
destination.getDocument().setVersion(srcVersion);
}
if (destCatalog.getOpenAction() == null)
{
destCatalog.setOpenAction(srcCatalog.getOpenAction());
}
// maybe there are some shared resources for all pages
COSDictionary srcPages = (COSDictionary) srcCatalog.getCOSDictionary().getDictionaryObject(COSName.PAGES);
COSDictionary srcResources = (COSDictionary) srcPages.getDictionaryObject(COSName.RESOURCES);
COSDictionary destPages = (COSDictionary) destCatalog.getCOSDictionary().getDictionaryObject(COSName.PAGES);
COSDictionary destResources = (COSDictionary) destPages.getDictionaryObject(COSName.RESOURCES);
if (srcResources != null)
{
if (destResources != null)
{
destResources.mergeInto(srcResources);
}
else
{
destPages.setItem(COSName.RESOURCES, srcResources);
}
}
PDFCloneUtility cloner = new PDFCloneUtility(destination);
try
{
PDAcroForm destAcroForm = destCatalog.getAcroForm();
PDAcroForm srcAcroForm = srcCatalog.getAcroForm();
if (destAcroForm == null)
{
cloner.cloneForNewDocument(srcAcroForm);
destCatalog.setAcroForm(srcAcroForm);
}
else
{
if (srcAcroForm != null)
{
mergeAcroForm(cloner, destAcroForm, srcAcroForm);
}
}
}
catch (Exception e)
{
// if we are not ignoring exceptions, we'll re-throw this
if (!ignoreAcroFormErrors)
{
throw (IOException) e;
}
}
COSArray destThreads = (COSArray) destCatalog.getCOSDictionary().getDictionaryObject(COSName.THREADS);
COSArray srcThreads = (COSArray) cloner.cloneForNewDocument(destCatalog.getCOSDictionary().getDictionaryObject(
COSName.THREADS));
if (destThreads == null)
{
destCatalog.getCOSDictionary().setItem(COSName.THREADS, srcThreads);
}
else
{
destThreads.addAll(srcThreads);
}
PDDocumentNameDictionary destNames = destCatalog.getNames();
PDDocumentNameDictionary srcNames = srcCatalog.getNames();
if (srcNames != null)
{
if (destNames == null)
{
destCatalog.getCOSDictionary().setItem(COSName.NAMES, cloner.cloneForNewDocument(srcNames));
}
else
{
cloner.cloneMerge(srcNames, destNames);
}
}
PDDocumentOutline destOutline = destCatalog.getDocumentOutline();
PDDocumentOutline srcOutline = srcCatalog.getDocumentOutline();
if (srcOutline != null)
{
if (destOutline == null)
{
PDDocumentOutline cloned = new PDDocumentOutline((COSDictionary) cloner.cloneForNewDocument(srcOutline));
destCatalog.setDocumentOutline(cloned);
}
else
{
PDOutlineItem first = srcOutline.getFirstChild();
if (first != null)
{
PDOutlineItem clonedFirst = new PDOutlineItem((COSDictionary) cloner.cloneForNewDocument(first));
destOutline.appendChild(clonedFirst);
}
}
}
String destPageMode = destCatalog.getPageMode();
String srcPageMode = srcCatalog.getPageMode();
if (destPageMode == null)
{
destCatalog.setPageMode(srcPageMode);
}
COSDictionary destLabels = (COSDictionary) destCatalog.getCOSDictionary().getDictionaryObject(
COSName.PAGE_LABELS);
COSDictionary srcLabels = (COSDictionary) srcCatalog.getCOSDictionary()
.getDictionaryObject(COSName.PAGE_LABELS);
if (srcLabels != null)
{
int destPageCount = destination.getNumberOfPages();
COSArray destNums = null;
if (destLabels == null)
{
destLabels = new COSDictionary();
destNums = new COSArray();
destLabels.setItem(COSName.NUMS, destNums);
destCatalog.getCOSDictionary().setItem(COSName.PAGE_LABELS, destLabels);
}
else
{
destNums = (COSArray) destLabels.getDictionaryObject(COSName.NUMS);
}
COSArray srcNums = (COSArray) srcLabels.getDictionaryObject(COSName.NUMS);
if (srcNums != null)
{
for (int i = 0; i < srcNums.size(); i += 2)
{
COSNumber labelIndex = (COSNumber) srcNums.getObject(i);
long labelIndexValue = labelIndex.intValue();
destNums.add(COSInteger.get(labelIndexValue + destPageCount));
destNums.add(cloner.cloneForNewDocument(srcNums.getObject(i + 1)));
}
}
}
COSStream destMetadata = (COSStream) destCatalog.getCOSDictionary().getDictionaryObject(COSName.METADATA);
COSStream srcMetadata = (COSStream) srcCatalog.getCOSDictionary().getDictionaryObject(COSName.METADATA);
if (destMetadata == null && srcMetadata != null)
{
PDStream newStream = new PDStream(destination, srcMetadata.getUnfilteredStream(), false);
newStream.getStream().mergeInto(srcMetadata);
newStream.addCompression();
destCatalog.getCOSDictionary().setItem(COSName.METADATA, newStream);
}
// merge logical structure hierarchy if logical structure information is available in both source pdf and
// destination pdf
boolean mergeStructTree = false;
int destParentTreeNextKey = -1;
COSDictionary destParentTreeDict = null;
COSDictionary srcParentTreeDict = null;
COSArray destNumbersArray = null;
COSArray srcNumbersArray = null;
PDMarkInfo destMark = destCatalog.getMarkInfo();
PDStructureTreeRoot destStructTree = destCatalog.getStructureTreeRoot();
PDMarkInfo srcMark = srcCatalog.getMarkInfo();
PDStructureTreeRoot srcStructTree = srcCatalog.getStructureTreeRoot();
if (destStructTree != null)
{
PDNumberTreeNode destParentTree = destStructTree.getParentTree();
destParentTreeNextKey = destStructTree.getParentTreeNextKey();
if (destParentTree != null)
{
destParentTreeDict = destParentTree.getCOSDictionary();
destNumbersArray = (COSArray) destParentTreeDict.getDictionaryObject(COSName.NUMS);
if (destNumbersArray != null)
{
if (destParentTreeNextKey < 0)
{
destParentTreeNextKey = destNumbersArray.size() / 2;
}
if (destParentTreeNextKey > 0)
{
if (srcStructTree != null)
{
PDNumberTreeNode srcParentTree = srcStructTree.getParentTree();
if (srcParentTree != null)
{
srcParentTreeDict = srcParentTree.getCOSDictionary();
srcNumbersArray = (COSArray) srcParentTreeDict.getDictionaryObject(COSName.NUMS);
if (srcNumbersArray != null)
{
mergeStructTree = true;
}
}
}
}
}
}
if (destMark != null && destMark.isMarked() && !mergeStructTree)
{
destMark.setMarked(false);
}
if (!mergeStructTree)
{
destCatalog.setStructureTreeRoot(null);
}
}
// finally append the pages
List<PDPage> pages = srcCatalog.getAllPages();
Iterator<PDPage> pageIter = pages.iterator();
HashMap<COSDictionary, COSDictionary> objMapping = new HashMap<COSDictionary, COSDictionary>();
while (pageIter.hasNext())
{
PDPage page = pageIter.next();