Hi,
To simplify handling of custom types I have created a YambBuilder,
whose code I
am pasting at bottom. Here is, for example, how to use it to read
numeric
values, including optional percent sign ad double instead of float:
YamlBuilder builder = new YamlBuilder();
builder.addHelper(new YamlBuilder.BaseHelper(Double.class, "!
Double",
"^ *(-?[0-9]+(\\.[0-9]*)?)(%?) *$", "-123456789") {
public Object construct(Node node, String[] groups) {
double value = Double.parseDouble(groups[1]);
if ("%".equals(groups[3]))
value = value / 100.0;
return value;
}
});
yaml = builder.buildYaml();
And here is how it can be used with the [dice example](http://
www.google.com/url?sa=D&q=http://code.google.com/p/snakeyaml/wiki/Documentation%23Constructors,_representers,_resolvers&usg=AFQjCNFU-tzdF7IvTFiXHpd0BudH-liFBA):
YamlBuilder builder = new YamlBuilder();
builder.addHelper(new YamlBuilder.BaseHelper(Double.class, "!
Double",
"(\\d+)d(\\d+)"", "1234567890") {
public Object construct(Node node, String[] groups) {
return new Dice(Integer.parseInt(groups[1]),
Integer.parseInt(groups[2]));
}
});
yaml = builder.buildYaml();
Here is its source for anybode who wish to use it:
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.AbstractConstruct;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Represent;
import org.yaml.snakeyaml.representer.Representer;
public class YamlBuilder {
private List<Helper> helpers = new ArrayList<Helper>();
private Constructor constructor;
public void addHelper(Helper helper) {
helpers.add(helper);
}
public Yaml buildYaml() {
Yaml result = new Yaml(constructor = new MyConstructor(), new
MyRepresenter());
for (Helper helper : helpers) {
if (helper.getPattern() != null)
result.addImplicitResolver(new Tag(helper.getTag()),
helper.getPattern(),
helper.getFirstCharacterSet());
}
return result;
}
public Constructor getConstructor() {
return constructor;
}
/**
* A Helper is responsible for converting between instanced of
its type and Yaml.
* @param <E> The type to be converted.
*/
public interface Helper<E> {
/**
* @return The type itself.
*/
public Class<? extends E> getType();
/**
* Shall convert type instance to a node.
*/
public Node representData(E data);
/**
* Shall convert a node to a type instance.
* @param groups If a regular expression has been used to
recognize the
* type, this array contains the groups of the regular
expression,
* otherwise it is null.
*/
public E construct(Node node, String[] groups);
/**
* Shall return the tag used to recognize the type
*/
public String getTag();
/**
* @return The pattern (if any) used to recognize an instance
of this type
* (used to add an implicit resolver)
*/
public Pattern getPattern();
/**
* @return The set of first characters used to add an implicit
resolver.
*/
public String getFirstCharacterSet();
}
class MyRepresenter extends Representer {
public MyRepresenter() {
for (Helper helper : helpers)
representers.put(helper.getType(), new
RepresentType(helper));
}
}
class RepresentType implements Represent {
private Helper helper;
public RepresentType(Helper helper) {
this.helper = helper;
}
@Override
public Node representData(Object o) {
return helper.representData(o);
}
}
class MyConstructor extends Constructor {
public MyConstructor() {
for (Helper helper : helpers) {
yamlConstructors.put(new Tag(helper.getTag()), new
ConstructType(helper));
}
}
class ConstructType extends AbstractConstruct {
private Helper helper;
public ConstructType(Helper helper) {
this.helper = helper;
}
@Override
public Object construct(Node node) {
String[] groups = null;
String value = ((ScalarNode) node).getValue();
if (helper.getPattern() != null) {
Matcher m = helper.getPattern().matcher(value);
if (m.matches()) {
groups = new String[m.groupCount() + 1];
for (int i = 0; i <= m.groupCount(); i++)
groups[i] = m.group(i);
}
}
return helper.construct(node, groups);
}
}
}
public static abstract class BaseHelper implements Helper {
private Class<?> type;
private String tag;
private Pattern pattern;
private String firstCharacterSet;
public BaseHelper(Class<?> type) {
this(type, null);
}
public BaseHelper(Class<?> type, String tag) {
this(type, tag, null, null);
}
public BaseHelper(Class<?> type, String tag, String regex,
String firstCharacterSet) {
this.type = type;
this.tag = tag;
pattern = regex == null ? null : Pattern.compile(regex);
this.firstCharacterSet = firstCharacterSet;
}
@Override
public Class getType() {
return type;
}
@Override
public String getTag() {
return tag == null ? type.getName() : tag;
}
@Override
public String getFirstCharacterSet() {
return firstCharacterSet;
}
@Override
public Pattern getPattern() {
return pattern;
}
@Override
public Node representData(Object data) {
Node result = new ScalarNode(new Tag(getTag()),
data.toString(), null,
null, null);
return result;
}
}
}