/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 ro.nextreports.server.web.pivot; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.util.collections.MultiMap; import ro.nextreports.server.pivot.Aggregator; import ro.nextreports.server.pivot.PivotField; import ro.nextreports.server.pivot.PivotModel; import ro.nextreports.server.pivot.PivotUtils; import ro.nextreports.server.web.dashboard.pivot.PivotWidget; import ro.nextreports.engine.exporter.util.TableData; /** * * @author Mihai Dinca-Panaitescu * */ public class PivotUtil { private static int NUMBER_OF_DECIMALS = 3; private static double FACTOR = Math.pow(10.0, NUMBER_OF_DECIMALS); //@see PivoTable for same algorithm public static TableData getTableData(PivotModel pivotModel) { List<List<Object>> data = new ArrayList<List<Object>>(); List<PivotField> columnFields = pivotModel.getFields(PivotField.Area.COLUMN); List<PivotField> rowFields = pivotModel.getFields(PivotField.Area.ROW); List<PivotField> dataFields = pivotModel.getFields(PivotField.Area.DATA); List<List<Object>> rowKeys = pivotModel.getRowKeys(); List<List<Object>> columnKeys = pivotModel.getColumnKeys(); int headerRowCount = columnFields.size(); if (headerRowCount == 0) { headerRowCount = 1; } if (dataFields.size() > 1) { // add an extra row (the row with data field titles) headerRowCount++; } for (int i = 0; i < headerRowCount; i++) { List<Object> row = new ArrayList<Object>(); data.add(row); for (int j = 0; j < rowFields.size(); j++) { if (i < headerRowCount - 1) { // empty cell row.add(""); } else { row.add(rowFields.get(j).getName()); } } // column keys for (List<Object> columnKey : columnKeys) { if (i < columnFields.size()) { row.add(columnKey.get(i)); for (int k=0; k<dataFields.size()-1; k++) { row.add(""); } } else { for (PivotField dataField : dataFields) { row.add(dataField.getTitle()); } } } // grand total column if (!columnFields.isEmpty() && pivotModel.isShowGrandTotalForRow()) { if (i == 0) { row.add(new StringResourceModel("pivot.grandTotal", null).getString()); for (int k = 0; k < dataFields.size() - 1; k++) { row.add(""); } } else if (i < columnFields.size()) { for (int k = 0; k < dataFields.size() - 1; k++) { row.add(""); } } else { for (PivotField dataField : dataFields) { row.add(dataField.getName()); } } } } // rows for (List<Object> rowKey : rowKeys) { List<Object> row = new ArrayList<Object>(); data.add(row); for (int k = 0; k < rowKey.size(); k++) { row.add(convert(rowKey.get(k))); } for (List<Object> columnKey : columnKeys) { for (PivotField dataField : dataFields) { Number cellValue = (Number) pivotModel.getValueAt(dataField, rowKey, columnKey); row.add(convert(cellValue)); } } if (!columnFields.isEmpty() && pivotModel.isShowGrandTotalForRow()) { MultiMap<PivotField, Object> values = new MultiMap<PivotField, Object>(); for (List<Object> columnKey: columnKeys) { for (PivotField dataField : dataFields) { values.addValue(dataField, pivotModel.getValueAt(dataField, rowKey, columnKey)); } } for (PivotField dataField : dataFields) { double grandTotalForRow = PivotUtils.getSummary(dataField, values.get(dataField)).doubleValue(); row.add(convert(grandTotalForRow)); } } } if (!rowFields.isEmpty() && pivotModel.isShowGrandTotalForColumn()) { List<Object> row = new ArrayList<Object>(); data.add(row); row.add(new StringResourceModel("pivot.grandTotal", null).getString()); for (int k = 0; k < rowFields.size() - 1; k++) { row.add(""); } Map<PivotField, Double> grandTotal = new HashMap<PivotField, Double>(); for (List<Object> columnKey : columnKeys) { MultiMap<PivotField, Object> values = new MultiMap<PivotField, Object>(); for (List<Object> rowKey : rowKeys) { for (PivotField dataField : dataFields) { values.addValue(dataField, pivotModel.getValueAt(dataField, rowKey, columnKey)); } } for (PivotField dataField : dataFields) { double grandTotalForColumn = PivotUtils.getSummary(dataField, values.get(dataField)).doubleValue(); if (!grandTotal.containsKey(dataField)) { grandTotal.put(dataField, grandTotalForColumn); } else { grandTotal.put(dataField, grandTotal.get(dataField) + grandTotalForColumn); } row.add(convert(grandTotalForColumn)); } } if (!columnFields.isEmpty() && pivotModel.isShowGrandTotalForRow()) { for (PivotField dataField : dataFields) { row.add(convert(grandTotal.get(dataField))); } } } return new TableData(null, data, null); } private static Object convert(Object obj) { if (obj instanceof Double) { if (Math.round((Double)obj) == ((Double)obj).longValue()) { return ((Double)obj).intValue(); } else { return Math.round( (Double)obj * FACTOR) / FACTOR; } } return obj; } public static void readPivotPropertiesFromWidget(PivotModel pivotModel, PivotWidget widget) { pivotModel.setShowGrandTotalForRow(widget.showRowTotal()); pivotModel.setShowGrandTotalForColumn(widget.showColumnTotal()); String[] rowFields = widget.getRowFields().split(","); int index = 0; for (String rowField : rowFields) { if (!rowField.isEmpty() && (pivotModel.getField(rowField) != null)) { pivotModel.getField(rowField).setArea(PivotField.Area.ROW).setAreaIndex(index); index++; } } String[] columnFields = widget.getColumnFields().split(","); index = 0; for (String columnField : columnFields) { if (!columnField.isEmpty() && (pivotModel.getField(columnField) != null)) { pivotModel.getField(columnField).setArea(PivotField.Area.COLUMN).setAreaIndex(index); index++; } } String[] dataFields = widget.getDataFields().split(","); index = 0; for (String dataField : dataFields) { if (!dataField.isEmpty() && (pivotModel.getField(dataField) != null)) { pivotModel.getField(dataField).setArea(PivotField.Area.DATA).setAreaIndex(index); index++; } } String[] aggregators = widget.getDataAggregators().split(","); for (int i=0, size=aggregators.length; i<size; i++) { String aggField = aggregators[i]; if (!aggField.isEmpty() && (pivotModel.getField(dataFields[i]) != null)) { pivotModel.getField(dataFields[i]).setAggregator(Aggregator.get(aggField)); } } } public static void writePivotPropertiesToWidget(PivotModel pivotModel, PivotWidget widget) { widget.setRowFields(getFieldsAsString(pivotModel.getFields(PivotField.Area.ROW))); widget.setColumnFields(getFieldsAsString(pivotModel.getFields(PivotField.Area.COLUMN))); widget.setDataFields(getFieldsAsString(pivotModel.getFields(PivotField.Area.DATA))); widget.setDataAggregators(getAggregators(pivotModel.getFields(PivotField.Area.DATA))); widget.setShowRowTotal(pivotModel.isShowGrandTotalForRow()); widget.setShowColumnTotal(pivotModel.isShowGrandTotalForColumn()); } private static String getFieldsAsString(List<PivotField> fields) { StringBuilder sb = new StringBuilder(); if (fields != null) { for (int i = 0, size = fields.size(); i < size; i++) { sb.append(fields.get(i).getName()); if (i < size-1) { sb.append(","); } } } return sb.toString(); } private static String getAggregators(List<PivotField> fields) { StringBuilder sb = new StringBuilder(); if (fields != null) { for (int i = 0, size = fields.size(); i < size; i++) { sb.append(fields.get(i).getAggregator().getFunction()); if (i < size-1) { sb.append(","); } } } return sb.toString(); } }