Java tutorial
/** * PureInfo QuakeCenter * @(#)MyTabeleDataHelper.java 1.0 2005-12-1 * * Copyright(c) 2004-2005, PureInfo Information Technology Corp. Ltd. * All rights reserved, see the license file. * * www.pureinfo.com.cn */ package com.pureinfo.srm.reports.table; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.ArrayUtils; import com.pureinfo.ark.content.ArkContentHelper; import com.pureinfo.ark.content.domain.IContentMgr; import com.pureinfo.common.namedvalue.model.INamedValue; import com.pureinfo.dolphin.DolphinHelper; import com.pureinfo.dolphin.model.DolphinObject; import com.pureinfo.dolphin.model.IObjects; import com.pureinfo.dolphin.persister.IStatement; import com.pureinfo.dolphin.query.logic.SQLCondition; import com.pureinfo.force.exception.PureException; /** * <P> * Created on 2005-12-1 14:32:57 <BR> * Last modified on 2005-12-1 * </P> * MyTabeleDataHelper to help build statistic * * @author elmar.chen * @version 1.0, 2005-12-1 * @since QuakeCenter 1.0 */ public class MyTabeleDataHelper { public static final String STR_COL = "_COL"; public static final String STR_ROW = "_ROW"; public static final String OTHER = "{%~@.other.@~%}"; public static final String TOTAL = "{%~@.total.@~%}"; public static Map getRowMap(Class _contentClass, SQLCondition _condition, String _sGroupProp, String[] _caredValues) throws PureException { IContentMgr mgr = ArkContentHelper.getContentMgrOf(_contentClass); List params = new ArrayList(); IObjects datas = null; IStatement query = null; Map row = null; try { String sCondion = ""; if (_condition != null) sCondion = _condition.toSQL(params); String strSQL = "SELECT COUNT(*) AS _COUNT, {this." + _sGroupProp + "} FROM {this}" + (sCondion == null || sCondion.trim().length() < 1 ? "" : " WHERE ") + sCondion + " GROUP BY {this." + _sGroupProp + '}'; query = mgr.createQuery(strSQL, 0); if (!params.isEmpty()) { query.setParameters(0, params); } datas = query.executeQuery(); row = new HashMap(datas.getSize()); do { DolphinObject data = datas.next(); if (data == null) { break; } row.put(data.getProperty(_sGroupProp), data.getProperty("_COUNT")); } while (true); } finally { params.clear(); DolphinHelper.clear(datas, query); } if (_caredValues != null) { int caredTotal = 0; int total = 0; for (Iterator iter = row.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); String sName = (String) entry.getKey(); Number num = (Number) entry.getValue(); if (ArrayUtils.contains(_caredValues, sName)) { caredTotal += num.intValue(); } total += num.intValue(); } row.put(OTHER, new Integer(total - caredTotal)); row.put(TOTAL, new Integer(total)); } return row; } /** * @param _contentClass content classes that take parts in do statistic; has at least 1 element * @param _alias alias for content classes,the fisrt one will be set to 'this' no matter what is passed in, * must have the same size as <code>_contentClass</code> * @param _sToCalculate to calculate what? this will be set in SELECT clause,and its value will be contained * in the data map returned * @param _condition conditions, that will be used in WHERE clause * @param _sGroupProp group by this * @param _caredValues what values are cared; if result is not in this array,it will be considered as "OTHER" * @return an map.contains <code>contentClass[0]._sGroupProp</code>->its result(a <code>java.lang.Number</code>) * @throws PureException if database access error or class metadata not found */ public static Map getRowMap(Class[] _contentClass, String[] _alias, String _sToCalculate, SQLCondition _condition, String _sGroupProp, String[] _caredValues) throws PureException { IContentMgr mgr = ArkContentHelper.getContentMgrOf(_contentClass[0]); List params = new ArrayList(); IObjects datas = null; IStatement query = null; Map row = null; if (_sToCalculate == null) _sToCalculate = "count( {this.*} )"; try { String sCondion = ""; if (_condition != null) sCondion = _condition.toSQL(params); String strSQL = "SELECT " + _sToCalculate + " AS _COUNT, {this." + _sGroupProp + "} FROM {this}"; for (int i = 1; i < _alias.length; i++) { strSQL += (",{" + _alias[i] + '}'); } strSQL += (sCondion == null || sCondion.trim().length() < 1 ? "" : " WHERE ") + sCondion + " GROUP BY {this." + _sGroupProp + '}'; query = mgr.createQuery(strSQL, 0); for (int i = 1; i < _contentClass.length; i++) { query.registerAlias(_alias[i], _contentClass[i]); } if (!params.isEmpty()) { query.setParameters(0, params); } datas = query.executeQuery(); row = new HashMap(datas.getSize()); do { DolphinObject data = datas.next(); if (data == null) { break; } row.put(data.getProperty(_sGroupProp), data.getProperty("_COUNT")); } while (true); } finally { params.clear(); DolphinHelper.clear(datas, query); } int caredTotal = 0; int total = 0; for (Iterator iter = row.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); String sName = (String) entry.getKey(); Number num = (Number) entry.getValue(); if (_caredValues != null) { if (ArrayUtils.contains(_caredValues, sName)) { caredTotal += num.intValue(); } } total += num.intValue(); } row.put(OTHER, new Integer(total - caredTotal)); row.put(TOTAL, new Integer(total)); return row; } public static Map getRowMap(Class[] _contentClass, String[] _alias, String[] _sToCalculate, SQLCondition _condition, String _sGroupProp, String[] _caredValues) throws PureException { IContentMgr mgr = ArkContentHelper.getContentMgrOf(_contentClass[0]); List params = new ArrayList(); IObjects datas = null; IStatement query = null; Map row = null; if (_sToCalculate == null) _sToCalculate = new String[] { "count( {this.*} )" }; try { String sCondion = ""; if (_condition != null) sCondion = _condition.toSQL(params); String strSQL = "SELECT "; for (int i = 0; i < _sToCalculate.length; i++) { strSQL += (_sToCalculate[i] + " AS _RESULT" + i + ','); } strSQL += " {this." + _sGroupProp + "} FROM {this}"; for (int i = 1; i < _alias.length; i++) { strSQL += (",{" + _alias[i] + '}'); } strSQL += (sCondion == null || sCondion.trim().length() < 1 ? "" : " WHERE ") + sCondion + " GROUP BY {this." + _sGroupProp + '}'; query = mgr.createQuery(strSQL, 0); for (int i = 1; i < _contentClass.length; i++) { query.registerAlias(_alias[i], _contentClass[i]); } if (!params.isEmpty()) { query.setParameters(0, params); } datas = query.executeQuery(); row = new HashMap(datas.getSize()); do { DolphinObject data = datas.next(); if (data == null) { break; } Object[] result = new Object[_sToCalculate.length]; for (int i = 0; i < result.length; i++) { result[i] = data.getProperty("_RESULT" + i); } row.put(data.getProperty(_sGroupProp), result); } while (true); } finally { params.clear(); DolphinHelper.clear(datas, query); } double[] caredTotal = new double[_sToCalculate.length]; double[] total = new double[_sToCalculate.length]; for (Iterator iter = row.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); String sName = (String) entry.getKey(); Object[] num = (Object[]) entry.getValue(); for (int i = 0; i < num.length; i++) { if (num[i] instanceof Number) { if (_caredValues != null) { if (ArrayUtils.contains(_caredValues, sName)) { caredTotal[i] += ((Number) num[i]).doubleValue(); } } caredTotal[i] += ((Number) num[i]).doubleValue(); } } } Object[] oOther = new Object[_sToCalculate.length]; Object[] oTotal = new Object[_sToCalculate.length]; for (int i = 0; i < total.length; i++) { oTotal[i] = new Double(total[i]); oOther[i] = new Double(total[i] - caredTotal[i]); } row.put(OTHER, oOther); row.put(TOTAL, oTotal); return row; } public static Map getDataMap2d(Class _contentClass, SQLCondition _condition, String _sGroupPropRow, String _sGroupPropCol, String[] _caredValuesRow, String[] _caredValuesCol) throws PureException { IContentMgr mgr = ArkContentHelper.getContentMgrOf(_contentClass); List params = new ArrayList(); IObjects datas = null; IStatement query = null; Map map2d = null; try { String sCondion = ""; if (_condition != null) sCondion = _condition.toSQL(params); String strSQL = "SELECT COUNT(*) AS _COUNT, {this." + _sGroupPropRow + "} AS " + STR_ROW + ", {this." + _sGroupPropCol + "} AS " + STR_COL + " FROM {this}" + (sCondion == null || sCondion.trim().length() < 1 ? "" : " WHERE ") + sCondion + " GROUP BY {this." + _sGroupPropRow + "},{this." + _sGroupPropCol + '}'; query = mgr.createQuery(strSQL, 0); if (!params.isEmpty()) { query.setParameters(0, params); } datas = query.executeQuery(); map2d = iObjectsToMap2D(datas); } finally { params.clear(); DolphinHelper.clear(datas, query); } calculateMap2d(map2d, _caredValuesRow, _caredValuesCol); return map2d; } public static Map getDataMap2d(Class _contentClass[], String[] _alias, String _sToCalculate, SQLCondition _condition, String _sGroupPropRow, String _sGroupPropCol, String[] _caredValuesRow, String[] _caredValuesCol) throws PureException { IContentMgr mgr = ArkContentHelper.getContentMgrOf(_contentClass[0]); List params = new ArrayList(); IObjects datas = null; IStatement query = null; Map map2d = null; if (_sToCalculate == null) _sToCalculate = "count( {this.id} )"; try { String sCondion = ""; if (_condition != null) sCondion = _condition.toSQL(params); String strSQL = "SELECT " + _sToCalculate + " AS _COUNT, {this." + _sGroupPropRow + "} AS " + STR_ROW + ", {this." + _sGroupPropCol + "} AS " + STR_COL + " FROM {this}"; for (int i = 1; i < _alias.length; i++) { strSQL += (",{" + _alias[i] + '}'); } strSQL += (sCondion == null || sCondion.trim().length() < 1 ? "" : " WHERE ") + sCondion + " GROUP BY {this." + _sGroupPropRow + "},{this." + _sGroupPropCol + '}'; query = mgr.createQuery(strSQL, 0); for (int i = 1; i < _contentClass.length; i++) { query.registerAlias(_alias[i], _contentClass[i]); } if (!params.isEmpty()) { query.setParameters(0, params); } datas = query.executeQuery(); map2d = iObjectsToMap2D(datas); } finally { params.clear(); DolphinHelper.clear(datas, query); } calculateMap2d(map2d, _caredValuesRow, _caredValuesCol); return map2d; } private static void calculateMap2d(Map _map2d, String[] _sValuesRow, String[] _sValuesCol) { for (Iterator iter = _map2d.values().iterator(); iter.hasNext();) { calculateAndSetMapRow((Map) iter.next(), _sValuesCol); ; } calculateAndSetMap2dGeneral(_map2d, _sValuesRow); } /** * @param _map2d * @param _sValuesRow */ private static void calculateAndSetMap2dGeneral(Map _map2d, String[] _sValuesRow) { if (_map2d == null) return; Map total = new HashMap(), cared = new HashMap(); for (int i = 0; i < _sValuesRow.length; i++) { Map row = (Map) _map2d.get(_sValuesRow[i]); if (row == null) continue; for (Iterator iter = row.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Entry) iter.next(); int v = getInt((Number) cared.get(entry.getKey())); v += getInt((Number) entry.getValue()); cared.put(entry.getKey(), new Integer(v)); } } for (Iterator iter = _map2d.values().iterator(); iter.hasNext();) { Map row = (Map) iter.next(); if (row == null) continue; for (Iterator iter1 = row.entrySet().iterator(); iter1.hasNext();) { Map.Entry entry = (Entry) iter1.next(); int v = getInt((Number) total.get(entry.getKey())); v += getInt((Number) entry.getValue()); total.put(entry.getKey(), new Integer(v)); } } _map2d.put(TOTAL, total); _map2d.put(OTHER, subMap(total, cared)); } /** * @param _total * @param _cared * @return */ private static Object subMap(Map _total, Map _cared) { Map map = new HashMap(_total.size()); for (Iterator iter = _total.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Entry) iter.next(); int total = getInt((Number) entry.getValue()); int cared = getInt((Number) _cared.get(entry.getKey())); map.put(entry.getKey(), new Integer(total - cared)); } return map; } /** * @param _sValuesCol * @param _sRow */ public static void calculateAndSetMapRow(Map _row, String[] _sValuesCol) { if (_row == null) return; int total = 0, cared = 0; for (int i = 0; i < _sValuesCol.length; i++) { Number num = (Number) _row.get(_sValuesCol[i]); if (num != null) { cared += num.intValue(); } } for (Iterator iter = _row.values().iterator(); iter.hasNext();) { Number num = (Number) iter.next(); if (num != null) { total += num.intValue(); } } _row.put(OTHER, new Integer(total - cared)); _row.put(TOTAL, new Integer(total)); } public static Map iObjectsToMap2D(IObjects datas) throws PureException { Map row; row = new HashMap(datas.getSize()); do { DolphinObject data = datas.next(); if (data == null) { break; } String sRowValue = data.getPropertyAsString(STR_ROW); String sColValue = data.getPropertyAsString(STR_COL); if (row.get(sRowValue) == null) { row.put(sRowValue, new HashMap()); } Map map = (Map) row.get(sRowValue); map.put(sColValue, data.getProperty("_COUNT")); } while (true); return row; } public static String[] clearDupAndNull(String[] _before) { if (_before == null) { return null; } String[] medial = new String[_before.length]; int n = 0; for (int i = 0; i < _before.length; i++) { if (_before[i] == null) { continue; } if (ArrayUtils.contains(medial, _before)) { continue; } medial[n++] = _before[i]; } if (n == _before.length) { return medial; } String[] result = new String[n]; for (int i = 0; i < n; i++) { result[i] = medial[i]; } return result; } public static Object[][] renderData(Map map2d, String[][] _caredRow, String[][] _caredCol) { return renderData(map2d, _caredRow[0], _caredCol[0], _caredRow[1], _caredCol[1]); } /** * @param map2d * @param _caredValuesRow * @param _caredValuesCol * @param _caredNamesRow * @param _caredNamesCol * @deprecated use <code>public static Object[][] renderData(Map map2d,String[][] _caredRow,String[][] _caredCol)</code> * @return */ public static Object[][] renderData(Map map2d, String[] _caredValuesRow, String[] _caredValuesCol, String[] _caredNamesRow, String[] _caredNamesCol) { Object[][] datas = new Object[_caredValuesRow.length + 3][_caredValuesCol.length + 3]; setTitle(datas, _caredNamesCol); int i = 0; for (; i < _caredValuesRow.length; i++) { datas[i + 1][0] = _caredNamesRow[i]; renderEach(datas, i + 1, (Map) map2d.get(_caredValuesRow[i]), _caredValuesCol); } datas[i + 1][0] = "[]"; renderEach(datas, i + 1, (Map) map2d.get(OTHER), _caredValuesCol); i++; datas[i + 1][0] = ""; renderEach(datas, i + 1, (Map) map2d.get(TOTAL), _caredValuesCol); return datas; } private static void renderEach(Object[][] _datas, int _nPosition, Map row, String[] _sCaredValuesCol) { if (row == null) { for (int i = 1; i < _datas[_nPosition].length; i++) { _datas[_nPosition][i] = new Integer(0); } return; } int i = 0; for (; i < _sCaredValuesCol.length; i++) { _datas[_nPosition][i + 1] = new Integer(getInt((Number) row.get(_sCaredValuesCol[i]))); } _datas[_nPosition][i + 1] = new Integer(getInt((Number) row.get(OTHER))); i++; _datas[_nPosition][i + 1] = new Integer(getInt((Number) row.get(TOTAL))); } private static void setTitle(Object[][] _datas, String[] _sCaredNamesCol) { int i = 0; for (; i < _sCaredNamesCol.length; i++) { _datas[0][i + 1] = _sCaredNamesCol[i]; } _datas[0][i + 1] = "[]"; i++; _datas[0][i + 1] = ""; } public static String getRatioString(double n, double d) { if (d < 0.0001) { return "----"; } DecimalFormat format = new DecimalFormat("#0.0%"); return format.format(n / d); } public static int getInt(Number num) { if (num != null) return num.intValue(); return 0; } /** * @param list list consists of <code>DolphinObject</code> * @param _sValueProp property of <code>DolphinObject</code> in the list which will be used as value * @param _sNameProp property of <code>DolphinObject</code> in the list which will be used as name * @return a n*2 array of String, which fisrt line is values and second is names */ public static String[][] list2Strings(List list, String _sValueProp, String _sNameProp) { String[][] arr = new String[2][list.size()]; int i = 0; for (Iterator iter = list.iterator(); iter.hasNext();) { DolphinObject obj = (DolphinObject) iter.next(); arr[0][i] = obj.getPropertyAsString(_sValueProp); arr[1][i] = obj.getPropertyAsString(_sNameProp); i++; } return arr; } /** * to insert an array to another array * @see void insertIntoLine(Object[] _des,Object[] _src, int beginIdx) */ public void insertIntoLine(Object[] _des, Object[] _src) { insertIntoLine(_des, _src, 0); } /** * to insert an array to another array at a given position, if the destination dosen't have enough space,redundant element will be ignored * @param _des array to insert into * @param _src array to be inserted from * @param beginIdx begin index of <code>_des</code> */ public void insertIntoLine(Object[] _des, Object[] _src, int beginIdx) { for (int i = 0, j = beginIdx; j < _des.length && i < _src.length; i++, j++) { _des[j] = _src[i]; } } public String[][] namdValueList2array(List list) { String[][] arr = new String[2][list.size()]; int i = 0; for (Iterator iter = list.iterator(); iter.hasNext();) { INamedValue nv = (INamedValue) iter.next(); arr[0][i] = nv.getValue(); arr[1][i] = nv.getName(); i++; } return arr; } public static Map List2Map(List objs, String _sKeyProp) { Map map = new HashMap(objs.size()); for (Iterator iter = objs.iterator(); iter.hasNext();) { DolphinObject obj = (DolphinObject) iter.next(); map.put(obj.getProperty(_sKeyProp), obj); } return map; } }