in pdfbox/src/main/java/org/apache/pdfbox/multipdf/Splitter.java [403:498]
private COSBase createDictionaryClone(COSBase src, COSBase dstParent, COSDictionary currentPageDict)
{
COSDictionary srcDict = (COSDictionary) src;
COSDictionary dstDict = structDictMap.get(srcDict);
if (dstDict != null)
{
return dstDict;
}
COSDictionary dstPageDict = null;
if (srcDict.containsKey(COSName.PG))
{
COSDictionary srcPageDict = srcDict.getCOSDictionary(COSName.PG);
if (srcPageDict == null)
{
return null;
}
dstPageDict = pageDictMap.get(srcPageDict);
if (dstPageDict == null)
{
return null;
}
PDPage dstPage = new PDPage(dstPageDict);
if (dstPageTree.indexOf(dstPage) == -1)
{
return null;
}
}
// Create and fill clone
dstDict = new COSDictionary();
structDictMap.put(srcDict, dstDict);
for (Map.Entry<COSName,COSBase> entry : srcDict.entrySet())
{
COSName key = entry.getKey();
if (!COSName.K.equals(key) &&
!COSName.PG.equals(key) &&
!COSName.P.equals(key))
{
dstDict.setItem(key, entry.getValue());
}
}
// special handling for OBJR items ("object reference dictionary")
// see e.g. file 488300.pdf and Root/StructTreeRoot/K/K/[2]/K/[1]/K/[0]/Obj
COSName type = srcDict.getCOSName(COSName.TYPE);
if (COSName.OBJR.equals(type))
{
COSDictionary srcObj = srcDict.getCOSDictionary(COSName.OBJ);
COSDictionary dstObj = annotDictMap.get(srcObj);
if (dstObj != null)
{
// replace annotation with clone
dstDict.setItem(COSName.OBJ, dstObj);
}
else
{
removePossibleOrphanAnnotation(srcObj, srcDict, currentPageDict, dstDict);
}
}
else
{
// /P not needed for OBJR items
dstDict.setItem(COSName.P, dstParent);
}
dstDict.setItem(COSName.PG, dstPageDict);
COSBase kid = srcDict.getDictionaryObject(COSName.K);
// stack overflow here with 207658.pdf, too complex
COSBase cloneKid = createClone(kid, dstDict, dstPageDict != null ? dstPageDict : currentPageDict);
if (cloneKid == null && kid != null)
{
return null; // kids array wasn't empty, but is empty now => ignore
}
// removes orphan nodes, example:
// Root/StructTreeRoot/K/[7]/K/[3]/K/[5]/K/[2] in 271459.pdf
// decide about keeping source dictionaries with no /K and no /PG
if (dstPageDict == null && cloneKid == null && currentPageDict == null)
{
// if no parent page and no page here and no kids, assume this is an orphan
return null;
}
dstDict.setItem(COSName.K, cloneKid);
String id = dstDict.getString(COSName.ID);
if (id != null)
{
idSet.add(id);
}
COSName s = dstDict.getCOSName(COSName.S);
if (s != null)
{
roleSet.add(s);
}
return dstDict;
}