##### Coverage Report - org.yaml.snakeyaml.constructor.SafeConstructor

Classes in this File | Line Coverage | Branch Coverage | Complexity
SafeConstructor |
100% | 77/77
100% | 19/19
| 4.0;4
SafeConstructor$1 |
100% | 1/1
N/A | N/A
| 4.0;4
SafeConstructor$ConstructUndefined |
100% | 2/2
N/A | N/A
| 4.0;4
SafeConstructor$ConstructYamlBinary |
100% | 3/3
N/A | N/A
| 4.0;4
SafeConstructor$ConstructYamlBool |
100% | 3/3
N/A | N/A
| 4.0;4
SafeConstructor$ConstructYamlFloat |
100% | 24/24
100% | 14/14
| 4.0;4
SafeConstructor$ConstructYamlInt |
100% | 31/31
100% | 16/16
| 4.0;4
SafeConstructor$ConstructYamlMap |
87% | 7/8
75% | 3/4
| 4.0;4
SafeConstructor$ConstructYamlNull |
100% | 3/3
N/A | N/A
| 4.0;4
SafeConstructor$ConstructYamlOmap |
100% | 18/18
100% | 8/8
| 4.0;4
SafeConstructor$ConstructYamlPairs |
100% | 18/18
100% | 8/8
| 4.0;4
SafeConstructor$ConstructYamlSeq |
88% | 8/9
75% | 3/4
| 4.0;4
SafeConstructor$ConstructYamlSet |
87% | 7/8
75% | 3/4
| 4.0;4
SafeConstructor$ConstructYamlStr |
100% | 2/2
N/A | N/A
| 4.0;4
SafeConstructor$ConstructYamlTimestamp |
97% | 45/46
90% | 9/10
| 4.0;4

1 |  |
     /**
2 |  |
      * Copyright (c) 2008-2011, http://www.snakeyaml.org
3 |  |
      *
4 |  |
      * Licensed under the Apache License, Version 2.0 (the "License");
5 |  |
      * you may not use this file except in compliance with the License.
6 |  |
      * You may obtain a copy of the License at
7 |  |
      *
8 |  |
      *     http://www.apache.org/licenses/LICENSE-2.0
9 |  |
      *
10 |  |
      * Unless required by applicable law or agreed to in writing, software
11 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
12 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  |
      * See the License for the specific language governing permissions and
14 |  |
      * limitations under the License.
15 |  |
      */
16 |  |
17 |  |
     package org.yaml.snakeyaml.constructor;
18 |  |
19 |  |
     import java.math.BigInteger;
20 |  |
     import java.util.ArrayList;
21 |  |
     import java.util.Calendar;
22 |  |
     import java.util.HashMap;
23 |  |
     import java.util.Iterator;
24 |  |
     import java.util.LinkedHashMap;
25 |  |
     import java.util.List;
26 |  |
     import java.util.Map;
27 |  |
     import java.util.Set;
28 |  |
     import java.util.TimeZone;
29 |  |
     import java.util.regex.Matcher;
30 |  |
     import java.util.regex.Pattern;
31 |  |
32 |  |
     import org.yaml.snakeyaml.error.YAMLException;
33 |  |
     import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
34 |  |
     import org.yaml.snakeyaml.nodes.MappingNode;
35 |  |
     import org.yaml.snakeyaml.nodes.Node;
36 |  |
     import org.yaml.snakeyaml.nodes.NodeId;
37 |  |
     import org.yaml.snakeyaml.nodes.NodeTuple;
38 |  |
     import org.yaml.snakeyaml.nodes.ScalarNode;
39 |  |
     import org.yaml.snakeyaml.nodes.SequenceNode;
40 |  |
     import org.yaml.snakeyaml.nodes.Tag;
41 |  |
42 |  |
     /**
43 |  |
      * Construct standard Java classes
44 |  |
      */
45 | 102503 |
     public class SafeConstructor extends BaseConstructor {
46 |  |
47 | 1 |
         public static ConstructUndefined undefinedConstructor = new ConstructUndefined();
48 |  |
49 | 3984 |
         public SafeConstructor() {
50 | 3984 |
             this.yamlConstructors.put(Tag.NULL, new ConstructYamlNull());
51 | 3984 |
             this.yamlConstructors.put(Tag.BOOL, new ConstructYamlBool());
52 | 3984 |
             this.yamlConstructors.put(Tag.INT, new ConstructYamlInt());
53 | 3984 |
             this.yamlConstructors.put(Tag.FLOAT, new ConstructYamlFloat());
54 | 3984 |
             this.yamlConstructors.put(Tag.BINARY, new ConstructYamlBinary());
55 | 3984 |
             this.yamlConstructors.put(Tag.TIMESTAMP, new ConstructYamlTimestamp());
56 | 3984 |
             this.yamlConstructors.put(Tag.OMAP, new ConstructYamlOmap());
57 | 3984 |
             this.yamlConstructors.put(Tag.PAIRS, new ConstructYamlPairs());
58 | 3984 |
             this.yamlConstructors.put(Tag.SET, new ConstructYamlSet());
59 | 3984 |
             this.yamlConstructors.put(Tag.STR, new ConstructYamlStr());
60 | 3984 |
             this.yamlConstructors.put(Tag.SEQ, new ConstructYamlSeq());
61 | 3984 |
             this.yamlConstructors.put(Tag.MAP, new ConstructYamlMap());
62 | 3984 |
             this.yamlConstructors.put(null, undefinedConstructor);
63 | 3984 |
             this.yamlClassConstructors.put(NodeId.scalar, undefinedConstructor);
64 | 3984 |
             this.yamlClassConstructors.put(NodeId.sequence, undefinedConstructor);
65 | 3984 |
             this.yamlClassConstructors.put(NodeId.mapping, undefinedConstructor);
66 | 3984 |
         }
67 |  |
68 |  |
         protected void flattenMapping(MappingNode node) {
69 |  |
             // perform merging only on nodes containing merge node(s)
70 | 22912 |
             if (node.isMerged()) {
71 | 27 |
                 node.setValue(mergeNode(node, true, new HashMap<Object, Integer>(),
72 |  |
                         new ArrayList<NodeTuple>()));
73 |  |
             }
74 | 22908 |
         }
75 |  |
76 |  |
         /**
77 |  |
          * Does merge for supplied mapping node.
78 |  |
          *
79 |  |
          * @param node
80 |  |
          *            where to merge
81 |  |
          * @param isPreffered
82 |  |
          *            true if keys of node should take precedence over others...
83 |  |
          * @param key2index
84 |  |
          *            maps already merged keys to index from values
85 |  |
          * @param values
86 |  |
          *            collects merged NodeTuple
87 |  |
          * @return list of the merged NodeTuple (to be set as value for the
88 |  |
          *         MappingNode)
89 |  |
          */
90 |  |
         private List<NodeTuple> mergeNode(MappingNode node, boolean isPreffered,
91 |  |
                 Map<Object, Integer> key2index, List<NodeTuple> values) {
92 | 68 |
             List<NodeTuple> nodeValue = node.getValue();
93 | 68 |
             for (Iterator<NodeTuple> iter = nodeValue.iterator(); iter.hasNext();) {
94 | 130 |
                 final NodeTuple nodeTuple = iter.next();
95 | 130 |
                 final Node keyNode = nodeTuple.getKeyNode();
96 | 130 |
                 final Node valueNode = nodeTuple.getValueNode();
97 | 130 |
                 if (keyNode.getTag().equals(Tag.MERGE)) {
98 | 27 |
                     iter.remove();
99 | 27 |
                     switch (valueNode.getNodeId()) {
100 |  |
                     case mapping:
101 | 13 |
                         MappingNode mn = (MappingNode) valueNode;
102 | 13 |
                         mergeNode(mn, false, key2index, values);
103 | 13 |
                         break;
104 |  |
                     case sequence:
105 | 12 |
                         SequenceNode sn = (SequenceNode) valueNode;
106 | 12 |
                         List<Node> vals = sn.getValue();
107 | 12 |
                         for (Node subnode : vals) {
108 | 30 |
                             if (!(subnode instanceof MappingNode)) {
109 | 2 |
                                 throw new ConstructorException("while constructing a mapping",
110 |  |
                                         node.getStartMark(),
111 |  |
                                         "expected a mapping for merging, but found "
112 |  |
                                                 + subnode.getNodeId(), subnode.getStartMark());
113 |  |
                             }
114 | 28 |
                             MappingNode mnode = (MappingNode) subnode;
115 | 28 |
                             mergeNode(mnode, false, key2index, values);
116 | 28 |
                         }
117 | 10 |
                         break;
118 |  |
                     default:
119 | 2 |
                         throw new ConstructorException("while constructing a mapping",
120 |  |
                                 node.getStartMark(),
121 |  |
                                 "expected a mapping or list of mappings for merging, but found "
122 |  |
                                         + valueNode.getNodeId(), valueNode.getStartMark());
123 |  |
                     }
124 |  |
                 } else {
125 |  |
                     // we need to construct keys to avoid duplications
126 | 103 |
                     Object key = constructObject(keyNode);
127 | 103 |
                     if (!key2index.containsKey(key)) { // 1st time merging key
128 | 84 |
                         values.add(nodeTuple);
129 |  |
                         // keep track where tuple for the key is
130 | 84 |
                         key2index.put(key, values.size() - 1);
131 | 19 |
                     } else if (isPreffered) { // there is value for the key, but we
132 |  |
                                               // need to override it
133 |  |
                         // change value for the key using saved position
134 | 13 |
                         values.set(key2index.get(key), nodeTuple);
135 |  |
                     }
136 |  |
                 }
137 | 126 |
             }
138 | 64 |
             return values;
139 |  |
         }
140 |  |
141 |  |
         protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
142 | 21332 |
             flattenMapping(node);
143 | 21328 |
             super.constructMapping2ndStep(node, mapping);
144 | 21324 |
         }
145 |  |
146 |  |
         @Override
147 |  |
         protected void constructSet2ndStep(MappingNode node, java.util.Set<Object> set) {
148 | 43 |
             flattenMapping(node);
149 | 43 |
             super.constructSet2ndStep(node, set);
150 | 43 |
         }
151 |  |
152 | 3984 |
         public class ConstructYamlNull extends AbstractConstruct {
153 |  |
             public Object construct(Node node) {
154 | 247 |
                 constructScalar((ScalarNode) node);
155 | 247 |
                 return null;
156 |  |
             }
157 |  |
         }
158 |  |
159 | 1 |
         private final static Map<String, Boolean> BOOL_VALUES = new HashMap<String, Boolean>();
160 |  |
         static {
161 | 1 |
             BOOL_VALUES.put("yes", Boolean.TRUE);
162 | 1 |
             BOOL_VALUES.put("no", Boolean.FALSE);
163 | 1 |
             BOOL_VALUES.put("true", Boolean.TRUE);
164 | 1 |
             BOOL_VALUES.put("false", Boolean.FALSE);
165 | 1 |
             BOOL_VALUES.put("on", Boolean.TRUE);
166 | 1 |
             BOOL_VALUES.put("off", Boolean.FALSE);
167 |  |
         }
168 |  |
169 | 3984 |
         public class ConstructYamlBool extends AbstractConstruct {
170 |  |
             public Object construct(Node node) {
171 | 159 |
                 String val = (String) constructScalar((ScalarNode) node);
172 | 159 |
                 return BOOL_VALUES.get(val.toLowerCase());
173 |  |
             }
174 |  |
         }
175 |  |
176 | 3984 |
         public class ConstructYamlInt extends AbstractConstruct {
177 |  |
             public Object construct(Node node) {
178 | 102135 |
                 String value = constructScalar((ScalarNode) node).toString().replaceAll("_", "");
179 | 102135 |
                 int sign = +1;
180 | 102135 |
                 char first = value.charAt(0);
181 | 102135 |
                 if (first == '-') {
182 | 18 |
                     sign = -1;
183 | 18 |
                     value = value.substring(1);
184 | 102117 |
                 } else if (first == '+') {
185 | 4 |
                     value = value.substring(1);
186 |  |
                 }
187 | 102135 |
                 int base = 10;
188 | 102135 |
                 if ("0".equals(value)) {
189 | 32 |
                     return new Integer(0);
190 | 102103 |
                 } else if (value.startsWith("0b")) {
191 | 1 |
                     value = value.substring(2);
192 | 1 |
                     base = 2;
193 | 102102 |
                 } else if (value.startsWith("0x")) {
194 | 3 |
                     value = value.substring(2);
195 | 3 |
                     base = 16;
196 | 102099 |
                 } else if (value.startsWith("0")) {
197 | 3 |
                     value = value.substring(1);
198 | 3 |
                     base = 8;
199 | 102096 |
                 } else if (value.indexOf(':') != -1) {
200 | 4 |
                     String[] digits = value.split(":");
201 | 4 |
                     int bes = 1;
202 | 4 |
                     int val = 0;
203 | 16 |
                     for (int i = 0, j = digits.length; i < j; i++) {
204 | 12 |
                         val += (Long.parseLong(digits[(j - i) - 1]) * bes);
205 | 12 |
                         bes *= 60;
206 |  |
                     }
207 | 4 |
                     return createNumber(sign, String.valueOf(val), 10);
208 |  |
                 } else {
209 | 102092 |
                     return createNumber(sign, value, 10);
210 |  |
                 }
211 | 7 |
                 return createNumber(sign, value, base);
212 |  |
             }
213 |  |
         }
214 |  |
215 |  |
         private Number createNumber(int sign, String number, int radix) {
216 |  |
             Number result;
217 | 102103 |
             if (sign < 0) {
218 | 17 |
                 number = "-" + number;
219 |  |
             }
220 |  |
             try {
221 | 102103 |
                 result = Integer.valueOf(number, radix);
222 | 13 |
             } catch (NumberFormatException e) {
223 |  |
                 try {
224 | 13 |
                     result = Long.valueOf(number, radix);
225 | 4 |
                 } catch (NumberFormatException e1) {
226 | 4 |
                     result = new BigInteger(number, radix);
227 | 9 |
                 }
228 | 102090 |
             }
229 | 102103 |
             return result;
230 |  |
         }
231 |  |
232 | 3984 |
         public class ConstructYamlFloat extends AbstractConstruct {
233 |  |
             public Object construct(Node node) {
234 | 193 |
                 String value = constructScalar((ScalarNode) node).toString().replaceAll("_", "");
235 | 193 |
                 int sign = +1;
236 | 193 |
                 char first = value.charAt(0);
237 | 193 |
                 if (first == '-') {
238 | 5 |
                     sign = -1;
239 | 5 |
                     value = value.substring(1);
240 | 188 |
                 } else if (first == '+') {
241 | 4 |
                     value = value.substring(1);
242 |  |
                 }
243 | 193 |
                 String valLower = value.toLowerCase();
244 | 193 |
                 if (".inf".equals(valLower)) {
245 | 6 |
                     return new Double(sign == -1 ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
246 | 187 |
                 } else if (".nan".equals(valLower)) {
247 | 3 |
                     return new Double(Double.NaN);
248 | 184 |
                 } else if (value.indexOf(':') != -1) {
249 | 2 |
                     String[] digits = value.split(":");
250 | 2 |
                     int bes = 1;
251 | 2 |
                     double val = 0.0;
252 | 7 |
                     for (int i = 0, j = digits.length; i < j; i++) {
253 | 5 |
                         val += (Double.parseDouble(digits[(j - i) - 1]) * bes);
254 | 5 |
                         bes *= 60;
255 |  |
                     }
256 | 2 |
                     return new Double(sign * val);
257 |  |
                 } else {
258 | 182 |
                     Double d = Double.valueOf(value);
259 | 181 |
                     return new Double(d.doubleValue() * sign);
260 |  |
                 }
261 |  |
             }
262 |  |
         }
263 |  |
264 | 3984 |
         public class ConstructYamlBinary extends AbstractConstruct {
265 |  |
             public Object construct(Node node) {
266 | 15 |
                 byte[] decoded = Base64Coder.decode(constructScalar((ScalarNode) node).toString()
267 |  |
                         .toCharArray());
268 | 12 |
                 return decoded;
269 |  |
             }
270 |  |
         }
271 |  |
272 | 1 |
         private final static Pattern TIMESTAMP_REGEXP = Pattern
273 |  |
                 .compile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[ \t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \t]*(?:Z|([-+][0-9][0-9]?)(?::([0-9][0-9])?)?))?)?$");
274 | 1 |
         private final static Pattern YMD_REGEXP = Pattern
275 |  |
                 .compile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$");
276 |  |
277 | 3994 |
         public class ConstructYamlTimestamp extends AbstractConstruct {
278 |  |
             private Calendar calendar;
279 |  |
280 |  |
             public Calendar getCalendar() {
281 | 7 |
                 return calendar;
282 |  |
             }
283 |  |
284 |  |
             public Object construct(Node node) {
285 | 130 |
                 ScalarNode scalar = (ScalarNode) node;
286 | 130 |
                 String nodeValue = scalar.getValue();
287 | 130 |
                 Matcher match = YMD_REGEXP.matcher(nodeValue);
288 | 130 |
                 if (match.matches()) {
289 | 19 |
                     String year_s = match.group(1);
290 | 19 |
                     String month_s = match.group(2);
291 | 19 |
                     String day_s = match.group(3);
292 | 19 |
                     calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
293 | 19 |
                     calendar.clear();
294 | 19 |
                     calendar.set(Calendar.YEAR, Integer.parseInt(year_s));
295 |  |
                     // Java's months are zero-based...
296 | 19 |
                     calendar.set(Calendar.MONTH, Integer.parseInt(month_s) - 1); // x
297 | 19 |
                     calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day_s));
298 | 19 |
                     return calendar.getTime();
299 |  |
                 } else {
300 | 111 |
                     match = TIMESTAMP_REGEXP.matcher(nodeValue);
301 | 111 |
                     if (!match.matches()) {
302 | 0 |
                         throw new YAMLException("Unexpected timestamp: " + nodeValue);
303 |  |
                     }
304 | 111 |
                     String year_s = match.group(1);
305 | 111 |
                     String month_s = match.group(2);
306 | 111 |
                     String day_s = match.group(3);
307 | 111 |
                     String hour_s = match.group(4);
308 | 111 |
                     String min_s = match.group(5);
309 |  |
                     // seconds and milliseconds
310 | 111 |
                     String seconds = match.group(6);
311 | 111 |
                     String millis = match.group(7);
312 | 111 |
                     if (millis != null) {
313 | 40 |
                         seconds = seconds + "." + millis;
314 |  |
                     }
315 | 111 |
                     double fractions = Double.parseDouble(seconds);
316 | 111 |
                     int sec_s = (int) Math.round(Math.floor(fractions));
317 | 111 |
                     int usec = (int) Math.round(((fractions - sec_s) * 1000));
318 |  |
                     // timezone
319 | 111 |
                     String timezoneh_s = match.group(8);
320 | 111 |
                     String timezonem_s = match.group(9);
321 |  |
                     TimeZone timeZone;
322 | 111 |
                     if (timezoneh_s != null) {
323 | 22 |
                         String time = timezonem_s != null ? ":" + timezonem_s : "00";
324 | 22 |
                         timeZone = TimeZone.getTimeZone("GMT" + timezoneh_s + time);
325 | 22 |
                     } else {
326 |  |
                         // no time zone provided
327 | 89 |
                         timeZone = TimeZone.getTimeZone("UTC");
328 |  |
                     }
329 | 111 |
                     calendar = Calendar.getInstance(timeZone);
330 | 111 |
                     calendar.set(Calendar.YEAR, Integer.parseInt(year_s));
331 |  |
                     // Java's months are zero-based...
332 | 111 |
                     calendar.set(Calendar.MONTH, Integer.parseInt(month_s) - 1);
333 | 111 |
                     calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day_s));
334 | 111 |
                     calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour_s));
335 | 111 |
                     calendar.set(Calendar.MINUTE, Integer.parseInt(min_s));
336 | 111 |
                     calendar.set(Calendar.SECOND, sec_s);
337 | 111 |
                     calendar.set(Calendar.MILLISECOND, usec);
338 | 111 |
                     return calendar.getTime();
339 |  |
                 }
340 |  |
             }
341 |  |
         }
342 |  |
343 | 3984 |
         public class ConstructYamlOmap extends AbstractConstruct {
344 |  |
             public Object construct(Node node) {
345 |  |
                 // Note: we do not check for duplicate keys, because it's too
346 |  |
                 // CPU-expensive.
347 | 9 |
                 Map<Object, Object> omap = new LinkedHashMap<Object, Object>();
348 | 9 |
                 if (!(node instanceof SequenceNode)) {
349 | 2 |
                     throw new ConstructorException("while constructing an ordered map",
350 |  |
                             node.getStartMark(), "expected a sequence, but found " + node.getNodeId(),
351 |  |
                             node.getStartMark());
352 |  |
                 }
353 | 7 |
                 SequenceNode snode = (SequenceNode) node;
354 | 7 |
                 for (Node subnode : snode.getValue()) {
355 | 17 |
                     if (!(subnode instanceof MappingNode)) {
356 | 2 |
                         throw new ConstructorException("while constructing an ordered map",
357 |  |
                                 node.getStartMark(), "expected a mapping of length 1, but found "
358 |  |
                                         + subnode.getNodeId(), subnode.getStartMark());
359 |  |
                     }
360 | 15 |
                     MappingNode mnode = (MappingNode) subnode;
361 | 15 |
                     if (mnode.getValue().size() != 1) {
362 | 2 |
                         throw new ConstructorException("while constructing an ordered map",
363 |  |
                                 node.getStartMark(), "expected a single mapping item, but found "
364 |  |
                                         + mnode.getValue().size() + " items", mnode.getStartMark());
365 |  |
                     }
366 | 13 |
                     Node keyNode = mnode.getValue().get(0).getKeyNode();
367 | 13 |
                     Node valueNode = mnode.getValue().get(0).getValueNode();
368 | 13 |
                     Object key = constructObject(keyNode);
369 | 13 |
                     Object value = constructObject(valueNode);
370 | 13 |
                     omap.put(key, value);
371 | 13 |
                 }
372 | 3 |
                 return omap;
373 |  |
             }
374 |  |
         }
375 |  |
376 |  |
         // Note: the same code as `construct_yaml_omap`.
377 | 3984 |
         public class ConstructYamlPairs extends AbstractConstruct {
378 |  |
             public Object construct(Node node) {
379 |  |
                 // Note: we do not check for duplicate keys, because it's too
380 |  |
                 // CPU-expensive.
381 | 8 |
                 if (!(node instanceof SequenceNode)) {
382 | 2 |
                     throw new ConstructorException("while constructing pairs", node.getStartMark(),
383 |  |
                             "expected a sequence, but found " + node.getNodeId(), node.getStartMark());
384 |  |
                 }
385 | 6 |
                 SequenceNode snode = (SequenceNode) node;
386 | 6 |
                 List<Object[]> pairs = new ArrayList<Object[]>(snode.getValue().size());
387 | 6 |
                 for (Node subnode : snode.getValue()) {
388 | 14 |
                     if (!(subnode instanceof MappingNode)) {
389 | 2 |
                         throw new ConstructorException("while constructingpairs", node.getStartMark(),
390 |  |
                                 "expected a mapping of length 1, but found " + subnode.getNodeId(),
391 |  |
                                 subnode.getStartMark());
392 |  |
                     }
393 | 12 |
                     MappingNode mnode = (MappingNode) subnode;
394 | 12 |
                     if (mnode.getValue().size() != 1) {
395 | 2 |
                         throw new ConstructorException("while constructing pairs", node.getStartMark(),
396 |  |
                                 "expected a single mapping item, but found " + mnode.getValue().size()
397 |  |
                                         + " items", mnode.getStartMark());
398 |  |
                     }
399 | 10 |
                     Node keyNode = mnode.getValue().get(0).getKeyNode();
400 | 10 |
                     Node valueNode = mnode.getValue().get(0).getValueNode();
401 | 10 |
                     Object key = constructObject(keyNode);
402 | 10 |
                     Object value = constructObject(valueNode);
403 | 10 |
                     pairs.add(new Object[] { key, value });
404 | 10 |
                 }
405 | 2 |
                 return pairs;
406 |  |
             }
407 |  |
         }
408 |  |
409 | 3984 |
         public class ConstructYamlSet implements Construct {
410 |  |
             public Object construct(Node node) {
411 | 19 |
                 if (node.isTwoStepsConstruction()) {
412 | 6 |
                     return createDefaultSet();
413 |  |
                 } else {
414 | 13 |
                     return constructSet((MappingNode) node);
415 |  |
                 }
416 |  |
             }
417 |  |
418 |  |
             @SuppressWarnings("unchecked")
419 |  |
             public void construct2ndStep(Node node, Object object) {
420 | 6 |
                 if (node.isTwoStepsConstruction()) {
421 | 6 |
                     constructSet2ndStep((MappingNode) node, (Set<Object>) object);
422 |  |
                 } else {
423 | 0 |
                     throw new YAMLException("Unexpected recursive set structure. Node: " + node);
424 |  |
                 }
425 | 6 |
             }
426 |  |
         }
427 |  |
428 | 3984 |
         public class ConstructYamlStr extends AbstractConstruct {
429 |  |
             public Object construct(Node node) {
430 | 248361 |
                 return constructScalar((ScalarNode) node);
431 |  |
             }
432 |  |
         }
433 |  |
434 | 3984 |
         public class ConstructYamlSeq implements Construct {
435 |  |
             public Object construct(Node node) {
436 | 10607 |
                 SequenceNode seqNode = (SequenceNode) node;
437 | 10605 |
                 if (node.isTwoStepsConstruction()) {
438 | 3 |
                     return createDefaultList((seqNode.getValue()).size());
439 |  |
                 } else {
440 | 10602 |
                     return constructSequence(seqNode);
441 |  |
                 }
442 |  |
             }
443 |  |
444 |  |
             @SuppressWarnings("unchecked")
445 |  |
             public void construct2ndStep(Node node, Object data) {
446 | 3 |
                 if (node.isTwoStepsConstruction()) {
447 | 3 |
                     constructSequenceStep2((SequenceNode) node, (List<Object>) data);
448 |  |
                 } else {
449 | 0 |
                     throw new YAMLException("Unexpected recursive sequence structure. Node: " + node);
450 |  |
                 }
451 | 3 |
             }
452 |  |
         }
453 |  |
454 | 3987 |
         public class ConstructYamlMap implements Construct {
455 |  |
             public Object construct(Node node) {
456 | 21175 |
                 if (node.isTwoStepsConstruction()) {
457 | 19 |
                     return createDefaultMap();
458 |  |
                 } else {
459 | 21156 |
                     return constructMapping((MappingNode) node);
460 |  |
                 }
461 |  |
             }
462 |  |
463 |  |
             @SuppressWarnings("unchecked")
464 |  |
             public void construct2ndStep(Node node, Object object) {
465 | 19 |
                 if (node.isTwoStepsConstruction()) {
466 | 19 |
                     constructMapping2ndStep((MappingNode) node, (Map<Object, Object>) object);
467 |  |
                 } else {
468 | 0 |
                     throw new YAMLException("Unexpected recursive mapping structure. Node: " + node);
469 |  |
                 }
470 | 19 |
             }
471 |  |
         }
472 |  |
473 | 1 |
         public static final class ConstructUndefined extends AbstractConstruct {
474 |  |
             public Object construct(Node node) {
475 | 2 |
                 throw new ConstructorException(null, null,
476 |  |
                         "could not determine a constructor for the tag " + node.getTag(),
477 |  |
                         node.getStartMark());
478 |  |
             }
479 |  |
         }
480 |  |
     }