public boolean handles(NodeTuple tuple) { if (tuple.getKeyNode() instanceof ScalarNode) { ScalarNode keyNode = (ScalarNode) tuple.getKeyNode(); return keyNode.getValue().startsWith("/"); } else { return false; } }
private ScalarNode cloneScalarNode(ScalarNode node, Map<String, String> parameters) { Pattern pattern = Pattern.compile("<<[^>]+>>"); String value = node.getValue(); Matcher matcher = pattern.matcher(value); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, ""); sb.append(resolveParameter(matcher.group(), parameters, node)); } matcher.appendTail(sb); return new ScalarNode( node.getTag(), sb.toString(), node.getStartMark(), node.getEndMark(), node.getStyle()); }
@SuppressWarnings("unchecked") private Object constructStandardJavaInstance( @SuppressWarnings("rawtypes") Class type, ScalarNode node) { Object result; if (type == String.class) { Construct stringConstructor = yamlConstructors.get(Tag.STR); result = stringConstructor.construct(node); } else if (type == Boolean.class || type == Boolean.TYPE) { Construct boolConstructor = yamlConstructors.get(Tag.BOOL); result = boolConstructor.construct(node); } else if (type == Character.class || type == Character.TYPE) { Construct charConstructor = yamlConstructors.get(Tag.STR); String ch = (String) charConstructor.construct(node); if (ch.length() == 0) { result = null; } else if (ch.length() != 1) { throw new YAMLException("Invalid node Character: '" + ch + "'; length: " + ch.length()); } else { result = Character.valueOf(ch.charAt(0)); } } else if (Date.class.isAssignableFrom(type)) { Construct dateConstructor = yamlConstructors.get(Tag.TIMESTAMP); Date date = (Date) dateConstructor.construct(node); if (type == Date.class) { result = date; } else { try { java.lang.reflect.Constructor<?> constr = type.getConstructor(long.class); result = constr.newInstance(date.getTime()); } catch (Exception e) { throw new YAMLException("Cannot construct: '" + type + "'"); } } } else if (type == Float.class || type == Double.class || type == Float.TYPE || type == Double.TYPE || type == BigDecimal.class) { if (type == BigDecimal.class) { result = new BigDecimal(node.getValue()); } else { Construct doubleConstructor = yamlConstructors.get(Tag.FLOAT); result = doubleConstructor.construct(node); if (type == Float.class || type == Float.TYPE) { result = new Float((Double) result); } } } else if (type == Byte.class || type == Short.class || type == Integer.class || type == Long.class || type == BigInteger.class || type == Byte.TYPE || type == Short.TYPE || type == Integer.TYPE || type == Long.TYPE) { Construct intConstructor = yamlConstructors.get(Tag.INT); result = intConstructor.construct(node); if (type == Byte.class || type == Byte.TYPE) { result = new Byte(result.toString()); } else if (type == Short.class || type == Short.TYPE) { result = new Short(result.toString()); } else if (type == Integer.class || type == Integer.TYPE) { result = Integer.parseInt(result.toString()); } else if (type == Long.class || type == Long.TYPE) { result = new Long(result.toString()); } else { // only BigInteger left result = new BigInteger(result.toString()); } } else if (Enum.class.isAssignableFrom(type)) { String enumValueName = node.getValue(); try { result = Enum.valueOf(type, enumValueName); } catch (Exception ex) { throw new YAMLException( "Unable to find enum value '" + enumValueName + "' for enum class: " + type.getName()); } } else if (Calendar.class.isAssignableFrom(type)) { ConstructYamlTimestamp contr = new ConstructYamlTimestamp(); contr.construct(node); result = contr.getCalendar(); } else { throw new YAMLException("Unsupported class: " + type); } return result; }
public Object construct(Node nnode) { ScalarNode node = (ScalarNode) nnode; Class<?> type = node.getType(); Object result; if (type.isPrimitive() || type == String.class || Number.class.isAssignableFrom(type) || type == Boolean.class || Date.class.isAssignableFrom(type) || type == Character.class || type == BigInteger.class || type == BigDecimal.class || Enum.class.isAssignableFrom(type) || Tag.BINARY.equals(node.getTag()) || Calendar.class.isAssignableFrom(type)) { // standard classes created directly result = constructStandardJavaInstance(type, node); } else { // there must be only 1 constructor with 1 argument java.lang.reflect.Constructor<?>[] javaConstructors = type.getConstructors(); int oneArgCount = 0; java.lang.reflect.Constructor<?> javaConstructor = null; for (java.lang.reflect.Constructor<?> c : javaConstructors) { if (c.getParameterTypes().length == 1) { oneArgCount++; javaConstructor = c; } } Object argument; if (javaConstructor == null) { throw new YAMLException("No single argument constructor found for " + type); } else if (oneArgCount == 1) { argument = constructStandardJavaInstance(javaConstructor.getParameterTypes()[0], node); } else { // TODO it should be possible to use implicit types instead // of forcing String. Resolver must be available here to // obtain the implicit tag. Then we can set the tag and call // callConstructor(node) to create the argument instance. // On the other hand it may be safer to require a custom // constructor to avoid guessing the argument class argument = constructScalar(node); try { javaConstructor = type.getConstructor(String.class); } catch (Exception e) { throw new ConstructorException( null, null, "Can't construct a java object for scalar " + node.getTag() + "; No String constructor found. Exception=" + e.getMessage(), node.getStartMark(), e); } } try { result = javaConstructor.newInstance(argument); } catch (Exception e) { throw new ConstructorException( null, null, "Can't construct a java object for scalar " + node.getTag() + "; exception=" + e.getMessage(), node.getStartMark(), e); } } return result; }
protected Object constructJavaBean2ndStep(MappingNode node, Object object) { flattenMapping(node); Class<? extends Object> beanType = node.getType(); List<NodeTuple> nodeValue = node.getValue(); for (NodeTuple tuple : nodeValue) { ScalarNode keyNode; if (tuple.getKeyNode() instanceof ScalarNode) { // key must be scalar keyNode = (ScalarNode) tuple.getKeyNode(); } else { throw new YAMLException("Keys must be scalars but found: " + tuple.getKeyNode()); } Node valueNode = tuple.getValueNode(); // keys can only be Strings keyNode.setType(String.class); String key = (String) constructObject(keyNode); try { Property property = getProperty(beanType, key); valueNode.setType(property.getType()); TypeDescription memberDescription = typeDefinitions.get(beanType); boolean typeDetected = false; if (memberDescription != null) { switch (valueNode.getNodeId()) { case sequence: SequenceNode snode = (SequenceNode) valueNode; Class<? extends Object> memberType = memberDescription.getListPropertyType(key); if (memberType != null) { snode.setListType(memberType); typeDetected = true; } else if (property.getType().isArray()) { snode.setListType(property.getType().getComponentType()); typeDetected = true; } break; case mapping: MappingNode mnode = (MappingNode) valueNode; Class<? extends Object> keyType = memberDescription.getMapKeyType(key); if (keyType != null) { mnode.setTypes(keyType, memberDescription.getMapValueType(key)); typeDetected = true; } break; default: // scalar } } if (!typeDetected && valueNode.getNodeId() != NodeId.scalar) { // only if there is no explicit TypeDescription Class<?>[] arguments = property.getActualTypeArguments(); if (arguments != null) { // type safe (generic) collection may contain the // proper class if (valueNode.getNodeId() == NodeId.sequence) { Class<?> t = arguments[0]; SequenceNode snode = (SequenceNode) valueNode; snode.setListType(t); } else if (valueNode.getTag().equals(Tag.SET)) { Class<?> t = arguments[0]; MappingNode mnode = (MappingNode) valueNode; mnode.setOnlyKeyType(t); mnode.setUseClassConstructor(true); } else if (property.getType().isAssignableFrom(Map.class)) { Class<?> ketType = arguments[0]; Class<?> valueType = arguments[1]; MappingNode mnode = (MappingNode) valueNode; mnode.setTypes(ketType, valueType); mnode.setUseClassConstructor(true); } else { // the type for collection entries cannot be // detected } } } Object value = constructObject(valueNode); property.set(object, value); } catch (Exception e) { throw new YAMLException( "Cannot create property=" + key + " for JavaBean=" + object + "; " + e.getMessage(), e); } } return object; }