From e27e11cfce6e9113c15e2662c0550b31519ce7de Mon Sep 17 00:00:00 2001 From: hengsin Date: Mon, 19 Jul 2021 17:26:48 +0800 Subject: [PATCH] IDEMPIERE-4868 Implement column lookup support for Jasper Report (#770) * IDEMPIERE-4868 Implement column lookup support for Jasper Report add support for more display type Fix passing of report locale to ColumnLookup and MsgResourceBundle add alternate short notation for location, account, locator and asi. --- .../META-INF/MANIFEST.MF | 2 + .../adempiere/report/jasper/ColumnLookup.java | 153 ++++++++++++++---- .../report/jasper/ReportStarter.java | 6 +- 3 files changed, 130 insertions(+), 31 deletions(-) diff --git a/org.adempiere.report.jasper/META-INF/MANIFEST.MF b/org.adempiere.report.jasper/META-INF/MANIFEST.MF index 36605ddb22..d23ab11707 100644 --- a/org.adempiere.report.jasper/META-INF/MANIFEST.MF +++ b/org.adempiere.report.jasper/META-INF/MANIFEST.MF @@ -10,6 +10,8 @@ Import-Package: net.sourceforge.barbecue, org.apache.commons.codec.binary, org.apache.commons.logging;version="1.1.1", org.apache.commons.logging.impl;version="1.1.1", + org.jfree.chart, + org.jfree.chart.plot, org.osgi.service.event Require-Bundle: org.adempiere.base;bundle-version="0.0.0", net.sf.jasperreports.engine;bundle-version="6.3.1" diff --git a/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ColumnLookup.java b/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ColumnLookup.java index b24058c229..c00bbb4894 100644 --- a/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ColumnLookup.java +++ b/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ColumnLookup.java @@ -24,30 +24,35 @@ **********************************************************************/ package org.adempiere.report.jasper; -import java.sql.PreparedStatement; -import java.sql.ResultSet; +import java.awt.image.BufferedImage; +import java.math.BigDecimal; import java.util.function.BiFunction; -import java.util.logging.Level; +import org.adempiere.apps.graph.ChartBuilder; +import org.compiere.model.MAccount; +import org.compiere.model.MAttributeSetInstance; +import org.compiere.model.MChart; import org.compiere.model.MColumn; +import org.compiere.model.MImage; import org.compiere.model.MLocation; +import org.compiere.model.MLocator; import org.compiere.model.MLookup; import org.compiere.model.MLookupFactory; import org.compiere.model.MLookupInfo; import org.compiere.model.MTable; -import org.compiere.util.CLogger; -import org.compiere.util.DB; import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.Language; -import org.compiere.util.NamePair; +import org.compiere.util.Msg; import org.compiere.util.Util; +import org.jfree.chart.ChartRenderingInfo; +import org.jfree.chart.JFreeChart; /** * @author hengsin * */ -public class ColumnLookup implements BiFunction { +public class ColumnLookup implements BiFunction { private Language language; @@ -59,7 +64,7 @@ public class ColumnLookup implements BiFunction { } @Override - public String apply(String t, Object key) { + public Object apply(String t, Object key) { if (!Util.isEmpty(t, true) && key != null) { String[] parts = t.split("[.]"); if (parts.length == 2) { @@ -72,41 +77,133 @@ public class ColumnLookup implements BiFunction { if (DisplayType.isList(column.getAD_Reference_ID())) { MLookupInfo linfo = MLookupFactory.getLookup_List(language, column.getAD_Reference_Value_ID()); MLookup lookup = new MLookup(linfo, -1); - NamePair np = lookup.getDirect(key, false, false); - return np != null ? np.toString() : ""; + return lookup.getDisplay(key); } else if (DisplayType.isLookup(column.getAD_Reference_ID()) && (key instanceof Number)) { return getLookupDisplay(column, (Number) key); + } else if ((column.getAD_Reference_ID()==DisplayType.ChosenMultipleSelectionList + || column.getAD_Reference_ID()==DisplayType.ChosenMultipleSelectionSearch + || column.getAD_Reference_ID()==DisplayType.ChosenMultipleSelectionTable) && (key instanceof String)) { + return getMultiLookupDisplay(column, (String) key); } else if (DisplayType.Location == column.getAD_Reference_ID() && (key instanceof Number)) { - MLocation loc = MLocation.get(((Number)key).intValue()); - return loc.toStringCR(); + return getLocation((Number) key); + } else if (DisplayType.Image == column.getAD_Reference_ID() && (key instanceof Number)) { + return getImage(((Number)key).intValue()); + } else if (DisplayType.YesNo == column.getAD_Reference_ID() && (key instanceof String)) { + String value = (String) key; + return getYesNoText(value); + } else if (DisplayType.Account == column.getAD_Reference_ID() && (key instanceof Number)) { + return getAccountCombination((Number) key); + } else if (DisplayType.Locator == column.getAD_Reference_ID() && (key instanceof Number)) { + return getLocator((Number) key); + } else if (DisplayType.PAttribute == column.getAD_Reference_ID() && (key instanceof Number)) { + return getAttributeSetInstance((Number) key); } } } + } else if (t.equalsIgnoreCase("location") && (key instanceof Number)) { + return getLocation((Number) key); + } else if (t.equalsIgnoreCase("account") && (key instanceof Number)) { + return getAccountCombination((Number) key); + } else if (t.equalsIgnoreCase("locator") && (key instanceof Number)) { + return getLocator((Number) key); + } else if (t.equalsIgnoreCase("asi") && (key instanceof Number)) { + return getAttributeSetInstance((Number) key); + } else if (t.equalsIgnoreCase("AmtInWords")) { + if (key instanceof String) { + return Msg.getAmtInWords(language, (String) key); + } else if (key instanceof BigDecimal) { + String s = DisplayType.getNumberFormat(DisplayType.Amount, language).format((BigDecimal)key); + return Msg.getAmtInWords(language, s); + } + } else if (t.equalsIgnoreCase("Image") && (key instanceof Number)) { + return getImage(((Number)key).intValue()); + } else if (t.equalsIgnoreCase("YesNo") && (key instanceof String)) { + return getYesNoText((String) key); + } else if (t.toLowerCase().startsWith("chart/") && (key instanceof Number)) { + parts = t.split("[/]"); + if (parts.length == 3) { + int width = 0; + int height = 0; + try { + width = Integer.parseInt(parts[1]); + height = Integer.parseInt(parts[1]); + } catch (Exception e) {} + if (width > 0 && height > 0) { + return getChartImage(((Number)key).intValue(), width, height); + } + } + return null; } } return ""; } + private Object getAttributeSetInstance(Number key) { + MAttributeSetInstance asi = new MAttributeSetInstance (Env.getCtx(), key.intValue(), null); + if (asi.getM_AttributeSetInstance_ID() > 0) + return asi.getDescription(); + else + return ""; + } + + private Object getLocator(Number key) { + MLocator locator = MLocator.get(key.intValue()); + return locator != null ? locator.toString() : ""; + } + + private Object getAccountCombination(Number key) { + MAccount account = MAccount.get(key.intValue()); + return account != null ? account.getCombination() : ""; + } + + private Object getLocation(Number key) { + MLocation loc = MLocation.get(key.intValue()); + return loc.toStringCR(); + } + + private Object getChartImage(int id, int width, int height) { + MChart mc = new MChart(Env.getCtx(), id, null); + if (mc.get_ID() == id) { + ChartBuilder chartBuilder = new ChartBuilder(mc); + JFreeChart chart = chartBuilder.createChart(); + chart.getPlot().setForegroundAlpha(0.8f); + ChartRenderingInfo info = new ChartRenderingInfo(); + BufferedImage bi = chart.createBufferedImage(width, height, + BufferedImage.TRANSLUCENT, info); + return bi; + } + return null; + } + + private Object getYesNoText(String value) { + if (value.equals("Y")) { + return Msg.getMsg(language, "Yes"); + } else if (value.equals("N")) { + return Msg.getMsg(language, "No"); + } else { + return ""; + } + } + + private Object getImage(int key) { + MImage image = MImage.get(key); + return image != null ? image.getImage() : null; + } + + private Object getMultiLookupDisplay(MColumn column, String key) { + MLookupInfo mli = MLookupFactory.getLookupInfo(Env.getCtx(), -1, column.getAD_Column_ID(), column.getAD_Reference_ID(), language, column.getColumnName(), + column.getAD_Reference_Value_ID(), false, ""); + + MLookup lookup = new MLookup(mli, -1); + return lookup.getDisplay(key); + } + private String getLookupDisplay(MColumn column, Number key) { MLookupInfo mli = MLookupFactory.getLookupInfo(Env.getCtx(), -1, column.getAD_Column_ID(), column.getAD_Reference_ID(), language, column.getColumnName(), column.getAD_Reference_Value_ID(), false, ""); - StringBuilder name = new StringBuilder(""); - try (PreparedStatement pstmt = DB.prepareStatement(mli.QueryDirect, null);) { - pstmt.setInt(1, key.intValue()); - - ResultSet rs = pstmt.executeQuery(); - if (rs.next()) { - name.append(rs.getString(3)); - boolean isActive = rs.getString(4).equals("Y"); - if (!isActive) - name.insert(0, MLookup.INACTIVE_S).append(MLookup.INACTIVE_E); - } - } catch (Exception e) { - CLogger.getCLogger(getClass()).log(Level.SEVERE, e.getMessage(), e); - } - - return name.toString(); + MLookup lookup = new MLookup(mli, -1); + return lookup.getDisplay(key); } } diff --git a/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java b/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java index d0c8144ba9..9d622fa7e7 100644 --- a/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java +++ b/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java @@ -607,8 +607,7 @@ public class ReportStarter implements ProcessCall, ClientProcess String langInfo = params.get("AD_Language") != null ? params.get("AD_Language").toString() : params.get("CURRENT_LANG").toString(); currLang = Language.getLanguage(langInfo); - } - params.put("COLUMN_LOOKUP", new ColumnLookup(currLang)); + } String printerName = null; MPrintFormat printFormat = null; @@ -643,6 +642,7 @@ public class ReportStarter implements ProcessCall, ClientProcess params.put("CURRENT_LANG", currLang.getAD_Language()); params.put(JRParameter.REPORT_LOCALE, currLang.getLocale()); + params.put("COLUMN_LOOKUP", new ColumnLookup(currLang)); // Resources File resFile = null; @@ -670,7 +670,7 @@ public class ReportStarter implements ProcessCall, ClientProcess ; } } - params.put(JRParameter.REPORT_RESOURCE_BUNDLE, new MsgResourceBundle(res)); + params.put(JRParameter.REPORT_RESOURCE_BUNDLE, new MsgResourceBundle(res, currLang.getLocale(), currLang.getAD_Language(), Env.isSOTrx(Env.getCtx()))); Connection conn = null; JRSwapFileVirtualizer virtualizer = null;