XMPNodeImpl.java 12.1 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.xmp.core.impl;

import com.adobe.xmp.core.XMPArray;
import com.adobe.xmp.core.XMPException;
import com.adobe.xmp.core.XMPLanguageAlternative;
import com.adobe.xmp.core.XMPMetadata;
import com.adobe.xmp.core.XMPNode;
import com.adobe.xmp.core.XMPNodeVisitor;
import com.adobe.xmp.core.XMPQualifiers;
import com.adobe.xmp.core.XMPSimple;
import com.adobe.xmp.core.XMPStruct;
import com.adobe.xmp.core.impl.XMPNodeCopyReplaceVisitor;
import com.adobe.xmp.core.impl.XMPQualifiersImpl;
import com.adobe.xmp.path.XMPPath;
import com.adobe.xmp.path.XMPPathSegment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

abstract class XMPNodeImpl
implements XMPNode {
    private String namespace;
    private String name;
    private XMPNode parent;
    private XMPQualifiers qualifiers = null;

    XMPNodeImpl(XMPNode parent, String namespace, String name) {
        this.parent = parent;
        this.namespace = namespace;
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNamespace() {
        return this.namespace;
    }

    public void setNamespace(String namespace) {
        this.namespace = namespace;
    }

    public XMPNode getParent() {
        return this.parent;
    }

    public XMPQualifiers accessQualifiers() {
        if (this.qualifiers == null) {
            this.qualifiers = new XMPQualifiersImpl(this);
        }
        return this.qualifiers;
    }

    public boolean isArrayItem() {
        return this.getParent() != null && this.getParent() instanceof XMPArray;
    }

    public boolean hasQualifiers() {
        return this.qualifiers != null && this.qualifiers.size() != 0;
    }

    public XMPPath getXMPPath() {
        ArrayList<XMPNodeImpl> pathToParent = new ArrayList<XMPNodeImpl>();
        XMPNode node = this;
        while (node != null) {
            pathToParent.add((XMPNodeImpl)node);
            if (node instanceof XMPQualifiers) {
                node = ((XMPQualifiers)node).getHost();
                continue;
            }
            node = node.getParent();
        }
        XMPPath xmpPath = new XMPPath();
        Collections.reverse(pathToParent);
        XMPNode parent = null;
        for (XMPNode pNode : pathToParent) {
            if (pNode.getParent() == null) continue;
            XMPPathSegment segment = this.createSegment(pNode, parent);
            if (segment != null) {
                xmpPath.add(segment);
            }
            parent = pNode;
        }
        return xmpPath;
    }

    private XMPPathSegment createSegment(XMPNode node, XMPNode parent) {
        XMPPathSegment segment = null;
        if (parent != null && parent.hasQualifiers()) {
            XMPQualifiers qualifiers = parent.accessQualifiers();
            for (XMPNode qualifier : qualifiers) {
                if (qualifier != node) continue;
                return XMPPathSegment.createQualifierSegment(node.getNamespace(), node.getName());
            }
        }
        if (parent instanceof XMPArray) {
            int index = 0;
            for (XMPNode child : parent) {
                ++index;
                if (child != node) continue;
                break;
            }
            segment = XMPPathSegment.createArrayIndexSegment(parent.getNamespace(), index);
        } else {
            segment = XMPPathSegment.createPropertySegment(node.getNamespace(), node.getName());
        }
        return segment;
    }

    public XMPNode get(XMPPath path) {
        XMPNodeImpl parent = this;
        XMPNode current = this;
        XMPNodeImpl res = null;
        Iterator<XMPPathSegment> pathIterator = path.iterator();
        while (pathIterator.hasNext() && current != null) {
            XMPPathSegment seg = pathIterator.next();
            switch (seg.getType()) {
                case PROPERTY: {
                    if (parent instanceof XMPStruct) {
                        current = parent.adaptTo(XMPStruct.class).get(seg.getNamespace(), seg.getName());
                        break;
                    }
                    current = null;
                    break;
                }
                case ARRAY_INDEX: {
                    if (parent instanceof XMPArray) {
                        XMPArray array = parent.adaptTo(XMPArray.class);
                        if (array.size() >= seg.getIndex()) {
                            current = array.get(seg.getIndex() - 1);
                            break;
                        }
                        current = null;
                        break;
                    }
                    current = null;
                    break;
                }
                case QUALIFIER: {
                    if (parent.hasQualifiers()) {
                        current = parent.accessQualifiers().get(seg.getNamespace(), seg.getName());
                        break;
                    }
                    current = null;
                    break;
                }
                case QUALIFIER_SELECTOR: {
                    if (parent instanceof XMPArray) {
                        current = this.getArrayItemBasedOnSimpleQual(parent.adaptTo(XMPArray.class), seg.getNamespace(), seg.getName(), seg.getValue());
                        break;
                    }
                    current = null;
                    break;
                }
                default: {
                    current = null;
                }
            }
            parent = res = current;
        }
        return res;
    }

    public XMPNode remove(XMPPath path) throws XMPException {
        XMPNode parent;
        XMPNode node = this.get(path);
        XMPNode removedNode = null;
        if (node != null && (parent = node.getParent()) != null) {
            if (parent instanceof XMPArray) {
                assert (node.isArrayItem());
                XMPPathSegment selector = path.get(path.size() - 1);
                if (selector.getType().equals((Object)XMPPathSegment.Type.ARRAY_INDEX)) {
                    int index = selector.getIndex() - 1;
                    removedNode = parent.adaptTo(XMPArray.class).remove(index);
                } else if (selector.getType().equals((Object)XMPPathSegment.Type.QUALIFIER_SELECTOR)) {
                    removedNode = this.removeArrayItemBasedOnSimpleQual(parent.adaptTo(XMPArray.class), selector.getNamespace(), selector.getName(), selector.getValue());
                }
            } else if (parent instanceof XMPStruct) {
                if (parent instanceof XMPQualifiers) {
                    XMPQualifiers quals = parent.adaptTo(XMPQualifiers.class);
                    removedNode = quals.remove(node.getNamespace(), node.getName());
                } else {
                    removedNode = parent.adaptTo(XMPStruct.class).remove(node.getNamespace(), node.getName());
                }
            }
        }
        return removedNode;
    }

    public XMPSimple getSimple(XMPPath path) {
        XMPNode node = this.get(path);
        return node.adaptTo(XMPSimple.class);
    }

    public XMPStruct getStruct(XMPPath path) {
        XMPNode node = this.get(path);
        return node.adaptTo(XMPStruct.class);
    }

    public XMPArray getArray(XMPPath path) {
        XMPNode node = this.get(path);
        return node.adaptTo(XMPArray.class);
    }

    public XMPLanguageAlternative getLanguageAlternative(XMPPath path) {
        XMPArray array = this.getArray(path);
        if (array != null) {
            return XMPLanguageAlternative.newInstance(array);
        }
        return null;
    }

    public String dump() {
        StringBuffer result = new StringBuffer(512);
        this.dumpNode(result, true, 0, 0);
        return result.toString();
    }

    private void writeIndent(StringBuffer result, int indent) {
        for (int i = 0; i < indent; ++i) {
            result.append('\t');
        }
    }

    private void writeNS(StringBuffer result) {
        if (!(this.getParent() instanceof XMPArray)) {
            result.append(this.namespace);
            result.append(" | ");
        }
    }

    protected void dumpNode(StringBuffer result, boolean recursive, int indent, int index) {
        if (this.parent != null) {
            this.writeIndent(result, indent);
            if (this.getParent() instanceof XMPQualifiers) {
                result.append('?');
                result.append(this.name);
            } else if (this.getParent() instanceof XMPArray) {
                result.append('[');
                result.append(index);
                result.append(']');
            } else {
                result.append(this.name);
            }
        } else if (!(this instanceof XMPQualifiers)) {
            String name;
            result.append("ROOT NODE");
            if (this instanceof XMPMetadata && (name = this.adaptTo(XMPMetadata.class).getAboutURI()) != null) {
                result.append("\t( ");
                result.append(name);
                result.append(" )");
            }
        }
        if (this instanceof XMPSimple) {
            String value = this.adaptTo(XMPSimple.class).getValue();
            if (value != null && value.length() > 0) {
                result.append(" = \"");
                result.append(value);
                result.append('\"');
                result.append("\t( ");
                this.writeNS(result);
                result.append("SIMPLE");
                if (this.adaptTo(XMPSimple.class).isURI()) {
                    result.append(" | URI");
                }
                result.append(" )");
            }
        } else if (this instanceof XMPArray) {
            result.append("\t( ");
            this.writeNS(result);
            result.append((Object)this.adaptTo(XMPArray.class).getForm());
            result.append(" ARRAY");
            result.append(" )");
        } else if (this instanceof XMPStruct && this.parent != null) {
            result.append("\t( ");
            this.writeNS(result);
            result.append("STRUCT");
            result.append(" )");
        }
        if (!(this instanceof XMPQualifiers)) {
            result.append('\n');
        }
        if (recursive) {
            if (this.qualifiers != null && this.qualifiers.size() != 0) {
                ((XMPNodeImpl)((Object)this.qualifiers)).dumpNode(result, recursive, indent, 0);
            }
            Iterator<XMPNode> it = this.iterator();
            int cnt = 0;
            while (it.hasNext()) {
                XMPNode node = it.next();
                ((XMPNodeImpl)node).dumpNode(result, recursive, indent + 1, cnt + 1);
                ++cnt;
            }
        }
    }

    public void copyReplace(XMPNode copyFrom) {
        if (copyFrom == null) {
            throw new IllegalArgumentException("XMPNode from which copying is to be done should not be null.");
        }
        if (this.getClass() != copyFrom.getClass()) {
            throw new IllegalArgumentException("XMPNode from which copying is to be done should be of the same type as current node.");
        }
        XMPNodeCopyReplaceVisitor copyReplaceVisitor = new XMPNodeCopyReplaceVisitor(this);
        copyFrom.accept(copyReplaceVisitor);
    }

    private XMPNode getArrayItemBasedOnSimpleQual(XMPArray array, String qualNS, String qualName, String qualValue) {
        for (XMPNode node : array) {
            XMPNode qual;
            if (!node.hasQualifiers() || !((qual = node.accessQualifiers().get(qualNS, qualName)) instanceof XMPSimple) || !qual.adaptTo(XMPSimple.class).getValue().equals(qualValue)) continue;
            return node;
        }
        return null;
    }

    private XMPNode removeArrayItemBasedOnSimpleQual(XMPArray array, String qualNS, String qualName, String qualValue) {
        Iterator<XMPNode> it = array.iterator();
        while (it.hasNext()) {
            XMPNode qual;
            XMPNode node = it.next();
            if (!node.hasQualifiers() || !((qual = node.accessQualifiers().get(qualNS, qualName)) instanceof XMPSimple) || !qual.adaptTo(XMPSimple.class).getValue().equals(qualValue)) continue;
            it.remove();
            return node;
        }
        return null;
    }

}