001package org.dcm4che3.conf.core.util;
002
003import java.util.ArrayList;
004import java.util.HashMap;
005import java.util.List;
006import java.util.Map;
007import java.util.regex.Matcher;
008import java.util.regex.Pattern;
009
010/**
011 * Refrain from using, will most likely be removed in near future
012 */
013@Deprecated
014public class XNodeUtil {
015    private final static String IDENTIFIER = "@?[a-zA-Z \\d_\\.-]+";
016    private final static String IDENTIFIER_NAMED = "(?<identifier>" + IDENTIFIER + ")";
017    private static final String VALUE = "(('.+?')|(\\-?[\\d]+)|true|false)";
018    private final static String XPREDICATE = "(" + IDENTIFIER + "=" + VALUE + ")";
019    private final static Pattern xPredicatePattern = Pattern.compile(XPREDICATE);
020    private final static String XPATHNODE = "/(?<nodename>" + IDENTIFIER + "|\\*)" + "(\\[(?<predicates>" + XPREDICATE + "( and " + XPREDICATE + ")*)\\])?";
021    public final static Pattern xPathNodePattern = Pattern.compile(XPATHNODE);
022    private final static String XPATH = "(" + XPATHNODE + ")*";
023    public final static Pattern xPathPattern = Pattern.compile(XPATH);
024    private static final String VALUE_NAMED = "(('(?<strvalue>.+?)')|(?<intvalue>\\-?[\\d]+)|(?<boolvalue>true|false))";
025    private final static String XPREDICATENAMED = "(" + IDENTIFIER_NAMED + "=" + VALUE_NAMED + ")";
026    private final static Pattern xNamedPredicatePattern = Pattern.compile(XPREDICATENAMED);
027    private static final String AND = " and ";
028    private final static Pattern xAndPattern = Pattern.compile(AND);
029    private static final String APOS = "&apos;";
030    private final static Pattern aposPattern = Pattern.compile(APOS);
031
032    /**
033     * Returns list of path elements.
034     * $name - name of the node (not @name, which is a predicate)
035     * other entries are just key - value
036     *
037     * @param s
038     * @return
039     */
040    public static List<Map<String, Object>> parseReference(String s) {
041
042        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
043
044        //special case
045        if (s.equals("/")) return list;
046
047        if (!xPathPattern.matcher(s).matches()) {
048            throw new IllegalArgumentException("Failed to parse provided reference (" + s + ")");
049        }
050
051
052        Matcher nodeMatcher = xPathNodePattern.matcher(s);
053        while (nodeMatcher.find()) {
054
055            Map<String, Object> propMap = new HashMap<String, Object>();
056            list.add(propMap);
057
058            String node = nodeMatcher.group();
059
060            // nodename $name
061            String nodeName = nodeMatcher.group("nodename");
062            propMap.put("$name", nodeName);
063
064            // now key-value
065            String predicatesStr = nodeMatcher.group("predicates");
066            if (predicatesStr != null) {
067                String[] predicates = xAndPattern.split(predicatesStr);
068
069                for (String p : predicates) {
070                    Matcher matcher = xNamedPredicatePattern.matcher(p);
071                    if (!matcher.find()) throw new RuntimeException("Unexpected error");
072
073
074                    String boolvalue = matcher.group("boolvalue");
075                    String intvalue = matcher.group("intvalue");
076                    String strvalue = matcher.group("strvalue");
077
078                    Object value;
079                    if (boolvalue != null)
080                        value = Boolean.parseBoolean(boolvalue);
081                    else if (intvalue != null)
082                        value = Integer.parseInt(intvalue);
083                    else if (strvalue != null)
084                        value = strvalue.replace(APOS, "'");
085                    else throw new RuntimeException("Unexpected error: no value");
086
087
088                    String identifier = matcher.group("identifier");
089                    propMap.put(identifier, value);
090
091                }
092
093            }
094        }
095
096        return list;
097    }
098}