JsonDecoder.java
package com.mackenziehigh.autumn.util.json;
import autumn.lang.Module;
import autumn.lang.Record;
import com.google.common.collect.Maps;
import com.mackenziehigh.autumn.util.json.parser.Parser;
import com.mackenziehigh.autumn.util.json.parser.Visitor;
import com.mackenziehigh.snowflake.ITreeNode;
import com.mackenziehigh.snowflake.ParserOutput;
import com.mackenziehigh.snowflake.ParsingFailedException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* Instances of this class are used to convert a JSON string to an Autumn object.
*
* @author Mackenzie High
*/
public final class JsonDecoder
{
private final Map<Set<String>, Record> types = Maps.newHashMap();
public Object decode(final Module module,
final String input)
{
try
{
loadTypes(module);
final Parser parser = new Parser();
final ParserOutput output = parser.parse(input);
output.requireSuccess();
final ITreeNode tree = output.parseTree();
final Visitor converter = new Visitor();
converter.prototypes.putAll(types);
converter.visitUnknown(tree);
final Object result = converter.stack.pop();
return result;
}
catch (ParsingFailedException ex)
{
throw new IllegalArgumentException(ex);
}
}
private void loadTypes(final Module module)
{
for (Class type : module.info().structs())
{
loadType(type);
}
for (Class type : module.info().tuples())
{
loadType(type);
}
}
private void loadType(final Class type)
{
try
{
final Record instance = (Record) type.getMethod("instance").invoke(null);
final Set<String> keys = new TreeSet(instance.keys());
types.put(keys, instance);
}
catch (IllegalAccessException ex)
{
throw new IllegalArgumentException(ex);
}
catch (NoSuchMethodException ex)
{
throw new IllegalArgumentException(ex);
}
catch (SecurityException ex)
{
throw new IllegalArgumentException(ex);
}
catch (InvocationTargetException ex)
{
throw new IllegalArgumentException(ex);
}
}
}