com.jsmartdb.framework.manager.EntityWhere.java Source code

Java tutorial

Introduction

Here is the source code for com.jsmartdb.framework.manager.EntityWhere.java

Source

/*
 * JSmartDB - Java ORM Framework
 * Copyright (c) 2014, Jeferson Albino da Silva, All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/

package com.jsmartdb.framework.manager;

import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;

import org.apache.commons.lang.StringUtils;

import com.jsmartdb.framework.types.JoinType;
import com.jsmartdb.framework.types.TableType;

import com.jsmartdb.framework.annotation.Column;
import com.jsmartdb.framework.annotation.Id;
import com.jsmartdb.framework.annotation.JoinId;
import com.jsmartdb.framework.annotation.ManyToMany;
import com.jsmartdb.framework.annotation.OneToMany;
import com.jsmartdb.framework.annotation.OneToOne;

/*package*/ final class EntityWhere {

    public static final String WHERE_STATEMENT = " where ";

    public static final String AND_OPERATOR = " and ";

    public static final String OR_OPERATOR = " or ";

    /*
     * No recursive method to get object values to place in where clause, just one join level
     */
    @SuppressWarnings("unchecked")
    public static void getDefaultWhere(Entity entity, Field[] fields) {

        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];

            if (EntityHandler.isReserved(field) || EntityHandler.isTransient(field)) {
                continue;
            }

            if (buildFieldWhere(entity, EntityAlias.getAlias(entity.getClass()), field)) {
                continue;
            }

            if (!EntityContext.isBlockJoin()) {

                JoinId joinId = EntityHandler.getJoinId(field);
                if (joinId != null && !EntityContext.getJoinBlockClasses().contains(field.getType())) {
                    if (joinId.join().type() != JoinType.NO_JOIN) {

                        Entity obj = (Entity) EntityHandler.getValue(entity, field);
                        if (obj != null) {
                            String alias = EntityAlias.getAlias(entity.getClass(), field.getType().getName(),
                                    field.getName());
                            buildFieldsWhere(obj, alias, EntityFieldsMapper.getFields(field.getType()));
                        }
                    }
                    continue;
                }

                OneToOne oneToOne = EntityHandler.getOneToOne(field);
                if (oneToOne != null && !EntityContext.getJoinBlockClasses().contains(field.getType())) {
                    if (oneToOne.join().type() != JoinType.NO_JOIN) {

                        Entity obj = (Entity) EntityHandler.getValue(entity, field);
                        if (obj != null) {
                            String alias = EntityAlias.getAlias(entity.getClass(), field.getType().getName(),
                                    field.getName());
                            buildFieldsWhere(obj, alias, EntityFieldsMapper.getFields(field.getType()));
                        }
                    }
                    continue;
                }

                OneToMany oneToMany = EntityHandler.getOneToMany(field);
                if (oneToMany != null) {
                    Class<?> oneToManyClass = EntityHandler.getGenericType(field);

                    if (!EntityContext.getJoinBlockClasses().contains(oneToManyClass)) {
                        if (oneToMany.join().type() != JoinType.NO_JOIN) {

                            if (EntityHandler.getTable(oneToManyClass).type() == TableType.DEFAULT_TABLE) {
                                Collection<Entity> collection = (Collection<Entity>) EntityHandler.getValue(entity,
                                        field);

                                if (collection != null && !collection.isEmpty()) {
                                    EntityContext.getWhereBuilder().append("(");
                                    String alias = EntityAlias.getAlias(entity.getClass(), oneToManyClass.getName(),
                                            field.getName());

                                    for (Entity obj : collection) {
                                        EntityContext.getWhereBuilder().append("(");

                                        buildFieldsWhere(obj, alias, EntityFieldsMapper.getFields(oneToManyClass));

                                        EntityContext.getWhereBuilder()
                                                .replace(
                                                        EntityContext.getWhereBuilder().length()
                                                                - AND_OPERATOR.length(),
                                                        EntityContext.getWhereBuilder().length(), "")
                                                .append(")" + OR_OPERATOR);
                                    }
                                    EntityContext.getWhereBuilder()
                                            .replace(
                                                    EntityContext.getWhereBuilder().length() - OR_OPERATOR.length(),
                                                    EntityContext.getWhereBuilder().length(), "")
                                            .append(")" + AND_OPERATOR);
                                }

                            } else {

                                Collection<Entity> collection = (Collection<Entity>) EntityHandler.getValue(entity,
                                        field);

                                if (collection != null && !collection.isEmpty()) {
                                    EntityContext.getWhereBuilder().append("(");

                                    String alias = EntityAlias.getAlias(entity.getClass(), oneToManyClass.getName(),
                                            field.getName());

                                    for (Entity obj : collection) {
                                        EntityContext.getWhereBuilder().append("(");

                                        for (Field fieldy : EntityFieldsMapper.getFields(oneToManyClass)) {
                                            JoinId joinIdn = EntityHandler.getJoinId(fieldy);

                                            if (buildFieldWhere(obj, alias, fieldy)) {
                                                continue;
                                            }

                                            if (joinIdn != null && fieldy.getType() != entity.getClass()) {
                                                Entity joinObj = (Entity) EntityHandler.getValue(obj, fieldy);

                                                if (joinObj != null) {
                                                    EntityContext.getWhereBuilder().append("(");
                                                    String joinAlias = EntityAlias.getAlias(oneToManyClass,
                                                            fieldy.getType().getName(), fieldy.getName());

                                                    buildFieldsWhere(joinObj, joinAlias,
                                                            EntityFieldsMapper.getFields(fieldy.getType()));

                                                    EntityContext.getWhereBuilder()
                                                            .replace(
                                                                    EntityContext.getWhereBuilder().length()
                                                                            - AND_OPERATOR.length(),
                                                                    EntityContext.getWhereBuilder().length(), "")
                                                            .append(")" + OR_OPERATOR);
                                                }
                                                continue;
                                            }
                                        }
                                        EntityContext.getWhereBuilder()
                                                .replace(
                                                        EntityContext.getWhereBuilder().length()
                                                                - AND_OPERATOR.length(),
                                                        EntityContext.getWhereBuilder().length(), "")
                                                .append(")" + OR_OPERATOR);
                                    }
                                    EntityContext.getWhereBuilder()
                                            .replace(
                                                    EntityContext.getWhereBuilder().length() - OR_OPERATOR.length(),
                                                    EntityContext.getWhereBuilder().length(), "")
                                            .append(")" + AND_OPERATOR);
                                }
                            }
                        }
                        continue;
                    }
                }

                ManyToMany manyToMany = EntityHandler.getManyToMany(field);
                if (manyToMany != null) {
                    Class<?> manyToManyClass = EntityHandler.getGenericType(field);

                    if (!EntityContext.getJoinBlockClasses().contains(manyToManyClass)) {
                        if (manyToMany.join().type() != JoinType.NO_JOIN) {
                            Collection<Entity> collection = (Collection<Entity>) EntityHandler.getValue(entity,
                                    field);

                            if (collection != null && !collection.isEmpty()) {
                                EntityContext.getWhereBuilder().append("(");
                                String alias = EntityAlias.getAlias(entity.getClass(), manyToManyClass.getName(),
                                        field.getName());

                                for (Entity obj : collection) {
                                    EntityContext.getWhereBuilder().append("(");
                                    buildFieldsWhere(obj, alias, EntityFieldsMapper.getFields(manyToManyClass));

                                    EntityContext.getWhereBuilder().replace(
                                            EntityContext.getWhereBuilder().length() - AND_OPERATOR.length(),
                                            EntityContext.getWhereBuilder().length(), "").append(")" + OR_OPERATOR);
                                }
                                EntityContext.getWhereBuilder()
                                        .replace(EntityContext.getWhereBuilder().length() - OR_OPERATOR.length(),
                                                EntityContext.getWhereBuilder().length(), "")
                                        .append(")" + AND_OPERATOR);
                            }
                        }
                        continue;
                    }
                }
            }
        }

        if (EntityContext.getWhereBuilder().length() > WHERE_STATEMENT.length()) {
            EntityContext.getWhereBuilder().replace(
                    EntityContext.getWhereBuilder().length() - AND_OPERATOR.length(),
                    EntityContext.getWhereBuilder().length(), "");

        } else {
            EntityContext.getWhereBuilder().replace(
                    EntityContext.getWhereBuilder().length() - WHERE_STATEMENT.length(),
                    EntityContext.getWhereBuilder().length(), "");
        }
    }

    public static void getCustomWhere(Class<?> entityClazz, Field[] fields, QueryParam param) {

        String customWhere = EntityContext.getWhereBuilder().toString();
        Map<Integer, Object> paramValues = new TreeMap<Integer, Object>();

        for (String key : param.getFilterParamKeys()) {
            int index = 0;
            for (int i = 0; i < StringUtils.countMatches(customWhere, key); i++) {
                index = customWhere.indexOf(key, index);
                paramValues.put(index, param.get(key));
            }
        }

        EntityContext.addAllBuilderValue(paramValues.values());

        for (String key : param.getFilterParamKeys()) {
            customWhere = customWhere.replaceAll(key, " ? ");
        }

        String[] matches = customWhere.split(" ");
        Map<String, String> queryMap = new HashMap<String, String>();

        for (String match : matches) {
            if (match.trim().isEmpty()) {
                continue;
            }
            Matcher matcher = EntitySelect.SQL_FUNCTION_PATTERN.matcher(match);
            if (matcher.find()) {
                match = matcher.group();
                match = match.replace("(", "").replace(")", "");
            }

            String value = EntityAlias.getMatchColumn(entityClazz, fields, match, EntityAlias.getAlias(entityClazz),
                    EntityContext.getJoinBuilder());
            if (value != null) {
                queryMap.put(match, value);
            }
        }

        for (String key : queryMap.keySet()) {
            customWhere = customWhere.replace(key, queryMap.get(key));
        }

        EntityContext.getWhereBuilder().replace(0, EntityContext.getWhereBuilder().length(), customWhere);

        if (EntityContext.getWhereBuilder().length() <= WHERE_STATEMENT.length()) {
            EntityContext.getWhereBuilder().replace(
                    EntityContext.getWhereBuilder().length() - WHERE_STATEMENT.length(),
                    EntityContext.getWhereBuilder().length(), "");
        }
    }

    /*package*/ static void setPreparedStatementWhereValues(PreparedStatement pstmt, boolean containsInnerSelect)
            throws SQLException {
        List<Object> whereBuilderValues = EntityContext.getBuilderValues();
        if (containsInnerSelect) {
            whereBuilderValues.addAll(whereBuilderValues);
        }
        for (int index = 1; index < whereBuilderValues.size() + 1; index++) {
            pstmt.setObject(index, whereBuilderValues.get(index - 1));
        }
    }

    private static void buildFieldsWhere(Entity entity, String alias, Field[] fields) {
        if (entity != null && fields != null) {
            for (Field field : fields) {
                buildFieldWhere(entity, alias, field);
            }
        }
    }

    private static boolean buildFieldWhere(Entity entity, String alias, Field field) {
        if (entity != null && field != null) {

            Column columnn = EntityHandler.getColumn(field);
            if (columnn != null) {
                Object obj = EntityHandler.getValue(entity, field);
                if (obj != null) {
                    EntityContext.addBuilderValue(obj);
                    EntityContext.getWhereBuilder().append(alias + "." + columnn.name() + "= ?" + AND_OPERATOR);
                    return true;
                }
            }

            Id id = EntityHandler.getId(field);
            if (id != null) {
                Object obj = EntityHandler.getValue(entity, field);
                if (obj != null) {
                    EntityContext.addBuilderValue(obj);
                    EntityContext.getWhereBuilder().append(alias + "." + id.name() + "= ?" + AND_OPERATOR);
                    return true;
                }
            }

            JoinId joinId = EntityHandler.getJoinId(field);
            if (joinId != null) {
                Entity obj = (Entity) EntityHandler.getValue(entity, field);
                if (obj != null) {
                    try {
                        Field refererField = EntityFieldsMapper.getField(obj.getClass(), joinId.referer());
                        EntityContext.addBuilderValue(EntityHandler.getValue(obj, refererField));
                        EntityContext.getWhereBuilder()
                                .append(alias + "." + joinId.column() + "= ?" + AND_OPERATOR);
                        return true;
                    } catch (Exception ex) {
                        throw new RuntimeException(ex);
                    }
                }
            }
        }
        return false;
    }

}