CubeEngine / ReflecT

Typesafe serialization of data for Java
http://cubeisland.de
MIT License
13 stars 2 forks source link

Extract Section converting to a converter #18

Closed Faithcaio closed 9 years ago

Faithcaio commented 10 years ago

currently converting sections is done in the Codec directly. Having a converter would allow converting sections externally

tlaundal commented 10 years ago

Here is the super hacky converter I made that does this. It uses reflection.

import de.cubeisland.engine.reflect.Reflected;
import de.cubeisland.engine.reflect.Section;
import de.cubeisland.engine.reflect.codec.ConverterManager;
import de.cubeisland.engine.reflect.codec.converter.Converter;
import de.cubeisland.engine.reflect.exception.ConversionException;
import de.cubeisland.engine.reflect.node.MapNode;
import de.cubeisland.engine.reflect.node.Node;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class SectionConverter<S extends Section> implements Converter<S>
{

    private final Reflected reflected;
    private final S defaultSection;

    public SectionConverter(Reflected reflected, S defaultSection)
    {
        this.reflected = reflected;
        this.defaultSection = defaultSection;
    }

    @Override
    public Node toNode(S section, ConverterManager converterManager) throws ConversionException
    {
        try
        {
            Method method = reflected.getCodec().getClass().getMethod("convertSection", Section.class, Section.class,
                                                                      Reflected.class);
            method.setAccessible(true);
            return (MapNode)method.invoke(reflected.getCodec(), defaultSection, section, reflected);
        }
        catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex)
        {
            throw ConversionException.of(this, section, "Could not convert because of reflection error", ex);
        }
    }

    @Override
    public S fromNode(Node node, ConverterManager converterManager) throws ConversionException
    {
        if (!(node instanceof MapNode))
        {
            throw ConversionException.of(this, node, "Node must be a map.");
        }
        MapNode map = (MapNode)node;
        String className = map.getExactNode("className").asText();
        try
        {
            Class<? extends S> clazz = (Class<? extends S>)Class.forName(className);
            S section = clazz.newInstance();

            Method method = reflected.getCodec().getClass().getMethod("dumpIntoSection", Section.class, Section.class,
                                                                      MapNode.class, Reflected.class);
            method.setAccessible(true);
            method.invoke(reflected.getCodec(), defaultSection, section, map, reflected);
            return section;
        }
        catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException |
                InstantiationException ex)
        {
            throw ConversionException.of(this, node, "Could not convert because of reflection error", ex);
        }
    }
}