All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dongliu.dbutils.NamedSQLParser Maven / Gradle / Ivy

package net.dongliu.dbutils;

import net.dongliu.commons.collection.Pair;
import net.dongliu.commons.reflect.Property;
import net.dongliu.dbutils.exception.ParameterNotFoundException;
import net.dongliu.dbutils.mapping.BeanMapping;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Liu Dong
 */
public class NamedSQLParser {

    static Pair translate(String clause, Map map) {
        Pair> pair = parseClause(clause);
        clause = pair.first();
        List names = pair.second();
        Object[] params = getParameters(map, names);
        return Pair.of(clause, params);
    }


    static Pair translate(String clause, List> mapList) {
        Pair> pair = parseClause(clause);
        clause = pair.first();
        List names = pair.second();

        Object[][] paramsArray = new Object[mapList.size()][];
        for (int i = 0; i < mapList.size(); i++) {
            Map map = mapList.get(i);
            paramsArray[i] = getParameters(map, names);
        }

        return Pair.of(clause, paramsArray);
    }


    private static Object[] getParameters(Map map, List names) {
        Object[] params = new Object[names.size()];
        for (int i = 0; i < names.size(); i++) {
            String name = names.get(i);
            if (!map.containsKey(name)) {
                throw new ParameterNotFoundException(name);
            }
            params[i] = map.get(name);
        }
        return params;
    }


    static Pair translateBean(String clause, Object bean) {
        Pair> pair = parseClause(clause);
        clause = pair.first();
        List names = pair.second();
        Object[] params = getParameters(bean, names);
        return Pair.of(clause, params);
    }

    static Pair translateBean(String clause, List beanList) {
        Pair> pair = parseClause(clause);
        clause = pair.first();
        List names = pair.second();

        Object[][] paramsArray = new Object[beanList.size()][];
        for (int i = 0; i < beanList.size(); i++) {
            Object bean = beanList.get(i);
            paramsArray[i] = getParameters(bean, names);
        }

        return Pair.of(clause, paramsArray);
    }

    private static Object[] getParameters(Object bean, List names) {
        BeanMapping beanMapping = BeanMapping.getBeanMapping(bean.getClass());
        Object[] params = new Object[names.size()];
        for (int i = 0; i < names.size(); i++) {
            String name = names.get(i);
            Property property = beanMapping.getProperty(name);
            if (property == null) {
                throw new ParameterNotFoundException(name);
            }
            params[i] = property.get(bean);
        }
        return params;
    }

    private static final int NORMAL = 0;
    private static final int EXPECT_NAME = 1;
    private static final int IN_NAME = 2;

    static Pair> parseClause(String clause) {
        int state = NORMAL;
        StringBuilder sb = new StringBuilder(clause.length());
        StringBuilder buffer = new StringBuilder();
        List names = new ArrayList<>();
        for (int i = 0; i < clause.length(); i++) {
            char c = clause.charAt(i);

            switch (state) {
                case NORMAL:
                    if (c == ':') {
                        state = EXPECT_NAME;
                    } else {
                        sb.append(c);
                    }
                    break;
                case EXPECT_NAME:
                    if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'z' || c == '_') {
                        buffer.setLength(0);
                        buffer.append(c);
                        state = IN_NAME;
                    } else {
                        // illegal name character, just skip it?
                        sb.append(':').append(c);
                        state = NORMAL;
                    }
                    break;

                case IN_NAME:
                    if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
                        names.add(buffer.toString());
                        sb.append("?").append(c);
                        state = NORMAL;
                    } else if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'z' || c == '_' || c >= '0' && c <= '9') {
                        buffer.append(c);
                    } else {
                        // illegal name character, just skip it?
                        sb.append(buffer);
                        sb.append(c);
                    }
            }

        }
        if (state == IN_NAME) {
            names.add(buffer.toString());
            sb.append("?");
        } else if (state == EXPECT_NAME) {
            sb.append(':');
        }
        return Pair.of(sb.toString(), names);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy