com.bugull.mongo.BuguMapper.java Source code

Java tutorial

Introduction

Here is the source code for com.bugull.mongo.BuguMapper.java

Source

/*
 * Copyright (c) www.bugull.com
 * 
 * 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 com.bugull.mongo;

import com.bugull.mongo.annotations.Default;
import com.bugull.mongo.annotations.Ref;
import com.bugull.mongo.annotations.RefList;
import com.bugull.mongo.cache.DaoCache;
import com.bugull.mongo.cache.FieldsCache;
import com.bugull.mongo.exception.FieldException;
import com.bugull.mongo.utils.DataType;
import com.bugull.mongo.utils.FieldUtil;
import com.bugull.mongo.misc.InternalDao;
import com.bugull.mongo.utils.MapperUtil;
import com.bugull.mongo.utils.Operator;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;

/**
 * The utility class for ODM(Object Document Mapping), mainly fetch lazy and cascade data.
 * 
 * @author Frank Wen(xbwen@hotmail.com)
 */
@SuppressWarnings("unchecked")
public class BuguMapper {

    private final static Logger logger = Logger.getLogger(BuguMapper.class);

    /**
     * Convert to JSON string.
     * @param obj
     * @return 
     */
    public static String toJsonString(Object obj) {
        DBObject dbo = MapperUtil.toDBObject(obj);
        BasicDBObject bdbo = (BasicDBObject) dbo;
        return bdbo.toString();
    }

    /**
     * Fetch out the lazy @Property, @Embed, @EmbedList field of a list
     * @param list the list needs to operate on
     */
    public static void fetchLazy(List list) {
        for (Object o : list) {
            if (o != null) {
                BuguEntity obj = (BuguEntity) o;
                BuguEntity newObj = (BuguEntity) DaoCache.getInstance().get(obj.getClass()).findOne(obj.getId());
                FieldUtil.copy(newObj, obj);
            }
        }
    }

    /**
     * Fetch out the lazy @Property, @Embed, @EmbedList field of an entity.
     * <p>The entity must be an element of a list.</p>
     * @param obj the entity needs to operate on
     */
    public static void fetchLazy(BuguEntity obj) {
        BuguEntity newObj = (BuguEntity) DaoCache.getInstance().get(obj.getClass()).findOne(obj.getId());
        FieldUtil.copy(newObj, obj);
    }

    /**
     * Fetch out the cascade @Ref or @RefList entity.
     * @param obj the entity needs to operate on
     * @param names the fields' names
     */
    public static void fetchCascade(BuguEntity obj, String... names) {
        if (obj != null) {
            for (String name : names) {
                String remainder = null;
                int index = name.indexOf(".");
                if (index > 0) {
                    remainder = name.substring(index + 1);
                    name = name.substring(0, index);
                }
                fetchOneLevel(obj, name);
                if (remainder != null) {
                    fetchRemainder(obj, name, remainder);
                }
            }
        }
    }

    /**
     * Fetch out the cascade @Ref or @RefList entity.
     * @param list the list needs to operate on
     * @param names the fields' names
     */
    public static void fetchCascade(List list, String... names) {
        for (Object o : list) {
            if (o != null) {
                BuguEntity obj = (BuguEntity) o;
                fetchCascade(obj, names);
            }
        }
    }

    private static void fetchOneLevel(BuguEntity obj, String fieldName) {
        Field field = null;
        try {
            field = FieldsCache.getInstance().getField(obj.getClass(), fieldName);
        } catch (FieldException ex) {
            logger.error(ex.getMessage(), ex);
        }
        if (field.getAnnotation(Ref.class) != null) {
            fetchRef(obj, field);
        } else if (field.getAnnotation(RefList.class) != null) {
            fetchRefList(obj, field);
        }
    }

    private static void fetchRemainder(BuguEntity obj, String fieldName, String remainder) {
        Field field = null;
        try {
            field = FieldsCache.getInstance().getField(obj.getClass(), fieldName);
        } catch (FieldException ex) {
            logger.error(ex.getMessage(), ex);
        }
        Object value = FieldUtil.get(obj, field);
        if (value == null) {
            return;
        }
        if (field.getAnnotation(Ref.class) != null) {
            BuguEntity entity = (BuguEntity) value;
            fetchCascade(entity, remainder);
        } else if (field.getAnnotation(RefList.class) != null) {
            Class type = field.getType();
            if (DataType.isMapType(type)) {
                Map<Object, BuguEntity> map = (Map<Object, BuguEntity>) value;
                for (Entry<Object, BuguEntity> entry : map.entrySet()) {
                    fetchCascade(entry.getValue(), remainder);
                }
            } else {
                Collection<BuguEntity> collection = (Collection<BuguEntity>) value;
                for (BuguEntity entity : collection) {
                    fetchCascade(entity, remainder);
                }
            }
        }
    }

    private static void fetchRef(BuguEntity obj, Field field) {
        Object o = FieldUtil.get(obj, field);
        if (o == null) {
            return;
        }
        BuguEntity refObj = (BuguEntity) o;
        String id = refObj.getId();
        Class cls = FieldUtil.getRealType(field);
        InternalDao dao = DaoCache.getInstance().get(cls);
        Object value = dao.findOne(id);
        FieldUtil.set(obj, field, value);
    }

    private static void fetchRefList(BuguEntity obj, Field field) {
        Class<?> type = field.getType();
        if (type.isArray()) {
            fetchArray(obj, field, type.getComponentType());
        } else {
            ParameterizedType paramType = (ParameterizedType) field.getGenericType();
            Type[] types = paramType.getActualTypeArguments();
            int len = types.length;
            if (len == 1) {
                //for Collection
                fetchCollection(obj, field, (Class) types[0]);
            } else if (len == 2) {
                //for Map
                fetchMap(obj, field, (Class) types[1]);
            }
        }
    }

    private static void fetchArray(BuguEntity obj, Field field, Class clazz) {
        Object o = FieldUtil.get(obj, field);
        if (o == null) {
            return;
        }
        int len = Array.getLength(o);
        clazz = FieldUtil.getRealType(clazz, field);
        Object arr = Array.newInstance(clazz, len);
        List<String> idList = new ArrayList<String>();
        for (int i = 0; i < len; i++) {
            Object item = Array.get(o, i);
            if (item != null) {
                BuguEntity ent = (BuguEntity) item;
                idList.add(ent.getId());
            }
        }
        RefList refList = field.getAnnotation(RefList.class);
        String sort = refList.sort();
        InternalDao dao = DaoCache.getInstance().get(clazz);
        BuguQuery query = dao.query().in(Operator.ID, idList);
        List<BuguEntity> entityList = null;
        if (sort.equals(Default.SORT)) {
            entityList = query.results();
        } else {
            entityList = query.sort(sort).results();
        }
        if (entityList.size() != len) {
            len = entityList.size();
            arr = Array.newInstance(clazz, len);
        }
        for (int i = 0; i < len; i++) {
            Array.set(arr, i, entityList.get(i));
        }
        FieldUtil.set(obj, field, arr);
    }

    private static void fetchCollection(BuguEntity obj, Field field, Class clazz) {
        Object o = FieldUtil.get(obj, field);
        if (o == null) {
            return;
        }
        Collection<BuguEntity> collection = (Collection<BuguEntity>) o;
        List<String> idList = new ArrayList<String>();
        for (BuguEntity ent : collection) {
            if (ent != null) {
                idList.add(ent.getId());
            }
        }
        RefList refList = field.getAnnotation(RefList.class);
        String sort = refList.sort();
        clazz = FieldUtil.getRealType(clazz, field);
        InternalDao dao = DaoCache.getInstance().get(clazz);
        BuguQuery query = dao.query().in(Operator.ID, idList);
        List result = null;
        if (sort.equals(Default.SORT)) {
            result = query.results();
        } else {
            result = query.sort(sort).results();
        }
        Class type = field.getType();
        if (DataType.isListType(type)) {
            FieldUtil.set(obj, field, result);
        } else if (DataType.isSetType(type)) {
            FieldUtil.set(obj, field, new HashSet(result));
        } else if (DataType.isQueueType(type)) {
            FieldUtil.set(obj, field, new LinkedList(result));
        }
    }

    private static void fetchMap(BuguEntity obj, Field field, Class clazz) {
        Object o = FieldUtil.get(obj, field);
        if (o == null) {
            return;
        }
        Map<Object, BuguEntity> map = (Map<Object, BuguEntity>) o;
        Map result = new HashMap();
        clazz = FieldUtil.getRealType(clazz, field);
        InternalDao dao = DaoCache.getInstance().get(clazz);
        for (Entry<Object, BuguEntity> entry : map.entrySet()) {
            BuguEntity refObj = entry.getValue();
            if (refObj != null) {
                String id = refObj.getId();
                Object value = dao.findOne(id);
                result.put(entry.getKey(), value);
            } else {
                result.put(entry.getKey(), null);
            }
        }
        FieldUtil.set(obj, field, result);
    }

}