com.bosscs.spark.mongodb.utils.UtilMongoDB.java Source code

Java tutorial

Introduction

Here is the source code for com.bosscs.spark.mongodb.utils.UtilMongoDB.java

Source

/*
 * Copyright 2016, Jerry Xiong, BOSSCS
 *
 * 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.bosscs.spark.mongodb.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.bson.BSONObject;
import org.bson.BasicBSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.bosscs.spark.commons.entity.Cell;
import com.bosscs.spark.commons.entity.Cells;
import com.bosscs.spark.commons.entity.IType;
import com.bosscs.spark.commons.utils.AnnotationUtils;
import com.bosscs.spark.commons.utils.Utils;

/**
 * Several utilities to work used in the Spark <=> MongoDB integration.
 */
public final class UtilMongoDB {

    /**
     * The constant MONGO_DEFAULT_ID.
     */
    public static final String MONGO_DEFAULT_ID = "_id";

    /**
     * The constant LOG.
     */
    private static final Logger LOG = LoggerFactory.getLogger(UtilMongoDB.class);

    /**
     * Private default constructor.
     */

    private UtilMongoDB() {
        throw new UnsupportedOperationException();
    }

    /**
     * converts from BsonObject to an entity class with deep's anotations
     *
     * @param classEntity the entity name.
     * @param bsonObject  the instance of the BSONObjet to convert.
     * @return the provided bsonObject converted to an instance of T.
     * @throws IllegalAccessException the illegal access exception
     * @throws IllegalAccessException the instantiation exception
     * @throws IllegalAccessException the invocation target exception
     */
    public static <T> T getObjectFromBson(Class<T> classEntity, BSONObject bsonObject)
            throws IllegalAccessException, InstantiationException, InvocationTargetException {
        T t = classEntity.newInstance();

        Field[] fields = AnnotationUtils.filterDeepFields(classEntity);

        Object insert = null;

        for (Field field : fields) {
            Object currentBson = null;
            Method method = null;
            try {
                method = Utils.findSetter(field.getName(), classEntity, field.getType());

                Class<?> classField = field.getType();

                currentBson = bsonObject.get(AnnotationUtils.deepFieldName(field));
                if (currentBson != null) {

                    if (Iterable.class.isAssignableFrom(classField)) {
                        Type type = field.getGenericType();

                        insert = subDocumentListCase(type,
                                (List) bsonObject.get(AnnotationUtils.deepFieldName(field)));

                    } else if (IType.class.isAssignableFrom(classField)) {
                        insert = getObjectFromBson(classField,
                                (BSONObject) bsonObject.get(AnnotationUtils.deepFieldName(field)));
                    } else {
                        insert = currentBson;
                    }
                    method.invoke(t, insert);
                }
            } catch (IllegalAccessException | InstantiationException | InvocationTargetException
                    | IllegalArgumentException e) {
                LOG.error("impossible to create a java object from Bson field:" + field.getName() + " and type:"
                        + field.getType() + " and value:" + t + "; bsonReceived:" + currentBson
                        + ", bsonClassReceived:" + currentBson.getClass());

                method.invoke(t, Utils.castNumberType(insert, t.getClass()));
            }

        }

        return t;
    }

    /**
     * Sub document list case.
     *
     * @param <T>       the type parameter
     * @param type      the type
     * @param bsonOject the bson oject
     * @return the object
     * @throws IllegalAccessException    the illegal access exception
     * @throws InstantiationException    the instantiation exception
     * @throws InvocationTargetException the invocation target exception
     */
    private static <T> Object subDocumentListCase(Type type, List<T> bsonOject)
            throws IllegalAccessException, InstantiationException, InvocationTargetException {
        ParameterizedType listType = (ParameterizedType) type;

        Class<?> listClass = (Class<?>) listType.getActualTypeArguments()[0];

        List list = new ArrayList();
        for (T t : bsonOject) {
            list.add(getObjectFromBson(listClass, (BSONObject) t));
        }

        return list;
    }

    /**
     * converts from an entity class with deep's anotations to BsonObject.
     *
     * @param t an instance of an object of type T to convert to BSONObject.
     * @return the provided object converted to BSONObject.
     * @throws IllegalAccessException the illegal access exception
     * @throws IllegalAccessException the instantiation exception
     * @throws IllegalAccessException the invocation target exception
     */
    public static <T> DBObject getBsonFromObject(T t)
            throws IllegalAccessException, InstantiationException, InvocationTargetException {
        Field[] fields = AnnotationUtils.filterDeepFields(t.getClass());

        DBObject bson = new BasicDBObject();

        for (Field field : fields) {
            Method method = Utils.findGetter(field.getName(), t.getClass());
            Object object = method.invoke(t);
            if (object != null) {
                if (Collection.class.isAssignableFrom(field.getType())) {
                    Collection c = (Collection) object;
                    Iterator iterator = c.iterator();
                    List innerBsonList = new ArrayList<>();

                    while (iterator.hasNext()) {
                        innerBsonList.add(getBsonFromObject(iterator.next()));
                    }
                    bson.put(AnnotationUtils.deepFieldName(field), innerBsonList);
                } else if (IType.class.isAssignableFrom(field.getType())) {
                    bson.put(AnnotationUtils.deepFieldName(field), getBsonFromObject((IType) object));
                } else {
                    bson.put(AnnotationUtils.deepFieldName(field), object);
                }
            }
        }

        return bson;
    }

    /**
     * returns the id value annotated with @DeepField(fieldName = "_id")
     *
     * @param t an instance of an object of type T to convert to BSONObject.
     * @return the provided object converted to Object.
     * @throws IllegalAccessException the illegal access exception
     * @throws IllegalAccessException the instantiation exception
     * @throws IllegalAccessException the invocation target exception
     */
    public static <T extends IType> Object getId(T t)
            throws IllegalAccessException, InstantiationException, InvocationTargetException {
        Field[] fields = AnnotationUtils.filterDeepFields(t.getClass());

        for (Field field : fields) {
            if (MONGO_DEFAULT_ID.equals(AnnotationUtils.deepFieldName(field))) {
                return Utils.findGetter(field.getName(), t.getClass()).invoke(t);
            }

        }

        return null;
    }

    /**
     * converts from BsonObject to cell class with deep's anotations
     *
     * @param bsonObject the bson object
     * @param tableName  the table name
     * @return cell from bson
     * @throws IllegalAccessException the illegal access exception
     * @throws IllegalAccessException the instantiation exception
     * @throws IllegalAccessException the invocation target exception
     */
    public static Cells getCellFromBson(BSONObject bsonObject, String tableName) {

        Cells cells = tableName != null ? new Cells(tableName) : new Cells();

        Map<String, Object> map = bsonObject.toMap();

        Set<Map.Entry<String, Object>> entryBson = map.entrySet();

        for (Map.Entry<String, Object> entry : entryBson) {
            try {

                if (List.class.isAssignableFrom(entry.getValue().getClass())) {
                    List innerCell = new ArrayList<>();
                    for (Object innerBson : (List) entry.getValue()) {
                        if (innerBson instanceof DBObject) {
                            innerCell.add(getCellFromBson((DBObject) innerBson, null));
                        } else {
                            innerCell.add(innerBson);
                        }

                    }
                    cells.add(Cell.create(entry.getKey(), innerCell));
                } else if (BSONObject.class.isAssignableFrom(entry.getValue().getClass())) {
                    Cells innerCells = getCellFromBson((BSONObject) entry.getValue(), null);
                    cells.add(Cell.create(entry.getKey(), innerCells));
                } else {
                    cells.add(Cell.create(entry.getKey(), entry.getValue()));
                }
            } catch (IllegalArgumentException e) {
                LOG.error("impossible to create a java cell from Bson field:" + entry.getKey() + ", type:"
                        + entry.getValue().getClass() + ", value:" + entry.getValue());
            }

        }
        return cells;
    }

    /**
     * converts from and entity class with deep's anotations to BsonObject
     *
     * @param cells the cells
     * @return bson from cell
     */
    public static DBObject getDBObjectFromCell(Cells cells) {

        DBObject bson = new BasicDBObject();
        for (Cell cell : cells) {
            if (cell.getValue() != null) {
                if (Collection.class.isAssignableFrom(cell.getCellValue().getClass())) {
                    Collection c = (Collection) cell.getCellValue();
                    Iterator iterator = c.iterator();
                    List<Object> innerBsonList = new ArrayList<>();

                    while (iterator.hasNext()) {
                        Object currentO = iterator.next();
                        if (currentO instanceof Cells) {
                            innerBsonList.add(getDBObjectFromCell((Cells) currentO));
                        } else {
                            innerBsonList.add(currentO);
                        }
                    }
                    bson.put(cell.getCellName(), innerBsonList);
                } else if (Cells.class.isAssignableFrom(cell.getCellValue().getClass())) {
                    bson.put(cell.getCellName(), getDBObjectFromCell((Cells) cell.getCellValue()));
                } else {
                    bson.put(cell.getCellName(), cell.getCellValue());
                }
            }
        }

        return bson;
    }

}