com.jhkt.playgroundArena.db.nosql.mongodb.beans.AbstractDocument.java Source code

Java tutorial

Introduction

Here is the source code for com.jhkt.playgroundArena.db.nosql.mongodb.beans.AbstractDocument.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.jhkt.playgroundArena.db.nosql.mongodb.beans;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.jhkt.playgroundArena.db.nosql.mongodb.annotations.IDocumentKeyValue;
import com.jhkt.playgroundArena.shared.utils.JPAConstants;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;

/**
 * @author Ji Hoon Kim
 */
public abstract class AbstractDocument {

    private final static Log _log = LogFactory.getLog(AbstractDocument.class);

    private static Method RESOLVE_TO_BASIC_DB_OBJECT_METHOD;

    static {
        try {
            RESOLVE_TO_BASIC_DB_OBJECT_METHOD = AbstractDocument.class.getMethod("resolveToBasicDBObject",
                    JPAConstants.EMPTY_CLASS_ARGUMENT_LIST);
        } catch (Exception e) {

        }
    }

    AbstractDocument() {
        super();
    }

    private final static Object convertBacktoClassInstanceHelper(DBObject dBObject) {

        Object returnValue = null;

        try {
            String className = dBObject.get(JPAConstants.CONVERTER_CLASS.CLASS.name()).toString();
            Class<?> classCheck = Class.forName(className);

            if (AbstractDocument.class.isAssignableFrom(classCheck)) {
                Class<? extends AbstractDocument> classToConvertTo = classCheck.asSubclass(AbstractDocument.class);
                AbstractDocument dInstance = classToConvertTo.newInstance();

                for (String key : dBObject.keySet()) {
                    Object value = dBObject.get(key);

                    char[] propertyChars = key.toCharArray();
                    String methodMain = String.valueOf(propertyChars[0]).toUpperCase() + key.substring(1);
                    String methodName = "set" + methodMain;
                    String getMethodName = "get" + methodMain;

                    if (key.equals(JPAConstants.CONVERTER_CLASS.CLASS.name())) {
                        continue;
                    }

                    if (value instanceof BasicDBObject) {
                        value = convertBacktoClassInstanceHelper(BasicDBObject.class.cast(value));
                    }

                    try {
                        Method getMethod = classToConvertTo.getMethod(getMethodName);
                        Class<?> getReturnType = getMethod.getReturnType();
                        Method method = classToConvertTo.getMethod(methodName, getReturnType);

                        if (getMethod.isAnnotationPresent(IDocumentKeyValue.class)) {
                            method.invoke(dInstance, value);
                        }
                    } catch (NoSuchMethodException nsMe) {
                        _log.warn("Within convertBacktoClassInstance, following method was not found " + methodName,
                                nsMe);
                    }

                }

                returnValue = dInstance;

            } else if (Enum.class.isAssignableFrom(classCheck)) {

                List<?> constants = Arrays.asList(classCheck.getEnumConstants());
                String name = String.class.cast(dBObject.get(JPAConstants.CONVERTER_CLASS.CONTENT.name()));
                for (Object constant : constants) {
                    if (constant.toString().equals(name)) {
                        returnValue = constant;
                    }
                }

            } else if (Collection.class.isAssignableFrom(classCheck)) {

                @SuppressWarnings("unchecked")
                Class<? extends Collection<? super Object>> classToConvertTo = (Class<? extends Collection<? super Object>>) classCheck;
                Collection<? super Object> cInstance = classToConvertTo.newInstance();

                BasicDBList bDBList = (BasicDBList) dBObject.get(JPAConstants.CONVERTER_CLASS.CONTENT.name());
                cInstance.addAll(bDBList);

                returnValue = cInstance;

            } else if (Map.class.isAssignableFrom(classCheck)) {

                @SuppressWarnings("unchecked")
                Class<? extends Map<String, ? super Object>> classToConvertTo = (Class<? extends Map<String, ? super Object>>) classCheck;
                Map<String, ? super Object> mInstance = classToConvertTo.newInstance();

                BasicDBObject mapObject = (BasicDBObject) dBObject.get(JPAConstants.CONVERTER_CLASS.CONTENT.name());
                mInstance.putAll(mapObject);

                returnValue = mInstance;

            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return returnValue;
    }

    public final static AbstractDocument convertBacktoClassInstance(DBObject dBObject) {
        return AbstractDocument.class.cast(convertBacktoClassInstanceHelper(dBObject));
    }

    public final BasicDBObject resolveToBasicDBObject() {

        BasicDBObject bDBObject = new BasicDBObject();
        try {
            Class<? extends AbstractDocument> currClass = getClass();
            while (currClass != null) {

                for (Method method : currClass.getMethods()) {
                    IDocumentKeyValue dkv = method.getAnnotation(IDocumentKeyValue.class);
                    String mName = method.getName();
                    if (dkv != null && mName.startsWith(JPAConstants.GETTER_PREFIX)) {

                        try {
                            Object returnValue = method.invoke(this, JPAConstants.EMPTY_OBJECT_ARGUMENT_LIST);
                            char[] propertyChars = mName.substring(3).toCharArray();
                            String property = String.valueOf(propertyChars[0]).toLowerCase()
                                    + String.valueOf(propertyChars, 1, propertyChars.length - 1);

                            if (returnValue == null) {
                                continue;
                            }

                            if (returnValue instanceof AbstractDocument) {

                                Object subReturnValue = RESOLVE_TO_BASIC_DB_OBJECT_METHOD.invoke(returnValue,
                                        JPAConstants.EMPTY_OBJECT_ARGUMENT_LIST);
                                bDBObject.put(property, subReturnValue);

                            } else if (returnValue instanceof Enum) {

                                Enum<?> enumClass = Enum.class.cast(returnValue);
                                BasicDBObject enumObject = new BasicDBObject();

                                enumObject.put(JPAConstants.CONVERTER_CLASS.CLASS.name(),
                                        enumClass.getClass().getName());
                                enumObject.put(JPAConstants.CONVERTER_CLASS.CONTENT.name(), enumClass.name());

                                bDBObject.put(property, enumObject);

                            } else if (returnValue instanceof Collection) {

                                Collection<?> collectionContent = (Collection<?>) returnValue;
                                BasicDBObject collectionObject = new BasicDBObject();
                                collectionObject.put(JPAConstants.CONVERTER_CLASS.CLASS.name(),
                                        collectionContent.getClass().getName());

                                BasicDBList bDBList = new BasicDBList();
                                if (collectionContent.iterator().next() instanceof AbstractDocument) {
                                    for (Object content : collectionContent) {
                                        if (content instanceof AbstractDocument) {
                                            Object subReturnValue = RESOLVE_TO_BASIC_DB_OBJECT_METHOD
                                                    .invoke(returnValue, JPAConstants.EMPTY_OBJECT_ARGUMENT_LIST);
                                            bDBList.add(subReturnValue);
                                        }
                                    }
                                } else {
                                    bDBList.addAll(collectionContent);
                                }

                                collectionObject.put(JPAConstants.CONVERTER_CLASS.CONTENT.name(), bDBList);
                                bDBObject.put(property, collectionObject);

                            } else if (returnValue instanceof Map) {

                                Map<?, ?> mapContent = (Map<?, ?>) returnValue;
                                BasicDBObject mapObject = new BasicDBObject();
                                mapObject.put(JPAConstants.CONVERTER_CLASS.CLASS.name(),
                                        mapContent.getClass().getName());

                                Set<?> keys = mapContent.keySet();
                                if (keys.iterator().next() instanceof AbstractDocument) {

                                    Map<Object, Object> convertedMap = new HashMap<Object, Object>();
                                    for (Object key : keys) {
                                        Object value = mapContent.get(key);
                                        Object subReturnValue = RESOLVE_TO_BASIC_DB_OBJECT_METHOD.invoke(value,
                                                JPAConstants.EMPTY_OBJECT_ARGUMENT_LIST);

                                        convertedMap.put(key, subReturnValue);
                                    }

                                    mapContent = convertedMap;
                                }

                                mapObject.put(JPAConstants.CONVERTER_CLASS.CONTENT.name(), mapContent);
                                bDBObject.put(property, mapObject);

                            } else {
                                bDBObject.put(property, returnValue);
                            }

                        } catch (Exception e) {

                        }

                    }
                }

                currClass = currClass.getSuperclass().asSubclass(AbstractDocument.class);
            }

        } catch (ClassCastException castException) {

        }

        bDBObject.put(JPAConstants.CONVERTER_CLASS.CLASS.name(), getClass().getName());
        _log.info("BdBObject " + bDBObject);
        return bDBObject;
    }

}