Java tutorial
/** * 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); } } }