net.mindengine.blogix.db.readers.ObjectReader.java Source code

Java tutorial

Introduction

Here is the source code for net.mindengine.blogix.db.readers.ObjectReader.java

Source

/*******************************************************************************
* Copyright 2013 Ivan Shubin http://mindengine.net
* 
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* 
*   http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package net.mindengine.blogix.db.readers;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import net.mindengine.blogix.db.Entry;

import org.apache.commons.lang3.StringUtils;

public class ObjectReader<T> implements Reader<T> {

    private Map<String, Field> objectFields = null;
    private EntryReader entryConverter;
    private Class<T> objectType;

    public ObjectReader(Class<T> objectType, EntryReader entryConverter) {
        this.objectType = objectType;
        this.entryConverter = entryConverter;
    }

    @Override
    public T convert(String fileName) {
        Entry entry = entryConverter.convert(fileName);
        return convert(entry);
    }

    public T convert(Entry entry) {
        try {
            Constructor<T> constructor = objectType.getConstructor();
            T objectInstance = constructor.newInstance();

            Set<String> allEntryFields = entry.getAllFieldNames();

            for (String entryFieldName : allEntryFields) {
                resolveField(entryFieldName, entry, objectInstance);
            }

            Field field = getObjectFields().get("id");
            if (field != null) {
                setFieldValue(objectInstance, field, entry.id());
            }

            setEntryItselfIntoObject(entry, objectInstance);
            return objectInstance;
        } catch (Exception e) {
            throw new RuntimeException("Cannot bind entries to object " + objectType.getClass(), e);
        }
    }

    private void setEntryItselfIntoObject(Entry entry, T objectInstance)
            throws IllegalArgumentException, IllegalAccessException {
        Field entryField = getObjectFields().get("entry");
        if (entryField != null) {
            if (entryField.getType().equals(Entry.class)) {
                entryField.setAccessible(true);
                entryField.set(objectInstance, entry);
            }
        }
    }

    private void resolveField(String entryFieldName, Entry entry, T objectInstance) {
        Field field = getObjectFields().get(entryFieldName);
        if (field != null) {
            setFieldValue(objectInstance, field, entry.field(entryFieldName));
        }
    }

    private Map<String, Field> getObjectFields() {
        if (objectFields == null) {
            objectFields = getAllFieldsOfObjectType(objectType);
        }
        return objectFields;
    }

    private void setFieldValue(T objectInstance, Field field, String fieldValue) {
        Object convertedFieldValue = convertFieldValue(fieldValue, field);
        field.setAccessible(true);

        try {
            field.set(objectInstance, convertedFieldValue);
        } catch (Exception e) {
            throw new RuntimeException("Cannot set value to field " + field.toString());
        }
    }

    private Object convertFieldValue(String fieldValue, Field field) {
        if (fieldValue == null) {
            return null;
        }
        Class<?> type = field.getType();
        try {
            return convertStringValueToType(fieldValue, type);
        } catch (Exception e) {
            throw new IllegalArgumentException("Cannot convert value '" + StringUtils.abbreviate(fieldValue, 20)
                    + "' to field " + field.toString(), e);
        }
    }

    private Object convertStringValueToType(String fieldValue, Class<?> type) {
        if (type.equals(String.class)) {
            return fieldValue;
        } else if (type.equals(Integer.class) || type.equals(int.class)) {
            return Integer.parseInt(fieldValue.trim());
        } else if (type.equals(Long.class) || type.equals(long.class)) {
            return Long.parseLong(fieldValue.trim());
        } else if (type.equals(Float.class) || type.equals(float.class)) {
            return Float.parseFloat(fieldValue.trim());
        } else if (type.equals(Double.class) || type.equals(double.class)) {
            return Double.parseDouble(fieldValue.trim());
        } else if (type.equals(Boolean.class) || type.equals(boolean.class)) {
            return Boolean.parseBoolean(fieldValue.trim());
        } else if (type.equals(Date.class)) {
            return parseDate(fieldValue);
        } else if (type.equals(String[].class)) {
            if (fieldValue.trim().isEmpty()) {
                return new String[] {};
            }

            String[] items = fieldValue.split(",");
            String[] array = new String[items.length];
            for (int i = 0; i < array.length; i++) {
                array[i] = (String) convertStringValueToType(items[i].trim(), String.class);
            }
            return array;
        }

        throw new IllegalArgumentException(
                "Cannot convert value '" + StringUtils.abbreviate(fieldValue, 20) + "' to type " + type);
    }

    private Date parseDate(String fieldValue) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd hh:mm");
        try {
            return sdf.parse(fieldValue.trim());
        } catch (ParseException e) {
            throw new RuntimeException("Error parsing date: " + fieldValue, e);
        }
    }

    private Map<String, Field> getAllFieldsOfObjectType(Class<?> objectType) {
        Map<String, Field> fields = convertOnlyNonStaticFieldsToMap(objectType.getDeclaredFields());

        Class<?> superClass = objectType.getSuperclass();
        if (superClass != null) {
            fields.putAll(getAllFieldsOfObjectType(superClass));
        }
        return fields;
    }

    private Map<String, Field> convertOnlyNonStaticFieldsToMap(Field[] declaredFields) {
        Map<String, Field> fields = new HashMap<String, Field>();

        for (Field field : declaredFields) {
            if (!Modifier.isStatic(field.getModifiers())) {
                fields.put(field.getName(), field);
            }
        }
        return fields;
    }
}