PDFTreeNode.java 14.1 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.internal.pdftoolkit.core.cos.CosArray
 *  com.adobe.internal.pdftoolkit.core.cos.CosDictionary
 *  com.adobe.internal.pdftoolkit.core.cos.CosObject
 *  com.adobe.internal.pdftoolkit.core.cos.CosScalar
 *  com.adobe.internal.pdftoolkit.core.cos.CosScalarOps
 *  com.adobe.internal.pdftoolkit.core.exceptions.PDFException
 *  com.adobe.internal.pdftoolkit.core.exceptions.PDFIOException
 *  com.adobe.internal.pdftoolkit.core.exceptions.PDFInvalidDocumentException
 *  com.adobe.internal.pdftoolkit.core.exceptions.PDFInvalidParameterException
 *  com.adobe.internal.pdftoolkit.core.exceptions.PDFSecurityException
 *  com.adobe.internal.pdftoolkit.core.types.ASName
 */
package com.adobe.internal.pdftoolkit.pdf.document;

import com.adobe.internal.pdftoolkit.core.cos.CosArray;
import com.adobe.internal.pdftoolkit.core.cos.CosDictionary;
import com.adobe.internal.pdftoolkit.core.cos.CosObject;
import com.adobe.internal.pdftoolkit.core.cos.CosScalar;
import com.adobe.internal.pdftoolkit.core.cos.CosScalarOps;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFIOException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFInvalidDocumentException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFInvalidParameterException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFSecurityException;
import com.adobe.internal.pdftoolkit.core.types.ASName;
import com.adobe.internal.pdftoolkit.pdf.document.PDFCosDictionary;
import com.adobe.internal.pdftoolkit.pdf.document.PDFCosObject;
import com.adobe.internal.pdftoolkit.pdf.document.PDFDocument;
import com.adobe.internal.pdftoolkit.pdf.document.PDFTreeList;
import java.util.ListIterator;

/*
 * This class specifies class file version 49.0 but uses Java 6 signatures.  Assumed Java 6.
 */
class PDFTreeNode<K, V>
extends PDFCosDictionary {
    protected static final int SPLIT_NUMBER = 64;
    private final ASName nameDictionaryKey;
    protected PDFTreeNode<K, V> mParentNode = null;

    protected PDFTreeNode(CosObject cosObject, ASName nameDictionaryKey) throws PDFInvalidDocumentException {
        super(cosObject);
        this.nameDictionaryKey = nameDictionaryKey;
    }

    protected static <K, V> PDFTreeNode<K, V> getInstance(CosObject cosObject, PDFTreeNode<K, V> parent, ASName nameDictionaryKey) throws PDFInvalidDocumentException {
        if (PDFCosObject.checkNullCosObject(cosObject) == null) {
            return null;
        }
        PDFTreeNode<K, V> pdfTreeNode = new PDFTreeNode<K, V>(cosObject, nameDictionaryKey);
        pdfTreeNode.setParent(parent);
        return pdfTreeNode;
    }

    protected static <K, V> PDFTreeNode<K, V> newInstance(PDFDocument pdfDocument, ASName nameDictionaryKey, PDFTreeList<K, V> kids) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        CosDictionary cosObject = PDFCosObject.newCosDictionary(pdfDocument);
        PDFTreeNode<K, V> pdfTreeNode = new PDFTreeNode<K, V>((CosObject)cosObject, nameDictionaryKey);
        pdfTreeNode.setParent(kids.getParent());
        pdfTreeNode.getCosDictionary().put(ASName.k_Kids, kids.getCosObject());
        kids.setParent(pdfTreeNode);
        pdfTreeNode.resetLimits();
        return pdfTreeNode;
    }

    protected ASName getNameDictionaryKey() {
        return this.nameDictionaryKey;
    }

    protected PDFTreeList<K, V> getChildren() throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        return PDFTreeList.getInstance(this.getDictionaryCosObjectValue(ASName.k_Kids), this, this.getNameDictionaryKey());
    }

    protected boolean hasChildren() throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        return this.containsKey(ASName.k_Kids);
    }

    protected PDFTreeNode<K, V> getParent() {
        return this.mParentNode;
    }

    protected void setParent(PDFTreeNode<K, V> parent) {
        this.mParentNode = parent;
    }

    protected void resetLimits() throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        PDFTreeList<K, V> list = this.getChildren();
        if (list != null) {
            PDFTreeNode kid = (PDFTreeNode)list.get(0);
            this.setLimitLower(kid.getLimitLower());
            kid = (PDFTreeNode)list.get(list.size() - 1);
            this.setLimitUpper(kid.getLimitUpper());
            this.mParentNode.resetLimits();
        }
    }

    protected CosScalar getLimitLower() throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        CosArray limits = this.getDictionaryArrayValue(ASName.k_Limits);
        if (limits == null) {
            return null;
        }
        return (CosScalar)limits.get(0);
    }

    protected CosScalar getLimitUpper() throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        CosArray limits = this.getDictionaryArrayValue(ASName.k_Limits);
        if (limits == null) {
            return null;
        }
        return (CosScalar)limits.get(1);
    }

    protected void setLimits(CosScalar lower, CosScalar upper) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        this.setLimitLower(lower);
        this.setLimitUpper(upper);
    }

    protected void setLimitLower(CosScalar lower) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        CosArray limits = this.getDictionaryArrayValue(ASName.k_Limits);
        if (limits != null) {
            limits.set(0, (CosObject)lower);
            return;
        }
        limits = PDFCosObject.newCosArray(this.getPDFDocument());
        limits.add((CosObject)lower);
        limits.add((CosObject)lower);
        this.setDictionaryValue(ASName.k_Limits, (CosObject)limits);
    }

    protected void setLimitUpper(CosScalar upper) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        CosArray limits = this.getDictionaryArrayValue(ASName.k_Limits);
        if (limits != null) {
            limits.set(1, (CosObject)upper);
            return;
        }
        limits = PDFCosObject.newCosArray(this.getPDFDocument());
        limits.set(0, (CosObject)upper);
        limits.set(1, (CosObject)upper);
        this.setDictionaryValue(ASName.k_Limits, (CosObject)limits);
    }

    protected int inRange(CosScalar name) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        CosScalar lower = this.getLimitLower();
        if (lower != null && CosScalarOps.compareTo((CosScalar)name, (CosScalar)lower) < 0) {
            return -1;
        }
        CosScalar upper = this.getLimitUpper();
        if (upper != null && CosScalarOps.compareTo((CosScalar)name, (CosScalar)upper) > 0) {
            return 1;
        }
        return 0;
    }

    protected CosObject keyValue(CosScalar name) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        for (PDFTreeNode kid : this.getChildren()) {
            if (kid.inRange(name) != 0) continue;
            return kid.keyValue(name);
        }
        return null;
    }

    protected CosScalar previousKey(CosScalar name) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        CosScalar prevKey = null;
        for (PDFTreeNode kid : this.getChildren()) {
            int rangeSign = kid.inRange(name);
            if (rangeSign == 0) {
                return kid.previousKey(name);
            }
            if (rangeSign <= 0) continue;
            prevKey = kid.getLimitUpper();
        }
        return prevKey;
    }

    protected boolean removeKid(PDFTreeNode<K, V> kid) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        PDFTreeList<K, V> kids = this.getChildren();
        if (kids == null) {
            return false;
        }
        return kids.remove(kid);
    }

    @Override
    public boolean isEmpty() throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        PDFTreeList<K, V> kids = this.getChildren();
        if (kids == null) {
            return true;
        }
        return kids.isEmpty();
    }

    protected boolean deleteValue(CosScalar name) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        PDFTreeList<K, V> kids = this.getChildren();
        if (kids == null) {
            return false;
        }
        for (PDFTreeNode kid : kids) {
            if (kid.inRange(name) != 0 || !kid.deleteValue(name)) continue;
            if (kid.isEmpty()) {
                this.removeKid(kid);
                if (!this.isEmpty()) {
                    this.resetLimits();
                }
            }
            return true;
        }
        return false;
    }

    protected PDFTreeNode<K, V> putValue(CosScalar name, CosObject value, boolean replace) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException, PDFInvalidParameterException {
        PDFTreeList<K, V> newKids = this.getChildren().putValue(name, value, replace);
        this.resetLimits();
        if (newKids == null) {
            return null;
        }
        PDFTreeNode<K, V> newNode = PDFTreeNode.newInstance(this.getPDFDocument(), this.getNameDictionaryKey(), newKids);
        this.getChildren().add(newNode);
        this.resetLimits();
        return null;
    }

    protected ListIterator<PDFTreeNode<K, V>> treeNodeListIterator() throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        return new TreeNodeIterator(this.getChildren());
    }

    /*
     * This class specifies class file version 49.0 but uses Java 6 signatures.  Assumed Java 6.
     */
    private class TreeNodeIterator
    implements ListIterator<PDFTreeNode<K, V>> {
        private ListIterator<PDFTreeNode<K, V>> kidIterator;
        private PDFTreeNode<K, V> currentKid;
        private ListIterator<PDFTreeNode<K, V>> grandKidIterator;

        TreeNodeIterator(PDFTreeList<K, V> kids) throws PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
            if (kids == null) {
                return;
            }
            this.currentKid = null;
            this.kidIterator = kids.listIterator();
            if (this.kidIterator.hasNext()) {
                this.currentKid = this.kidIterator.next();
                this.grandKidIterator = this.currentKid.treeNodeListIterator();
            }
        }

        @Override
        public boolean hasNext() {
            if (this.currentKid == null) {
                return false;
            }
            if (this.kidIterator.hasNext()) {
                return true;
            }
            return this.grandKidIterator.hasNext();
        }

        @Override
        public PDFTreeNode<K, V> next() {
            try {
                if (this.grandKidIterator.hasNext()) {
                    return (InternalEntry)((Object)this.grandKidIterator.next());
                }
                if (this.kidIterator.hasNext()) {
                    this.currentKid = this.kidIterator.next();
                    this.grandKidIterator = this.currentKid.treeNodeListIterator();
                    return (InternalEntry)((Object)this.grandKidIterator.next());
                }
            }
            catch (PDFException e) {
                // empty catch block
            }
            return null;
        }

        @Override
        public void remove() {
            try {
                this.grandKidIterator.remove();
                if (this.currentKid.isEmpty()) {
                    this.kidIterator.remove();
                    if (!PDFTreeNode.this.isEmpty()) {
                        PDFTreeNode.this.resetLimits();
                    } else {
                        CosDictionary cosDict = (CosDictionary)PDFTreeNode.this.getCosObject();
                        cosDict.remove(ASName.k_Kids);
                        cosDict.remove(ASName.k_Limits);
                    }
                }
            }
            catch (PDFException e) {
                IllegalStateException newException = new IllegalStateException("Error during PDFTreeNodeIterator.remove().");
                newException.initCause((Throwable)e);
                throw newException;
            }
        }

        @Override
        public int nextIndex() {
            throw new UnsupportedOperationException();
        }

        @Override
        public int previousIndex() {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean hasPrevious() {
            if (this.currentKid == null) {
                return false;
            }
            if (this.kidIterator.hasPrevious()) {
                return true;
            }
            return this.grandKidIterator.hasPrevious();
        }

        @Override
        public PDFTreeNode<K, V> previous() {
            try {
                if (this.grandKidIterator.hasPrevious()) {
                    return (InternalEntry)((Object)this.grandKidIterator.previous());
                }
                if (this.kidIterator.hasPrevious()) {
                    this.currentKid = this.kidIterator.previous();
                    this.grandKidIterator = this.currentKid.treeNodeListIterator();
                    InternalEntry grandChild = null;
                    while (this.grandKidIterator.hasNext()) {
                        grandChild = (InternalEntry)((Object)this.grandKidIterator.next());
                    }
                    return grandChild;
                }
            }
            catch (PDFException e) {
                // empty catch block
            }
            return null;
        }

        @Override
        public void add(PDFTreeNode<K, V> o) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void set(PDFTreeNode<K, V> o) {
            throw new UnsupportedOperationException();
        }
    }

    public class InternalEntry {
        private final CosScalar key;
        private final CosObject value;

        protected InternalEntry(CosScalar key, CosObject value) {
            this.key = key;
            this.value = value;
        }

        public CosScalar getKey() {
            return this.key;
        }

        public CosObject getValue() {
            return this.value;
        }
    }

}