summaryrefslogtreecommitdiffstats
path: root/javatoscachecker/kwalify/src/main/java/kwalify/YamlParser.java
blob: fbe351c8cfcb03b957da1f31f04cff6593718d4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 * @(#)YamlParser.java	$Rev: 3 $ $Release: 0.5.1 $
 *
 * copyright(c) 2005 kuwata-lab all rights reserved.
 */
package kwalify;

import java.util.Map;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

/**
 *  yaml parser which can keep line number of path.
 *
 *  ex.
 *  <pre>
 *  String yaml_str = Util.readFile("document.yaml");
 *  YamlParser parser = new YamlParser(yaml_str);
 *  Object document = parser.parse();
 *  </pre>
 */
public class YamlParser extends PlainYamlParser {
    private Map _linenums_table = new IdentityHashMap(); // object => sequence or mapping
    private int _first_linenum = -1;
    private Object _document = null;

    public YamlParser(String yaml_str) {
        super(yaml_str);
    }

    public Object parse() throws SyntaxException {
        _document = super.parse();
        return _document;
    }

    protected String getLine() {
        String line = super.getLine();
        if (_first_linenum < 0) {
            _first_linenum = currentLineNumber();
        }
        return line;
    }


    public int getPathLineNumber(String ypath) throws InvalidPathException {
        if (_document == null) {
            return -1;
        }
        if (ypath.length() == 0 || ypath.equals("/")) {
            return 1;
        }
        String[] elems = ypath.split("/");
        String last_elem = elems.length > 0 ? elems[elems.length - 1] : null;
        int i = ypath.charAt(0) == '/' ? 1 : 0;
        int len = elems.length - 1;
        Object c = _document;   // collection
        for ( /* nothing */ ; i < len; i++) {
            if (c == null) {
                throw new InvalidPathException(ypath);
            } else if (c instanceof Map) {
                c = ((Map)c).get(elems[i]);
            } else if (c instanceof List) {
                int index = Integer.parseInt(elems[i]);
                if (index < 0 || ((List)c).size() < index) {
                    throw new InvalidPathException(ypath);
                }
                c = ((List)c).get(index);
            } else {
                throw new InvalidPathException(ypath);
            }
        }

        if (c == null) {
            throw new InvalidPathException(ypath);
        }
        Object linenums = _linenums_table.get(c); // Map or List
        int linenum = -1;
        if (c instanceof Map) {
            assert linenums instanceof Map;
            Object d = ((Map)linenums).get(last_elem);
            linenum = ((Integer)d).intValue();
        } else if (c instanceof List) {
            assert linenums instanceof List;
            int index = Integer.parseInt(last_elem);
            if (index < 0 || ((List)linenums).size() <= index) {
                throw new InvalidPathException(ypath);
            }
            Object d = ((List)linenums).get(index);
            linenum = ((Integer)d).intValue();
        } else {
            throw new InvalidPathException(ypath);
        }
        return linenum;
    }

    public void setErrorsLineNumber(List errors) throws InvalidPathException {
        for (Iterator it = errors.iterator(); it.hasNext(); ) {
            ValidationException ex = (ValidationException)it.next();
            ex.setLineNumber(getPathLineNumber(ex.getPath()));
        }
    }

    protected List createSequence(int linenum) {
        List seq = new ArrayList();
        _linenums_table.put(seq, new ArrayList());
        return seq;
    }

    protected void addSequenceValue(List seq, Object value, int linenum) {
        seq.add(value);
        List linenums = (List)_linenums_table.get(seq);
        linenums.add(new Integer(linenum));
    }

    protected void setSequenceValueAt(List seq, int index, Object value, int linenum) {
        seq.set(index, value);
        List linenums = (List)_linenums_table.get(seq);
        linenums.set(index, new Integer(linenum));
    }

    protected Map createMapping(int linenum) {
        Map map = super.createMapping(linenum);
        _linenums_table.put(map, new HashMap());
        return map;
    }

    protected void setMappingValueWith(Map map, Object key, Object value, int linenum) {
        map.put(key, value);
        Map linenums = (Map)_linenums_table.get(map);
        assert linenums != null;
        linenums.put(key, new Integer(linenum));
    }

    protected void setMappingDefault(Map map, Object value, int linenum) {
        super.setMappingDefault(map, value, linenum);
        Map linenums = (Map)_linenums_table.get(map);
        linenums.put(new Character('='), new Integer(linenum));
    }

    protected void mergeMapping(Map map, Map map2, int linenum) {
        Map linenums  = (Map)_linenums_table.get(map);
        Map linenums2 = (Map)_linenums_table.get(map2);
        assert linenums2 != null;
        for (Iterator it = map2.keySet().iterator(); it.hasNext(); ) {
            Object key = it.next();
            if (! map.containsKey(key)) {
                map.put(key, map2.get(key));
                linenums.put(key, linenums2.get(key));
            }
        }
    }

}