com.baidu.rigel.biplatform.ac.util.DataModelUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.baidu.rigel.biplatform.ac.util.DataModelUtils.java

Source

/**
 * Copyright (c) 2014 Baidu, Inc. All Rights Reserved.
 *
 * 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.baidu.rigel.biplatform.ac.util;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.baidu.rigel.biplatform.ac.query.data.DataModel;
import com.baidu.rigel.biplatform.ac.query.data.DataModel.FillDataType;
import com.baidu.rigel.biplatform.ac.query.data.HeadField;
import com.baidu.rigel.biplatform.ac.query.data.HeadFieldComparator;
import com.baidu.rigel.biplatform.ac.query.model.SortRecord;
import com.baidu.rigel.biplatform.ac.query.model.SortRecord.SortType;
import com.google.common.collect.Lists;

/**
 * DataModel?
 * 
 * @author xiaoming.chen
 *
 */
public class DataModelUtils {

    /**
     * logger
     */
    private static Logger logger = LoggerFactory.getLogger(DataModelUtils.class);

    /**
     * ??DataModel
     * 
     * @param columnBaseHeadField ??
     * @param rowHeadDefine ?
     * @return DataModel
     */
    public static DataModel buildDataModel(List<HeadField> columnBaseHeadField, List<HeadField> rowHeadDefine) {
        DataModel dataModel = new DataModel();
        dataModel.setRowHeadFields(rowHeadDefine);
        dataModel.setColumnHeadFields(columnBaseHeadField);
        fillColumnData(dataModel, FillDataType.COLUMN);
        return dataModel;
    }

    /**
     * ??UniqueName
     * 
     * @param fileds ?
     * @param uniqueName // TODO ??UniqueName??
     * @return
     */
    public static int foundIndexByLeafeValue(List<HeadField> fileds, String uniqueName) {
        if (CollectionUtils.isEmpty(fileds)) {
            throw new IllegalArgumentException("root fields can not be empty!");
        }
        if (StringUtils.isBlank(uniqueName)) {
            throw new IllegalArgumentException("value can not be empty!");
        }
        List<HeadField> leafFileds = new ArrayList<HeadField>(50);
        for (HeadField columnFiled : fileds) {
            leafFileds.addAll(columnFiled.getLeafFileds(false));
        }
        int index = -1;
        for (int i = 0; i < leafFileds.size(); i++) {
            if (uniqueName.equals(leafFileds.get(i).getValue())) {
                index = i;
            }
        }
        if (index == -1) {
            throw new IllegalArgumentException("can not found leaf field with value:" + uniqueName);
        }
        return index;
    }

    /**
     * ???dataModel
     * 
     * @param dataModel ??
     * @param datas ??
     * @param type ??
     * @return ????
     */
    public static DataModel addData(DataModel dataModel, List<HeadField> datas, FillDataType type) {
        if (dataModel == null) {
            throw new IllegalArgumentException("dataModel can not be null");
        }
        if (CollectionUtils.isEmpty(datas)) {
            return dataModel;
        }
        // ??
        fillFieldData(dataModel, type);
        if (type.equals(FillDataType.COLUMN)) {
            dataModel.getColumnHeadFields().addAll(datas);
        } else {
            dataModel.getRowHeadFields().addAll(datas);
        }
        // ?????dataModel?
        fillColumnData(dataModel, type);
        return dataModel;
    }

    /**
     * DataModel?
     * 
     * @param dataModel ?DataModel
     * @param sort ?
     * @throws IllegalAccessException ??
     */
    public static void sortByRow(DataModel dataModel, SortType sort) throws IllegalAccessException {
        if (dataModel == null) {
            throw new IllegalArgumentException("can not sort empty dataModel!");
        }
        fillFieldData(dataModel, FillDataType.ROW);
        buildSortSummary(dataModel);
        sortListHeadFields(dataModel.getRowHeadFields(), sort);
        fillColumnData(dataModel, FillDataType.ROW);
    }

    /**
     * ??
     * 
     * @param headFields ?????
     * @param sort ?
     */
    private static void sortListHeadFields(List<HeadField> headFields, SortType sort) {
        if (CollectionUtils.isNotEmpty(headFields)) {
            for (HeadField filed : headFields) {
                sortListHeadFields(filed.getNodeList(), sort);
                sortListHeadFields(filed.getChildren(), sort);
                for (HeadField child : filed.getChildren()) {
                    sortListHeadFields(child.getNodeList(), sort);
                }
            }
            Collections.sort(headFields, new HeadFieldComparator(sort));
        }

    }

    /**
     * ???????List
     * 
     * @param dataModel DataModel
     * @param type ??
     */
    public static void fillColumnData(DataModel dataModel, FillDataType type) {

        List<HeadField> columnLeafs = getLeafNodeList(dataModel.getColumnHeadFields());
        List<HeadField> rowLeafs = getLeafNodeList(dataModel.getRowHeadFields());
        dataModel.getColumnBaseData().clear();
        if (type.equals(FillDataType.COLUMN)) {

            for (int i = 0; i < columnLeafs.size(); i++) {
                HeadField rowField = columnLeafs.get(i);
                dataModel.getColumnBaseData().add(rowField.getCompareDatas());
                while (dataModel.getColumnBaseData().get(i).size() < rowLeafs.size()) {
                    dataModel.getColumnBaseData().get(i).add(null);
                }
            }
        } else if (type.equals(FillDataType.ROW)) {

            List<List<BigDecimal>> columnBaseData = new ArrayList<List<BigDecimal>>(columnLeafs.size());
            for (int i = 0; i < rowLeafs.size(); i++) {
                HeadField rowFiled = rowLeafs.get(i);
                for (int j = 0; j < columnLeafs.size(); j++) {
                    if (columnBaseData.size() <= j) {
                        columnBaseData.add(new ArrayList<BigDecimal>(columnLeafs.size()));
                    }
                    if (rowFiled.getCompareDatas().size() < j) {
                        columnBaseData.get(j).add(null);
                    } else {
                        columnBaseData.get(j).add(rowFiled.getCompareDatas().get(j));
                    }
                }
            }
            dataModel.setColumnBaseData(columnBaseData);

        }
    }

    /**
     * ?Datamodel?
     * 
     * @param dataModel DataModel
     * @param type ?
     */
    public static void fillFieldData(DataModel dataModel, FillDataType type) {
        List<HeadField> columnLeafs = getLeafNodeList(dataModel.getColumnHeadFields());
        List<HeadField> rowLeafs = getLeafNodeList(dataModel.getRowHeadFields());
        if (type.equals(FillDataType.COLUMN)) {
            if (!CollectionUtils.isEmpty(columnLeafs) && dataModel.getColumnBaseData() != null) {
                for (int i = 0; i < columnLeafs.size(); i++) {
                    columnLeafs.get(i).setCompareDatas(dataModel.getColumnBaseData().get(i));
                }
            }
        } else if (type.equals(FillDataType.ROW)) {
            if (CollectionUtils.isNotEmpty(rowLeafs)) {
                List<BigDecimal> rowDatas = null;
                for (int i = 0; i < rowLeafs.size(); i++) {
                    rowDatas = new ArrayList<BigDecimal>(rowLeafs.size());
                    for (int j = 0; j < columnLeafs.size(); j++) {
                        rowDatas.add(dataModel.getColumnBaseData().get(j).get(i));
                    }
                    rowLeafs.get(i).setCompareDatas(rowDatas);
                }
            }
        }
    }

    /**
     * DataModel??
     * 
     * @param dataModel DataModel
     * @throws IllegalAccessException 
     */
    private static void buildSortSummary(DataModel dataModel) throws IllegalAccessException {
        List<HeadField> rowLeafs = getLeafNodeList(dataModel.getRowHeadFields());
        if (CollectionUtils.isNotEmpty(rowLeafs)) {
            if (dataModel.getOperateIndex() > rowLeafs.get(0).getCompareDatas().size()) {
                throw new IllegalAccessException("can not access operate index:" + dataModel.getOperateIndex());
            }
            for (HeadField rowHeadField : dataModel.getRowHeadFields()) {
                List<HeadField> leafFileds = rowHeadField.getLeafFileds(true);
                if (CollectionUtils.isNotEmpty(leafFileds)) {

                    Queue<HeadField> queue = new LinkedList<HeadField>(leafFileds);
                    while (!queue.isEmpty()) {
                        HeadField leafFiled = queue.remove();
                        if (CollectionUtils.isNotEmpty(leafFiled.getCompareDatas())) {
                            leafFiled
                                    .setSummarizeData(leafFiled.getCompareDatas().get(dataModel.getOperateIndex()));
                        }
                        HeadField parent = null;
                        if (leafFiled.getParent() != null) {
                            parent = leafFiled.getParent();
                        } else if (leafFiled.getParentLevelField() != null) {
                            parent = leafFiled.getParentLevelField();
                            if (!queue.contains(parent)) {
                                queue.add(parent);
                            }
                        }

                        if (parent != null && CollectionUtils.isEmpty(parent.getCompareDatas())) {
                            parent.setSummarizeData(BigDecimalUtils.addBigDecimal(parent.getSummarizeData(),
                                    leafFiled.getSummarizeData()));
                        }
                    }
                }

            }
        }
    }

    // private static void addTailFiled(List<HeadField> leafFileds, HeadField insertFiled) {
    // for (HeadField leafFiled : leafFileds) {
    // HeadField insertFiledCopy = insertFiled.simpleClone();
    // insertFiledCopy.setParentLevelField(leafFiled);
    // leafFiled.getNodeList().add(insertFiledCopy);
    // }
    // }

    /**
     * DataModel
     * 
     * @param dataModel DataModel
     * @return 
     */
    public static int filterBlankRow(DataModel dataModel) {
        int blankRowCount = 0;
        fillFieldData(dataModel, FillDataType.ROW);
        List<HeadField> leafFileds = getLeafNodeList(dataModel.getRowHeadFields());
        if (CollectionUtils.isNotEmpty(leafFileds)) {
            for (HeadField field : leafFileds) {
                boolean isBlank = true;
                for (BigDecimal data : field.getCompareDatas()) {
                    if (data != null) {
                        isBlank = false;
                        break;
                    }
                }
                if (isBlank) {
                    blankRowCount++;
                    removeField(field, dataModel.getRowHeadFields());
                }
            }
        }
        fillColumnData(dataModel, FillDataType.ROW);
        logger.info("[INFO] ---- ---- ---- ---- ---- after remove filter blank row ,current dataModel is : "
                + dataModel);
        return blankRowCount;
    }

    /**
     * ?
     * 
     * @param field 
     * @param rowHeadFields datamodel
     */
    public static void removeField(HeadField field, List<HeadField> rowHeadFields) {
        HeadField parentField = field.getParentLevelField();
        if (field.getParentLevelField() != null) {
            parentField.getNodeList().remove(field);
            if (parentField.getChildren().isEmpty() && parentField.getNodeList().isEmpty()) {
                removeField(parentField, rowHeadFields);
            }
        } else {
            rowHeadFields.remove(field);
        }
        if (field.getParent() != null) {
            field.getParent().getChildren().remove(field);
        }
    }

    /**
     * ?rowspan
     * 
     * @param rowHeadFields 
     * @return rowspan
     */
    public static int getRowSpan(List<HeadField> rowHeadFields) {
        if (CollectionUtils.isNotEmpty(rowHeadFields)) {
            for (HeadField filed : rowHeadFields) {
                return filed.getLeafSize();
            }
        }
        return 0;
    }

    /**
     * caption??caption
     * 
     * @param startDay 
     * @param pattern ?
     * @return caption
     * @throws ParseException 
     */
    public static String parseToEntireWeekCaption(String startDay, String pattern) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        Calendar calendar = new GregorianCalendar(2012, Calendar.JANUARY, 1);
        calendar.setTime(sdf.parse(startDay));
        calendar.add(Calendar.DAY_OF_MONTH, 6);
        String endDay = sdf.format(calendar.getTime());
        return startDay + "~" + endDay;
    }

    /**
     * ?List<HeadField>??
     * 
     * @param headFields ??
     * @return ??
     */
    public static List<HeadField> getLeafNodeList(List<HeadField> headFields) {
        List<HeadField> resultList = new ArrayList<HeadField>();

        for (HeadField headField : headFields) {
            resultList.addAll(headField.getLeafFileds(true));
        }
        return resultList;

    }

    /**
     * ?headField
     * 
     * @param headField 
     * @return ?
     */
    public static List<HeadField> getHeadFieldListOutofHeadField(HeadField headField) {
        List<HeadField> resultList = new ArrayList<HeadField>();
        if (headField == null) {
            return resultList;
        } else {
            resultList.add(headField);
            resultList.addAll(getHeadFieldListOutofHeadField(headField.getParentLevelField()));
        }
        return resultList;
    }

    // /**
    // * ????
    // * @param nodeUniqueName
    // * @return
    // */
    // public static List<HeadField> getHeadFieldListOutofHeadField(String nodeUniqueName){
    //
    //
    // }
    //
    // /**
    // * ????
    // * @param nodeUniqueName
    // * @return
    // */
    // public static HeadField getHeadFieldByNodeUniqueName(String nodeUniqueName){
    //
    // }

    /**
     * UniqueName??value
     * 
     * @param nodeUniqueName
     * @return
     */
    public static String[] parseNodeUniqueNameToNodeValueArray(String nodeUniqueName) {
        if (StringUtils.isBlank(nodeUniqueName)) {
            throw new IllegalArgumentException("node unique is illegal:" + nodeUniqueName);
        }
        String preSplitUniqueName = nodeUniqueName;
        if (preSplitUniqueName.startsWith("{")) {
            preSplitUniqueName = preSplitUniqueName.substring(1);
        }
        if (preSplitUniqueName.endsWith("}")) {
            preSplitUniqueName = preSplitUniqueName.substring(0, preSplitUniqueName.length() - 1);
        }
        // ].[??
        return StringUtils.splitByWholeSeparator(preSplitUniqueName, "}.{");

    }

    /**
     * 
     * 
     * @param headField 
     * @param indent ?
     * @return ?
     */
    private static int getIndentOfHeadField(HeadField headField, int indent) {
        if (headField != null && headField.getParent() != null) {
            return getIndentOfHeadField(headField.getParent(), indent + 1);
        } else {
            return indent;
        }
    }

    /**
     * ?
     * 
     * @param headField 
     * @return 
     */
    public static int getIndentOfHeadField(HeadField headField) {
        return getIndentOfHeadField(headField, 0);
    }

    /**
     * ???
     * 
     * @param columnBasedData ??
     * @return ??
     */
    public static List<List<BigDecimal>> transColumnBasedData2RowBasedData(List<List<BigDecimal>> columnBasedData) {
        List<List<BigDecimal>> rowBasedData = new ArrayList<List<BigDecimal>>();

        for (List<BigDecimal> currColumnData : columnBasedData) {
            for (int i = 0; i < currColumnData.size(); i++) {
                // ?i
                List<BigDecimal> currRowData = new ArrayList<BigDecimal>();
                if (rowBasedData.size() >= i + 1) {
                    currRowData = rowBasedData.get(i);
                } else {
                    rowBasedData.add(currRowData);
                }

                currRowData.add(currColumnData.get(i));

            }
        }

        return rowBasedData;

    }

    /**
     * DataModel?
     * 
     * @param dataModel ?DataModel
     * @param sortRecord ??
     */
    public static void sortDataModelBySort(DataModel dataModel, SortRecord sortRecord) {
        if (sortRecord != null && StringUtils.isNotBlank(sortRecord.getSortColumnUniquename())
                && !sortRecord.getSortType().equals(SortType.NONE)) {
            try {
                int index = DataModelUtils.foundIndexByLeafeValue(dataModel.getColumnHeadFields(),
                        sortRecord.getSortColumnUniquename());
                dataModel.setOperateIndex(index);
                DataModelUtils.sortByRow(dataModel, sortRecord.getSortType());
            } catch (Exception e) {
                logger.warn("can not sort by  columnName:" + sortRecord.getSortColumnUniquename());
            }
        }
    }

    /**
     * ?
     * @param oriModel 
     * @param recordSize ?
     * @return DataModel ?
     */
    public static DataModel truncModel(DataModel oriModel, int recordSize) {
        DataModel model = new DataModel();
        model.setColumnHeadFields(oriModel.getColumnHeadFields());
        model.setRecordSize(getRecordSize(oriModel.getColumnBaseData()));
        // ?
        if (model.getRecordSize() <= recordSize) {
            model.setColumnBaseData(oriModel.getColumnBaseData());
            model.setColumnHeadFields(oriModel.getColumnHeadFields());
            model.setOperateIndex(oriModel.getOperateIndex());
            model.setRowHeadFields(oriModel.getRowHeadFields());
            return model;
        }
        // ??
        int tmp = recordSize;
        List<List<BigDecimal>> datas = Lists.newArrayList();
        oriModel.getColumnBaseData().forEach(list -> {
            List<BigDecimal> data = Lists.newArrayList();
            for (int i = 0; i < tmp; ++i) {
                data.add(list.get(i));
            }
            datas.add(data);
        });
        model.setColumnBaseData(datas);
        // ??
        List<HeadField> rowHeadFields = Lists.newArrayList();
        int originRecord = recordSize;
        for (int i = 0; i < oriModel.getRowHeadFields().size(); ++i) {
            // ?i
            HeadField field = oriModel.getRowHeadFields().get(i);
            // ??
            rowHeadFields.add(field);
            if (i == originRecord - 1) {
                break;
            }
            boolean hasNodeList = false;
            // ?NodeList??NodeList
            if (field.getNodeList() != null && field.getNodeList().size() > 0) {
                hasNodeList = true;
                HeadFieldDetailRecord record = truncFieldHeads(field.getNodeList(), recordSize);
                field.setNodeList(record.headFields);
                if (record.count >= recordSize) {
                    field.setChildren(Lists.newArrayList());
                    break;
                } else {
                    recordSize = recordSize - record.count;
                }
            }

            // ??
            if (field.getChildren() != null && field.getChildren().size() > 0) { // ??
                if (!hasNodeList) {
                    recordSize -= 1;
                }
                HeadFieldDetailRecord record = truncFieldHeads(field.getChildren(), recordSize);
                field.setChildren(record.headFields);
                if (record.count >= recordSize) {
                    break;
                } else {
                    recordSize = recordSize - record.count;
                }
            }
        }
        model.setRowHeadFields(rowHeadFields);
        return model;
    }

    /**
     * 
     * @param nodeList
     * @param recordSize
     * @return HeadFieldDetailRecord
     */
    private static HeadFieldDetailRecord truncFieldHeads(List<HeadField> nodeList, int recordSize) {
        int oriRecordSize = recordSize;
        List<HeadField> tmp = Lists.newArrayList();
        for (int i = 0; i < nodeList.size(); ++i) {
            if (recordSize <= 0) {
                break;
            }
            HeadField field = nodeList.get(i);
            // NodeList?children
            if (field.getNodeList() == null || field.getNodeList().size() == 0) {
                // ?
                if (field.getChildren() == null || field.getChildren().size() == 0) {
                    tmp.add(field);
                    recordSize -= 1;
                } else { // NodeList?children
                    HeadFieldDetailRecord record = truncFieldHeads(field.getChildren(), recordSize - 1);
                    field.setChildren(record.headFields);
                    recordSize -= record.count;
                    tmp.add(field);
                    if (recordSize <= 0) {
                        recordSize = 0;
                        break;
                    }
                }
            } else {
                HeadFieldDetailRecord record = truncFieldHeads(field.getNodeList(), recordSize);
                field.setNodeList(record.headFields);
                recordSize -= record.count;
                tmp.add(field);
                if (recordSize <= 0) {
                    recordSize = 0;
                    field.setChildren(Lists.newArrayList());
                    break;
                }
            }
        }
        return new HeadFieldDetailRecord(oriRecordSize - recordSize, tmp);
    }

    /**
     * ?
     * @param columnBaseData ?
     * @return 
     */
    private static int getRecordSize(List<List<BigDecimal>> columnBaseData) {
        if (columnBaseData == null || columnBaseData.size() == 0) {
            return 0;
        }
        if (columnBaseData.get(0) == null) {
            return 0;
        }
        return columnBaseData.get(0).size();
    }

    /**
     * 
     * @author david.wang
     *
     */
    private static class HeadFieldDetailRecord {

        /**
         * 
         */
        public final int count;

        /**
         * 
         */
        public final List<HeadField> headFields;

        /**
         * 
         * @param count
         * @param headFields
         */
        public HeadFieldDetailRecord(int count, List<HeadField> headFields) {
            super();
            this.count = count;
            this.headFields = headFields;
        }

    }

    public static void sortDataModelBySort(DataModel dataModel, SortRecord sortRecord,
            Comparator<HeadField> headFieldComparator) {
        if (sortRecord != null && StringUtils.isNotBlank(sortRecord.getSortColumnUniquename())
                && !sortRecord.getSortType().equals(SortType.NONE)) {
            try {
                int index = DataModelUtils.foundIndexByLeafeValue(dataModel.getColumnHeadFields(),
                        sortRecord.getSortColumnUniquename());
                dataModel.setOperateIndex(index);
                sortByRow(dataModel, sortRecord.getSortType(), headFieldComparator);
            } catch (Exception e) {
                logger.warn("can not sort by  columnName:" + sortRecord.getSortColumnUniquename());
            }
        }
    }

    private static void sortByRow(DataModel dataModel, SortType sort, Comparator<HeadField> headFieldComparator)
            throws IllegalAccessException {
        if (dataModel == null) {
            throw new IllegalArgumentException("can not sort empty dataModel!");
        }
        fillFieldData(dataModel, FillDataType.ROW);
        buildSortSummary(dataModel);
        sortListHeadFields(dataModel.getRowHeadFields(), sort, headFieldComparator);
        fillColumnData(dataModel, FillDataType.ROW);
    }

    private static void sortListHeadFields(List<HeadField> headFields, SortType sort,
            Comparator<HeadField> headFieldComparator) {
        if (CollectionUtils.isNotEmpty(headFields)) {
            for (HeadField filed : headFields) {
                sortListHeadFields(filed.getNodeList(), sort, headFieldComparator);
                sortListHeadFields(filed.getChildren(), sort, headFieldComparator);
                for (HeadField child : filed.getChildren()) {
                    sortListHeadFields(child.getNodeList(), sort, headFieldComparator);
                }
            }
            Collections.sort(headFields, headFieldComparator);
        }
    }

}