XMPPathParser.java 4.57 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.xmp.path;

import com.adobe.xmp.path.XMPPath;
import com.adobe.xmp.path.XMPPathParserException;
import com.adobe.xmp.path.XMPPathSegment;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
 * This class specifies class file version 49.0 but uses Java 6 signatures.  Assumed Java 6.
 */
public class XMPPathParser {
    private static Pattern ARRAY_INDEX_EXPR = Pattern.compile("\\[(\\d*)\\]");
    private static Pattern PROP_EXPR = Pattern.compile("([^@:/\\[\\]]+):([^:/\\[\\]]+)");
    private static Pattern QUALIFIER_EXPR = Pattern.compile("@([^:/\\[\\]]+):([^:/\\[\\]]+)");
    private static Pattern QUALIFIER_SELECTOR_EXPR = Pattern.compile("\\[\\?([^:/\\[\\]]+):([^:/\\[\\]]+)=('[^']+'|\"[^\"]+\")\\]");

    public static XMPPath parse(String path, Map<String, String> prefixContract) throws XMPPathParserException {
        if (path == null || prefixContract == null) {
            throw new IllegalArgumentException("Arguments must not be null");
        }
        if (path.length() == 0 || path.length() == 1 && path.charAt(0) == '/') {
            throw new XMPPathParserException("Path is empty");
        }
        XMPPath xmpPath = new XMPPath();
        Matcher arrayMatcher = ARRAY_INDEX_EXPR.matcher(path);
        Matcher propMatcher = PROP_EXPR.matcher(path);
        Matcher qualifierMatcher = QUALIFIER_EXPR.matcher(path);
        Matcher qualifierSelectorMatcher = QUALIFIER_SELECTOR_EXPR.matcher(path);
        int index = 0;
        while (index < path.length()) {
            String prefix;
            if (path.charAt(index) == '/') {
                ++index;
                continue;
            }
            if (propMatcher.find(index) && propMatcher.start() == index) {
                prefix = propMatcher.group(1);
                if (!prefixContract.containsKey(prefix)) {
                    throw new XMPPathParserException("Unknown namespace prefix: " + prefix);
                }
                xmpPath.add(XMPPathSegment.createPropertySegment(prefixContract.get(prefix), propMatcher.group(2)));
                index = propMatcher.end();
                continue;
            }
            if (arrayMatcher.find(index) && arrayMatcher.start() == index) {
                if (index == 0 || path.charAt(index - 1) == '/' || xmpPath.size() == 0) {
                    throw new XMPPathParserException("Array index without a property");
                }
                int foundIndex = 0;
                if (arrayMatcher.groupCount() > 0) {
                    try {
                        String indexString = arrayMatcher.group(1);
                        if (indexString != null && indexString.length() > 0) {
                            foundIndex = Integer.parseInt(arrayMatcher.group(1));
                        }
                    }
                    catch (NumberFormatException e) {
                        throw new XMPPathParserException("Array index is not an integer value", e);
                    }
                }
                xmpPath.add(XMPPathSegment.createArrayIndexSegment(xmpPath.get(xmpPath.size() - 1).getNamespace(), foundIndex));
                index = arrayMatcher.end();
                continue;
            }
            if (qualifierMatcher.find(index) && qualifierMatcher.start() == index) {
                prefix = qualifierMatcher.group(1);
                if (!prefixContract.containsKey(prefix)) {
                    throw new XMPPathParserException("Unknown namespace prefix: " + prefix);
                }
                xmpPath.add(XMPPathSegment.createQualifierSegment(prefixContract.get(prefix), qualifierMatcher.group(2)));
                index = qualifierMatcher.end();
                continue;
            }
            if (qualifierSelectorMatcher.find(index) && qualifierSelectorMatcher.start() == index) {
                prefix = qualifierSelectorMatcher.group(1);
                if (!prefixContract.containsKey(prefix)) {
                    throw new XMPPathParserException("Unknown namespace prefix: " + prefix);
                }
                xmpPath.add(XMPPathSegment.createQualifierSelectorSegment(prefixContract.get(prefix), qualifierSelectorMatcher.group(2), qualifierSelectorMatcher.group(3).substring(1, qualifierSelectorMatcher.group(3).length() - 1)));
                index = qualifierSelectorMatcher.end();
                continue;
            }
            String subPath = path.substring(index);
            throw new XMPPathParserException("Invalid Property: " + subPath + ". Only qualified Names are alowed! ");
        }
        return xmpPath;
    }
}