summaryrefslogtreecommitdiff
path: root/reportbuilder/java/com/sun/star/report/pentaho/PentahoReportJob.java
diff options
context:
space:
mode:
Diffstat (limited to 'reportbuilder/java/com/sun/star/report/pentaho/PentahoReportJob.java')
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/PentahoReportJob.java419
1 files changed, 419 insertions, 0 deletions
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/PentahoReportJob.java b/reportbuilder/java/com/sun/star/report/pentaho/PentahoReportJob.java
new file mode 100644
index 000000000000..a30a97a1e7e1
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/PentahoReportJob.java
@@ -0,0 +1,419 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho;
+
+import com.sun.star.report.DataSourceFactory;
+import com.sun.star.report.ImageService;
+import com.sun.star.report.InputRepository;
+import com.sun.star.report.JobDefinitionException;
+import com.sun.star.report.JobProgressIndicator;
+import com.sun.star.report.JobProperties;
+import com.sun.star.report.OutputRepository;
+import com.sun.star.report.ParameterMap;
+import com.sun.star.report.ReportEngineParameterNames;
+import com.sun.star.report.ReportExecutionException;
+import com.sun.star.report.ReportJob;
+import com.sun.star.report.ReportJobDefinition;
+import com.sun.star.report.SDBCReportDataFactory;
+import com.sun.star.report.pentaho.loader.InputRepositoryLoader;
+import com.sun.star.report.pentaho.model.OfficeDetailSection;
+import com.sun.star.report.pentaho.model.OfficeDocument;
+import com.sun.star.report.pentaho.model.OfficeGroup;
+import com.sun.star.report.pentaho.model.OfficeReport;
+import com.sun.star.report.pentaho.output.chart.ChartRawReportProcessor;
+import com.sun.star.report.pentaho.output.spreadsheet.SpreadsheetRawReportProcessor;
+import com.sun.star.report.pentaho.output.text.TextRawReportProcessor;
+
+import java.io.IOException;
+
+import java.lang.Integer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.jfree.report.expressions.Expression;
+import org.jfree.report.expressions.FormulaExpression;
+import org.jfree.report.flow.DefaultReportJob;
+import org.jfree.report.flow.ReportProcessor;
+import org.jfree.report.flow.raw.XmlPrintReportProcessor;
+import org.jfree.report.structure.Node;
+import org.jfree.report.structure.Section;
+import org.jfree.report.util.ReportParameters;
+
+import org.pentaho.reporting.libraries.formula.lvalues.ContextLookup;
+import org.pentaho.reporting.libraries.formula.lvalues.FormulaFunction;
+import org.pentaho.reporting.libraries.formula.lvalues.LValue;
+import org.pentaho.reporting.libraries.formula.lvalues.Term;
+import org.pentaho.reporting.libraries.formula.parser.FormulaParser;
+import org.pentaho.reporting.libraries.formula.parser.ParseException;
+import org.pentaho.reporting.libraries.resourceloader.Resource;
+import org.pentaho.reporting.libraries.resourceloader.ResourceException;
+import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
+
+
+/**
+ * ToDo: Allow interrupting of jobs and report the report progress
+ */
+public class PentahoReportJob implements ReportJob
+{
+
+ private static final Log LOGGER = LogFactory.getLog(PentahoReportJob.class);
+ private boolean finished;
+ private final List listeners;
+ private final DataSourceFactory dataSourceFactory;
+ private final OutputRepository outputRepository;
+ private final JobProperties jobProperties;
+ private OfficeDocument report;
+ private final ResourceManager resourceManager;
+ private final String outputName;
+ private final ImageService imageService;
+ private final InputRepository inputRepository;
+ private final ReportJobDefinition definition;
+ private final List masterValues;
+ private final List detailColumns;
+
+ public ReportJobDefinition getDefinition()
+ {
+ return definition;
+ }
+
+ public PentahoReportJob(final ReportJobDefinition definition)
+ throws JobDefinitionException
+ {
+ if (definition == null)
+ {
+ throw new NullPointerException();
+ }
+
+ this.definition = definition;
+ this.listeners = new ArrayList();
+ this.jobProperties = definition.getProcessingParameters().copy();
+
+ this.dataSourceFactory = (DataSourceFactory) jobProperties.getProperty(ReportEngineParameterNames.INPUT_DATASOURCE_FACTORY);
+ if (this.dataSourceFactory == null)
+ {
+ throw new JobDefinitionException("DataSourceFactory must not be null.");
+ }
+
+ this.outputRepository = (OutputRepository) jobProperties.getProperty(ReportEngineParameterNames.OUTPUT_REPOSITORY);
+ if (this.outputRepository == null)
+ {
+ throw new JobDefinitionException("OutputRepository must not be null.");
+ }
+
+ this.inputRepository =
+ (InputRepository) jobProperties.getProperty(ReportEngineParameterNames.INPUT_REPOSITORY);
+ if (inputRepository == null)
+ {
+ throw new JobDefinitionException("InputRepository must not be null.");
+ }
+
+ this.outputName = (String) jobProperties.getProperty(ReportEngineParameterNames.OUTPUT_NAME);
+ if (outputName == null)
+ {
+ throw new JobDefinitionException("OutputName must not be null");
+ }
+
+ this.imageService = (ImageService) jobProperties.getProperty(ReportEngineParameterNames.IMAGE_SERVICE);
+ if (imageService == null)
+ {
+ throw new JobDefinitionException("A valid image-service implementation must be given.");
+ }
+
+ this.masterValues = (ArrayList) jobProperties.getProperty(ReportEngineParameterNames.INPUT_MASTER_VALUES);
+ this.detailColumns = (ArrayList) jobProperties.getProperty(ReportEngineParameterNames.INPUT_DETAIL_COLUMNS);
+ Integer maxRows=(Integer) jobProperties.getProperty(ReportEngineParameterNames.MAXROWS);
+
+ this.resourceManager = new ResourceManager();
+ this.resourceManager.registerDefaults();
+ this.resourceManager.registerLoader(new InputRepositoryLoader(inputRepository));
+
+ try
+ {
+ this.report = parseReport(definition);
+ }
+ catch (ResourceException e)
+ {
+ throw new JobDefinitionException("Failed to parse the report.", e);
+ }
+ }
+
+ private OfficeDocument parseReport(final ReportJobDefinition definition)
+ throws ResourceException, JobDefinitionException
+ {
+ final String reportResource = (String) this.jobProperties.getProperty(ReportEngineParameterNames.INPUT_NAME);
+ if (reportResource == null)
+ {
+ throw new JobDefinitionException("Report definition name must be given");
+ }
+
+ final Resource res = resourceManager.createDirectly("sun:oo://" + reportResource, OfficeDocument.class);
+ final OfficeDocument tempReport = (OfficeDocument) res.getResource();
+ tempReport.setDataFactory(new StarReportDataFactory(dataSourceFactory));
+ tempReport.setJobProperties(definition.getProcessingParameters().copy());
+ final ReportParameters inputParameters = tempReport.getInputParameters();
+
+ final ParameterMap queryParameters = definition.getQueryParameters();
+ final String[] paramKeys = queryParameters.keys();
+ for (int i = 0; i < paramKeys.length; i++)
+ {
+ final String key = paramKeys[i];
+ inputParameters.put(key, queryParameters.get(key));
+ }
+
+ return tempReport;
+ }
+
+ public void addProgressIndicator(final JobProgressIndicator indicator)
+ {
+ listeners.add(indicator);
+ }
+
+ /**
+ * Interrupt the job.
+ */
+ public void interrupt()
+ {
+ // hey, not yet ..
+ }
+
+ /**
+ * Queries the jobs result status.
+ *
+ * @return true, if the job is finished (or has been interrupted), false if the job
+ * waits for activation.
+ */
+ public boolean isFinished()
+ {
+ return finished;
+ }
+
+ public void finish()
+ {
+ finished = true;
+ }
+
+ /**
+ * Queries the jobs execution status.
+ *
+ * @return true, if the job is currently running, false otherwise.
+ */
+ public boolean isRunning()
+ {
+ return !finished;
+ }
+
+ public void removeProgressIndicator(final JobProgressIndicator indicator)
+ {
+ listeners.remove(indicator);
+ }
+
+ private void collectGroupExpressions(final Node[] nodes, final List expressions, final FormulaParser parser, final Expression reportFunctions[])
+ {
+ for (int i = 0; i < nodes.length; i++)
+ {
+ final Node node = nodes[i];
+ if (node instanceof OfficeGroup)
+ {
+ final OfficeGroup group = (OfficeGroup) node;
+ final FormulaExpression exp = (FormulaExpression) group.getGroupingExpression();
+ if (exp == null)
+ {
+ continue;
+ }
+
+ try
+ {
+ final String expression = exp.getFormulaExpression();
+ if (expression == null)
+ {
+ continue;
+ }
+ final FormulaFunction function = (FormulaFunction) parser.parse(expression);
+ final LValue[] parameters = function.getChildValues();
+ if (parameters.length > 0)
+ {
+ String name = parameters[0].toString();
+ if (parameters[0] instanceof ContextLookup)
+ {
+ final ContextLookup context = (ContextLookup) parameters[0];
+ name = context.getName();
+ }
+ for (int j = 0; j < reportFunctions.length; j++)
+ {
+ if (reportFunctions[j] instanceof FormulaExpression)
+ {
+ final FormulaExpression reportExp = (FormulaExpression) reportFunctions[j];
+
+ if (reportExp.getName().equals(name))
+ {
+ LValue val = parser.parse(reportExp.getFormulaExpression());
+ while( !(val instanceof ContextLookup))
+ {
+ if (val instanceof Term)
+ {
+ val = ((Term)val).getHeadValue();
+ }
+ else if (val instanceof FormulaFunction)
+ {
+ final FormulaFunction reportFunction = (FormulaFunction) val;
+ val = reportFunction.getChildValues()[0];
+ }
+ }
+ if (val instanceof ContextLookup)
+ {
+ final ContextLookup context = (ContextLookup) val;
+ name = context.getName();
+ }
+ break;
+ }
+ }
+ }
+
+ final Object[] pair = new Object[2];
+ pair[0] = name;
+ pair[1] = group.getAttribute(OfficeNamespaces.OOREPORT_NS, "sort-ascending");
+ expressions.add(pair);
+ }
+ }
+ catch (ParseException ex)
+ {
+ LOGGER.error("ReportProcessing failed", ex);
+ }
+ }
+ else if (node instanceof OfficeDetailSection)
+ {
+ return;
+ }
+ if (node instanceof Section)
+ {
+ final Section section = (Section) node;
+ collectGroupExpressions(section.getNodeArray(), expressions, parser, reportFunctions);
+ }
+ }
+ }
+
+ private void setMetaDataProperties(DefaultReportJob job)
+ {
+ job.getConfiguration().setConfigProperty(ReportEngineParameterNames.AUTHOR, (String) jobProperties.getProperty(ReportEngineParameterNames.AUTHOR));
+ job.getConfiguration().setConfigProperty(ReportEngineParameterNames.TITLE, (String) jobProperties.getProperty(ReportEngineParameterNames.TITLE));
+ }
+
+ /**
+ * Although we might want to run the job as soon as it has been created, sometimes it is
+ * wiser to let the user add some listeners first. If we execute at once, the user
+ * either has to deal with threading code or wont receive any progress information in
+ * single threaded environments.
+ */
+ public void execute()
+ throws ReportExecutionException, IOException
+ {
+ final DefaultReportJob job = new DefaultReportJob(report);
+ setMetaDataProperties(job);
+ final String contentType = (String) jobProperties.getProperty(ReportEngineParameterNames.CONTENT_TYPE);
+ //noinspection OverlyBroadCatchBlock
+ try
+ {
+ final ReportParameters parameters = job.getParameters();
+
+ if (masterValues != null && detailColumns != null)
+ {
+ parameters.put(SDBCReportDataFactory.MASTER_VALUES, masterValues);
+ parameters.put(SDBCReportDataFactory.DETAIL_COLUMNS, detailColumns);
+ }
+
+ final Node[] nodes = report.getNodeArray();
+
+ final FormulaParser parser = new FormulaParser();
+ final ArrayList expressions = new ArrayList();
+ final OfficeReport officeReport = (OfficeReport) ((Section) nodes[0]).getNode(0);
+ final Section reportBody = (Section) officeReport.getBodySection();
+ collectGroupExpressions(reportBody.getNodeArray(), expressions, parser, officeReport.getExpressions());
+ parameters.put(SDBCReportDataFactory.GROUP_EXPRESSIONS, expressions);
+ final String command = (String) officeReport.getAttribute(OfficeNamespaces.OOREPORT_NS, "command");
+ final String commandType = (String) officeReport.getAttribute(OfficeNamespaces.OOREPORT_NS, SDBCReportDataFactory.COMMAND_TYPE);
+ final String escapeProcessing = (String) officeReport.getAttribute(OfficeNamespaces.OOREPORT_NS, SDBCReportDataFactory.ESCAPE_PROCESSING);
+ report.setQuery(command);
+ parameters.put(SDBCReportDataFactory.COMMAND_TYPE, commandType);
+ parameters.put(SDBCReportDataFactory.ESCAPE_PROCESSING, !("false".equals(escapeProcessing)));
+
+ final String filter = (String) officeReport.getAttribute(OfficeNamespaces.OOREPORT_NS, "filter");
+ parameters.put(SDBCReportDataFactory.UNO_FILTER, filter);
+
+ parameters.put(ReportEngineParameterNames.MAXROWS, report.getJobProperties().getProperty(ReportEngineParameterNames.MAXROWS));
+
+ final long startTime = System.currentTimeMillis();
+ final ReportProcessor rp = getProcessorForContentType(contentType);
+ rp.processReport(job);
+ job.close();
+ final long endTime = System.currentTimeMillis();
+ LOGGER.debug("Report processing time: " + (endTime - startTime));
+ }
+ catch (final Exception e)
+ {
+ String message = e.getMessage();
+ if (message == null || message.length() == 0)
+ {
+ message = "Failed to process the report";
+ }
+ throw new ReportExecutionException(message, e);
+ }
+
+ }
+
+ protected ReportProcessor getProcessorForContentType(final String mimeType)
+ throws ReportExecutionException
+ {
+ final ReportProcessor ret;
+
+ if (PentahoReportEngineMetaData.OPENDOCUMENT_SPREADSHEET.equals(mimeType))
+ {
+ ret = new SpreadsheetRawReportProcessor(inputRepository, outputRepository, outputName, imageService, dataSourceFactory);
+ }
+ else if (PentahoReportEngineMetaData.OPENDOCUMENT_TEXT.equals(mimeType))
+ {
+ ret = new TextRawReportProcessor(inputRepository, outputRepository, outputName, imageService, dataSourceFactory);
+ }
+ else if (PentahoReportEngineMetaData.OPENDOCUMENT_CHART.equals(mimeType))
+ {
+ ret = new ChartRawReportProcessor(inputRepository, outputRepository, outputName, imageService, dataSourceFactory);
+ }
+ else if (PentahoReportEngineMetaData.DEBUG.equals(mimeType))
+ {
+ ret = new XmlPrintReportProcessor(System.out, "ISO-8859-1");
+ }
+ else
+ {
+ throw new ReportExecutionException("Invalid mime-type");
+ }
+
+ return ret;
+ }
+}