private void processAnnotations()

in pdfbox/src/main/java/org/apache/pdfbox/multipdf/Splitter.java [761:922]


    private void processAnnotations(PDPage imported) throws IOException
    {
        List<PDAnnotation> annotations = imported.getAnnotations();
        if (annotations.isEmpty())
        {
            return;
        }
        List<PDAnnotation> clonedAnnotations = new ArrayList<>(annotations.size());
        for (PDAnnotation annotation : annotations)
        {
            // create a shallow clone
            COSDictionary clonedDict = new COSDictionary(annotation.getCOSObject());
            PDAnnotation annotationClone = PDAnnotation.createAnnotation(clonedDict);
            annotDictMap.put(annotation.getCOSObject(), clonedDict);
            clonedAnnotations.add(annotationClone);
            if (annotationClone instanceof PDAnnotationLink)
            {
                PDAnnotationLink link = (PDAnnotationLink) annotationClone;
                PDDestination srcDestination = null;
                try
                {
                    srcDestination = link.getDestination();
                }
                catch (IOException ex)
                {
                    LOG.warn("Incorrect destination in link annotation on page " +
                            (currentPageNumber + 1) + " is removed", ex);
                    link.setDestination(null);
                }
                PDAction action = null;
                if (srcDestination == null)
                {
                    action = link.getAction();
                    if (action instanceof PDActionGoTo)
                    {
                        PDActionGoTo goToAction = (PDActionGoTo) action;
                        try
                        {
                            srcDestination = goToAction.getDestination();
                        }
                        catch (IOException ex)
                        {
                            LOG.warn("GoToAction with incorrect destination in link annotation on page " +
                                    (currentPageNumber + 1) + " is removed", ex);
                            link.setAction(null);
                        }
                    }
                }
                if (srcDestination instanceof PDNamedDestination)
                {
                    srcDestination = sourceDocument.getDocumentCatalog().
                            findNamedDestinationPage((PDNamedDestination) srcDestination);
                    // we do not use the named destination anymore because names get modified, e.g.
                    // 0xAD becomes 0, see file 410609.pdf where the name no longer matches with the
                    // entry in the new name tree; plus the original solution was 40 additional loc
                }
                if (srcDestination instanceof PDPageDestination)
                {
                    // preserve links to pages within the split result:
                    // not fully possible here because we don't have the full target document yet.
                    // However we're cloning as needed and remember what to do later.
                    PDPage destinationPage = ((PDPageDestination) srcDestination).getPage();
                    if (destinationPage != null)
                    {
                        // clone destination
                        COSArray clonedDestinationArray =
                                new COSArray(((PDPageDestination) srcDestination).getCOSObject().toList());
                        PDPageDestination dstDestination =
                                (PDPageDestination) PDDestination.create(clonedDestinationArray);

                        // remember the destination to adjust / remove page later
                        destToFixMap.put(dstDestination, imported);

                        if (action != null)
                        {
                            // if action is not null, then the destination came from an action,
                            // thus clone action as well, then assign destination clone, then action
                            COSDictionary clonedActionDict = new COSDictionary(action.getCOSObject());
                            PDActionGoTo dstAction =
                                    (PDActionGoTo) PDActionFactory.createAction(clonedActionDict);
                            dstAction.setDestination(dstDestination);
                            link.setAction(dstAction);
                        }
                        else
                        {
                            // just assign destination clone
                            link.setDestination(dstDestination);
                        }
                    }
                }
            }
            if (annotationClone instanceof PDAnnotationWidget &&
                annotationClone.getCOSObject().containsKey(COSName.PARENT))
            {
                // remove non-terminal field /Parent reference, because this may lead to orphan pages
                annotationClone.getCOSObject().removeItem(COSName.PARENT);
            }
            if (annotation.getPage() != null)
            {
                annotationClone.setPage(imported);
            }
        }
        // Second loop for markup and popup annotations, which reference annotations themselves
        for (PDAnnotation annotation : clonedAnnotations)
        {
            if (annotation instanceof PDAnnotationMarkup)
            {
                PDAnnotationPopup annotationPopup = ((PDAnnotationMarkup) annotation).getPopup();
                if (annotationPopup == null)
                {
                    continue;
                }
                COSDictionary clonedPopupDict = annotDictMap.get(annotationPopup.getCOSObject());
                if (clonedPopupDict != null)
                {
                    annotation.getCOSObject().setItem(COSName.POPUP, clonedPopupDict);
                }
                else
                {
                    // orphan popup (not in annotation list); clone it and fix references 
                    clonedPopupDict = new COSDictionary(annotationPopup.getCOSObject());
                    annotDictMap.put(annotationPopup.getCOSObject(), clonedPopupDict);
                    PDAnnotationPopup annotationPopupClone =
                            (PDAnnotationPopup) PDAnnotation.createAnnotation(clonedPopupDict);
                    annotationPopupClone.setParent((PDAnnotationMarkup) annotation);
                    ((PDAnnotationMarkup) annotation).setPopup(annotationPopupClone);
                    if (annotationPopupClone.getPage() != null)
                    {
                        annotationPopupClone.setPage(imported);
                    }
                }
            }
            if (annotation instanceof PDAnnotationPopup)
            {
                PDAnnotationMarkup annotationMarkup = ((PDAnnotationPopup) annotation).getParent();
                if (annotationMarkup == null)
                {
                    continue;
                }
                COSDictionary clonedMarkupDict = annotDictMap.get(annotationMarkup.getCOSObject());
                if (clonedMarkupDict != null)
                {
                    annotation.getCOSObject().setItem(COSName.PARENT, clonedMarkupDict);
                }
                else
                {
                    // orphan markup (not in annotation list); clone it and fix references 
                    clonedMarkupDict = new COSDictionary(annotationMarkup.getCOSObject());
                    annotDictMap.put(annotationMarkup.getCOSObject(), clonedMarkupDict);
                    PDAnnotationMarkup annotationMarkupClone =
                            (PDAnnotationMarkup) PDAnnotation.createAnnotation(clonedMarkupDict);
                    annotationMarkupClone.setPopup((PDAnnotationPopup) annotation);
                    ((PDAnnotationPopup) annotation).setParent(annotationMarkupClone);
                    if (annotationMarkupClone.getPage() != null)
                    {
                        annotationMarkupClone.setPage(imported);
                    }
                }
            }
        }
        imported.setAnnotations(clonedAnnotations);
    }