All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.deephacks.tools4j.config.internal.core.runtime.ObjectToBeanConverter Maven / Gradle / Ivy

There is a newer version: 0.15.0
Show newest version
package org.deephacks.tools4j.config.internal.core.runtime;

import com.google.common.base.Optional;
import org.deephacks.tools4j.config.Config;
import org.deephacks.tools4j.config.Id;
import org.deephacks.tools4j.config.internal.core.runtime.ClassIntrospector.FieldWrap;
import org.deephacks.tools4j.config.internal.core.runtime.ClassToSchemaConverter.ConfigClass;
import org.deephacks.tools4j.config.model.Bean;
import org.deephacks.tools4j.config.model.Bean.BeanId;
import org.deephacks.tools4j.config.model.Schema;
import org.deephacks.tools4j.config.spi.Conversion;
import org.deephacks.tools4j.config.spi.Conversion.Converter;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public class ObjectToBeanConverter implements Converter {
    Conversion conversion = Conversion.get();

    @Override
    public Bean convert(Object source, Class specificType) {
        ClassIntrospector i = new ClassIntrospector(source.getClass());
        Bean bean = Bean.create(getBeanId(source));

        for (FieldWrap field : i.getFieldList()) {
            field.checkNotPublic();
            Object value = field.getValue(source);
            if (value == null) {
                continue;
            }
            addProperty(value, bean, field);
        }

        Schema schema = conversion.convert(source.getClass(), Schema.class);
        bean.set(schema);
        return bean;
    }

    @SuppressWarnings("unchecked")
    private void addProperty(Object value, Bean bean, FieldWrap fieldwrap) {
        Optional optional = fieldwrap.getAnnotation();
        ConfigClass field = new ConfigClass();
        if (!optional.isPresent()) {
            field.name = fieldwrap.getFieldName();
            field.desc = "";
        } else {
            Config config = (Config) optional.get();
            field.name = config.name();
            field.desc = config.desc();
        }
        String name = field.name;
        if (name == null || "".equals(name)) {
            name = fieldwrap.getFieldName();
        }
        if (fieldwrap.isCollection()) {
            Class paramClass = fieldwrap.getType();
            Collection values = (Collection) value;
            if (paramClass.isAnnotationPresent(Config.class)) {
                for (Object object : values) {
                    bean.addReference(name, getRecursiveBeanId(object));
                }
            } else {
                bean.addProperty(name, conversion.convert(values, String.class));
            }
        } else if (fieldwrap.isMap()) {
            Class paramClass = fieldwrap.getMapParamTypes().get(1);
            Map values = (Map) value;
            if (paramClass.isAnnotationPresent(Config.class)) {
                for (Object object : values.values()) {
                    bean.addReference(name, getRecursiveBeanId(object));
                }
            }
        } else {
            if (value.getClass().isAnnotationPresent(Config.class)) {
                bean.addReference(name, getRecursiveBeanId(value));
            } else {
                String converted = conversion.convert(value, String.class);
                bean.setProperty(name, converted);
            }
        }
    }

    private BeanId getBeanId(Object bean) {
        Config config = bean.getClass().getAnnotation(Config.class);
        if (config == null) {
            throw new IllegalArgumentException("Bean [" + bean
                    + "] does not have a @Config annotation.");
        }
        String schemaName = config.name();
        if (schemaName == null || "".equals(schemaName.trim())) {
            schemaName = bean.getClass().getName();
        }
        ClassIntrospector i = new ClassIntrospector(bean.getClass());
        List ids = i.getFieldList(Id.class);
        if (ids == null || ids.size() != 1) {
            // a get
            return BeanId.createSingleton(schemaName);
        }
        FieldWrap id = ids.get(0);
        BeanId targetId;
        Object idValue = id.getValue(bean);
        if (idValue == null) {
            throw new IllegalArgumentException("Cannot convert an objects that have empty id ["
                    + bean + "]");
        }
        targetId = BeanId.create(id.getValue(bean).toString(), schemaName);
        return targetId;
    }

    private BeanId getRecursiveBeanId(Object bean) {
        BeanId targetId = getBeanId(bean);
        Bean targetBean = conversion.convert(bean, Bean.class);
        targetBean.set(conversion.convert(bean.getClass(), Schema.class));
        targetId.setBean(targetBean);
        return targetId;
    }
}