1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
package org.yaml.snakeyaml.constructor; |
18 | |
|
19 | |
import java.beans.IntrospectionException; |
20 | |
import java.math.BigDecimal; |
21 | |
import java.math.BigInteger; |
22 | |
import java.util.ArrayList; |
23 | |
import java.util.Calendar; |
24 | |
import java.util.Collection; |
25 | |
import java.util.Date; |
26 | |
import java.util.HashMap; |
27 | |
import java.util.List; |
28 | |
import java.util.Map; |
29 | |
import java.util.Properties; |
30 | |
import java.util.Set; |
31 | |
import java.util.SortedMap; |
32 | |
import java.util.SortedSet; |
33 | |
import java.util.TreeMap; |
34 | |
import java.util.TreeSet; |
35 | |
|
36 | |
import org.yaml.snakeyaml.TypeDescription; |
37 | |
import org.yaml.snakeyaml.error.YAMLException; |
38 | |
import org.yaml.snakeyaml.introspector.Property; |
39 | |
import org.yaml.snakeyaml.nodes.MappingNode; |
40 | |
import org.yaml.snakeyaml.nodes.Node; |
41 | |
import org.yaml.snakeyaml.nodes.NodeId; |
42 | |
import org.yaml.snakeyaml.nodes.NodeTuple; |
43 | |
import org.yaml.snakeyaml.nodes.ScalarNode; |
44 | |
import org.yaml.snakeyaml.nodes.SequenceNode; |
45 | |
import org.yaml.snakeyaml.nodes.Tag; |
46 | |
|
47 | |
|
48 | |
|
49 | |
|
50 | 2508 | public class Constructor extends SafeConstructor { |
51 | |
private final Map<Tag, Class<? extends Object>> typeTags; |
52 | |
private final Map<Class<? extends Object>, TypeDescription> typeDefinitions; |
53 | |
|
54 | |
public Constructor() { |
55 | 3920 | this(Object.class); |
56 | 3920 | } |
57 | |
|
58 | |
|
59 | |
|
60 | |
|
61 | |
|
62 | |
|
63 | |
|
64 | |
public Constructor(Class<? extends Object> theRoot) { |
65 | 3961 | this(new TypeDescription(checkRoot(theRoot))); |
66 | 3960 | } |
67 | |
|
68 | |
|
69 | |
|
70 | |
|
71 | |
private static Class<? extends Object> checkRoot(Class<? extends Object> theRoot) { |
72 | 3961 | if (theRoot == null) { |
73 | 1 | throw new NullPointerException("Root class must be provided."); |
74 | |
} else |
75 | 3960 | return theRoot; |
76 | |
} |
77 | |
|
78 | 3971 | public Constructor(TypeDescription theRoot) { |
79 | 3971 | if (theRoot == null) { |
80 | 0 | throw new NullPointerException("Root type must be provided."); |
81 | |
} |
82 | 3971 | this.yamlConstructors.put(null, new ConstructYamlObject()); |
83 | 3971 | if (!Object.class.equals(theRoot.getType())) { |
84 | 48 | rootTag = new Tag(theRoot.getType()); |
85 | |
} |
86 | 3970 | typeTags = new HashMap<Tag, Class<? extends Object>>(); |
87 | 3970 | typeDefinitions = new HashMap<Class<? extends Object>, TypeDescription>(); |
88 | 3970 | yamlClassConstructors.put(NodeId.scalar, new ConstructScalar()); |
89 | 3970 | yamlClassConstructors.put(NodeId.mapping, new ConstructMapping()); |
90 | 3970 | yamlClassConstructors.put(NodeId.sequence, new ConstructSequence()); |
91 | 3970 | addTypeDescription(theRoot); |
92 | 3970 | } |
93 | |
|
94 | |
|
95 | |
|
96 | |
|
97 | |
|
98 | |
|
99 | |
|
100 | |
|
101 | |
|
102 | |
|
103 | |
public Constructor(String theRoot) throws ClassNotFoundException { |
104 | 4 | this(Class.forName(check(theRoot))); |
105 | 2 | } |
106 | |
|
107 | |
private static final String check(String s) { |
108 | 4 | if (s == null) { |
109 | 1 | throw new NullPointerException("Root type must be provided."); |
110 | |
} |
111 | 3 | if (s.trim().length() == 0) { |
112 | 1 | throw new YAMLException("Root type must be provided."); |
113 | |
} |
114 | 2 | return s; |
115 | |
} |
116 | |
|
117 | |
|
118 | |
|
119 | |
|
120 | |
|
121 | |
|
122 | |
|
123 | |
|
124 | |
|
125 | |
|
126 | |
|
127 | |
public TypeDescription addTypeDescription(TypeDescription definition) { |
128 | 4010 | if (definition == null) { |
129 | 2 | throw new NullPointerException("TypeDescription is required."); |
130 | |
} |
131 | 4008 | Tag tag = definition.getTag(); |
132 | 4008 | typeTags.put(tag, definition.getType()); |
133 | 4008 | return typeDefinitions.put(definition.getType(), definition); |
134 | |
} |
135 | |
|
136 | |
|
137 | |
|
138 | |
|
139 | |
|
140 | 3971 | protected class ConstructMapping implements Construct { |
141 | |
|
142 | |
|
143 | |
|
144 | |
|
145 | |
|
146 | |
|
147 | |
|
148 | |
|
149 | |
|
150 | |
|
151 | |
public Object construct(Node node) { |
152 | 1605 | MappingNode mnode = (MappingNode) node; |
153 | 1605 | if (Properties.class.isAssignableFrom(node.getType())) { |
154 | 2 | Properties properties = new Properties(); |
155 | 2 | if (!node.isTwoStepsConstruction()) { |
156 | 1 | constructMapping2ndStep(mnode, properties); |
157 | |
} else { |
158 | 1 | throw new YAMLException("Properties must not be recursive."); |
159 | |
} |
160 | 1 | return properties; |
161 | 1603 | } else if (SortedMap.class.isAssignableFrom(node.getType())) { |
162 | 2 | SortedMap<Object, Object> map = new TreeMap<Object, Object>(); |
163 | 2 | if (!node.isTwoStepsConstruction()) { |
164 | 1 | constructMapping2ndStep(mnode, map); |
165 | |
} |
166 | 2 | return map; |
167 | 1601 | } else if (Map.class.isAssignableFrom(node.getType())) { |
168 | 36 | if (node.isTwoStepsConstruction()) { |
169 | 2 | return createDefaultMap(); |
170 | |
} else { |
171 | 34 | return constructMapping(mnode); |
172 | |
} |
173 | 1565 | } else if (SortedSet.class.isAssignableFrom(node.getType())) { |
174 | 9 | SortedSet<Object> set = new TreeSet<Object>(); |
175 | |
|
176 | |
|
177 | 9 | constructSet2ndStep(mnode, set); |
178 | |
|
179 | 9 | return set; |
180 | 1556 | } else if (Collection.class.isAssignableFrom(node.getType())) { |
181 | 15 | if (node.isTwoStepsConstruction()) { |
182 | 1 | return createDefaultSet(); |
183 | |
} else { |
184 | 14 | return constructSet(mnode); |
185 | |
} |
186 | |
} else { |
187 | 1541 | if (node.isTwoStepsConstruction()) { |
188 | 32 | return createEmptyJavaBean(mnode); |
189 | |
} else { |
190 | 1509 | return constructJavaBean2ndStep(mnode, createEmptyJavaBean(mnode)); |
191 | |
} |
192 | |
} |
193 | |
} |
194 | |
|
195 | |
@SuppressWarnings("unchecked") |
196 | |
public void construct2ndStep(Node node, Object object) { |
197 | 36 | if (Map.class.isAssignableFrom(node.getType())) { |
198 | 3 | constructMapping2ndStep((MappingNode) node, (Map<Object, Object>) object); |
199 | 33 | } else if (Set.class.isAssignableFrom(node.getType())) { |
200 | 1 | constructSet2ndStep((MappingNode) node, (Set<Object>) object); |
201 | |
} else { |
202 | 32 | constructJavaBean2ndStep((MappingNode) node, object); |
203 | |
} |
204 | 36 | } |
205 | |
|
206 | |
protected Object createEmptyJavaBean(MappingNode node) { |
207 | |
try { |
208 | |
|
209 | |
|
210 | |
|
211 | |
|
212 | |
|
213 | |
|
214 | |
|
215 | |
|
216 | 1541 | java.lang.reflect.Constructor<?> c = node.getType().getDeclaredConstructor(); |
217 | 1538 | c.setAccessible(true); |
218 | 1538 | return c.newInstance(); |
219 | 3 | } catch (Exception e) { |
220 | 3 | throw new YAMLException(e); |
221 | |
} |
222 | |
} |
223 | |
|
224 | |
protected Object constructJavaBean2ndStep(MappingNode node, Object object) { |
225 | 1537 | flattenMapping(node); |
226 | 1537 | Class<? extends Object> beanType = node.getType(); |
227 | 1537 | List<NodeTuple> nodeValue = node.getValue(); |
228 | 1537 | for (NodeTuple tuple : nodeValue) { |
229 | |
ScalarNode keyNode; |
230 | 2519 | if (tuple.getKeyNode() instanceof ScalarNode) { |
231 | |
|
232 | 2518 | keyNode = (ScalarNode) tuple.getKeyNode(); |
233 | |
} else { |
234 | 1 | throw new YAMLException("Keys must be scalars but found: " + tuple.getKeyNode()); |
235 | |
} |
236 | 2518 | Node valueNode = tuple.getValueNode(); |
237 | |
|
238 | 2518 | keyNode.setType(String.class); |
239 | 2518 | String key = (String) constructObject(keyNode); |
240 | |
try { |
241 | 2518 | Property property = getProperty(beanType, key); |
242 | 2508 | valueNode.setType(property.getType()); |
243 | 2508 | TypeDescription memberDescription = typeDefinitions.get(beanType); |
244 | 2508 | boolean typeDetected = false; |
245 | 2508 | if (memberDescription != null) { |
246 | 656 | switch (valueNode.getNodeId()) { |
247 | |
case sequence: |
248 | 47 | SequenceNode snode = (SequenceNode) valueNode; |
249 | 47 | Class<? extends Object> memberType = memberDescription |
250 | |
.getListPropertyType(key); |
251 | 47 | if (memberType != null) { |
252 | 22 | snode.setListType(memberType); |
253 | 22 | typeDetected = true; |
254 | 25 | } else if (property.getType().isArray()) { |
255 | 1 | snode.setListType(property.getType().getComponentType()); |
256 | 1 | typeDetected = true; |
257 | |
} |
258 | |
break; |
259 | |
case mapping: |
260 | 152 | MappingNode mnode = (MappingNode) valueNode; |
261 | 152 | Class<? extends Object> keyType = memberDescription.getMapKeyType(key); |
262 | 152 | if (keyType != null) { |
263 | 27 | mnode.setTypes(keyType, memberDescription.getMapValueType(key)); |
264 | 27 | typeDetected = true; |
265 | |
} |
266 | |
break; |
267 | |
} |
268 | |
} |
269 | 2508 | if (!typeDetected && valueNode.getNodeId() != NodeId.scalar) { |
270 | |
|
271 | 298 | Class<?>[] arguments = property.getActualTypeArguments(); |
272 | 298 | if (arguments != null) { |
273 | |
|
274 | |
|
275 | 121 | if (valueNode.getNodeId() == NodeId.sequence) { |
276 | 79 | Class<?> t = arguments[0]; |
277 | 79 | SequenceNode snode = (SequenceNode) valueNode; |
278 | 79 | snode.setListType(t); |
279 | 79 | } else if (valueNode.getTag().equals(Tag.SET)) { |
280 | 20 | Class<?> t = arguments[0]; |
281 | 20 | MappingNode mnode = (MappingNode) valueNode; |
282 | 20 | mnode.setOnlyKeyType(t); |
283 | 20 | mnode.setUseClassConstructor(true); |
284 | 20 | } else if (property.getType().isAssignableFrom(Map.class)) { |
285 | 18 | Class<?> ketType = arguments[0]; |
286 | 18 | Class<?> valueType = arguments[1]; |
287 | 18 | MappingNode mnode = (MappingNode) valueNode; |
288 | 18 | mnode.setTypes(ketType, valueType); |
289 | 18 | mnode.setUseClassConstructor(true); |
290 | |
} else { |
291 | |
|
292 | |
|
293 | |
} |
294 | |
} |
295 | |
} |
296 | 2508 | Object value = constructObject(valueNode); |
297 | 2500 | property.set(object, value); |
298 | 19 | } catch (Exception e) { |
299 | 19 | throw new YAMLException("Cannot create property=" + key + " for JavaBean=" |
300 | |
+ object + "; " + e.getMessage(), e); |
301 | 2499 | } |
302 | 2499 | } |
303 | 1517 | return object; |
304 | |
} |
305 | |
|
306 | |
protected Property getProperty(Class<? extends Object> type, String name) |
307 | |
throws IntrospectionException { |
308 | 2518 | return getPropertyUtils().getProperty(type, name); |
309 | |
} |
310 | |
} |
311 | |
|
312 | |
|
313 | |
|
314 | |
|
315 | |
|
316 | |
|
317 | |
|
318 | 3971 | protected class ConstructYamlObject implements Construct { |
319 | |
|
320 | |
private Construct getConstructor(Node node) { |
321 | 1385 | Class<?> cl = getClassForNode(node); |
322 | 1379 | node.setType(cl); |
323 | |
|
324 | 1379 | Construct constructor = yamlClassConstructors.get(node.getNodeId()); |
325 | 1379 | return constructor; |
326 | |
} |
327 | |
|
328 | |
public Object construct(Node node) { |
329 | 1367 | Object result = null; |
330 | |
try { |
331 | 1367 | result = getConstructor(node).construct(node); |
332 | 37 | } catch (Exception e) { |
333 | 37 | throw new ConstructorException(null, null, "Can't construct a java object for " |
334 | |
+ node.getTag() + "; exception=" + e.getMessage(), node.getStartMark(), e); |
335 | 1330 | } |
336 | 1330 | return result; |
337 | |
} |
338 | |
|
339 | |
public void construct2ndStep(Node node, Object object) { |
340 | |
try { |
341 | 18 | getConstructor(node).construct2ndStep(node, object); |
342 | 0 | } catch (Exception e) { |
343 | 0 | throw new ConstructorException(null, null, |
344 | |
"Can't construct a second step for a java object for " + node.getTag() |
345 | |
+ "; exception=" + e.getMessage(), node.getStartMark(), e); |
346 | 18 | } |
347 | 18 | } |
348 | |
} |
349 | |
|
350 | |
|
351 | |
|
352 | |
|
353 | |
|
354 | 3984 | protected class ConstructScalar extends AbstractConstruct { |
355 | |
public Object construct(Node nnode) { |
356 | 4701 | ScalarNode node = (ScalarNode) nnode; |
357 | 4701 | Class<?> type = node.getType(); |
358 | |
Object result; |
359 | 4701 | if (type.isPrimitive() || type == String.class || Number.class.isAssignableFrom(type) |
360 | |
|| type == Boolean.class || Date.class.isAssignableFrom(type) |
361 | |
|| type == Character.class || type == BigInteger.class |
362 | |
|| type == BigDecimal.class || Enum.class.isAssignableFrom(type) |
363 | |
|| Tag.BINARY.equals(node.getTag()) || Calendar.class.isAssignableFrom(type)) { |
364 | |
|
365 | 4683 | result = constructStandardJavaInstance(type, node); |
366 | |
} else { |
367 | |
|
368 | 18 | java.lang.reflect.Constructor<?>[] javaConstructors = type.getConstructors(); |
369 | 18 | int oneArgCount = 0; |
370 | 18 | java.lang.reflect.Constructor<?> javaConstructor = null; |
371 | 55 | for (java.lang.reflect.Constructor<?> c : javaConstructors) { |
372 | 37 | if (c.getParameterTypes().length == 1) { |
373 | 23 | oneArgCount++; |
374 | 23 | javaConstructor = c; |
375 | |
} |
376 | |
} |
377 | |
Object argument; |
378 | 18 | if (javaConstructor == null) { |
379 | 1 | throw new YAMLException("No single argument constructor found for " + type); |
380 | 17 | } else if (oneArgCount == 1) { |
381 | 13 | argument = constructStandardJavaInstance( |
382 | |
javaConstructor.getParameterTypes()[0], node); |
383 | |
} else { |
384 | |
|
385 | |
|
386 | |
|
387 | |
|
388 | |
|
389 | |
|
390 | 4 | argument = constructScalar(node); |
391 | |
try { |
392 | 4 | javaConstructor = type.getConstructor(String.class); |
393 | 2 | } catch (Exception e) { |
394 | 2 | throw new ConstructorException(null, null, |
395 | |
"Can't construct a java object for scalar " + node.getTag() |
396 | |
+ "; No String constructor found. Exception=" |
397 | |
+ e.getMessage(), node.getStartMark(), e); |
398 | 2 | } |
399 | |
} |
400 | |
try { |
401 | 14 | result = javaConstructor.newInstance(argument); |
402 | 1 | } catch (Exception e) { |
403 | 1 | throw new ConstructorException(null, null, |
404 | |
"Can't construct a java object for scalar " + node.getTag() |
405 | |
+ "; exception=" + e.getMessage(), node.getStartMark(), e); |
406 | 13 | } |
407 | |
} |
408 | 4692 | return result; |
409 | |
} |
410 | |
|
411 | |
@SuppressWarnings("unchecked") |
412 | |
private Object constructStandardJavaInstance(@SuppressWarnings("rawtypes") Class type, |
413 | |
ScalarNode node) { |
414 | |
Object result; |
415 | 4696 | if (type == String.class) { |
416 | 3300 | Construct stringConstructor = yamlConstructors.get(Tag.STR); |
417 | 3300 | result = stringConstructor.construct(node); |
418 | 3300 | } else if (type == Boolean.class || type == Boolean.TYPE) { |
419 | 10 | Construct boolConstructor = yamlConstructors.get(Tag.BOOL); |
420 | 10 | result = boolConstructor.construct(node); |
421 | 10 | } else if (type == Character.class || type == Character.TYPE) { |
422 | 9 | Construct charConstructor = yamlConstructors.get(Tag.STR); |
423 | 9 | String ch = (String) charConstructor.construct(node); |
424 | 9 | if (ch.length() == 0) { |
425 | 1 | result = null; |
426 | 8 | } else if (ch.length() != 1) { |
427 | 1 | throw new YAMLException("Invalid node Character: '" + ch + "'; length: " |
428 | |
+ ch.length()); |
429 | |
} else { |
430 | 7 | result = new Character(ch.charAt(0)); |
431 | |
} |
432 | 8 | } else if (Date.class.isAssignableFrom(type)) { |
433 | 70 | Construct dateConstructor = yamlConstructors.get(Tag.TIMESTAMP); |
434 | 70 | Date date = (Date) dateConstructor.construct(node); |
435 | 70 | if (type == Date.class) { |
436 | 57 | result = date; |
437 | |
} else { |
438 | |
try { |
439 | 13 | java.lang.reflect.Constructor<?> constr = type.getConstructor(long.class); |
440 | 13 | result = constr.newInstance(date.getTime()); |
441 | 1 | } catch (Exception e) { |
442 | 1 | throw new YAMLException("Cannot construct: '" + type + "'"); |
443 | 12 | } |
444 | |
} |
445 | 69 | } else if (type == Float.class || type == Double.class || type == Float.TYPE |
446 | |
|| type == Double.TYPE || type == BigDecimal.class) { |
447 | 55 | if (type == BigDecimal.class) { |
448 | 5 | result = new BigDecimal(node.getValue()); |
449 | |
} else { |
450 | 50 | Construct doubleConstructor = yamlConstructors.get(Tag.FLOAT); |
451 | 50 | result = doubleConstructor.construct(node); |
452 | 50 | if (type == Float.class || type == Float.TYPE) { |
453 | 20 | result = new Float((Double) result); |
454 | |
} |
455 | 50 | } |
456 | 1252 | } else if (type == Byte.class || type == Short.class || type == Integer.class |
457 | |
|| type == Long.class || type == BigInteger.class || type == Byte.TYPE |
458 | |
|| type == Short.TYPE || type == Integer.TYPE || type == Long.TYPE) { |
459 | 1217 | Construct intConstructor = yamlConstructors.get(Tag.INT); |
460 | 1217 | result = intConstructor.construct(node); |
461 | 1217 | if (type == Byte.class || type == Byte.TYPE) { |
462 | 6 | result = new Byte(result.toString()); |
463 | 1211 | } else if (type == Short.class || type == Short.TYPE) { |
464 | 6 | result = new Short(result.toString()); |
465 | 1205 | } else if (type == Integer.class || type == Integer.TYPE) { |
466 | 1188 | result = new Integer(result.toString()); |
467 | 17 | } else if (type == Long.class || type == Long.TYPE) { |
468 | 14 | result = new Long(result.toString()); |
469 | |
} else { |
470 | |
|
471 | 3 | result = new BigInteger(result.toString()); |
472 | |
} |
473 | 1217 | } else if (Enum.class.isAssignableFrom(type)) { |
474 | 26 | String enumValueName = node.getValue(); |
475 | |
try { |
476 | 26 | result = Enum.valueOf(type, enumValueName); |
477 | 1 | } catch (Exception ex) { |
478 | 1 | throw new YAMLException("Unable to find enum value '" + enumValueName |
479 | |
+ "' for enum class: " + type.getName()); |
480 | 25 | } |
481 | 25 | } else if (Calendar.class.isAssignableFrom(type)) { |
482 | 7 | ConstructYamlTimestamp contr = new ConstructYamlTimestamp(); |
483 | 7 | contr.construct(node); |
484 | 7 | result = contr.getCalendar(); |
485 | 7 | } else { |
486 | 2 | throw new YAMLException("Unsupported class: " + type); |
487 | |
} |
488 | 4691 | return result; |
489 | |
} |
490 | |
} |
491 | |
|
492 | |
|
493 | |
|
494 | |
|
495 | |
|
496 | 3971 | protected class ConstructSequence implements Construct { |
497 | |
@SuppressWarnings("unchecked") |
498 | |
public Object construct(Node node) { |
499 | 139 | SequenceNode snode = (SequenceNode) node; |
500 | 139 | if (Set.class.isAssignableFrom(node.getType())) { |
501 | 11 | if (node.isTwoStepsConstruction()) { |
502 | 2 | throw new YAMLException("Set cannot be recursive."); |
503 | |
} else { |
504 | 9 | return constructSet(snode); |
505 | |
} |
506 | 128 | } else if (Collection.class.isAssignableFrom(node.getType())) { |
507 | 81 | if (node.isTwoStepsConstruction()) { |
508 | 1 | return createDefaultList(snode.getValue().size()); |
509 | |
} else { |
510 | 80 | return constructSequence(snode); |
511 | |
} |
512 | 47 | } else if (node.getType().isArray()) { |
513 | 23 | if (node.isTwoStepsConstruction()) { |
514 | 2 | return createArray(node.getType(), snode.getValue().size()); |
515 | |
} else { |
516 | 21 | return constructArray(snode); |
517 | |
} |
518 | |
} else { |
519 | |
|
520 | 24 | List<java.lang.reflect.Constructor<?>> possibleConstructors = new ArrayList<java.lang.reflect.Constructor<?>>( |
521 | |
snode.getValue().size()); |
522 | |
for (java.lang.reflect.Constructor<?> constructor : node.getType() |
523 | 79 | .getConstructors()) { |
524 | 55 | if (snode.getValue().size() == constructor.getParameterTypes().length) { |
525 | 33 | possibleConstructors.add(constructor); |
526 | |
} |
527 | |
} |
528 | 24 | if (!possibleConstructors.isEmpty()) { |
529 | 23 | if (possibleConstructors.size() == 1) { |
530 | 16 | Object[] argumentList = new Object[snode.getValue().size()]; |
531 | 16 | java.lang.reflect.Constructor<?> c = possibleConstructors.get(0); |
532 | 16 | int index = 0; |
533 | 16 | for (Node argumentNode : snode.getValue()) { |
534 | 38 | Class<?> type = c.getParameterTypes()[index]; |
535 | |
|
536 | 38 | argumentNode.setType(type); |
537 | 38 | argumentList[index++] = constructObject(argumentNode); |
538 | 38 | } |
539 | |
|
540 | |
try { |
541 | 16 | return c.newInstance(argumentList); |
542 | 0 | } catch (Exception e) { |
543 | 0 | throw new YAMLException(e); |
544 | |
} |
545 | |
} |
546 | |
|
547 | |
|
548 | 7 | List<Object> argumentList = (List<Object>) constructSequence(snode); |
549 | 7 | Class<?>[] parameterTypes = new Class[argumentList.size()]; |
550 | 7 | int index = 0; |
551 | 7 | for (Object parameter : argumentList) { |
552 | 21 | parameterTypes[index] = parameter.getClass(); |
553 | 21 | index++; |
554 | |
} |
555 | |
|
556 | 7 | for (java.lang.reflect.Constructor<?> c : possibleConstructors) { |
557 | 12 | Class<?>[] argTypes = c.getParameterTypes(); |
558 | 12 | boolean foundConstructor = true; |
559 | 33 | for (int i = 0; i < argTypes.length; i++) { |
560 | 27 | if (!wrapIfPrimitive(argTypes[i]).isAssignableFrom(parameterTypes[i])) { |
561 | 6 | foundConstructor = false; |
562 | 6 | break; |
563 | |
} |
564 | |
} |
565 | 12 | if (foundConstructor) { |
566 | |
try { |
567 | 6 | return c.newInstance(argumentList.toArray()); |
568 | 0 | } catch (Exception e) { |
569 | 0 | throw new YAMLException(e); |
570 | |
} |
571 | |
} |
572 | 6 | } |
573 | |
} |
574 | 2 | throw new YAMLException("No suitable constructor with " |
575 | |
+ String.valueOf(snode.getValue().size()) + " arguments found for " |
576 | |
+ node.getType()); |
577 | |
|
578 | |
} |
579 | |
} |
580 | |
|
581 | |
private final Class<? extends Object> wrapIfPrimitive(Class<?> clazz) { |
582 | 27 | if (!clazz.isPrimitive()) { |
583 | 5 | return clazz; |
584 | |
} |
585 | 22 | if (clazz == Integer.TYPE) { |
586 | 15 | return Integer.class; |
587 | |
} |
588 | 7 | if (clazz == Float.TYPE) { |
589 | 0 | return Float.class; |
590 | |
} |
591 | 7 | if (clazz == Double.TYPE) { |
592 | 3 | return Double.class; |
593 | |
} |
594 | 4 | if (clazz == Boolean.TYPE) { |
595 | 2 | return Boolean.class; |
596 | |
} |
597 | 2 | if (clazz == Long.TYPE) { |
598 | 2 | return Long.class; |
599 | |
} |
600 | 0 | if (clazz == Character.TYPE) { |
601 | 0 | return Character.class; |
602 | |
} |
603 | 0 | if (clazz == Short.TYPE) { |
604 | 0 | return Short.class; |
605 | |
} |
606 | 0 | if (clazz == Byte.TYPE) { |
607 | 0 | return Byte.class; |
608 | |
} |
609 | 0 | throw new YAMLException("Unexpected primitive " + clazz); |
610 | |
} |
611 | |
|
612 | |
@SuppressWarnings("unchecked") |
613 | |
public void construct2ndStep(Node node, Object object) { |
614 | 3 | SequenceNode snode = (SequenceNode) node; |
615 | 3 | if (List.class.isAssignableFrom(node.getType())) { |
616 | 1 | List<Object> list = (List<Object>) object; |
617 | 1 | constructSequenceStep2(snode, list); |
618 | 1 | } else if (node.getType().isArray()) { |
619 | 2 | constructArrayStep2(snode, object); |
620 | |
} else { |
621 | 0 | throw new YAMLException("Immutable objects cannot be recursive."); |
622 | |
} |
623 | 3 | } |
624 | |
} |
625 | |
|
626 | |
protected Class<?> getClassForNode(Node node) { |
627 | 1387 | Class<? extends Object> classForTag = typeTags.get(node.getTag()); |
628 | 1387 | if (classForTag == null) { |
629 | 310 | String name = node.getTag().getClassName(); |
630 | |
Class<?> cl; |
631 | |
try { |
632 | 307 | cl = getClassForName(name); |
633 | 2 | } catch (ClassNotFoundException e) { |
634 | 2 | throw new YAMLException("Class not found: " + name); |
635 | 304 | } |
636 | 304 | typeTags.put(node.getTag(), cl); |
637 | 304 | return cl; |
638 | |
} else { |
639 | 1077 | return classForTag; |
640 | |
} |
641 | |
} |
642 | |
|
643 | |
protected Class<?> getClassForName(String name) throws ClassNotFoundException { |
644 | 321 | return Class.forName(name); |
645 | |
} |
646 | |
} |