/****************************************************************************** * Product: Adempiere ERP & CRM Smart Business Solution * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * * or via info@compiere.org or http://www.compiere.org/license.html * *****************************************************************************/ package org.compiere.print; import java.io.Serializable; import java.math.BigDecimal; import java.sql.Clob; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Timestamp; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Properties; import java.util.logging.Level; import java.util.regex.Pattern; import org.adempiere.exceptions.AdempiereException; import org.compiere.model.MColumn; import org.compiere.model.MLookupFactory; import org.compiere.model.MQuery; import org.compiere.model.MReportView; import org.compiere.model.MRole; import org.compiere.model.MSysConfig; import org.compiere.model.MTable; import org.compiere.model.SystemIDs; import org.compiere.util.CLogMgt; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.Ini; import org.compiere.util.KeyNamePair; import org.compiere.util.Language; import org.compiere.util.Msg; import org.compiere.util.Util; import org.compiere.util.ValueNamePair; import bsh.EvalError; import bsh.Interpreter; /** * Data Engine.
* Creates SQL and loads data into PrintData (including totals/etc). * * @author Jorg Janke * @version $Id: DataEngine.java,v 1.3 2006/07/30 00:53:02 jjanke Exp $ * * @author Teo Sarca, SC ARHIPAC SERVICE SRL *
  • BF [ 1761891 ] Included print format with report view attached issue *
  • BF [ 1807368 ] DataEngine does not close DB connection *
  • BF [ 2549128 ] Report View Column not working at all *
  • BF [ 2865545 ] Error if not all parts of multikey are lookups * https://sourceforge.net/p/adempiere/bugs/2120/ * @author Teo Sarca, teo.sarca@gmail.com *
  • BF [ 2876268 ] DataEngine: error on text long fields * https://sourceforge.net/p/adempiere/bugs/2169/ * @author victor.perez@e-evolution.com *
  • FR [ 2011569 ] Implementing new Summary flag in Report View https://sourceforge.net/p/adempiere/feature-requests/478/ * @author Paul Bowden (phib) *
  • BF 2908435 Virtual columns with lookup reference types can't be printed * https://sourceforge.net/p/adempiere/bugs/2246/ * @contributor Fernandinho (FAIRE) * - http://jira.idempiere.com/browse/IDEMPIERE-153 */ public class DataEngine { /** * Constructor * @param language Language of the data (for translation) */ public DataEngine (Language language) { this(language, null, 0); } // DataEngine /** * Constructor * @param language * @param trxName */ public DataEngine (Language language, String trxName){ this(language,trxName,0); } /** * Constructor * @param language Language of the data (for translation) * @param trxName * @param windowNo */ public DataEngine (Language language, String trxName, int windowNo){ if (language != null) m_language = language; m_trxName = trxName; m_windowNo = windowNo; } // DataEngine /** Logger */ private static CLogger log = CLogger.getCLogger (DataEngine.class); /** Synonym */ private String m_synonym = "A"; /** Default Language */ private Language m_language = Language.getLoginLanguage(); /** Break & Column Functions */ private PrintDataGroup m_group = new PrintDataGroup(); /** Start Time */ private long m_startTime = System.currentTimeMillis(); /** Running Total after .. lines */ private int m_runningTotalLines = -1; /** Print String */ @SuppressWarnings("unused") private String m_runningTotalString = null; /** TrxName String */ private String m_trxName = null; /** Report Summary FR [ 2011569 ]**/ private boolean m_summary = false; /** Key Indicator in Report */ public static final String KEY = "*"; /** Window No */ private int m_windowNo = 0; private Map m_summarized = new HashMap(); public static final int DEFAULT_REPORT_LOAD_TIMEOUT_IN_SECONDS = 120; public static final int DEFAULT_GLOBAL_MAX_REPORT_RECORDS = 100000; /** * Load Data * * @param format print format * @param query query * @param ctx context * @return PrintData or null */ public PrintData getPrintData (Properties ctx, MPrintFormat format, MQuery query) { return getPrintData(ctx, format, query, false); } /** * Load Data * * @param format print format * @param query query * @param ctx context * @param summary * @return PrintData or null */ public PrintData getPrintData (Properties ctx, MPrintFormat format, MQuery query, boolean summary) { MQuery queryCopy = query.deepCopy(); /** Report Summary FR [ 2011569 ]**/ m_summary = summary; if (format == null) throw new IllegalStateException ("No print format"); if (format.getJasperProcess_ID() > 0) return null; String tableName = null; String reportName = format.getName(); // if (format.getAD_ReportView_ID() != 0) { StringBuilder sql = new StringBuilder("SELECT t.AD_Table_ID, t.TableName, rv.Name, rv.WhereClause ") .append("FROM AD_Table t") .append(" INNER JOIN AD_ReportView rv ON (t.AD_Table_ID=rv.AD_Table_ID) ") .append("WHERE rv.AD_ReportView_ID=?"); // 1 PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(sql.toString(), m_trxName); pstmt.setInt(1, format.getAD_ReportView_ID()); rs = pstmt.executeQuery(); if (rs.next()) { tableName = rs.getString(2); // TableName reportName = rs.getString(3); // Add WhereClause restriction from AD_ReportView - teo_sarca BF [ 1761891 ] String whereClause = rs.getString(4); if (!Util.isEmpty(whereClause)) { whereClause = "(" + whereClause + ")"; // IDEMPIERE-2597 if (whereClause.indexOf("@") == -1) { queryCopy.addRestriction(whereClause); } else { // replace context variables queryCopy.addRestriction(Env.parseContext(ctx, m_windowNo, whereClause.toString(), false, true)); } } } } catch (SQLException e) { log.log(Level.SEVERE, sql.toString(), e); return null; } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } } else { tableName = MTable.getTableName(ctx, format.getAD_Table_ID()); } if (tableName == null) { log.log(Level.SEVERE, "Not found Format=" + format); return null; } if (format.isTranslationView() && tableName.toLowerCase().endsWith("_v")) // _vt not just _v { boolean hasVT = DB.isTableOrViewExists(tableName+"t"); if (hasVT) { tableName += "t"; format.setTranslationViewQuery (queryCopy); } } // PrintData pd = getPrintDataInfo (ctx, format, queryCopy, reportName, tableName); if (pd == null) return null; loadPrintData(pd, format); return pd; } // getPrintData /** * Construct Load Data SQL and create new PrintData instance * * @param ctx context * @param format print format * @param query query * @param reportName report name * @param tableName table name * @return PrintData or null */ private PrintData getPrintDataInfo (Properties ctx, MPrintFormat format, MQuery query, String reportName, String tableName) { m_startTime = System.currentTimeMillis(); if (log.isLoggable(Level.INFO)) log.info(reportName + " - " + m_language.getAD_Language()); if (log.isLoggable(Level.FINE)) { log.fine("TableName=" + tableName + ", Query=" + query); log.fine("Format=" + format); } ArrayList columns = new ArrayList(); m_group = new PrintDataGroup(); // Order Columns (identified by non zero/null SortNo) int[] orderAD_Column_IDs = format.getOrderAD_Column_IDs(); ArrayList orderColumns = new ArrayList(orderAD_Column_IDs.length); for (int i = 0; i < orderAD_Column_IDs.length; i++) { if (log.isLoggable(Level.FINEST)) log.finest("Order AD_Column_ID=" + orderAD_Column_IDs[i]); orderColumns.add(""); // initial value overwritten with fully qualified name } // Direct SQL w/o Reference Info StringBuilder sqlSELECT = new StringBuilder("SELECT "); StringBuilder sqlFROM = new StringBuilder(" FROM ").append(tableName); ArrayList groupByColumns = new ArrayList(); // boolean IsGroupedBy = false; // StringBuilder sql = new StringBuilder("SELECT c.AD_Column_ID,c.ColumnName,") // 1..2 .append("c.AD_Reference_ID,c.AD_Reference_Value_ID,") // 3..4 .append("c.FieldLength,c.IsMandatory,c.IsKey,c.IsParent,") // 5..8 .append("COALESCE(rvc.IsGroupFunction,'N'),rvc.FunctionColumn,") // 9..10 .append("pfi.IsGroupBy,pfi.IsSummarized,pfi.IsAveraged,pfi.IsCounted, ") // 11..14 .append("pfi.IsPrinted,pfi.SortNo,pfi.IsPageBreak, ") // 15..17 .append("pfi.IsMinCalc,pfi.IsMaxCalc, ") // 18..19 .append("pfi.isRunningTotal,pfi.RunningTotalLines, ") // 20..21 .append("pfi.IsVarianceCalc, pfi.IsDeviationCalc, ") // 22..23 .append("c.ColumnSQL, COALESCE(pfi.FormatPattern, c.FormatPattern) ") // 24, 25 //BEGIN http://jira.idempiere.com/browse/IDEMPIERE-153 /** START DEVCOFFEE: script column **/ .append(" , pfi.isDesc, pfi.Script, pfi.Name, pfi.AD_PrintFormatItem_ID, pfi.PrintFormatType ") // 26..30 //END .append("FROM AD_PrintFormat pf") .append(" INNER JOIN AD_PrintFormatItem pfi ON (pf.AD_PrintFormat_ID=pfi.AD_PrintFormat_ID)") .append(" LEFT JOIN AD_Column c ON (pfi.AD_Column_ID=c.AD_Column_ID)") .append(" LEFT OUTER JOIN AD_ReportView_Col rvc ON (pf.AD_ReportView_ID=rvc.AD_ReportView_ID AND c.AD_Column_ID=rvc.AD_Column_ID) ") .append("WHERE pf.AD_PrintFormat_ID=?") // #1 .append(" AND pfi.IsActive='Y' AND (pfi.IsPrinted='Y' OR c.IsKey='Y' OR pfi.SortNo > 0 ") .append(" OR EXISTS(select 1 from AD_PrintFormatItem x where x.AD_PrintFormat_ID=pf.AD_PrintFormat_ID and x.DisplayLogic is not null and ") .append("(x.DisplayLogic Like '%@'||c.ColumnName||'@%' OR x.DisplayLogic Like '%@'||c.ColumnName||':%@%' OR x.DisplayLogic Like '%@'||c.ColumnName||'.%@%'))) ") .append(" AND pfi.PrintFormatType IN ('" + MPrintFormatItem.PRINTFORMATTYPE_Field + "','" + MPrintFormatItem.PRINTFORMATTYPE_Image + "','" + MPrintFormatItem.PRINTFORMATTYPE_PrintFormat + "','" + MPrintFormatItem.PRINTFORMATTYPE_Script + "') ") .append(" ORDER BY pfi.IsPrinted DESC, pfi.SeqNo"); // Functions are put in first column PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(sql.toString(), m_trxName); pstmt.setInt(1, format.get_ID()); rs = pstmt.executeQuery(); m_synonym = "A"; // synonym // init regular object to replace table name in virtual column String orgTable = null; Pattern regTranslateTable = null; if (tableName.toLowerCase().endsWith("_vt")){ orgTable = MTable.getTableName(ctx, format.getAD_Table_ID()); regTranslateTable = Pattern.compile("\\b" + orgTable + "\\b", Pattern.CASE_INSENSITIVE); } while (rs.next()) { // get Values from record int AD_Column_ID = rs.getInt(1); int AD_PrintFormatItem_ID = rs.getInt("AD_PrintFormatItem_ID"); String ColumnName = rs.getString(2); String ColumnSQL = rs.getString(24); if (ColumnSQL != null && ColumnSQL.length() > 0 && ColumnSQL.startsWith(MColumn.VIRTUAL_SEARCH_COLUMN_PREFIX)) ColumnSQL = ColumnSQL.substring(9); if (ColumnSQL != null && ColumnSQL.length() > 0 && ColumnSQL.startsWith(MColumn.VIRTUAL_UI_COLUMN_PREFIX)) ColumnSQL = "NULL"; if (ColumnSQL != null && ColumnSQL.contains("@")) ColumnSQL = Env.parseContext(Env.getCtx(), m_windowNo, ColumnSQL, false, true); if (ColumnSQL == null) ColumnSQL = ""; else{ // replace table with translate table IDEMPIERE-2234 if (tableName.toLowerCase().endsWith("_vt")){ ColumnSQL = regTranslateTable.matcher(ColumnSQL).replaceAll(tableName); } } int AD_Reference_ID = rs.getInt(3); int AD_Reference_Value_ID = rs.getInt(4); // ColumnInfo int FieldLength = rs.getInt(5); boolean IsMandatory = "Y".equals(rs.getString(6)); boolean IsKey = "Y".equals(rs.getString(7)); // SQL GroupBy boolean IsGroupFunction = "Y".equals(rs.getString(9)); if (IsGroupFunction) IsGroupedBy = true; String FunctionColumn = rs.getString(10); if (FunctionColumn == null) FunctionColumn = ""; // Breaks/Column Functions if ("Y".equals(rs.getString(11))) m_group.addGroupColumn(AD_PrintFormatItem_ID); if ("Y".equals(rs.getString(12))) m_group.addFunction(AD_PrintFormatItem_ID, PrintDataFunction.F_SUM); if ("Y".equals(rs.getString(13))) m_group.addFunction(AD_PrintFormatItem_ID, PrintDataFunction.F_MEAN); if ("Y".equals(rs.getString(14))) m_group.addFunction(AD_PrintFormatItem_ID, PrintDataFunction.F_COUNT); if ("Y".equals(rs.getString(18))) // IsMinCalc m_group.addFunction(AD_PrintFormatItem_ID, PrintDataFunction.F_MIN); if ("Y".equals(rs.getString(19))) // IsMaxCalc m_group.addFunction(AD_PrintFormatItem_ID, PrintDataFunction.F_MAX); if ("Y".equals(rs.getString(22))) // IsVarianceCalc m_group.addFunction(AD_PrintFormatItem_ID, PrintDataFunction.F_VARIANCE); if ("Y".equals(rs.getString(23))) // IsDeviationCalc m_group.addFunction(AD_PrintFormatItem_ID, PrintDataFunction.F_DEVIATION); if ("Y".equals(rs.getString(20))) // isRunningTotal // RunningTotalLines only once - use max m_runningTotalLines = Math.max(m_runningTotalLines, rs.getInt(21)); // General Info boolean IsPrinted = "Y".equals(rs.getString(15)); boolean isPageBreak = "Y".equals(rs.getString(17)); String formatPattern = rs.getString(25); String printFormatType = rs.getString(30); //BEGIN http://jira.idempiere.com/browse/IDEMPIERE-153 boolean isDesc = "Y".equals(rs.getString(26)); //END /** START DEVCOFFEE: script column **/ String script = rs.getString(27); String pfiName = rs.getString(28); // Fully qualified Table.Column for ordering String orderName = tableName + "." + ColumnName; String lookupSQL = orderName; PrintDataColumn pdc = null; // -- Key -- if (IsKey) { // => Table.Column, sqlSELECT.append(tableName).append(".").append(ColumnName).append(","); groupByColumns.add(tableName+"."+ColumnName); pdc = new PrintDataColumn(AD_PrintFormatItem_ID, AD_Column_ID, ColumnName, AD_Reference_ID, FieldLength, KEY, isPageBreak); // KeyColumn } /** START DEVCOFFEE: script column **/ else if (ColumnName == null || script != null && !script.isEmpty()) { // => (..) AS AName, Table.ID, if (script != null && !script.isEmpty()) { if (script.startsWith(MColumn.VIRTUAL_UI_COLUMN_PREFIX)) { script = "(" + script.replace(MColumn.VIRTUAL_UI_COLUMN_PREFIX, "").trim() + ")"; script = Env.parseContext(Env.getCtx(), m_windowNo, script, false); } else script = "'@SCRIPT" + script + "'"; } else script = ""; if (ColumnName == null && script.isEmpty()) continue; sqlSELECT.append(script).append(" AS \"").append(m_synonym).append(pfiName).append("\",") // Warning here: Oracle treats empty strings '' as NULL and the code below checks for wasNull on this column .append("' '").append(" AS \"").append(pfiName).append("\","); // int scriptDisplayType = getDisplayTypeFromPattern(formatPattern); pdc = new PrintDataColumn(AD_PrintFormatItem_ID, -1, pfiName, scriptDisplayType, FieldLength, orderName, isPageBreak); synonymNext(); } // -- Parent, TableDir (and unqualified Search) -- else if ( AD_Reference_ID == DisplayType.TableDir || (AD_Reference_ID == DisplayType.Search && AD_Reference_Value_ID == 0) ) { // Creates Embedded SQL in the form // SELECT ColumnTable.Name FROM ColumnTable WHERE TableName.ColumnName=ColumnTable.ColumnName String eSql; if (ColumnSQL.length() > 0) { eSql = MLookupFactory.getLookup_TableDirEmbed(m_language, ColumnName, tableName, "(" + ColumnSQL + ")"); lookupSQL = ColumnSQL; } else { eSql = MLookupFactory.getLookup_TableDirEmbed(m_language, ColumnName, tableName); } if (Util.isEmpty(eSql)) { // No Identifier records found eSql = lookupSQL; } // DisplayColumn String display = ColumnName; // => (..) AS AName, Table.ID, sqlSELECT.append("(").append(eSql).append(") AS ").append(m_synonym).append(display).append(",") .append(lookupSQL).append(" AS ").append(ColumnName).append(","); groupByColumns.add(lookupSQL); orderName = m_synonym + display; // pdc = new PrintDataColumn(AD_PrintFormatItem_ID, AD_Column_ID, ColumnName, AD_Reference_ID, FieldLength, orderName, isPageBreak); synonymNext(); } // -- Table -- else if (AD_Reference_ID == DisplayType.Table || (AD_Reference_ID == DisplayType.Search && AD_Reference_Value_ID != 0) ) { String eSql = MLookupFactory.getLookup_TableEmbed(m_language, ColumnName, tableName, AD_Reference_Value_ID); if (ColumnSQL.length() > 0) lookupSQL = ColumnSQL; // DisplayColumn String display = ColumnName; // => (..) AS AName, Table.ID, sqlSELECT.append("(").append(eSql).append(") AS ").append(m_synonym).append(display).append(",") .append(lookupSQL).append(" AS ").append(ColumnName).append(","); groupByColumns.add(m_synonym+display); groupByColumns.add(lookupSQL); orderName = m_synonym + display; // TableReference tr = getTableReference(AD_Reference_Value_ID); String foreignColumnName = tr.KeyColumn; pdc = new PrintDataColumn(AD_PrintFormatItem_ID, AD_Column_ID, ColumnName, AD_Reference_ID, FieldLength, orderName, isPageBreak, foreignColumnName); synonymNext(); } // -- List or Button with ReferenceValue -- else if (DisplayType.isList(AD_Reference_ID) || (AD_Reference_ID == DisplayType.Button && AD_Reference_Value_ID != 0)) { if (ColumnSQL.length() > 0) { lookupSQL = ColumnSQL; } if (Env.isBaseLanguage(m_language, "AD_Ref_List")) { // => A.Name AS AName, sqlSELECT.append(m_synonym).append(".Name AS ").append(m_synonym).append("Name,"); groupByColumns.add(m_synonym+".Name"); orderName = m_synonym + "Name"; // => x JOIN AD_Ref_List A ON (x.KeyColumn=A.Value AND A.AD_Reference_ID=123) sqlFROM.append(" LEFT OUTER JOIN "); sqlFROM.append("AD_Ref_List ").append(m_synonym).append(" ON (") .append(lookupSQL).append("=").append(m_synonym).append(".Value") .append(" AND ").append(m_synonym).append(".AD_Reference_ID=").append(AD_Reference_Value_ID).append(")"); } else { // => A.Name AS AName, sqlSELECT.append(m_synonym).append(".Name AS ").append(m_synonym).append("Name,"); groupByColumns.add(m_synonym+".Name"); orderName = m_synonym + "Name"; // LEFT OUTER JOIN AD_Ref_List XA ON (AD_Table.EntityType=XA.Value AND XA.AD_Reference_ID=245) // LEFT OUTER JOIN AD_Ref_List_Trl A ON (XA.AD_Ref_List_ID=A.AD_Ref_List_ID AND A.AD_Language='de_DE') sqlFROM.append(" LEFT OUTER JOIN "); sqlFROM.append(" AD_Ref_List X").append(m_synonym).append(" ON (") .append(lookupSQL).append("=X") .append(m_synonym).append(".Value AND X").append(m_synonym).append(".AD_Reference_ID=").append(AD_Reference_Value_ID) .append(")"); sqlFROM.append(" LEFT OUTER JOIN "); sqlFROM.append(" AD_Ref_List_Trl ").append(m_synonym).append(" ON (X") .append(m_synonym).append(".AD_Ref_List_ID=").append(m_synonym).append(".AD_Ref_List_ID") .append(" AND ").append(m_synonym).append(".AD_Language='").append(m_language.getAD_Language()).append("')"); } // TableName.ColumnName, sqlSELECT.append(lookupSQL).append(" AS ").append(ColumnName).append(","); groupByColumns.add(lookupSQL); pdc = new PrintDataColumn(AD_PrintFormatItem_ID, AD_Column_ID, ColumnName, AD_Reference_ID, FieldLength, orderName, isPageBreak); synonymNext(); } // -- Special Lookups -- else if (AD_Reference_ID == DisplayType.Location || AD_Reference_ID == DisplayType.Account || AD_Reference_ID == DisplayType.Locator || AD_Reference_ID == DisplayType.PAttribute ) { if (ColumnSQL.length() > 0) { lookupSQL = ColumnSQL; } // TableName, DisplayColumn String table = ""; String key = ""; String display = ""; String synonym = null; // if (AD_Reference_ID == DisplayType.Location) { table = "C_Location"; key = "C_Location_ID"; display = "City||'.'"; // in case City is empty synonym = "Address"; } else if (AD_Reference_ID == DisplayType.Account) { table = "C_ValidCombination"; key = "C_ValidCombination_ID"; display = "Combination"; } else if (AD_Reference_ID == DisplayType.Locator) { table = "M_Locator"; key = "M_Locator_ID"; display = "Value"; } else if (AD_Reference_ID == DisplayType.PAttribute) { table = "M_AttributeSetInstance"; key = "M_AttributeSetInstance_ID"; display = "Description"; if (CLogMgt.isLevelFine()) display += "||'{'||" + m_synonym + ".M_AttributeSetInstance_ID||'}'"; synonym = "Description"; } if (synonym == null) synonym = display; // => A.Name AS AName, table.ID, sqlSELECT.append(m_synonym).append(".").append(display).append(" AS ") .append(m_synonym).append(synonym).append(",") .append(lookupSQL).append(" AS ").append(ColumnName).append(","); groupByColumns.add(m_synonym+"."+synonym); groupByColumns.add(lookupSQL); orderName = m_synonym + synonym; // => x JOIN table A ON (table.ID=A.Key) if (IsMandatory) sqlFROM.append(" INNER JOIN "); else sqlFROM.append(" LEFT OUTER JOIN "); sqlFROM.append(table).append(" ").append(m_synonym).append(" ON (") .append(lookupSQL).append("=") .append(m_synonym).append(".").append(key).append(")"); // pdc = new PrintDataColumn(AD_PrintFormatItem_ID, AD_Column_ID, ColumnName, AD_Reference_ID, FieldLength, orderName, isPageBreak); synonymNext(); } // -- Standard Column -- else { int index = FunctionColumn.indexOf('@'); if (ColumnSQL != null && ColumnSQL.length() > 0) { // => ColumnSQL AS ColumnName sqlSELECT.append(ColumnSQL).append(" AS ").append(ColumnName).append(","); if (!IsGroupFunction) groupByColumns.add(ColumnSQL); orderName = ColumnName; // no prefix for synonym } else if (index == -1) { // => Table.Column, StringBuilder sb = new StringBuilder(); sb.append(tableName).append(".").append(ColumnName); sqlSELECT.append(sb).append(","); if (!IsGroupFunction) groupByColumns.add(sb.toString()); } else { // => Function(Table.Column) AS Column -- function has @ where column name goes StringBuilder sb = new StringBuilder(); sb.append(FunctionColumn.substring(0, index)) .append(tableName).append(".").append(ColumnName) .append(FunctionColumn.substring(index+1)); sqlSELECT.append(sb).append(" AS ").append(ColumnName).append(","); if (!IsGroupFunction) groupByColumns.add(sb.toString()); orderName = ColumnName; // no prefix for synonym } pdc = new PrintDataColumn(AD_PrintFormatItem_ID, AD_Column_ID, ColumnName, AD_Reference_ID, FieldLength, ColumnName, isPageBreak); } // Order Sequence - Overwrite order column name for (int i = 0; i < orderAD_Column_IDs.length; i++) { if (AD_Column_ID == orderAD_Column_IDs[i]) { //BEGIN fernandinho - http://jira.idempiere.com/browse/IDEMPIERE-153 if (isDesc) orderName += " DESC"; //END orderColumns.set(i, orderName); // We need to GROUP BY even is not printed, because is used in ORDER clause if (!IsPrinted && !IsGroupFunction) { groupByColumns.add(tableName+"."+ColumnName); } break; } } // pdc.setFormatPattern(formatPattern); pdc.setPrintFormatType(printFormatType); columns.add(pdc); } // for all Fields in Tab } catch (SQLException e) { log.log(Level.SEVERE, "SQL=" + sql + " - ID=" + format.get_ID(), e); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } if (columns.size() == 0) { log.log(Level.SEVERE, "No Columns - Delete Report Format " + reportName + " and start again"); if (log.isLoggable(Level.FINEST)) log.finest("No Columns - SQL=" + sql + " - ID=" + format.get_ID()); return null; } boolean hasLevelNo = false; if (tableName.startsWith("T_Report")) { hasLevelNo = true; if (sqlSELECT.indexOf("LevelNo") == -1) sqlSELECT.append("LevelNo,"); if (tableName.equals("T_Report") && sqlSELECT.indexOf("PA_ReportLine_ID") == -1) sqlSELECT.append("PA_ReportLine_ID,"); } /** * Assemble final SQL - delete last SELECT ',' */ StringBuilder finalSQL = new StringBuilder(); finalSQL.append(sqlSELECT.substring(0, sqlSELECT.length()-1)) .append(sqlFROM); // WHERE clause if (tableName.startsWith("T_Report")) { finalSQL.append(" WHERE "); for (int i = 0; i < query.getRestrictionCount(); i++) { String q = query.getWhereClause (i); if (q.indexOf("AD_PInstance_ID") != -1) // ignore all other Parameters finalSQL.append (q); } // for all restrictions } else { // User supplied Where Clause if (query != null && query.isActive ()) { finalSQL.append (" WHERE "); if (!query.getTableName ().equals (tableName)) query.setTableName (tableName); finalSQL.append (query.getWhereClause (true)); } // Access Restriction MRole role = MRole.getDefault(ctx, false); if (role.getAD_Role_ID() == SystemIDs.ROLE_SYSTEM && !Ini.isClient()) ; // System Access else finalSQL = new StringBuilder (role.addAccessSQL (finalSQL.toString (), tableName, MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO)); } // Add GROUP BY clause if (IsGroupedBy) { for (int i = 0; i < groupByColumns.size(); i++) { if (i == 0) finalSQL.append(" GROUP BY "); else finalSQL.append(","); finalSQL.append(groupByColumns.get(i)); } } // Add ORDER BY clause if (orderColumns != null && orderColumns.size() > 0) { for (int i = 0; i < orderColumns.size(); i++) { if (i == 0) finalSQL.append(" ORDER BY "); else finalSQL.append(","); String by = (String)orderColumns.get(i); if (by == null || by.length() == 0) by = String.valueOf(i+1); finalSQL.append(by); } } // order by else if (format.getAD_ReportView_ID() > 0) { MReportView reportView = MReportView.get(Env.getCtx(),format.getAD_ReportView_ID()); if (reportView!=null && !Util.isEmpty(reportView.getOrderByClause(), true)) { finalSQL.append(" ORDER BY ").append(reportView.getOrderByClause()); } } // Report view order by clause. // Print Data PrintData pd = new PrintData (ctx, reportName); PrintDataColumn[] info = new PrintDataColumn [columns.size()]; columns.toArray(info); // column order is is m_synonymc with SELECT column position pd.setColumnInfo(info); pd.setTableName(tableName); pd.setSQL(finalSQL.toString()); pd.setHasLevelNo(hasLevelNo); if (log.isLoggable(Level.FINEST)) { log.finest (finalSQL.toString ()); log.finest ("Group=" + m_group); } return pd; } // getPrintDataInfo /** * Try to determine the display type from a pattern * - try a DecimalFormat if the pattern contains any of the characters # 0 * - try a SimpleDateFormat if the pattern contains any of the characters y M d h H m s S * - otherwise (or if the format is not valid) return Text * @param pattern * @return DateTime for a SimpleDateFormat, Number for a DecimalFormat, otherwise Text */ private int getDisplayTypeFromPattern(String pattern) { if (! Util.isEmpty(pattern, true)) { if (pattern.matches(".*[#0].*")) { try { new DecimalFormat(pattern); return DisplayType.Number; } catch (Exception ex) {} } else if (pattern.matches(".*[yMdhHmsS].*")) { try { new SimpleDateFormat(pattern); return DisplayType.DateTime; } catch (Exception ex) {} } } return DisplayType.Text; } /** * Next Synonym.
    * Creates next synonym A..Z AA..ZZ AAA..ZZZ */ private void synonymNext() { int length = m_synonym.length(); char cc = m_synonym.charAt(0); if (cc == 'Z') { cc = 'A'; length++; } else { cc++; // Refs #6532 if (cc == 'X') cc++; } // m_synonym = String.valueOf(cc); for (int i = 1; i < length; i++) { m_synonym += String.valueOf(cc); } } // synonymNext /** * Get TableName and ColumnName for Reference Tables. * @param AD_Reference_Value_ID reference value * @return 0=TableName, 1=KeyColumn, 2=DisplayColumn */ public static TableReference getTableReference (int AD_Reference_Value_ID) { if (AD_Reference_Value_ID <= 0) throw new IllegalArgumentException("AD_Reference_Value_ID <= 0"); // TableReference tr = new TableReference(); // StringBuilder SQL = new StringBuilder("SELECT t.TableName, ck.ColumnName AS KeyColumn,") // 1..2 .append(" cd.ColumnName AS DisplayColumn, rt.IsValueDisplayed, cd.IsTranslated ") .append("FROM AD_Ref_Table rt") .append(" INNER JOIN AD_Table t ON (rt.AD_Table_ID = t.AD_Table_ID)") .append(" INNER JOIN AD_Column ck ON (rt.AD_Key = ck.AD_Column_ID)") .append(" INNER JOIN AD_Column cd ON (rt.AD_Display = cd.AD_Column_ID) ") .append("WHERE rt.AD_Reference_ID=?") // 1 .append(" AND rt.IsActive = 'Y' AND t.IsActive = 'Y'"); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(SQL.toString(), null); pstmt.setInt (1, AD_Reference_Value_ID); rs = pstmt.executeQuery(); if (rs.next()) { tr.TableName = rs.getString(1); tr.KeyColumn = rs.getString(2); tr.DisplayColumn = rs.getString(3); tr.IsValueDisplayed = "Y".equals(rs.getString(4)); tr.IsTranslated = "Y".equals(rs.getString(5)); } } catch (SQLException ex) { log.log(Level.SEVERE, SQL.toString(), ex); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } return tr; } // getTableReference /** * Load Data into PrintData * @param pd print data with SQL and ColumnInfo set * @param format print format */ private void loadPrintData (PrintData pd, MPrintFormat format) { // Translate Spool Output boolean translateSpool = pd.getTableName().equals("T_Spool"); m_runningTotalString = Msg.getMsg(format.getLanguage(), "RunningTotal"); int rowNo = 0; PrintDataColumn pdc = null; boolean hasLevelNo = pd.hasLevelNo(); int levelNo = 0; int reportLineID = 0; ArrayList scriptColumns = new ArrayList(); // int timeout = MSysConfig.getIntValue(MSysConfig.REPORT_LOAD_TIMEOUT_IN_SECONDS, DEFAULT_REPORT_LOAD_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx())); PreparedStatement pstmt = null; ResultSet rs = null; String sql = pd.getSQL(); try { int maxRows = MSysConfig.getIntValue(MSysConfig.GLOBAL_MAX_REPORT_RECORDS, DEFAULT_GLOBAL_MAX_REPORT_RECORDS, Env.getAD_Client_ID(Env.getCtx())); if (maxRows > 0 && DB.getDatabase().isPagingSupported()) sql = DB.getDatabase().addPagingSQL(sql, 1, maxRows+1); pstmt = DB.prepareNormalReadReplicaStatement(sql, m_trxName); if (maxRows > 0 && ! DB.getDatabase().isPagingSupported()) pstmt.setMaxRows(maxRows+1); if (timeout > 0) pstmt.setQueryTimeout(timeout); rs = pstmt.executeQuery(); boolean isExistsT_Report_PA_ReportLine_ID = false; if (pd.getTableName().equals("T_Report")) { ResultSetMetaData rsmd = rs.getMetaData(); for (int i = 1; i <= rsmd.getColumnCount(); i++) { if (rsmd.getColumnLabel(i).equalsIgnoreCase("PA_ReportLine_ID")) { isExistsT_Report_PA_ReportLine_ID = true; break; } } } int cnt = 0; // Row Loop while (rs.next()) { cnt++; if (maxRows > 0 && cnt > maxRows) throw new AdempiereException(Msg.getMsg(Env.getCtx(), "ReportMaxRowsReached", new Object[] {maxRows})); if (hasLevelNo) { levelNo = rs.getInt("LevelNo"); if (isExistsT_Report_PA_ReportLine_ID) reportLineID = rs.getInt("PA_ReportLine_ID"); } else levelNo = 0; // Check Group Change ---------------------------------------- if (m_group.getGroupColumnCount() > 1) // one is GRANDTOTAL_ { ArrayList changedGroups = new ArrayList(); ArrayList changedValues = new ArrayList(); boolean force = false; // Check Columns for Function Columns for (int i = 0; i < pd.getColumnInfo().length; i++) { PrintDataColumn group_pdc = pd.getColumnInfo()[i]; if (!m_group.isGroupColumn(group_pdc.getAD_PrintFormatItem_ID())) continue; // Group change Object value = m_group.groupChange(group_pdc.getAD_PrintFormatItem_ID(), rs.getObject(group_pdc.getAlias()), force); if (value != null) // Group change { changedGroups.add(group_pdc); changedValues.add(value); force = true; // all subsequent groups force change } } for (int j = changedGroups.size() - 1; j >= 0; j--) // backwards (least group first) { PrintDataColumn group_pdc = changedGroups.get(j); Object value = changedValues.get(j); char[] functions = m_group.getFunctions(group_pdc.getAD_PrintFormatItem_ID()); for (int f = 0; f < functions.length; f++) { printRunningTotal(pd, levelNo, rowNo++); pd.addRow(true, levelNo); // get columns for (int c = 0; c < pd.getColumnInfo().length; c++) { pdc = pd.getColumnInfo()[c]; // log.fine("loadPrintData - PageBreak = " + pdc.isPageBreak()); if (group_pdc.getAD_PrintFormatItem_ID() == pdc.getAD_PrintFormatItem_ID()) { String valueString = value.toString(); if (value instanceof Timestamp) valueString = DisplayType.getDateFormat(pdc.getDisplayType(), m_language, pdc.getFormatPattern()).format(value); if (format.getTableFormat().isPrintFunctionSymbols()) // Translate Sum, etc. valueString += PrintDataFunction.getFunctionSymbol(functions[f]); pd.addNode(new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), valueString, DisplayType.String, false, pdc.isPageBreak(), pdc.getFormatPattern())); } else if (m_group.isFunctionColumn(pdc.getAD_PrintFormatItem_ID(), functions[f])) { pd.addNode(new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), m_group.getValue(group_pdc.getAD_PrintFormatItem_ID(), pdc.getAD_PrintFormatItem_ID(), functions[f]), PrintDataFunction.getFunctionDisplayType(functions[f], pdc.getDisplayType()), false, pdc.isPageBreak(), pdc.getFormatPattern())); } } // for all columns } // for all functions // Reset Group Values for (int c = 0; c < pd.getColumnInfo().length; c++) { pdc = pd.getColumnInfo()[c]; m_group.reset(group_pdc.getAD_PrintFormatItem_ID(), pdc.getAD_PrintFormatItem_ID()); } } // Group change } // group change // new row --------------------------------------------------- printRunningTotal(pd, levelNo, rowNo++); /** Report Summary FR [ 2011569 ]**/ if (!m_summary) pd.addRow(false, levelNo, reportLineID); int counter = 1; // get columns for (int i = 0; i < pd.getColumnInfo().length; i++) { pdc = pd.getColumnInfo()[i]; PrintDataElement pde = null; // Key Column - No DisplayColumn if (pdc.getAlias().equals(KEY)) { if (pdc.getColumnName().endsWith("_ID")) { int id = rs.getInt(counter++); if (!rs.wasNull()) { KeyNamePair pp = new KeyNamePair(id, KEY); // Key pde = new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), pp, pdc.getDisplayType(), true, pdc.isPageBreak(), pdc.getFormatPattern()); } } else { String id = rs.getString(counter++); if (!rs.wasNull()) { ValueNamePair pp = new ValueNamePair(id, KEY); // Key pde = new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), pp, pdc.getDisplayType(), true, pdc.isPageBreak(), pdc.getFormatPattern()); } } } // Non-Key Column else { // Display and Value Column if (pdc.hasAlias()) { int displayIndex = counter++; // DisplayColumn first String display = rs.getString(displayIndex); if (pdc.getColumnName().endsWith("_ID")) { int id = rs.getInt(counter++); if (display != null && !rs.wasNull()) { KeyNamePair pp = new KeyNamePair(id, display); pde = new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), pp, pdc.getDisplayType(), pdc.getFormatPattern(), pdc.getForeignColumnName()); } } else { String id = rs.getString(counter++); if (display != null && !rs.wasNull()) { /** START DEVCOFFEE: script column **/ int displayType = pdc.getDisplayType(); if(MPrintFormatItem.PRINTFORMATTYPE_Script.equalsIgnoreCase(pdc.getPrintFormatType())) { // ScriptColumn Object value = rs.getObject(displayIndex); if (display.startsWith("@SCRIPT")) { if(!scriptColumns.contains(pdc)) scriptColumns.add(pdc); displayType = DisplayType.Text; } else { displayType = getDisplayType(value); } pde = new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), (Serializable) value, displayType, pdc.getFormatPattern()); } else { ValueNamePair pp = new ValueNamePair(id, display); pde = new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), pp, displayType, pdc.getFormatPattern()); } } } } // Display Value only else { // Transformation for Booleans if (pdc.getDisplayType() == DisplayType.YesNo) { String s = rs.getString(counter++); if (!rs.wasNull()) { boolean b = s.equals("Y"); pde = new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), Boolean.valueOf(b), pdc.getDisplayType(), pdc.getFormatPattern()); } } else if (pdc.getDisplayType() == DisplayType.TextLong || (pdc.getDisplayType() == DisplayType.JSON && DB.isOracle())) { String value = ""; if ("java.lang.String".equals(rs.getMetaData().getColumnClassName(counter))) { value = rs.getString(counter++); } else { Clob clob = rs.getClob(counter++); if (clob != null) { long length = clob.length(); value = clob.getSubString(1, (int)length); } } pde = new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), value, pdc.getDisplayType(), pdc.getFormatPattern()); } // fix bug [ 1755592 ] Printing time in format else if (pdc.getDisplayType() == DisplayType.DateTime) { Timestamp datetime = rs.getTimestamp(counter++); pde = new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), datetime, pdc.getDisplayType(), pdc.getFormatPattern()); } else // The general case { Object obj = rs.getObject(counter++); if (obj != null && obj instanceof String) { obj = ((String)obj).trim(); if (((String)obj).length() == 0) obj = null; } if (obj != null) { // Translate Spool Output if (translateSpool && obj instanceof String) { String s = (String)obj; s = Msg.parseTranslation(pd.getCtx(), s); pde = new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), s, pdc.getDisplayType(), pdc.getFormatPattern()); } else pde = new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), (Serializable)obj, pdc.getDisplayType(), pdc.getFormatPattern()); } } } // Value only } // Non-Key Column if (pde != null) { /** Report Summary FR [ 2011569 ]**/ if(!m_summary) pd.addNode(pde); m_group.addValue(pde.getAD_PrintFormatItem_ID(), pde.getFunctionValue()); } } // for all columns } // for all rows } catch (SQLException e) { if (DB.getDatabase().isQueryTimeout(e)) throw new AdempiereException(Msg.getMsg(Env.getCtx(), "ReportQueryTimeout", new Object[] {timeout})); log.log(Level.SEVERE, pdc + " - " + e.getMessage() + "\nSQL=" + sql); throw new AdempiereException(e); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } // Parse Script column values if(scriptColumns.size() > 0) { for(int i = 0; i < pd.getRowCount(); i++) { for(PrintDataColumn c : scriptColumns) { pd.setRowIndex(i); PrintDataElement e = (PrintDataElement) pd.getNodeByPrintFormatItemId(c.getAD_PrintFormatItem_ID()); if(e == null) // primarily on grouping rows, if no functions are assigned to the script column continue; Object value = parseVariable(e.getValueAsString().replace("@SCRIPT", ""), c, pd); Interpreter bsh = new Interpreter(); try { value = bsh.eval(value.toString()); } catch (EvalError err) { log.severe(err.getMessage()); } e.setDisplayType(getDisplayType(value)); if(value instanceof Serializable) e.setValue((Serializable) value); else e.setValue(Objects.toString(value, "")); } } } // -- we have all rows - finish // Check last Group Change if (m_group.getGroupColumnCount() > 1) // one is TOTAL { for (int i = pd.getColumnInfo().length-1; i >= 0; i--) // backwards (last group first) { PrintDataColumn group_pdc = pd.getColumnInfo()[i]; if (!m_group.isGroupColumn(group_pdc.getAD_PrintFormatItem_ID())) continue; Object value = m_group.groupChange(group_pdc.getAD_PrintFormatItem_ID(), new Object(), false); if (value != null) // Group change { char[] functions = m_group.getFunctions(group_pdc.getAD_PrintFormatItem_ID()); for (int f = 0; f < functions.length; f++) { printRunningTotal(pd, levelNo, rowNo++); pd.addRow(true, levelNo); // get columns for (int c = 0; c < pd.getColumnInfo().length; c++) { pdc = pd.getColumnInfo()[c]; if (group_pdc.getColumnName().equals(pdc.getColumnName())) { String valueString = value.toString(); if (value instanceof Timestamp) valueString = DisplayType.getDateFormat(pdc.getDisplayType(), m_language, pdc.getFormatPattern()).format(value); if (format.getTableFormat().isPrintFunctionSymbols()) // Translate Sum, etc. valueString += PrintDataFunction.getFunctionSymbol(functions[f]); pd.addNode(new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), valueString, DisplayType.String, pdc.getFormatPattern())); } else if (m_group.isFunctionColumn(pdc.getAD_PrintFormatItem_ID(), functions[f])) { pd.addNode(new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), m_group.getValue(group_pdc.getAD_PrintFormatItem_ID(), pdc.getAD_PrintFormatItem_ID(), functions[f]), PrintDataFunction.getFunctionDisplayType(functions[f], pdc.getDisplayType()),pdc.getFormatPattern())); } } } // for all functions // No Need to Reset } // Group change } } // last group change // Add Total Lines if (m_group.isGroupColumn(PrintDataGroup.TOTAL)) { char[] functions = m_group.getFunctions(PrintDataGroup.TOTAL); for (int f = 0; f < functions.length; f++) { printRunningTotal(pd, levelNo, rowNo++); pd.addRow(true, levelNo); // get columns for (int c = 0; c < pd.getColumnInfo().length; c++) { pdc = pd.getColumnInfo()[c]; if (c == 0) // put Function in first Column { String name; if (!format.getTableFormat().isPrintFunctionSymbols()) // Translate Sum, etc. name = Msg.getMsg(format.getLanguage(), PrintDataFunction.getFunctionName(functions[f])); else name = PrintDataFunction.getFunctionSymbol(functions[f]); // Symbol if (m_group.isFunctionColumn(pdc.getAD_PrintFormatItem_ID(), functions[f])) name += " " + m_group.getValue(PrintDataGroup.TOTAL, pdc.getAD_PrintFormatItem_ID(), functions[f]); pd.addNode(new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), name.trim(), DisplayType.String, pdc.getFormatPattern())); } else if (m_group.isFunctionColumn(pdc.getAD_PrintFormatItem_ID(), functions[f])) { pd.addNode(new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), m_group.getValue(PrintDataGroup.TOTAL, pdc.getAD_PrintFormatItem_ID(), functions[f]), PrintDataFunction.getFunctionDisplayType(functions[f], pdc.getDisplayType()), pdc.getFormatPattern())); } } // for all columns } // for all functions // No Need to Reset } // TotalLine if (pd.getRowCount() == 0) { if (CLogMgt.isLevelFiner()) log.finer("NO Rows - ms=" + (System.currentTimeMillis()-m_startTime) + " - " + sql); else log.info("NO Rows - ms=" + (System.currentTimeMillis()-m_startTime)); } else if (log.isLoggable(Level.INFO)) log.info("Rows=" + pd.getRowCount() + " - ms=" + (System.currentTimeMillis()-m_startTime)); } // loadPrintData /** * Print Running Total * @param pd Print Data to add lines to * @param levelNo level no * @param rowNo row no */ private void printRunningTotal (PrintData pd, int levelNo, int rowNo) { if (m_runningTotalLines < 1) // -1 = none return; if (log.isLoggable(Level.FINE)) log.fine("(" + m_runningTotalLines + ") - Row=" + rowNo + ", mod=" + rowNo % m_runningTotalLines); if (rowNo % m_runningTotalLines != 0) return; if (log.isLoggable(Level.FINE)) log.fine("Row=" + rowNo); PrintDataColumn pdc = null; int start = 0; if (rowNo == 0) // no page break on page 1 start = 1; for (int rt = start; rt < 2; rt++) { pd.addRow (true, levelNo); // get sum columns for (int c = 0; c < pd.getColumnInfo().length; c++) { pdc = pd.getColumnInfo()[c]; if (c == 0) { String title = "RunningTotal"; pd.addNode(new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), title, DisplayType.String, false, rt==0, pdc.getFormatPattern())); // page break } else if (m_group.isFunctionColumn(pdc.getAD_PrintFormatItem_ID(), PrintDataFunction.F_SUM)) { pd.addNode(new PrintDataElement(pdc.getAD_PrintFormatItem_ID(), pdc.getColumnName(), m_group.getValue(PrintDataGroup.TOTAL, pdc.getAD_PrintFormatItem_ID(), PrintDataFunction.F_SUM), PrintDataFunction.getFunctionDisplayType(PrintDataFunction.F_SUM, pdc.getDisplayType()), false, false, pdc.getFormatPattern())); } } // for all sum columns } // two lines } // printRunningTotal /** * Get Display Type of value * @param value * @return int Display Type */ private int getDisplayType(Object value) { if (value instanceof Number) return DisplayType.Number; else if (value instanceof Boolean) return DisplayType.YesNo; else if (value instanceof Date) return DisplayType.Date; else return DisplayType.Text; } /** * Parse expression, replaces @tag@ with column value (COL/) or pdc value (ACCUMULATE/ or LINE) * @param expression * @param pdc * @param pd * @return String */ public String parseVariable(String expression, PrintDataColumn pdc, PrintData pd) { if (expression == null || expression.length() == 0) return ""; if (log.isLoggable(Level.CONFIG)) log.config("Analyzing Expression " + expression); String token; String inStr = new String(expression); StringBuffer outStr = new StringBuffer(); int i = inStr.indexOf('@'); while (i != -1) { outStr.append(inStr.substring(0, i)); // up to @ inStr = inStr.substring(i+1, inStr.length()); // from first @ int j = inStr.indexOf('@'); // next @ if (j < 0) { return ""; // no second tag } token = inStr.substring(0, j); if (token.startsWith("ACCUMULATE/")) { token = token.replace("ACCUMULATE/", ""); Object tokenPDE = pd.getNode(token); if (tokenPDE == null) return "\"Item not found: " + token + "\""; BigDecimal value = (BigDecimal) ((PrintDataElement)tokenPDE).getValue(); if (m_summarized.containsKey(pdc)) { value= ((BigDecimal) m_summarized.get(pdc)).add(value); m_summarized.remove(pdc); } m_summarized.put(pdc, value); outStr.append(value); } else if (token.startsWith("COL/")) { token = token.replace("COL/", ""); Object tokenPDE = pd.getNode(token); if (tokenPDE == null) return "\"Item not found: " + token + "\""; Object value; if (token.endsWith("_ID") || token.endsWith("_UU")) value = ((PrintDataElement)tokenPDE).getValueKey(); else value = ((PrintDataElement)tokenPDE).getValue(); outStr.append(value); } else if (token.equals("LINE")) { BigDecimal value = Env.ONE; if (m_summarized.containsKey(pdc)) { value = ((BigDecimal)m_summarized.get(pdc)).add(value); m_summarized.remove(pdc); } m_summarized.put(pdc, value); outStr.append(value); } inStr = inStr.substring(j+1, inStr.length()); // from second @ i = inStr.indexOf('@'); } outStr.append(inStr); // add the rest of the string return outStr.toString(); } /** * Get window no * @return window no */ public int getWindowNo() { return m_windowNo; } /** * Set window no * @param windowNo */ public void setWindowNo(int windowNo) { this.m_windowNo = windowNo; } } // DataEngine /** * Table Reference Info */ class TableReference { /** Table Name */ public String TableName; /** Key Column */ public String KeyColumn; /** Display Column */ public String DisplayColumn; /** Displayed */ public boolean IsValueDisplayed = false; /** Translated */ public boolean IsTranslated = false; } // TableReference