com.clican.pluto.dataprocess.dpl.impl.DplStatementImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.clican.pluto.dataprocess.dpl.impl.DplStatementImpl.java

Source

/**
 * The Clican-Pluto software suit is Copyright 2009, Clican Company and individual contributors, and is licensed under the GNU LGPL.
 *
 * @author clican
 *
 */
package com.clican.pluto.dataprocess.dpl.impl;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

import com.clican.pluto.common.util.TypeUtils;
import com.clican.pluto.dataprocess.dpl.DplStatement;
import com.clican.pluto.dataprocess.dpl.comparator.GroupConditionComparator;
import com.clican.pluto.dataprocess.dpl.comparator.OrderByComparator;
import com.clican.pluto.dataprocess.dpl.function.MultiRowFunction;
import com.clican.pluto.dataprocess.dpl.function.SingleRowFunction;
import com.clican.pluto.dataprocess.dpl.parser.FilterParser;
import com.clican.pluto.dataprocess.dpl.parser.FromParser;
import com.clican.pluto.dataprocess.dpl.parser.GroupByParser;
import com.clican.pluto.dataprocess.dpl.parser.OrderByParser;
import com.clican.pluto.dataprocess.dpl.parser.PagingParser;
import com.clican.pluto.dataprocess.dpl.parser.SelectParser;
import com.clican.pluto.dataprocess.dpl.parser.SubDplParser;
import com.clican.pluto.dataprocess.dpl.parser.bean.Column;
import com.clican.pluto.dataprocess.dpl.parser.bean.DplResultSet;
import com.clican.pluto.dataprocess.dpl.parser.bean.Group;
import com.clican.pluto.dataprocess.dpl.parser.bean.GroupCondition;
import com.clican.pluto.dataprocess.dpl.parser.bean.PrefixAndSuffix;
import com.clican.pluto.dataprocess.dpl.parser.object.From;
import com.clican.pluto.dataprocess.dpl.parser.object.GroupBy;
import com.clican.pluto.dataprocess.dpl.parser.object.OrderBy;
import com.clican.pluto.dataprocess.dpl.parser.object.Pagination;
import com.clican.pluto.dataprocess.dpl.parser.object.Select;
import com.clican.pluto.dataprocess.dpl.parser.object.SubDpl;
import com.clican.pluto.dataprocess.dpl.parser.object.filter.CompareFilter;
import com.clican.pluto.dataprocess.dpl.parser.object.filter.Filter;
import com.clican.pluto.dataprocess.engine.ProcessorContext;
import com.clican.pluto.dataprocess.engine.impl.ProcessorContextImpl;
import com.clican.pluto.dataprocess.exception.DplException;
import com.clican.pluto.dataprocess.exception.DplParseException;

/**
 * <code>DplStatement</code>
 * <p>
 * ?<code>DplStatement</code>?
 * 
 * ?DPL??Select, From, Filter, Order By  Group By
 * 
 * <ul>
 * <li>??</li>
 * <li>??</li>
 * <li>??</li>
 * <li>?Filter???</li>
 * <li>?Group By???</li>
 * <li>????Select????Filter?Select?
 * Selectfunction???</li>
 * <li>????????selectas??</li>
 * <li></li>
 * </ul>
 * 
 * <p>
 * ?List??Map?????? Class???
 * <code>DplStatementImpl</code>Map?Class??
 * <p/>
 * 
 * @author clican
 * 
 */
public class DplStatementImpl implements DplStatement {

    private final static Log log = LogFactory.getLog(DplStatementImpl.class);

    /**
     * <code>FilterParser</code>
     */
    private FilterParser filterParser;
    /**
     * <code>GroupByParser</code>
     */
    private GroupByParser groupByParser;
    /**
     * <code>OrderByParser</code>
     */
    private OrderByParser orderByParser;
    /**
     * <code>SelectParser</code>
     */
    private SelectParser selectParser;
    /**
     * <code>FromParser</code>
     */
    private FromParser fromParser;

    private PagingParser pagingParser;

    private SubDplParser subDplParser;

    public void setFilterParser(FilterParser filterParser) {
        this.filterParser = filterParser;
    }

    public void setGroupByParser(GroupByParser groupByParser) {
        this.groupByParser = groupByParser;
    }

    public void setOrderByParser(OrderByParser orderByParser) {
        this.orderByParser = orderByParser;
    }

    public void setSelectParser(SelectParser selectParser) {
        this.selectParser = selectParser;
    }

    public void setFromParser(FromParser fromParser) {
        this.fromParser = fromParser;
    }

    public void setPagingParser(PagingParser pagingParser) {
        this.pagingParser = pagingParser;
    }

    public void setSubDplParser(SubDplParser subDplParser) {
        this.subDplParser = subDplParser;
    }

    /**
     * @see DplStatement#execute(String, ProcessorContext)
     */

    public List<Map<String, Object>> execute(String dpl, ProcessorContext context) throws DplException {
        dpl = trimDpl(dpl);
        if (dpl.trim().length() == 0) {
            log.warn("dpl statement empty, simple return null");
            return null;
        }
        ProcessorContext clone = context.getCloneContext();
        PrefixAndSuffix.setLocalContext(clone);
        try {
            // ?dpl??
            SubDpl subDpl = subDplParser.parseSubDpl(dpl, clone);
            if (subDpl != null) {
                for (String subDplStr : subDpl.getSubDplStrAliasMap().keySet()) {
                    String alias = subDpl.getSubDplStrAliasMap().get(subDplStr);
                    Object result = subDpl.getAliasResultMap().get(alias);
                    dpl = StringUtils.replaceOnce(dpl, subDplStr, alias);
                    if (alias.startsWith("dual")) {
                        clone.setAttribute(alias.substring(5), result);
                    } else {
                        clone.setAttribute(alias, result);
                    }
                }
            }
            From from = fromParser.parseFrom(dpl, clone);
            if (from.getVariableNames().size() == 0) {
                throw new DplParseException("From?");
            }
            Filter filter = filterParser.parseFilter(dpl, clone);
            GroupBy groupBy = groupByParser.parseGroupBy(dpl, clone);
            OrderBy orderBy = orderByParser.parseOrderBy(dpl, clone);
            Select select = selectParser.parseSelect(dpl, clone);
            Pagination pagination = pagingParser.parsePagination(dpl, clone);

            // ????
            DplResultSet dplResultSet = null;
            if (filter != null) {
                filter.filter(clone);
                dplResultSet = clone.getAttribute(CompareFilter.DPL_RESULT_SET);
            }
            if (dplResultSet == null) {
                dplResultSet = new DplResultSet();
                for (String name : from.getVariableNames()) {
                    dplResultSet.getResultNames().add(name);
                    List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
                    List<Object> list = clone.getAttribute(name);
                    if (list.size() == 0) {
                        dplResultSet = new DplResultSet();
                        break;
                    }
                    if (dplResultSet.getResultSet().size() == 0) {
                        for (Object obj : list) {
                            Map<String, Object> map = new HashMap<String, Object>();
                            map.put(name, obj);
                            result.add(map);
                        }
                        dplResultSet.setResultSet(result);
                    } else {
                        for (Object obj : list) {
                            for (Map<String, Object> row : new ArrayList<Map<String, Object>>(
                                    dplResultSet.getResultSet())) {
                                Map<String, Object> map = new HashMap<String, Object>(row);
                                map.put(name, obj);
                                result.add(map);
                            }
                        }
                        dplResultSet.setResultSet(result);
                    }
                }
            }
            // Join???

            // ??
            Map<String, Set<Object>> data = new HashMap<String, Set<Object>>();
            for (String name : from.getVariableNames()) {
                if (!name.equals(CompareFilter.DPL_RESULT_SET)) {
                    List<Object> list = clone.getAttribute(name);
                    data.put(name, new HashSet<Object>(list));
                }
            }
            // ??
            List<Map<String, Object>> rs = new ArrayList<Map<String, Object>>();

            // ???Join???
            for (Map<String, Object> result : dplResultSet.getResultSet()) {
                boolean valid = true;
                for (String key : result.keySet()) {
                    if (result.get(key) != null && !data.get(key).contains(result.get(key))) {
                        valid = false;
                    }
                }
                if (valid) {
                    rs.add(result);
                }
            }
            // ????
            Map<List<GroupCondition>, List<Map<String, Object>>> groupByRs = new HashMap<List<GroupCondition>, List<Map<String, Object>>>();

            // ???????
            if (groupBy != null) {
                try {
                    for (Map<String, Object> result : rs) {
                        List<GroupCondition> gcSet = new ArrayList<GroupCondition>();
                        for (int i = 0; i < groupBy.getGroups().size(); i++) {
                            Group group = groupBy.getGroups().get(i);
                            Object groupValue = group.getValue(result);
                            GroupCondition gc = new GroupCondition();
                            gc.setPosition(i);
                            gc.setGroupName(group.getExpr());
                            gc.setGroupValue(groupValue);
                            gcSet.add(gc);
                        }
                        if (!groupByRs.containsKey(gcSet)) {
                            groupByRs.put(gcSet, new ArrayList<Map<String, Object>>());
                        }
                        groupByRs.get(gcSet).add(result);
                    }
                } catch (Exception e) {
                    throw new DplParseException(e);
                }
            }
            // SelectFunction???
            List<Map<String, Object>> newRs = new ArrayList<Map<String, Object>>();

            try {
                if (groupBy != null) {
                    List<List<GroupCondition>> temp = new ArrayList<List<GroupCondition>>(groupByRs.keySet());
                    // ????
                    Collections.sort(temp, new GroupConditionComparator());
                    // ??????Select???
                    for (List<GroupCondition> gcSet : temp) {
                        Map<String, Object> groupMap = new HashMap<String, Object>();
                        for (GroupCondition gc : gcSet) {
                            groupMap.put(gc.getGroupName(), gc.getGroupValue());
                        }
                        Map<String, Object> row = new HashMap<String, Object>();

                        for (Column column : select.getColumns()) {
                            String key = column.getColumnName();
                            PrefixAndSuffix pas = column.getPrefixAndSuffix();
                            if (pas.getFunction() instanceof SingleRowFunction) {
                                SingleRowFunction fun = (SingleRowFunction) pas.getFunction();
                                if (groupMap.containsKey(fun.getExpr())) {
                                    Object value = groupMap.get(fun.getExpr());
                                    row.put(key, value);
                                    groupMap.put(key, value);
                                } else {
                                    Object value = fun.recurseCalculate(groupByRs.get(gcSet), groupMap);
                                    row.put(key, value);
                                    groupMap.put(key, value);
                                }
                            } else if (pas.getFunction() instanceof MultiRowFunction) {
                                MultiRowFunction fun = (MultiRowFunction) pas.getFunction();
                                Object value = fun.recurseCalculate(groupByRs.get(gcSet));
                                row.put(key, value);
                                groupMap.put(key, value);
                            } else {
                                Object value = pas.getValue(groupMap);
                                row.put(key, value);
                                groupMap.put(key, value);
                            }
                        }
                        newRs.add(row);
                    }
                } else {
                    // ???Join????Select???
                    if (select.containMultiRowCalculation()) {
                        // ?
                        Map<String, Object> map = new HashMap<String, Object>();
                        Map<String, Object> row = new HashMap<String, Object>();
                        map.putAll(context.getMap());
                        for (Column column : select.getColumns()) {
                            String key = column.getColumnName();
                            PrefixAndSuffix pas = column.getPrefixAndSuffix();
                            if (pas.getFunction() instanceof SingleRowFunction) {
                                SingleRowFunction fun = (SingleRowFunction) pas.getFunction();
                                Object value = fun.recurseCalculate(rs, map);
                                map.put(key, value);
                                row.put(key, value);
                            } else if (pas.getFunction() instanceof MultiRowFunction) {
                                MultiRowFunction cal = (MultiRowFunction) pas.getFunction();
                                Object value = cal.recurseCalculate(rs);
                                map.put(key, value);
                                row.put(key, value);
                            } else {
                                Object value = pas.getValue(map);
                                if (value == null) {
                                    pas.isSupportInMultiFunctionWithoutGroupBy();
                                }
                                map.put(key, value);
                                row.put(key, value);
                            }
                        }
                        newRs.add(row);
                    } else {
                        for (Map<String, Object> map : rs) {
                            Map<String, Object> row = new HashMap<String, Object>();
                            for (Column column : select.getColumns()) {
                                String key = column.getColumnName();
                                PrefixAndSuffix pas = column.getPrefixAndSuffix();
                                if (pas.getFunction() instanceof SingleRowFunction) {
                                    SingleRowFunction fun = (SingleRowFunction) pas.getFunction();
                                    Object value = fun.recurseCalculate(rs, map);
                                    map.put(key, value);
                                    row.put(key, value);
                                } else if (pas.getFunction() instanceof MultiRowFunction) {
                                    throw new DplException("????");
                                } else {
                                    Object value = pas.getValue(map);
                                    map.put(key, value);
                                    row.put(key, value);
                                }
                            }
                            newRs.add(row);
                        }
                    }
                }

            } catch (Exception e) {
                throw new DplException(e);
            }
            // ????
            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(newRs);
            if (orderBy != null) {
                Collections.sort(list, new OrderByComparator(orderBy));
            }
            // ??
            if (pagination != null) {
                if (pagination.isReverse()) {
                    if (pagination.getLimit() == null) {
                        if (list.size() - pagination.getOffset() > 0) {
                            return list.subList(0, list.size() - pagination.getOffset());
                        } else {
                            return new ArrayList<Map<String, Object>>();
                        }
                    } else {
                        if (list.size() - pagination.getOffset() > 0) {
                            if (list.size() - pagination.getOffset() - pagination.getLimit() >= 0) {
                                return list.subList(list.size() - pagination.getOffset() - pagination.getLimit(),
                                        list.size() - pagination.getOffset());
                            } else {
                                return list.subList(0, list.size() - pagination.getOffset());
                            }
                        } else {
                            return new ArrayList<Map<String, Object>>();
                        }
                    }
                } else {
                    if (pagination.getLimit() == null) {
                        if (list.size() - pagination.getOffset() > 0) {
                            return list.subList(pagination.getOffset(), list.size());
                        } else {
                            return new ArrayList<Map<String, Object>>();
                        }
                    } else {
                        if (list.size() - pagination.getOffset() > 0) {
                            if (list.size() - pagination.getOffset() - pagination.getLimit() >= 0) {
                                return list.subList(pagination.getOffset(),
                                        pagination.getOffset() + pagination.getLimit());
                            } else {
                                return list.subList(pagination.getOffset(), list.size());
                            }
                        } else {
                            return new ArrayList<Map<String, Object>>();
                        }
                    }

                }
            } else {
                return list;
            }
        } finally {
            PrefixAndSuffix.releaseLocalContext();
        }
    }

    /**
     * 
     * 
     * @param dpl
     * @return
     */
    private String trimDpl(String dpl) {
        String[] dplLines = dpl.split("\n");
        StringBuffer buf = new StringBuffer(dpl.length());

        for (String dplLine : dplLines) {
            if (dplLine.trim().startsWith("--")) {
                continue;
            } else {
                // ???
                dplLine = " " + dplLine.trim() + " ";
            }
            buf.append(dplLine);
        }

        dpl = buf.toString();
        // tab??
        dpl = dpl.replaceAll("\t", " ");
        return dpl;
    }

    /**
     * @see DplStatement#execute(String, ProcessorContext, Class)
     */
    @SuppressWarnings("unchecked")
    public <T> List<T> execute(String dpl, ProcessorContext context, Class<T> clazz) throws DplException {
        List<Map<String, Object>> list = this.execute(dpl, context);
        if (clazz == null) {
            return (List<T>) list;
        }
        List<T> result = new ArrayList<T>();
        for (Map<String, Object> row : list) {
            T t = null;
            // ??
            if (row.size() == 1) {
                t = (T) row.entrySet().iterator().next().getValue();
            } else {
                // ???clazz????
                try {
                    t = clazz.newInstance();
                } catch (Exception e) {
                    throw new DplException(e);
                }
                Method[] methods = clazz.getMethods();
                Map<String, Method> methodMap = new HashMap<String, Method>();
                for (Method method : methods) {
                    methodMap.put(method.getName(), method);
                    methodMap.put(method.getName().toLowerCase(), method);
                }
                for (String name : row.keySet()) {
                    try {
                        if (row.get(name) != null) {
                            String setMethodName = com.clican.pluto.common.util.StringUtils.getSetMethodName(name);
                            Object value = row.get(name);
                            if (methodMap.containsKey(setMethodName)
                                    || methodMap.containsKey(setMethodName.toLowerCase())) {
                                Class type = methodMap.get(setMethodName.toLowerCase()).getParameterTypes()[0];
                                if (!value.getClass().equals(type)) {
                                    if (value instanceof Number) {
                                        value = TypeUtils.numberToNumber((Number) value, type);
                                    } else if (value instanceof String) {
                                        value = TypeUtils.stringToNumber((String) value, type);
                                    }
                                }
                                if (methodMap.containsKey(setMethodName)) {
                                    methodMap.get(setMethodName).invoke(t, new Object[] { value });
                                } else {
                                    methodMap.get(setMethodName.toLowerCase()).invoke(t, new Object[] { value });
                                }
                            } else {
                                if (log.isTraceEnabled()) {
                                    log.trace("There is no this property [" + name + "]");
                                }
                            }
                        }
                    } catch (Exception e) {
                        if (log.isTraceEnabled()) {
                            log.trace("There is no this property [" + name + "]");
                        }
                    }
                }
            }

            result.add(t);
        }
        return result;
    }

    public <T> List<T> execute(String dpl, Map<String, Object> context, Class<T> clazz) throws DplException {
        ProcessorContext ctx = new ProcessorContextImpl();
        for (String key : context.keySet()) {
            ctx.setAttribute(key, context.get(key));
        }
        return this.execute(dpl, ctx, clazz);
    }

    public List<Map<String, Object>> execute(String dpl, Map<String, Object> context) throws DplException {
        ProcessorContext ctx = new ProcessorContextImpl();
        for (String key : context.keySet()) {
            ctx.setAttribute(key, context.get(key));
        }
        return this.execute(dpl, ctx);
    }

}

// $Id: DplStatementImpl.java 16208 2010-07-16 00:57:34Z wei.zhang $