diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-01-08 10:47:13 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-01-08 10:47:13 +0000 |
commit | 0d1d10afd0e490a3fd860e5ffcf18ceeccb58acf (patch) | |
tree | 5446a68ff33cc1a638e94d8190d7fda20e67d1cd /reportdesign/java | |
parent | 5fd15610fd5fbc6a8373285e35031135d9c1d266 (diff) |
CWS-TOOLING: integrate CWS frmdlg
2008-12-18 09:13:09 +0100 oj r265667 : merge from odff05
2008-12-18 07:58:16 +0100 oj r265658 : #i94555# patch from <regina>, ODFF:
Add GAMMA, CHISQDIST, CHISQINV.
Make the 'cumulative' parameter of GAMMADIST optional.
Adapt the domain of CHIDIST to allow negative x.
Remove the constraint "degrees of freedom < 1.0E5" from CHIDIST and CHIINV.
Plus a mechanism to write the now optional parameter of GAMMADIST to PODF and
ODFF if omitted, for backwards compatibility.
2008-12-15 14:06:11 +0100 oj r265490 : CWS-TOOLING: rebase CWS frmdlg to trunk@264807 (milestone: DEV300:m37)
2008-12-15 13:55:28 +0100 oj r265488 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 13:55:07 +0100 oj r265487 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 13:54:48 +0100 oj r265486 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 13:54:36 +0100 oj r265485 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 13:54:24 +0100 oj r265484 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 13:48:11 +0100 oj r265483 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 13:31:12 +0100 oj r265479 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 13:13:58 +0100 oj r265477 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 13:10:09 +0100 oj r265476 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 13:05:11 +0100 oj r265475 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 10:47:17 +0100 oj r265467 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 10:46:19 +0100 oj r265466 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 10:45:47 +0100 oj r265465 : CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'
CWS: frmdlg
New MWS: DEV300
New milestone: m37
2008-12-15 07:35:07 +0100 oj r265458 : add dependency to formula
2008-12-15 07:34:24 +0100 oj r265457 : add dependency to formula
2008-12-12 13:22:00 +0100 msc r265413 : #i97089#
2008-12-12 13:20:25 +0100 msc r265412 : #i97089#
2008-12-12 12:35:12 +0100 msc r265406 : #i97089#
2008-12-12 12:34:16 +0100 msc r265405 : #i97089#
2008-12-12 12:33:05 +0100 msc r265404 : #i97089#
2008-12-12 12:31:11 +0100 msc r265403 : #i97089#
2008-12-08 11:59:10 +0100 oj r264981 : insert RTL_LOG
2008-12-08 11:50:17 +0100 oj r264980 : some small changes
2008-12-05 12:57:57 +0100 oj r264902 : eof changed
2008-12-05 12:56:46 +0100 oj r264901 : eof changed
2008-12-05 12:28:47 +0100 oj r264899 : wrong var used
2008-12-05 10:08:57 +0100 oj r264890 : token order reversed
2008-12-04 13:49:22 +0100 oc r264843 : #i96688: Adapt autotests because of outsourced functionwizard
2008-12-04 13:45:27 +0100 oc r264842 : #i96688: Adapt autotests because of outsourced functionwizard
2008-12-04 13:42:54 +0100 oc r264841 : #i96688: Adapt autotests because of outsourced functionwizard
2008-12-04 13:37:41 +0100 oc r264840 : #i96688: Adapt autotests because of outsourced functionwizard
2008-12-04 13:34:11 +0100 oc r264839 : #i96688: Adapt autotests because of outsourced functionwizard
2008-12-04 12:35:31 +0100 oj r264835 : new help ids for struct and function tabpage
2008-12-04 12:00:35 +0100 oj r264828 : set explicit help id
2008-12-03 14:53:27 +0100 oj r264786 : #i96845# change ref button
2008-12-03 14:51:49 +0100 oj r264785 : #i96845# change ref button
2008-12-03 08:51:57 +0100 oj r264746 : convert dos to unix lineends
2008-12-03 08:50:45 +0100 oj r264745 : convert dos to unix lineends
2008-12-03 08:50:05 +0100 oj r264744 : convert dos to unix lineends
2008-12-02 12:28:33 +0100 oj r264686 : clear help text when new helpid is set
2008-12-02 12:28:02 +0100 oj r264685 : set help id for listbox category
2008-12-02 07:15:56 +0100 oj r264655 : remove define to auto generate help ids
2008-12-01 14:36:43 +0100 oj r264604 : use temp var
2008-12-01 14:18:31 +0100 oj r264601 : moved ScJumpToken to formula
2008-12-01 14:18:11 +0100 oj r264600 : moved ScJumpToken to formula
2008-12-01 14:14:35 +0100 oj r264599 : moved ScJumpToken from sc
2008-12-01 10:48:51 +0100 oj r264589 : change quickhelptext from Shrink to Select
2008-12-01 10:28:41 +0100 oj r264588 : fix opcode data, has to be Any.Void
2008-11-28 11:16:48 +0100 oj r264532 : add help ids
2008-11-28 10:16:56 +0100 oj r264529 : set help id
2008-11-28 10:16:43 +0100 oj r264528 : set help id
2008-11-26 13:55:04 +0100 oj r264381 : #94535# use of optional instead of deleting a string myself and some small changes
2008-11-26 09:53:20 +0100 oj r264346 : compile error with debug/without debug
2008-11-25 07:41:28 +0100 oj r264271 : put static into the method which make use of them
2008-11-24 08:16:07 +0100 oj r264196 : removed not needed classes for op code
2008-11-24 08:13:44 +0100 oj r264195 : removed not needed classes for op code
2008-11-21 14:05:53 +0100 oj r264135 : make GetOpCode inline
2008-11-21 12:35:27 +0100 oj r264124 : hold symbols
2008-11-20 09:27:27 +0100 oj r264028 : merged code from DEV300_m35 which got lost
2008-11-19 20:42:12 +0100 oj r264022 : more changes for formula dialog remove
2008-11-19 20:37:41 +0100 oj r264021 : removed unused var
2008-11-19 20:35:35 +0100 oj r264020 : some more changes at token
2008-11-19 10:59:47 +0100 oj r263967 : deleted
2008-11-19 10:58:24 +0100 oj r263966 : add forui and for res files
2008-11-18 15:27:36 +0100 oj r263777 : unused para removed
2008-11-18 15:23:23 +0100 oj r263775 : add insert button to add field dlg
2008-11-18 13:39:53 +0100 oj r263764 : enable the formula dialog as well for conditional print as for conditional formatting
2008-11-18 12:03:25 +0100 oj r263760 : rename isRef in IsRef
2008-11-17 11:46:16 +0100 oj r263711 : patches for function handling
2008-11-17 11:36:22 +0100 oj r263710 : add new for forui and res file
2008-11-17 09:21:12 +0100 oj r263704 : patches for some resource for libformula
2008-11-15 12:45:30 +0100 oj r263701 : changes for formula editor extraction
2008-11-07 08:23:27 +0100 oj r263416 : merge from DEV300:m35
2008-11-07 08:22:35 +0100 oj r263415 : merge from DEV300:m35
2008-11-07 08:22:16 +0100 oj r263414 : merge from DEV300:m35
2008-11-07 08:21:41 +0100 oj r263413 : merge from DEV300:m35
2008-11-07 08:21:31 +0100 oj r263412 : merge from DEV300:m35
2008-11-07 08:20:38 +0100 oj r263411 : merge from DEV300:m35
2008-11-07 08:20:00 +0100 oj r263410 : merge from DEV300:m35
2008-11-07 08:18:50 +0100 oj r263409 : merge from DEV300:m35
2008-11-07 08:18:19 +0100 oj r263408 : merge from DEV300:m35
2008-11-07 08:10:27 +0100 oj r263407 : merge from DEV300:m35
2008-10-21 07:43:46 +0200 oj r262560 : some compile errors resolved
2008-10-17 16:40:01 +0200 oj r262291 : dep for 1st target
2008-10-07 10:08:39 +0200 oj r262077 : copy
2008-10-07 09:45:31 +0200 oj r262076 : #i94535#
2008-10-07 09:44:26 +0200 oj r262075 : #i94535# new base class
2008-10-07 09:43:21 +0200 oj r262074 : moved to formula
2008-10-07 09:41:51 +0200 oj r262073 : new images
2008-10-07 09:03:01 +0200 oj r262072 : new ids for formula
2008-10-02 08:46:27 +0200 oj r262024 : #i94535# move the formula compiler to formula
2008-10-02 08:08:54 +0200 oj r262023 : #i94535#
2008-10-02 08:06:28 +0200 oj r262022 : #i94535#
2008-10-02 08:05:52 +0200 oj r262021 : #i94535#
2008-10-01 17:15:29 +0200 oj r262014 : #i94535#
2008-10-01 17:12:40 +0200 oj r262013 : new module formula
2008-10-01 17:04:55 +0200 oj r262012 : #i94535#
2008-10-01 16:49:03 +0200 oj r262010 : #i94535#
2008-10-01 16:46:59 +0200 oj r262009 : #i94535#
Diffstat (limited to 'reportdesign/java')
18 files changed, 5257 insertions, 3999 deletions
diff --git a/reportdesign/java/com/sun/star/report/SDBCReportDataFactory.java b/reportdesign/java/com/sun/star/report/SDBCReportDataFactory.java index 463bf0a44f11..e5d9bdbceb93 100644 --- a/reportdesign/java/com/sun/star/report/SDBCReportDataFactory.java +++ b/reportdesign/java/com/sun/star/report/SDBCReportDataFactory.java @@ -1,637 +1,637 @@ -/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2008 by Sun Microsystems, Inc.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * $RCSfile: SDBCReportDataFactory.java,v $
- * $Revision: 1.9.18.1 $
- *
- * 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;
-
-import com.sun.star.beans.PropertyVetoException;
-import com.sun.star.beans.UnknownPropertyException;
-import com.sun.star.beans.XPropertySet;
-import com.sun.star.container.NoSuchElementException;
-import com.sun.star.container.XIndexAccess;
-import com.sun.star.lang.IllegalArgumentException;
-import com.sun.star.lang.WrappedTargetException;
-import com.sun.star.sdbc.XConnection;
-import com.sun.star.container.XNameAccess;
-import com.sun.star.lang.XComponent;
-import com.sun.star.lang.XMultiServiceFactory;
-import com.sun.star.sdb.CommandType;
-import com.sun.star.sdb.XCompletedExecution;
-import com.sun.star.sdb.XParametersSupplier;
-import com.sun.star.sdb.XQueriesSupplier;
-import com.sun.star.sdb.XSingleSelectQueryComposer;
-import com.sun.star.sdb.tools.XConnectionTools;
-import com.sun.star.sdbc.SQLException;
-import com.sun.star.sdbc.XParameters;
-import com.sun.star.sdbc.XPreparedStatement;
-import com.sun.star.uno.Exception;
-import java.util.Map;
-
-import com.sun.star.sdbc.XRowSet;
-import com.sun.star.sdbcx.XColumnsSupplier;
-import com.sun.star.sdbcx.XTablesSupplier;
-import com.sun.star.task.XInteractionHandler;
-import com.sun.star.uno.UnoRuntime;
-import com.sun.star.uno.XComponentContext;
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.jfree.util.Log;
-
-/**
- * Very primitive implementation, just to show how this could be used ...
- *
- */
-public class SDBCReportDataFactory implements DataSourceFactory
-{
-
- public static final String COMMAND_TYPE = "command-type";
- public static final String ESCAPE_PROCESSING = "escape-processing";
- public static final String GROUP_EXPRESSIONS = "group-expressions";
- public static final String MASTER_VALUES = "master-values";
- public static final String MASTER_COLUMNS = "master-columns";
- public static final String DETAIL_COLUMNS = "detail-columns";
- public static final String UNO_FILTER = "Filter";
- private static final String APPLY_FILTER = "ApplyFilter";
- private static final String UNO_COMMAND = "Command";
- private static final String UNO_ORDER = "Order";
- private static final String UNO_APPLY_FILTER = "ApplyFilter";
- private static final String UNO_COMMAND_TYPE = "CommandType";
- private final XConnection connection;
- private final XComponentContext m_cmpCtx;
- private static final int FAILED = 0;
- private static final int DONE = 1;
- private static final int RETRIEVE_COLUMNS = 2;
- private static final int RETRIEVE_OBJECT = 3;
- private static final int HANDLE_QUERY = 4;
- private static final int HANDLE_TABLE = 5;
- private static final int HANDLE_SQL = 6;
-
- public SDBCReportDataFactory(final XComponentContext cmpCtx, final XConnection connection)
- {
- this.connection = connection;
- m_cmpCtx = cmpCtx;
- }
-
- public DataSource queryData(final String command, final Map parameters) throws DataSourceException
- {
- try
- {
- if ( command == null )
- {
- return new SDBCReportData(null);
- }
- int commandType = CommandType.COMMAND;
- final String commandTypeValue = (String) parameters.get(COMMAND_TYPE);
- if ( commandTypeValue != null )
- {
- if ( commandTypeValue.equals("query") )
- {
- commandType = CommandType.QUERY;
- }
- else if ( commandTypeValue.equals("table") )
- {
- commandType = CommandType.TABLE;
- }
- else
- {
- commandType = CommandType.COMMAND;
- }
- }
- final XRowSet rowSet = createRowSet(command, commandType, parameters);
- final XPropertySet rowSetProp = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, rowSet);
-
- final XConnectionTools tools = (XConnectionTools) UnoRuntime.queryInterface(XConnectionTools.class, connection);
- fillOrderStatement(command, commandType, parameters, tools, rowSetProp);
-
- if ( command.length() != 0 )
- {
- final int oldParameterCount = fillParameter(parameters, tools, command, commandType, rowSet);
-
- final XCompletedExecution execute = (XCompletedExecution) UnoRuntime.queryInterface(XCompletedExecution.class, rowSet);
- if ( execute != null && oldParameterCount > 0 )
- {
- final XInteractionHandler handler = (XInteractionHandler) UnoRuntime.queryInterface(XInteractionHandler.class, m_cmpCtx.getServiceManager().createInstanceWithContext("com.sun.star.sdb.InteractionHandler", m_cmpCtx));
- execute.executeWithCompletion(handler);
- }
- else
- {
- rowSet.execute();
- }
- }
- return new SDBCReportData(rowSet);
- } catch ( Exception ex )
- {
- throw new DataSourceException(ex.getMessage(), ex);
- }
- }
-
- private String getOrderStatement(final int commandType, final String command, final List groupExpressions)
- {
- final StringBuffer order = new StringBuffer();
- final int count = groupExpressions.size();
- if ( count != 0 )
- {
- try
- {
- final String quote = connection.getMetaData().getIdentifierQuoteString();
- final XComponent[] hold = new XComponent[1];
- final XNameAccess columns = getFieldsByCommandDescriptor(commandType, command, hold);
-
- for (int i = 0; i < count; i++)
- {
- final Object[] pair = (Object[]) groupExpressions.get(i);
- String expression = (String) pair[0];
-
- if ( columns.hasByName(expression) )
- {
- expression = quote + expression + quote;
- }
- expression = expression.trim(); // Trim away white spaces
-
- if ( expression.length() > 0 )
- {
- order.append(expression);
- if ( order.length() > 0 )
- {
- order.append(' ');
- }
- final String sorting = (String) pair[1];
- if ( sorting == null || sorting.equals(OfficeToken.FALSE) )
- {
- order.append("DESC");
- }
- if ( (i + 1) < count )
- {
- order.append(' ');
- }
- }
- }
- } catch ( IndexOutOfBoundsException ex )
- {
- Log.error("ReportProcessing failed", ex);
- } catch ( SQLException ex )
- {
- Log.error("ReportProcessing failed", ex);
- }
- }
- return order.toString();
- }
-
- private XNameAccess getFieldsByCommandDescriptor(final int commandType, final String command, final XComponent[] out) throws SQLException
- {
- final Class[] parameter = new Class[3];
- parameter[0] = Integer.class;
- parameter[1] = String.class;
- parameter[2] = out.getClass();
- final XConnectionTools tools = (XConnectionTools) UnoRuntime.queryInterface(XConnectionTools.class, connection);
- try
- {
- tools.getClass().getMethod("getFieldsByCommandDescriptor", parameter);
- return tools.getFieldsByCommandDescriptor(commandType, command, out);
- } catch ( NoSuchMethodException ex )
- {
- }
-
- XNameAccess xFields = null;
- // some kind of state machine to ease the sharing of code
- int eState = FAILED;
- switch ( commandType )
- {
- case CommandType.TABLE:
- eState = HANDLE_TABLE;
- break;
- case CommandType.QUERY:
- eState = HANDLE_QUERY;
- break;
- case CommandType.COMMAND:
- eState = HANDLE_SQL;
- break;
- }
-
- // needed in various states:
- XNameAccess xObjectCollection = null;
- XColumnsSupplier xSupplyColumns = null;
-
- try
- {
- // go!
- while ((DONE != eState) && (FAILED != eState))
- {
- switch ( eState )
- {
- case HANDLE_TABLE:
- {
- // initial state for handling the tables
-
- // get the table objects
- final XTablesSupplier xSupplyTables = (XTablesSupplier) UnoRuntime.queryInterface(XTablesSupplier.class, connection);
- if ( xSupplyTables != null )
- {
- xObjectCollection = xSupplyTables.getTables();
- // if something went wrong 'til here, then this will be handled in the next state
-
- // next state: get the object
- }
- eState = RETRIEVE_OBJECT;
- }
- break;
-
- case HANDLE_QUERY:
- {
- // initial state for handling the tables
-
- // get the table objects
- final XQueriesSupplier xSupplyQueries = (XQueriesSupplier) UnoRuntime.queryInterface(XQueriesSupplier.class, connection);
- if ( xSupplyQueries != null )
- {
- xObjectCollection = xSupplyQueries.getQueries();
- // if something went wrong 'til here, then this will be handled in the next state
-
- // next state: get the object
- }
- eState = RETRIEVE_OBJECT;
- }
- break;
-
- case RETRIEVE_OBJECT:
- // here we should have an object (aka query or table) collection, and are going
- // to retrieve the desired object
-
- // next state: default to FAILED
- eState = FAILED;
-
- if ( xObjectCollection != null && xObjectCollection.hasByName(command) )
- {
- xSupplyColumns = (XColumnsSupplier) UnoRuntime.queryInterface(XColumnsSupplier.class, xObjectCollection.getByName(command));
-
- // next: go for the columns
- eState = RETRIEVE_COLUMNS;
- }
- break;
-
- case RETRIEVE_COLUMNS:
- // next state: default to FAILED
- eState = FAILED;
-
- if ( xSupplyColumns != null )
- {
- xFields = xSupplyColumns.getColumns();
- // that's it
- eState = DONE;
- }
- break;
-
- case HANDLE_SQL:
- {
- String sStatementToExecute = command;
-
- // well, the main problem here is to handle statements which contain a parameter
- // If we would simply execute a parametrized statement, then this will fail because
- // we cannot supply any parameter values.
- // Thus, we try to analyze the statement, and to append a WHERE 0=1 filter criterion
- // This should cause every driver to not really execute the statement, but to return
- // an empty result set with the proper structure. We then can use this result set
- // to retrieve the columns.
-
- try
- {
- final XMultiServiceFactory xComposerFac = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, connection);
-
- if ( xComposerFac != null )
- {
- final XSingleSelectQueryComposer xComposer = (XSingleSelectQueryComposer) UnoRuntime.queryInterface(XSingleSelectQueryComposer.class, xComposerFac.createInstance("com.sun.star.sdb.SingleSelectQueryComposer"));
- if ( xComposer != null )
- {
- xComposer.setQuery(sStatementToExecute);
-
- // Now set the filter to a dummy restriction which will result in an empty
- // result set.
- xComposer.setFilter("0=1");
-
- sStatementToExecute = xComposer.getQuery();
- }
- }
- } catch ( com.sun.star.uno.Exception ex )
- {
- // silent this error, this was just a try. If we're here, we did not change sStatementToExecute,
- // so it will still be _rCommand, which then will be executed without being touched
- }
-
- // now execute
- XPreparedStatement xStatement = connection.prepareStatement(sStatementToExecute);
- // transfer ownership of this temporary object to the caller
- out[0] = (XComponent) UnoRuntime.queryInterface(XComponent.class, xStatement);
-
- // set the "MaxRows" to 0. This is just in case our attempt to append a 0=1 filter
- // failed - in this case, the MaxRows restriction should at least ensure that there
- // is no data returned (which would be potentially expensive)
- final XPropertySet xStatementProps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, xStatement);
- try
- {
- if ( xStatementProps != null )
- {
- xStatementProps.setPropertyValue("MaxRows", new Integer(0));
- }
- } catch ( com.sun.star.uno.Exception ex )
- {
- // oh damn. Not much of a chance to recover, we will no retrieve the complete
- // full blown result set
- }
-
- xSupplyColumns = (XColumnsSupplier) UnoRuntime.queryInterface(XColumnsSupplier.class, xStatement.executeQuery());
- // this should have given us a result set which does not contain any data, but
- // the structural information we need
-
- // so the next state is to get the columns
- eState = RETRIEVE_COLUMNS;
- }
- break;
- default:
- eState = FAILED;
- }
- }
- } catch ( com.sun.star.uno.Exception ex )
- {
- }
- return xFields;
- }
-
- private XSingleSelectQueryComposer getComposer(final XConnectionTools tools,
- final String command,
- final int commandType)
- {
- final Class[] parameter = new Class[2];
- parameter[0] = int.class;
- parameter[1] = String.class;
- try
- {
- final Object[] param = new Object[2];
- param[0] = new Integer(commandType);
- param[1] = command;
- return (XSingleSelectQueryComposer) tools.getClass().getMethod("getComposer", parameter).invoke(tools, param);
- } catch ( NoSuchMethodException ex )
- {
- } catch ( IllegalAccessException ex )
- {
- // should not happen
- // assert False
- } catch ( java.lang.reflect.InvocationTargetException ex )
- {
- // should not happen
- // assert False
- }
- try
- {
- final XMultiServiceFactory factory = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, connection);
- final XSingleSelectQueryComposer out = (XSingleSelectQueryComposer) UnoRuntime.queryInterface(XSingleSelectQueryComposer.class, factory.createInstance("com.sun.star.sdb.SingleSelectQueryAnalyzer"));
- final String quote = connection.getMetaData().getIdentifierQuoteString();
- String statement = command;
- switch ( commandType )
- {
- case CommandType.TABLE:
- statement = "SELECT * FROM " + quote + command + quote;
- break;
- case CommandType.QUERY:
- {
- final XQueriesSupplier xSupplyQueries = (XQueriesSupplier) UnoRuntime.queryInterface(XQueriesSupplier.class, connection);
- final XNameAccess queries = xSupplyQueries.getQueries();
- if ( queries.hasByName(command) )
- {
- final XPropertySet prop = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, queries.getByName(command));
- final Boolean escape = (Boolean) prop.getPropertyValue("EscapeProcessing");
- if (escape.booleanValue())
- {
- statement = (String) prop.getPropertyValue(UNO_COMMAND);
- final XSingleSelectQueryComposer composer = getComposer(tools, statement, CommandType.COMMAND);
- if (composer != null)
- {
- final String order = (String) prop.getPropertyValue(UNO_ORDER);
- if (order != null && order.length() != 0)
- {
- composer.setOrder(order);
- }
- final Boolean applyFilter = (Boolean) prop.getPropertyValue(UNO_APPLY_FILTER);
- if (applyFilter.booleanValue())
- {
- final String filter = (String) prop.getPropertyValue(UNO_FILTER);
- if (filter != null && filter.length() != 0)
- {
- composer.setFilter(filter);
- }
- }
- statement = composer.getQuery();
- }
- }
- }
- }
- break;
- case CommandType.COMMAND:
- statement = command;
- break;
- }
- out.setElementaryQuery(statement);
- return out;
- } catch ( Exception e )
- {
- }
- return null;
- }
-
- int fillParameter(final Map parameters,
- final XConnectionTools tools,
- final String command,
- final int commandType, final XRowSet rowSet)
- throws SQLException,
- UnknownPropertyException,
- PropertyVetoException,
- IllegalArgumentException,
- WrappedTargetException
- {
- int oldParameterCount = 0;
-
- final XSingleSelectQueryComposer composer = getComposer(tools, command, commandType);
- if ( composer != null )
- {
- final XPropertySet rowSetProp = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, rowSet);
- if ( ((Boolean)rowSetProp.getPropertyValue(APPLY_FILTER)).booleanValue() )
- {
- composer.setFilter((String)rowSetProp.getPropertyValue("Filter"));
- }
- // get old parameter count
- final XParametersSupplier paraSup = (XParametersSupplier) UnoRuntime.queryInterface(XParametersSupplier.class, composer);
- if ( paraSup != null )
- {
- final XIndexAccess params = paraSup.getParameters();
- if ( params != null )
- {
- oldParameterCount = params.getCount();
- }
- }
- final ArrayList masterValues = (ArrayList) parameters.get(MASTER_VALUES);
- if ( masterValues != null && !masterValues.isEmpty() )
- {
- // Vector masterColumns = (Vector) parameters.get("master-columns");
- final ArrayList detailColumns = (ArrayList) parameters.get(DETAIL_COLUMNS);
- if ( oldParameterCount < detailColumns.size() )
- {
- // create the new filter
- final String quote = connection.getMetaData().getIdentifierQuoteString();
- final StringBuffer oldFilter = new StringBuffer();
- oldFilter.append(composer.getFilter());
- if ( oldFilter.length() != 0 )
- {
- oldFilter.append(" AND ");
- }
- int newParamterCounter = 1;
- for (final Iterator it = detailColumns.iterator(); it.hasNext();
- ++newParamterCounter)
- {
- final String detail = (String) it.next();
- //String master = (String) masterIt.next();
- oldFilter.append(quote);
- oldFilter.append(detail);
- oldFilter.append(quote);
- oldFilter.append(" = :link_");
- oldFilter.append(newParamterCounter);
- if ( it.hasNext() )
- {
- oldFilter.append(" AND ");
- }
- }
-
- composer.setFilter(oldFilter.toString());
- }
- else
- oldParameterCount = 0;
-
- final String sQuery = composer.getQuery();
- rowSetProp.setPropertyValue(UNO_COMMAND, sQuery);
- rowSetProp.setPropertyValue(UNO_COMMAND_TYPE,
- new Integer(CommandType.COMMAND));
-
- final XParameters para = (XParameters) UnoRuntime.queryInterface(XParameters.class, rowSet);
-
- for (int i = 0;
- i < masterValues.size();
- i++)
- {
- Object object = masterValues.get(i);
- if ( object instanceof BigDecimal )
- {
- object = ((BigDecimal) object).toString();
- }
- para.setObject(oldParameterCount + i + 1, object);
- }
- }
- }
-
- return oldParameterCount;
- }
-
- private final XRowSet createRowSet(final String command,
- final int commandType, final Map parameters)
- throws Exception
- {
- final XRowSet rowSet = (XRowSet) UnoRuntime.queryInterface(XRowSet.class, m_cmpCtx.getServiceManager().createInstanceWithContext("com.sun.star.sdb.RowSet", m_cmpCtx));
- final XPropertySet rowSetProp = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, rowSet);
-
- rowSetProp.setPropertyValue("ActiveConnection", connection);
- final Boolean escapeProcessing = (Boolean)parameters.get(ESCAPE_PROCESSING);
- rowSetProp.setPropertyValue("EscapeProcessing", escapeProcessing);
- rowSetProp.setPropertyValue(UNO_COMMAND_TYPE, new Integer(commandType));
- rowSetProp.setPropertyValue(UNO_COMMAND, command);
-
- final String filter = (String) parameters.get(UNO_FILTER);
- if ( filter != null )
- {
- rowSetProp.setPropertyValue("Filter", filter);
- rowSetProp.setPropertyValue(APPLY_FILTER, Boolean.valueOf(filter.length() != 0));
- }
- else
- {
- rowSetProp.setPropertyValue(APPLY_FILTER, Boolean.FALSE);
- }
- return rowSet;
- }
-
- void fillOrderStatement(final String command,
- final int commandType, final Map parameters,
- final XConnectionTools tools,
- final XPropertySet rowSetProp)
- throws SQLException,
- UnknownPropertyException,
- PropertyVetoException,
- IllegalArgumentException,
- WrappedTargetException,
- NoSuchElementException
- {
- final StringBuffer order = new StringBuffer(getOrderStatement(commandType, command, (ArrayList) parameters.get(GROUP_EXPRESSIONS)));
- if ( order.length() > 0 && commandType != CommandType.TABLE )
- {
- String statement = command;
- final XSingleSelectQueryComposer composer = getComposer(tools, command, commandType);
- if ( composer != null )
- {
- statement = composer.getQuery();
- composer.setQuery(statement);
- final String sOldOrder = composer.getOrder();
- if ( sOldOrder.length() > 0 )
- {
- order.append(',');
- order.append(sOldOrder);
- composer.setOrder("");
- statement = composer.getQuery();
- }
- }
- else
- {
- if ( commandType == CommandType.QUERY )
- {
- final XQueriesSupplier xSupplyQueries = (XQueriesSupplier) UnoRuntime.queryInterface(XQueriesSupplier.class, connection);
- final XNameAccess queries = xSupplyQueries.getQueries();
- if ( queries.hasByName(command) )
- {
- final XPropertySet prop = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, queries.getByName(command));
- final String queryCommand = (String) prop.getPropertyValue(UNO_COMMAND);
- statement = "SELECT * FROM (" + queryCommand + ")";
- }
- }
- else
- {
- statement = "SELECT * FROM (" + command + ")";
- }
- }
- rowSetProp.setPropertyValue(UNO_COMMAND, statement);
- rowSetProp.setPropertyValue(UNO_COMMAND_TYPE, new Integer(CommandType.COMMAND));
- }
- rowSetProp.setPropertyValue("Order", order.toString());
- }
-}
-
+/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: SDBCReportDataFactory.java,v $ + * $Revision: 1.9.18.1 $ + * + * 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; + +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.container.XIndexAccess; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.sdbc.XConnection; +import com.sun.star.container.XNameAccess; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.sdb.CommandType; +import com.sun.star.sdb.XCompletedExecution; +import com.sun.star.sdb.XParametersSupplier; +import com.sun.star.sdb.XQueriesSupplier; +import com.sun.star.sdb.XSingleSelectQueryComposer; +import com.sun.star.sdb.tools.XConnectionTools; +import com.sun.star.sdbc.SQLException; +import com.sun.star.sdbc.XParameters; +import com.sun.star.sdbc.XPreparedStatement; +import com.sun.star.uno.Exception; +import java.util.Map; + +import com.sun.star.sdbc.XRowSet; +import com.sun.star.sdbcx.XColumnsSupplier; +import com.sun.star.sdbcx.XTablesSupplier; +import com.sun.star.task.XInteractionHandler; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.jfree.util.Log; + +/** + * Very primitive implementation, just to show how this could be used ... + * + */ +public class SDBCReportDataFactory implements DataSourceFactory +{ + + public static final String COMMAND_TYPE = "command-type"; + public static final String ESCAPE_PROCESSING = "escape-processing"; + public static final String GROUP_EXPRESSIONS = "group-expressions"; + public static final String MASTER_VALUES = "master-values"; + public static final String MASTER_COLUMNS = "master-columns"; + public static final String DETAIL_COLUMNS = "detail-columns"; + public static final String UNO_FILTER = "Filter"; + private static final String APPLY_FILTER = "ApplyFilter"; + private static final String UNO_COMMAND = "Command"; + private static final String UNO_ORDER = "Order"; + private static final String UNO_APPLY_FILTER = "ApplyFilter"; + private static final String UNO_COMMAND_TYPE = "CommandType"; + private final XConnection connection; + private final XComponentContext m_cmpCtx; + private static final int FAILED = 0; + private static final int DONE = 1; + private static final int RETRIEVE_COLUMNS = 2; + private static final int RETRIEVE_OBJECT = 3; + private static final int HANDLE_QUERY = 4; + private static final int HANDLE_TABLE = 5; + private static final int HANDLE_SQL = 6; + + public SDBCReportDataFactory(final XComponentContext cmpCtx, final XConnection connection) + { + this.connection = connection; + m_cmpCtx = cmpCtx; + } + + public DataSource queryData(final String command, final Map parameters) throws DataSourceException + { + try + { + if ( command == null ) + { + return new SDBCReportData(null); + } + int commandType = CommandType.COMMAND; + final String commandTypeValue = (String) parameters.get(COMMAND_TYPE); + if ( commandTypeValue != null ) + { + if ( commandTypeValue.equals("query") ) + { + commandType = CommandType.QUERY; + } + else if ( commandTypeValue.equals("table") ) + { + commandType = CommandType.TABLE; + } + else + { + commandType = CommandType.COMMAND; + } + } + final XRowSet rowSet = createRowSet(command, commandType, parameters); + final XPropertySet rowSetProp = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, rowSet); + + final XConnectionTools tools = (XConnectionTools) UnoRuntime.queryInterface(XConnectionTools.class, connection); + fillOrderStatement(command, commandType, parameters, tools, rowSetProp); + + if ( command.length() != 0 ) + { + final int oldParameterCount = fillParameter(parameters, tools, command, commandType, rowSet); + + final XCompletedExecution execute = (XCompletedExecution) UnoRuntime.queryInterface(XCompletedExecution.class, rowSet); + if ( execute != null && oldParameterCount > 0 ) + { + final XInteractionHandler handler = (XInteractionHandler) UnoRuntime.queryInterface(XInteractionHandler.class, m_cmpCtx.getServiceManager().createInstanceWithContext("com.sun.star.sdb.InteractionHandler", m_cmpCtx)); + execute.executeWithCompletion(handler); + } + else + { + rowSet.execute(); + } + } + return new SDBCReportData(rowSet); + } catch ( Exception ex ) + { + throw new DataSourceException(ex.getMessage(), ex); + } + } + + private String getOrderStatement(final int commandType, final String command, final List groupExpressions) + { + final StringBuffer order = new StringBuffer(); + final int count = groupExpressions.size(); + if ( count != 0 ) + { + try + { + final String quote = connection.getMetaData().getIdentifierQuoteString(); + final XComponent[] hold = new XComponent[1]; + final XNameAccess columns = getFieldsByCommandDescriptor(commandType, command, hold); + + for (int i = 0; i < count; i++) + { + final Object[] pair = (Object[]) groupExpressions.get(i); + String expression = (String) pair[0]; + + if ( columns.hasByName(expression) ) + { + expression = quote + expression + quote; + } + expression = expression.trim(); // Trim away white spaces + + if ( expression.length() > 0 ) + { + order.append(expression); + if ( order.length() > 0 ) + { + order.append(' '); + } + final String sorting = (String) pair[1]; + if ( sorting == null || sorting.equals(OfficeToken.FALSE) ) + { + order.append("DESC"); + } + if ( (i + 1) < count ) + { + order.append(' '); + } + } + } + } catch ( IndexOutOfBoundsException ex ) + { + Log.error("ReportProcessing failed", ex); + } catch ( SQLException ex ) + { + Log.error("ReportProcessing failed", ex); + } + } + return order.toString(); + } + + private XNameAccess getFieldsByCommandDescriptor(final int commandType, final String command, final XComponent[] out) throws SQLException + { + final Class[] parameter = new Class[3]; + parameter[0] = Integer.class; + parameter[1] = String.class; + parameter[2] = out.getClass(); + final XConnectionTools tools = (XConnectionTools) UnoRuntime.queryInterface(XConnectionTools.class, connection); + try + { + tools.getClass().getMethod("getFieldsByCommandDescriptor", parameter); + return tools.getFieldsByCommandDescriptor(commandType, command, out); + } catch ( NoSuchMethodException ex ) + { + } + + XNameAccess xFields = null; + // some kind of state machine to ease the sharing of code + int eState = FAILED; + switch ( commandType ) + { + case CommandType.TABLE: + eState = HANDLE_TABLE; + break; + case CommandType.QUERY: + eState = HANDLE_QUERY; + break; + case CommandType.COMMAND: + eState = HANDLE_SQL; + break; + } + + // needed in various states: + XNameAccess xObjectCollection = null; + XColumnsSupplier xSupplyColumns = null; + + try + { + // go! + while ((DONE != eState) && (FAILED != eState)) + { + switch ( eState ) + { + case HANDLE_TABLE: + { + // initial state for handling the tables + + // get the table objects + final XTablesSupplier xSupplyTables = (XTablesSupplier) UnoRuntime.queryInterface(XTablesSupplier.class, connection); + if ( xSupplyTables != null ) + { + xObjectCollection = xSupplyTables.getTables(); + // if something went wrong 'til here, then this will be handled in the next state + + // next state: get the object + } + eState = RETRIEVE_OBJECT; + } + break; + + case HANDLE_QUERY: + { + // initial state for handling the tables + + // get the table objects + final XQueriesSupplier xSupplyQueries = (XQueriesSupplier) UnoRuntime.queryInterface(XQueriesSupplier.class, connection); + if ( xSupplyQueries != null ) + { + xObjectCollection = xSupplyQueries.getQueries(); + // if something went wrong 'til here, then this will be handled in the next state + + // next state: get the object + } + eState = RETRIEVE_OBJECT; + } + break; + + case RETRIEVE_OBJECT: + // here we should have an object (aka query or table) collection, and are going + // to retrieve the desired object + + // next state: default to FAILED + eState = FAILED; + + if ( xObjectCollection != null && xObjectCollection.hasByName(command) ) + { + xSupplyColumns = (XColumnsSupplier) UnoRuntime.queryInterface(XColumnsSupplier.class, xObjectCollection.getByName(command)); + + // next: go for the columns + eState = RETRIEVE_COLUMNS; + } + break; + + case RETRIEVE_COLUMNS: + // next state: default to FAILED + eState = FAILED; + + if ( xSupplyColumns != null ) + { + xFields = xSupplyColumns.getColumns(); + // that's it + eState = DONE; + } + break; + + case HANDLE_SQL: + { + String sStatementToExecute = command; + + // well, the main problem here is to handle statements which contain a parameter + // If we would simply execute a parametrized statement, then this will fail because + // we cannot supply any parameter values. + // Thus, we try to analyze the statement, and to append a WHERE 0=1 filter criterion + // This should cause every driver to not really execute the statement, but to return + // an empty result set with the proper structure. We then can use this result set + // to retrieve the columns. + + try + { + final XMultiServiceFactory xComposerFac = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, connection); + + if ( xComposerFac != null ) + { + final XSingleSelectQueryComposer xComposer = (XSingleSelectQueryComposer) UnoRuntime.queryInterface(XSingleSelectQueryComposer.class, xComposerFac.createInstance("com.sun.star.sdb.SingleSelectQueryComposer")); + if ( xComposer != null ) + { + xComposer.setQuery(sStatementToExecute); + + // Now set the filter to a dummy restriction which will result in an empty + // result set. + xComposer.setFilter("0=1"); + + sStatementToExecute = xComposer.getQuery(); + } + } + } catch ( com.sun.star.uno.Exception ex ) + { + // silent this error, this was just a try. If we're here, we did not change sStatementToExecute, + // so it will still be _rCommand, which then will be executed without being touched + } + + // now execute + final XPreparedStatement xStatement = connection.prepareStatement(sStatementToExecute); + // transfer ownership of this temporary object to the caller + out[0] = (XComponent) UnoRuntime.queryInterface(XComponent.class, xStatement); + + // set the "MaxRows" to 0. This is just in case our attempt to append a 0=1 filter + // failed - in this case, the MaxRows restriction should at least ensure that there + // is no data returned (which would be potentially expensive) + final XPropertySet xStatementProps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, xStatement); + try + { + if ( xStatementProps != null ) + { + xStatementProps.setPropertyValue("MaxRows", new Integer(0)); + } + } catch ( com.sun.star.uno.Exception ex ) + { + // oh damn. Not much of a chance to recover, we will no retrieve the complete + // full blown result set + } + + xSupplyColumns = (XColumnsSupplier) UnoRuntime.queryInterface(XColumnsSupplier.class, xStatement.executeQuery()); + // this should have given us a result set which does not contain any data, but + // the structural information we need + + // so the next state is to get the columns + eState = RETRIEVE_COLUMNS; + } + break; + default: + eState = FAILED; + } + } + } catch ( com.sun.star.uno.Exception ex ) + { + } + return xFields; + } + + private XSingleSelectQueryComposer getComposer(final XConnectionTools tools, + final String command, + final int commandType) + { + final Class[] parameter = new Class[2]; + parameter[0] = int.class; + parameter[1] = String.class; + try + { + final Object[] param = new Object[2]; + param[0] = new Integer(commandType); + param[1] = command; + return (XSingleSelectQueryComposer) tools.getClass().getMethod("getComposer", parameter).invoke(tools, param); + } catch ( NoSuchMethodException ex ) + { + } catch ( IllegalAccessException ex ) + { + // should not happen + // assert False + } catch ( java.lang.reflect.InvocationTargetException ex ) + { + // should not happen + // assert False + } + try + { + final XMultiServiceFactory factory = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, connection); + final XSingleSelectQueryComposer out = (XSingleSelectQueryComposer) UnoRuntime.queryInterface(XSingleSelectQueryComposer.class, factory.createInstance("com.sun.star.sdb.SingleSelectQueryAnalyzer")); + final String quote = connection.getMetaData().getIdentifierQuoteString(); + String statement = command; + switch ( commandType ) + { + case CommandType.TABLE: + statement = "SELECT * FROM " + quote + command + quote; + break; + case CommandType.QUERY: + { + final XQueriesSupplier xSupplyQueries = (XQueriesSupplier) UnoRuntime.queryInterface(XQueriesSupplier.class, connection); + final XNameAccess queries = xSupplyQueries.getQueries(); + if ( queries.hasByName(command) ) + { + final XPropertySet prop = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, queries.getByName(command)); + final Boolean escape = (Boolean) prop.getPropertyValue("EscapeProcessing"); + if (escape.booleanValue()) + { + statement = (String) prop.getPropertyValue(UNO_COMMAND); + final XSingleSelectQueryComposer composer = getComposer(tools, statement, CommandType.COMMAND); + if (composer != null) + { + final String order = (String) prop.getPropertyValue(UNO_ORDER); + if (order != null && order.length() != 0) + { + composer.setOrder(order); + } + final Boolean applyFilter = (Boolean) prop.getPropertyValue(UNO_APPLY_FILTER); + if (applyFilter.booleanValue()) + { + final String filter = (String) prop.getPropertyValue(UNO_FILTER); + if (filter != null && filter.length() != 0) + { + composer.setFilter(filter); + } + } + statement = composer.getQuery(); + } + } + } + } + break; + case CommandType.COMMAND: + statement = command; + break; + } + out.setElementaryQuery(statement); + return out; + } catch ( Exception e ) + { + } + return null; + } + + int fillParameter(final Map parameters, + final XConnectionTools tools, + final String command, + final int commandType, final XRowSet rowSet) + throws SQLException, + UnknownPropertyException, + PropertyVetoException, + IllegalArgumentException, + WrappedTargetException + { + int oldParameterCount = 0; + + final XSingleSelectQueryComposer composer = getComposer(tools, command, commandType); + if ( composer != null ) + { + final XPropertySet rowSetProp = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, rowSet); + if ( ((Boolean)rowSetProp.getPropertyValue(APPLY_FILTER)).booleanValue() ) + { + composer.setFilter((String)rowSetProp.getPropertyValue("Filter")); + } + // get old parameter count + final XParametersSupplier paraSup = (XParametersSupplier) UnoRuntime.queryInterface(XParametersSupplier.class, composer); + if ( paraSup != null ) + { + final XIndexAccess params = paraSup.getParameters(); + if ( params != null ) + { + oldParameterCount = params.getCount(); + } + } + final ArrayList masterValues = (ArrayList) parameters.get(MASTER_VALUES); + if ( masterValues != null && !masterValues.isEmpty() ) + { + // Vector masterColumns = (Vector) parameters.get("master-columns"); + final ArrayList detailColumns = (ArrayList) parameters.get(DETAIL_COLUMNS); + if ( oldParameterCount < detailColumns.size() ) + { + // create the new filter + final String quote = connection.getMetaData().getIdentifierQuoteString(); + final StringBuffer oldFilter = new StringBuffer(); + oldFilter.append(composer.getFilter()); + if ( oldFilter.length() != 0 ) + { + oldFilter.append(" AND "); + } + int newParamterCounter = 1; + for (final Iterator it = detailColumns.iterator(); it.hasNext(); + ++newParamterCounter) + { + final String detail = (String) it.next(); + //String master = (String) masterIt.next(); + oldFilter.append(quote); + oldFilter.append(detail); + oldFilter.append(quote); + oldFilter.append(" = :link_"); + oldFilter.append(newParamterCounter); + if ( it.hasNext() ) + { + oldFilter.append(" AND "); + } + } + + composer.setFilter(oldFilter.toString()); + } + else + oldParameterCount = 0; + + final String sQuery = composer.getQuery(); + rowSetProp.setPropertyValue(UNO_COMMAND, sQuery); + rowSetProp.setPropertyValue(UNO_COMMAND_TYPE, + new Integer(CommandType.COMMAND)); + + final XParameters para = (XParameters) UnoRuntime.queryInterface(XParameters.class, rowSet); + + for (int i = 0; + i < masterValues.size(); + i++) + { + Object object = masterValues.get(i); + if ( object instanceof BigDecimal ) + { + object = ((BigDecimal) object).toString(); + } + para.setObject(oldParameterCount + i + 1, object); + } + } + } + + return oldParameterCount; + } + + private final XRowSet createRowSet(final String command, + final int commandType, final Map parameters) + throws Exception + { + final XRowSet rowSet = (XRowSet) UnoRuntime.queryInterface(XRowSet.class, m_cmpCtx.getServiceManager().createInstanceWithContext("com.sun.star.sdb.RowSet", m_cmpCtx)); + final XPropertySet rowSetProp = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, rowSet); + + rowSetProp.setPropertyValue("ActiveConnection", connection); + final Boolean escapeProcessing = (Boolean)parameters.get(ESCAPE_PROCESSING); + rowSetProp.setPropertyValue("EscapeProcessing", escapeProcessing); + rowSetProp.setPropertyValue(UNO_COMMAND_TYPE, new Integer(commandType)); + rowSetProp.setPropertyValue(UNO_COMMAND, command); + + final String filter = (String) parameters.get(UNO_FILTER); + if ( filter != null ) + { + rowSetProp.setPropertyValue("Filter", filter); + rowSetProp.setPropertyValue(APPLY_FILTER, Boolean.valueOf(filter.length() != 0)); + } + else + { + rowSetProp.setPropertyValue(APPLY_FILTER, Boolean.FALSE); + } + return rowSet; + } + + void fillOrderStatement(final String command, + final int commandType, final Map parameters, + final XConnectionTools tools, + final XPropertySet rowSetProp) + throws SQLException, + UnknownPropertyException, + PropertyVetoException, + IllegalArgumentException, + WrappedTargetException, + NoSuchElementException + { + final StringBuffer order = new StringBuffer(getOrderStatement(commandType, command, (ArrayList) parameters.get(GROUP_EXPRESSIONS))); + if ( order.length() > 0 && commandType != CommandType.TABLE ) + { + String statement = command; + final XSingleSelectQueryComposer composer = getComposer(tools, command, commandType); + if ( composer != null ) + { + statement = composer.getQuery(); + composer.setQuery(statement); + final String sOldOrder = composer.getOrder(); + if ( sOldOrder.length() > 0 ) + { + order.append(','); + order.append(sOldOrder); + composer.setOrder(""); + statement = composer.getQuery(); + } + } + else + { + if ( commandType == CommandType.QUERY ) + { + final XQueriesSupplier xSupplyQueries = (XQueriesSupplier) UnoRuntime.queryInterface(XQueriesSupplier.class, connection); + final XNameAccess queries = xSupplyQueries.getQueries(); + if ( queries.hasByName(command) ) + { + final XPropertySet prop = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, queries.getByName(command)); + final String queryCommand = (String) prop.getPropertyValue(UNO_COMMAND); + statement = "SELECT * FROM (" + queryCommand + ")"; + } + } + else + { + statement = "SELECT * FROM (" + command + ")"; + } + } + rowSetProp.setPropertyValue(UNO_COMMAND, statement); + rowSetProp.setPropertyValue(UNO_COMMAND_TYPE, new Integer(CommandType.COMMAND)); + } + rowSetProp.setPropertyValue("Order", order.toString()); + } +} + diff --git a/reportdesign/java/com/sun/star/report/function/metadata/Author-Function_en_US.properties b/reportdesign/java/com/sun/star/report/function/metadata/Author-Function_en_US.properties new file mode 100644 index 000000000000..4dfc3e01f0be --- /dev/null +++ b/reportdesign/java/com/sun/star/report/function/metadata/Author-Function_en_US.properties @@ -0,0 +1,33 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: Author-Function.properties,v $ +# +# $Revision: 1.2 $ +# +# 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. +# +#************************************************************************* + +display-name=AUTHOR +description=Returns the author of the report.
\ No newline at end of file diff --git a/reportdesign/java/com/sun/star/report/function/metadata/Title-Function_en_US.properties b/reportdesign/java/com/sun/star/report/function/metadata/Title-Function_en_US.properties new file mode 100644 index 000000000000..ef678be150da --- /dev/null +++ b/reportdesign/java/com/sun/star/report/function/metadata/Title-Function_en_US.properties @@ -0,0 +1,33 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: Title-Function.properties,v $ +# +# $Revision: 1.2 $ +# +# 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. +# +#************************************************************************* + +display-name=TITLE +description=Returns the title of the report.
\ No newline at end of file diff --git a/reportdesign/java/com/sun/star/report/function/metadata/category_en_US.properties b/reportdesign/java/com/sun/star/report/function/metadata/category_en_US.properties new file mode 100644 index 000000000000..44b7ed1d5e9b --- /dev/null +++ b/reportdesign/java/com/sun/star/report/function/metadata/category_en_US.properties @@ -0,0 +1,33 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: category.properties,v $ +# +# $Revision: 1.2 $ +# +# 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. +# +#************************************************************************* + +display-name=MetaData +description=Contains functions about meta data
\ No newline at end of file diff --git a/reportdesign/java/com/sun/star/report/function/metadata/makefile.mk b/reportdesign/java/com/sun/star/report/function/metadata/makefile.mk index 653839388818..5b038b8582b1 100644 --- a/reportdesign/java/com/sun/star/report/function/metadata/makefile.mk +++ b/reportdesign/java/com/sun/star/report/function/metadata/makefile.mk @@ -46,12 +46,17 @@ JARFILES += jcommon-1.0.10.jar libformula-0.1.14.jar JAVAFILES := AuthorFunction.java \ AuthorFunctionDescription.java \ - TitleFunction.java \ + TitleFunction.java \ TitleFunctionDescription.java \ MetaDataFunctionCategory.java +# PROPERTYFILES := $(shell @$(FIND) . -name "*.properties") PROPERTYFILES := $(CLASSDIR)$/$(PACKAGE)$/category.properties \ - $(CLASSDIR)$/$(PACKAGE)$/Author-Function.properties + $(CLASSDIR)$/$(PACKAGE)$/category_en_US.properties \ + $(CLASSDIR)$/$(PACKAGE)$/Author-Function.properties \ + $(CLASSDIR)$/$(PACKAGE)$/Author-Function_en_US.properties \ + $(CLASSDIR)$/$(PACKAGE)$/Title-Function.properties \ + $(CLASSDIR)$/$(PACKAGE)$/Title-Function_en_US.properties # --- Targets ------------------------------------------------------ .INCLUDE : target.mk diff --git a/reportdesign/java/com/sun/star/report/pentaho/PentahoFormulaContext.java b/reportdesign/java/com/sun/star/report/pentaho/PentahoFormulaContext.java index 60d55852907f..ce991e144b26 100644 --- a/reportdesign/java/com/sun/star/report/pentaho/PentahoFormulaContext.java +++ b/reportdesign/java/com/sun/star/report/pentaho/PentahoFormulaContext.java @@ -1,102 +1,102 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: PentahoFormulaContext.java,v $ - * $Revision: 1.2 $ - * - * 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 org.jfree.formula.ContextEvaluationException; -import org.jfree.formula.FormulaContext; -import org.jfree.formula.LocalizationContext; -import org.jfree.formula.function.FunctionRegistry; -import org.jfree.formula.operators.OperatorFactory; -import org.jfree.formula.typing.Type; -import org.jfree.formula.typing.TypeRegistry; -import org.jfree.formula.typing.coretypes.AnyType; -import org.jfree.report.util.ReportParameters; -import org.jfree.util.Configuration; - -/** - * - * @author Ocke Janssen - */ -public class PentahoFormulaContext implements FormulaContext -{ - - private FormulaContext backend; - private Configuration config; - - public PentahoFormulaContext(final FormulaContext backend, final Configuration _config) - { - this.backend = backend; - config = _config; - } - - public LocalizationContext getLocalizationContext() - { - return backend.getLocalizationContext(); - } - - public Configuration getConfiguration() - { - return config; - } - - public FunctionRegistry getFunctionRegistry() - { - return backend.getFunctionRegistry(); - } - - public TypeRegistry getTypeRegistry() - { - return backend.getTypeRegistry(); - } - - public OperatorFactory getOperatorFactory() - { - return backend.getOperatorFactory(); - } - - public Type resolveReferenceType(final Object name) throws ContextEvaluationException - { - return backend.resolveReferenceType(name); - } - - public Object resolveReference(final Object name) throws ContextEvaluationException - { - if (name == null) - { - throw new NullPointerException(); - } - return backend.resolveReference(name); - } - - public boolean isReferenceDirty(final Object name) throws ContextEvaluationException - { - return backend.isReferenceDirty(name); - } -} +/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: PentahoFormulaContext.java,v $
+ * $Revision: 1.2 $
+ *
+ * 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 org.jfree.formula.ContextEvaluationException;
+import org.jfree.formula.FormulaContext;
+import org.jfree.formula.LocalizationContext;
+import org.jfree.formula.function.FunctionRegistry;
+import org.jfree.formula.operators.OperatorFactory;
+import org.jfree.formula.typing.Type;
+import org.jfree.formula.typing.TypeRegistry;
+import org.jfree.formula.typing.coretypes.AnyType;
+import org.jfree.report.util.ReportParameters;
+import org.jfree.util.Configuration;
+
+/**
+ *
+ * @author Ocke Janssen
+ */
+public class PentahoFormulaContext implements FormulaContext
+{
+
+ final private FormulaContext backend;
+ final private Configuration config;
+
+ public PentahoFormulaContext(final FormulaContext backend, final Configuration _config)
+ {
+ this.backend = backend;
+ config = _config;
+ }
+
+ public LocalizationContext getLocalizationContext()
+ {
+ return backend.getLocalizationContext();
+ }
+
+ public Configuration getConfiguration()
+ {
+ return config;
+ }
+
+ public FunctionRegistry getFunctionRegistry()
+ {
+ return backend.getFunctionRegistry();
+ }
+
+ public TypeRegistry getTypeRegistry()
+ {
+ return backend.getTypeRegistry();
+ }
+
+ public OperatorFactory getOperatorFactory()
+ {
+ return backend.getOperatorFactory();
+ }
+
+ public Type resolveReferenceType(final Object name) throws ContextEvaluationException
+ {
+ return backend.resolveReferenceType(name);
+ }
+
+ public Object resolveReference(final Object name) throws ContextEvaluationException
+ {
+ if (name == null)
+ {
+ throw new NullPointerException();
+ }
+ return backend.resolveReference(name);
+ }
+
+ public boolean isReferenceDirty(final Object name) throws ContextEvaluationException
+ {
+ return backend.isReferenceDirty(name);
+ }
+}
diff --git a/reportdesign/java/com/sun/star/report/pentaho/PentahoReportJob.java b/reportdesign/java/com/sun/star/report/pentaho/PentahoReportJob.java index 63f890322112..987a3db28931 100644 --- a/reportdesign/java/com/sun/star/report/pentaho/PentahoReportJob.java +++ b/reportdesign/java/com/sun/star/report/pentaho/PentahoReportJob.java @@ -54,6 +54,9 @@ import com.sun.star.report.pentaho.output.chart.ChartRawReportProcessor; import com.sun.star.report.pentaho.output.text.TextRawReportProcessor; import com.sun.star.report.pentaho.output.spreadsheet.SpreadsheetRawReportProcessor; import java.util.List; +import org.jfree.formula.DefaultFormulaContext; +import org.jfree.formula.function.FunctionCategory; +import org.jfree.formula.function.FunctionRegistry; import org.jfree.formula.lvalues.ContextLookup; import org.jfree.formula.lvalues.FormulaFunction; import org.jfree.formula.lvalues.LValue; diff --git a/reportdesign/java/com/sun/star/report/pentaho/SOFormulaOpCodeMapper.java b/reportdesign/java/com/sun/star/report/pentaho/SOFormulaOpCodeMapper.java new file mode 100644 index 000000000000..a225c93a749d --- /dev/null +++ b/reportdesign/java/com/sun/star/report/pentaho/SOFormulaOpCodeMapper.java @@ -0,0 +1,155 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: SOFormulaOpCodeMapper.java,v $ + * + * $Revision: 1.7 $ + * + * 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.lang.XServiceInfo; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.sheet.FormulaLanguage; +import com.sun.star.sheet.FormulaMapGroup; +import com.sun.star.sheet.FormulaOpCodeMapEntry; +import com.sun.star.sheet.FormulaToken; +import java.util.ArrayList; +import java.util.Map; + +public final class SOFormulaOpCodeMapper extends WeakBase + implements com.sun.star.sheet.XFormulaOpCodeMapper, XServiceInfo +{ + + private final XComponentContext m_xContext; + private static final String __serviceName = "com.sun.star.report.pentaho.SOFormulaOpCodeMapper"; + private final SOFormulaParser parser; + // attributes + final private int m_OpCodeExternal = 0; + final private int m_OpCodeUnknown = 0; + + public SOFormulaOpCodeMapper(XComponentContext context, SOFormulaParser parser) + { + m_xContext = context; + this.parser = parser; + } + + + // com.sun.star.sheet.XFormulaOpCodeMapper: + public int getOpCodeExternal() + { + return m_OpCodeExternal; + } + + public int getOpCodeUnknown() + { + return m_OpCodeUnknown; + } + + public com.sun.star.sheet.FormulaToken[] getMappings(String[] Names, int Language) throws com.sun.star.lang.IllegalArgumentException + { + if ( Language != FormulaLanguage.ODFF ) + throw new IllegalArgumentException(); + final ArrayList token = new ArrayList(); + final Map parserNames = parser.getNames(); + for (int i = 0; i < Names.length; i++) + { + if ( parserNames.containsKey(Names[i]) ) + { + token.add(((FormulaOpCodeMapEntry) parserNames.get(Names[i])).Token); + } + + } + return (com.sun.star.sheet.FormulaToken[]) token.toArray(new FormulaToken[token.size()]); + } + + public com.sun.star.sheet.FormulaOpCodeMapEntry[] getAvailableMappings(int Language, int Groups) throws com.sun.star.lang.IllegalArgumentException + { + if ( Language != FormulaLanguage.ODFF ) + throw new IllegalArgumentException(); + final ArrayList token = new ArrayList(); + if ( Groups == FormulaMapGroup.SPECIAL ) + { + return (com.sun.star.sheet.FormulaOpCodeMapEntry[]) parser.getSpecialOpCodes().toArray(new FormulaOpCodeMapEntry[parser.getSpecialOpCodes().size()]); + } + else + { + if ( (Groups & FormulaMapGroup.ARRAY_SEPARATORS) != 0 ) + { + token.addAll(parser.getGroup(SOFormulaParser.ARRAY_SEPARATORS).values()); + } + if ( (Groups & FormulaMapGroup.SEPARATORS) != 0 ) + { + token.addAll(parser.getGroup(SOFormulaParser.SEPARATORS).values()); + } + if ( (Groups & FormulaMapGroup.ARRAY_SEPARATORS) != 0 ) + { + token.addAll(parser.getGroup(SOFormulaParser.ARRAY_SEPARATORS).values()); + } + if ( (Groups & FormulaMapGroup.UNARY_OPERATORS) != 0 ) + { + token.addAll(parser.getGroup(SOFormulaParser.UNARY_OPERATORS).values()); + } + if ( (Groups & FormulaMapGroup.BINARY_OPERATORS) != 0 ) + { + token.addAll(parser.getGroup(SOFormulaParser.BINARY_OPERATORS).values()); + } + if ( (Groups & FormulaMapGroup.FUNCTIONS) != 0 ) + { + token.addAll(parser.getGroup(SOFormulaParser.FUNCTIONS).values()); + } + } + + return (com.sun.star.sheet.FormulaOpCodeMapEntry[]) token.toArray(new FormulaOpCodeMapEntry[token.size()]); + } + + public String getImplementationName() + { + return SOFormulaOpCodeMapper.class.getName(); + } + + public boolean supportsService(String sServiceName) + { + return sServiceName.equals(__serviceName); + } + + public String[] getSupportedServiceNames() + { + return getServiceNames(); + } + + /** + * This method is a simple helper function to used in the static component initialisation functions as well as + * in getSupportedServiceNames. + */ + public static String[] getServiceNames() + { + return new String[] + { + __serviceName + }; + } +} diff --git a/reportdesign/java/com/sun/star/report/pentaho/SOFormulaParser.java b/reportdesign/java/com/sun/star/report/pentaho/SOFormulaParser.java new file mode 100644 index 000000000000..13da5c577c9d --- /dev/null +++ b/reportdesign/java/com/sun/star/report/pentaho/SOFormulaParser.java @@ -0,0 +1,429 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: SOFormulaParser.java,v $ + * + * $Revision: 1.7 $ + * + * 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.lang.XServiceInfo; +import com.sun.star.sheet.XFormulaOpCodeMapper; +import com.sun.star.uno.Exception; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lib.uno.helper.ComponentBase; +import com.sun.star.uno.Type; +import com.sun.star.lib.uno.helper.PropertySetMixin; +import com.sun.star.sheet.FormulaLanguage; +import com.sun.star.sheet.FormulaMapGroup; +import com.sun.star.sheet.FormulaMapGroupSpecialOffset; +import com.sun.star.sheet.FormulaOpCodeMapEntry; +import com.sun.star.sheet.FormulaToken; +import com.sun.star.uno.Any; +import com.sun.star.uno.UnoRuntime; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; +import org.jfree.formula.DefaultFormulaContext; +import org.jfree.formula.function.FunctionRegistry; +import org.jfree.formula.parser.FormulaParser; +import org.jfree.formula.parser.GeneratedFormulaParserConstants; +import org.jfree.formula.parser.GeneratedFormulaParserTokenManager; +import org.jfree.formula.parser.JavaCharStream; +import org.jfree.formula.parser.ParseException; +import org.jfree.formula.parser.Token; +import org.jfree.formula.parser.TokenMgrError; +import org.jfree.util.Configuration; + +public final class SOFormulaParser extends ComponentBase + implements com.sun.star.report.meta.XFormulaParser, XServiceInfo +{ + + public static final int SEPARATORS = 0; + public static final int ARRAY_SEPARATORS = 1; + public static final int UNARY_OPERATORS = 2; + public static final int BINARY_OPERATORS = 3; + public static final int FUNCTIONS = 4; + private final XComponentContext m_xContext; + private final PropertySetMixin m_prophlp; + private static final String __serviceName = "com.sun.star.report.meta.FormulaParser"; + private static final String OPERATORS = "org.jfree.formula.operators."; + + // attributes + final private List m_OpCodeMap = new ArrayList(); + private XFormulaOpCodeMapper formulaOpCodeMapper = null; + private final Map parserAllOpCodes = new HashMap(); + private final Map parserNames = new HashMap(); + private final Map[] groupOpCodes = new HashMap[5]; + private final Vector specialOpCodes = new Vector(); + + public Vector getSpecialOpCodes() + { + return specialOpCodes; + } + private int ownTokenCounter = 1000; + private final FormulaOpCodeMapEntry opCodePush; + private final FormulaParser parser; + + public SOFormulaParser(XComponentContext context) + { + + m_xContext = context; + final ClassLoader cl = java.lang.Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); + + parser = new FormulaParser(); + try + { + final XFormulaOpCodeMapper mapper = (XFormulaOpCodeMapper) UnoRuntime.queryInterface(XFormulaOpCodeMapper.class, m_xContext.getServiceManager().createInstanceWithContext("simple.formula.FormulaOpCodeMapperObj", m_xContext)); + FormulaOpCodeMapEntry[] opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.FUNCTIONS); + final DefaultFormulaContext defaultContext = new DefaultFormulaContext(); + final FunctionRegistry functionRegistry = defaultContext.getFunctionRegistry(); + + String[] names = functionRegistry.getFunctionNames(); + addOpCodes(names, opCodes, FUNCTIONS); + names = getOperators(defaultContext, OPERATORS); + opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.UNARY_OPERATORS); + addOpCodes(names, opCodes, UNARY_OPERATORS); + opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.BINARY_OPERATORS); + addOpCodes(names, opCodes, BINARY_OPERATORS); + + names = GeneratedFormulaParserConstants.tokenImage.clone(); + for (int i = 0; i < names.length; i++) + { + final String token = names[i]; + if ( token != null && token.length() > 0 && token.charAt(0) == '"' ) + { + names[i] = token.substring(1, token.length() - 1); + } + } + opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.SEPARATORS); + addOpCodes(names, opCodes, SEPARATORS, false); + + opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.ARRAY_SEPARATORS); + addOpCodes(names, opCodes, ARRAY_SEPARATORS, false); + + opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.SPECIAL); + names = new String[opCodes.length]; + + for (int i = 0; i < opCodes.length; i++) + { + final FormulaOpCodeMapEntry opCode = opCodes[i]; + parserAllOpCodes.put(opCode.Token.OpCode, opCode); + specialOpCodes.add(opCode); + } + // addOpCodes(names, opCodes,SPECIAL,false); + } catch ( Exception ex ) + { + ex.printStackTrace(); + } + opCodePush = (FormulaOpCodeMapEntry) specialOpCodes.get(FormulaMapGroupSpecialOffset.PUSH); + Thread.currentThread().setContextClassLoader(cl); + // use the last parameter of the PropertySetMixin constructor + // for your optional attributes if necessary. See the documentation + // of the PropertySetMixin helper for further information. + // Ensure that your attributes are initialized correctly! + m_prophlp = new PropertySetMixin(m_xContext, this, + new Type(com.sun.star.report.meta.XFormulaParser.class), null); + } + ; + + // com.sun.star.sheet.XFormulaParser: + public com.sun.star.sheet.FormulaToken[] parseFormula(String aFormula) + { + final ArrayList tokens = new ArrayList(); + if ( !"=".equals(aFormula) ) + { + String formula; + if ( aFormula.charAt(0) == '=' ) + formula = aFormula.substring(1); + else + formula = aFormula; + final ArrayList images = new ArrayList(); + try + { + int brackets = 0; + final GeneratedFormulaParserTokenManager tokenParser = new GeneratedFormulaParserTokenManager(new JavaCharStream(new StringReader(formula), 1, 1)); + Token token = tokenParser.getNextToken(); + while (token.kind != GeneratedFormulaParserConstants.EOF) + { + final FormulaToken formulaToken; + images.add(token.image); + final String upper = token.image.toUpperCase(); + if ( parserNames.containsKey(upper) ) + { + if ( token.image.equals("(")) + brackets++; + else if ( token.image.equals(")")) + --brackets; + final FormulaOpCodeMapEntry opCode = (FormulaOpCodeMapEntry) parserNames.get(upper); + formulaToken = opCode.Token; + } + else if ( token.kind == GeneratedFormulaParserConstants.WHITESPACE ) + { + final FormulaOpCodeMapEntry opCode = (FormulaOpCodeMapEntry) specialOpCodes.get(FormulaMapGroupSpecialOffset.SPACES); + formulaToken = opCode.Token; + } + else + { + formulaToken = new FormulaToken(); + formulaToken.OpCode = opCodePush.Token.OpCode; + formulaToken.Data = new Any(Type.STRING, token.image); + } + + tokens.add(formulaToken); + token = tokenParser.getNextToken(); + } + if ( brackets > 0 ) + { + final FormulaOpCodeMapEntry opCode = (FormulaOpCodeMapEntry) parserNames.get(")"); + while ( brackets-- != 0 ) + { + formula = formula.concat(")"); + images.add(")"); + tokens.add(opCode.Token); + } + + } + + parser.parse(formula); + } catch ( ParseException ex ) + { + boolean found = false; + // error occured so all token must be bad + for (int i = 0; i < tokens.size(); i++) + { + if ( !found && images.get(i).equals(ex.currentToken.image) ) + found = true; + if ( found ) + { + final FormulaToken dest = new FormulaToken(); + dest.OpCode = ((FormulaOpCodeMapEntry) specialOpCodes.get(FormulaMapGroupSpecialOffset.BAD)).Token.OpCode; + dest.Data = new Any(Type.STRING, images.get(i)); + tokens.remove(i); + tokens.add(i, dest); + } + } + } catch ( java.lang.Exception e ) + { + } catch ( TokenMgrError e ) + { + } + } + FormulaToken[] ret = (FormulaToken[]) tokens.toArray(new FormulaToken[tokens.size()]); + return ret; + } + + public String printFormula(com.sun.star.sheet.FormulaToken[] aTokens) + { + final StringBuffer ret = new StringBuffer(); + for (int i = 0; i < aTokens.length; i++) + { + final FormulaToken formulaToken = aTokens[i]; + if ( formulaToken.OpCode == opCodePush.Token.OpCode && !formulaToken.Data.equals(Any.VOID) ) + { + ret.append(formulaToken.Data); + } + else if ( parserAllOpCodes.containsKey(formulaToken.OpCode) ) + { + final FormulaOpCodeMapEntry opCode = (FormulaOpCodeMapEntry) parserAllOpCodes.get(formulaToken.OpCode); + if ( opCode.Name.length() > 0 ) + ret.append(opCode.Name); + else if ( !formulaToken.Data.equals(Any.VOID) ) + ret.append(formulaToken.Data); + } + } + return ret.toString(); + } + + // com.sun.star.beans.XPropertySet: + public com.sun.star.beans.XPropertySetInfo getPropertySetInfo() + { + return m_prophlp.getPropertySetInfo(); + } + + public void setPropertyValue(String aPropertyName, Object aValue) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.beans.PropertyVetoException, com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.setPropertyValue(aPropertyName, aValue); + } + + public Object getPropertyValue(String aPropertyName) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + return m_prophlp.getPropertyValue(aPropertyName); + } + + public void addPropertyChangeListener(String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.addPropertyChangeListener(aPropertyName, xListener); + } + + public void removePropertyChangeListener(String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.removePropertyChangeListener(aPropertyName, xListener); + } + + public void addVetoableChangeListener(String aPropertyName, com.sun.star.beans.XVetoableChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.addVetoableChangeListener(aPropertyName, xListener); + } + + public void removeVetoableChangeListener(String aPropertyName, com.sun.star.beans.XVetoableChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.removeVetoableChangeListener(aPropertyName, xListener); + } + + // com.sun.star.report.meta.XFormulaParser: + public com.sun.star.sheet.FormulaOpCodeMapEntry[] getOpCodeMap() + { + return (com.sun.star.sheet.FormulaOpCodeMapEntry[]) m_OpCodeMap.toArray(new FormulaOpCodeMapEntry[m_OpCodeMap.size()]); + } + + public void setOpCodeMap(com.sun.star.sheet.FormulaOpCodeMapEntry[] the_value) + { +// m_prophlp.prepareSet("OpCodeMap", null); +// synchronized (this) +// { +// m_OpCodeMap.clear(); +// } + } + + public String getImplementationName() + { + return SOFormulaParser.class.getName(); + } + + public boolean supportsService(String sServiceName) + { + return sServiceName.equals(__serviceName); + } + + public String[] getSupportedServiceNames() + { + return getServiceNames(); + } + + /** + * This method is a simple helper function to used in the static component initialisation functions as well as + * in getSupportedServiceNames. + */ + public static String[] getServiceNames() + { + return new String[] + { + __serviceName + }; + } + + public XFormulaOpCodeMapper getFormulaOpCodeMapper() + { + if ( formulaOpCodeMapper == null ) + { + formulaOpCodeMapper = new SOFormulaOpCodeMapper(m_xContext, this); + } + + return formulaOpCodeMapper; + } + + private void addOpCodes(String[] names, FormulaOpCodeMapEntry[] opCodes, int group) + { + addOpCodes(names, opCodes, group, true); + } + + private void addOpCodes(String[] names, FormulaOpCodeMapEntry[] opCodes, int group, boolean add) + { + groupOpCodes[group] = new HashMap(); + for (int j = 0; j < names.length; j++) + { + FormulaOpCodeMapEntry opCode = null; + int i = 0; + for (; i < opCodes.length; i++) + { + opCode = opCodes[i]; + if ( names[j].equals(opCode.Name) ) + { + break; + } + } + if ( i >= opCodes.length ) + { + if ( !add ) + continue; + final FormulaToken token = new FormulaToken(ownTokenCounter++, Any.VOID); + opCode = new FormulaOpCodeMapEntry(names[j], token); + } + parserNames.put(names[j], opCode); + parserAllOpCodes.put(opCode.Token.OpCode, opCode); + groupOpCodes[group].put(opCode.Token.OpCode, opCode); + } + } + + final public Map getNames() + { + return parserNames; + } + + final public Map getGroup(int group) + { + return groupOpCodes[group]; + } + + private String[] getOperators(DefaultFormulaContext defaultContext, final String _kind) + { + final ArrayList ops = new ArrayList(); + final Configuration configuration = defaultContext.getConfiguration(); + final Iterator iter = configuration.findPropertyKeys(_kind); + while (iter.hasNext()) + { + final String configKey = (String) iter.next(); + if ( configKey.endsWith(".class") == false ) + { + continue; + } + final String operatorClass = configuration.getConfigProperty(configKey); + if ( operatorClass == null ) + { + continue; + } + if ( operatorClass.length() == 0 ) + { + continue; + } + final String tokenKey = configKey.substring(0, configKey.length() - ".class".length()) + ".token"; + final String token = configuration.getConfigProperty(tokenKey); + if ( token == null ) + { + continue; + } + ops.add(token.trim()); + } + return (String[]) ops.toArray(new String[ops.size()]); + } +} + diff --git a/reportdesign/java/com/sun/star/report/pentaho/SOFunctionManager.java b/reportdesign/java/com/sun/star/report/pentaho/SOFunctionManager.java new file mode 100644 index 000000000000..188ca52dbd70 --- /dev/null +++ b/reportdesign/java/com/sun/star/report/pentaho/SOFunctionManager.java @@ -0,0 +1,198 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: XFunctionManager.java,v $ + * + * $Revision: 1.7 $ + * + * 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.container.NoSuchElementException; +import com.sun.star.lang.IndexOutOfBoundsException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.report.meta.XFunctionDescription; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lib.uno.helper.ComponentBase; +import com.sun.star.report.meta.XFunctionCategory; +import com.sun.star.report.meta.XFunctionManager; +import org.jfree.formula.DefaultFormulaContext; +import org.jfree.formula.function.FunctionCategory; +import org.jfree.formula.function.FunctionDescription; +import org.jfree.formula.function.FunctionRegistry; +import org.jfree.formula.lvalues.LValue; +import org.jfree.formula.parser.FormulaParser; +import org.jfree.formula.parser.ParseException; + +/** + * This class capsulates the class, that implements the minimal component, a factory for creating the service + * (<CODE>__getComponentFactory</CODE>) and a method, that writes the information into the given registry key + * (<CODE>__writeRegistryServiceInfo</CODE>). + */ +public final class SOFunctionManager extends ComponentBase implements XFunctionManager, XServiceInfo +{ + + private final XComponentContext m_xContext; + /** + * The service name, that must be used to get an instance of this service. + */ + private static final String __serviceName = + "com.sun.star.report.meta.FunctionManager"; + final private FunctionCategory[] categories; + final private FunctionRegistry functionRegistry; + final private DefaultFormulaContext defaultContext; + + public SOFunctionManager(XComponentContext context) + { + m_xContext = context; + final ClassLoader cl = java.lang.Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); + defaultContext = new DefaultFormulaContext(); + functionRegistry = defaultContext.getFunctionRegistry(); + categories = functionRegistry.getCategories(); + Thread.currentThread().setContextClassLoader(cl); + + } + + /** + * This method returns an array of all supported service names. + * + * @return Array of supported service names. + */ + public String[] getSupportedServiceNames() + { + return getServiceNames(); + } + + /** + * This method is a simple helper function to used in the static component initialisation functions as well as + * in getSupportedServiceNames. + */ + public static String[] getServiceNames() + { + return new String[] + { + __serviceName + }; + } + + /** + * This method returns true, if the given service will be supported by the component. + * + * @param sServiceName Service name. + * @return True, if the given service name will be supported. + */ + public boolean supportsService(final String sServiceName) + { + return sServiceName.equals(__serviceName); + } + + /** + * Return the class name of the component. + * + * @return Class name of the component. + */ + public String getImplementationName() + { + return SOFunctionManager.class.getName(); + } + + // com.sun.star.container.XElementAccess: + public com.sun.star.uno.Type getElementType() + { + return new com.sun.star.uno.Type(XFunctionCategory.class); + } + + public boolean hasElements() + { + return categories.length != 0; + } + + // com.sun.star.container.XIndexAccess: + public int getCount() + { + return categories.length; + } + + public Object getByIndex(int Index) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException + { + return getCategory(Index); + } + + // com.sun.star.report.meta.XFunctionManager: + public com.sun.star.report.meta.XFunctionCategory getCategory(int position) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException + { + if ( position >= categories.length ) + throw new com.sun.star.lang.IndexOutOfBoundsException(); + return new StarFunctionCategory(defaultContext,m_xContext, functionRegistry, position, categories[position]); + } + + public int getFunctionStartAtIndex(String formula, int position) + { + int nStartPos = -1; + try + { + final FormulaParser parser = new FormulaParser(); + final LValue x = parser.parse(formula); + String part = x.toString(); + while ( part.length() < position ) + { + final LValue[] children = x.getChildValues(); + if ( children != null ) + { + for(int i = 0; i < children.length;++i) + { + part = children[i].toString(); + } + } + } + } catch ( ParseException ex ) + { + } + return nStartPos; + } + + public XFunctionDescription getFunctionByName(String arg0) throws NoSuchElementException + { + final FunctionDescription func = functionRegistry.getMetaData(arg0); + if ( func == null ) + throw new NoSuchElementException(); + int i = 0; + for (; i < categories.length; i++) + { + if ( categories[i] == func.getCategory() ) + break; + } + try + { + return new StarFunctionDescription(defaultContext, m_xContext, getCategory(i), functionRegistry, func); + } + catch ( Exception ex ) + { + } + return null; + } +} diff --git a/reportdesign/java/com/sun/star/report/pentaho/SOReportJobFactory.java b/reportdesign/java/com/sun/star/report/pentaho/SOReportJobFactory.java index 9c93481645ee..626aedbdf885 100644 --- a/reportdesign/java/com/sun/star/report/pentaho/SOReportJobFactory.java +++ b/reportdesign/java/com/sun/star/report/pentaho/SOReportJobFactory.java @@ -1,369 +1,385 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: SOReportJobFactory.java,v $ - * $Revision: 1.7 $ - * - * 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.beans.NamedValue; -import com.sun.star.beans.XPropertySet; -import com.sun.star.beans.UnknownPropertyException; -import com.sun.star.beans.PropertyVetoException; -import com.sun.star.beans.XPropertyChangeListener; -import com.sun.star.beans.XVetoableChangeListener; -import com.sun.star.embed.XStorage; -import com.sun.star.lang.IllegalArgumentException; -import com.sun.star.lang.XInitialization; -import com.sun.star.lang.XServiceInfo; -import com.sun.star.lang.WrappedTargetException; -import com.sun.star.lang.XSingleComponentFactory; -import com.sun.star.lib.uno.helper.Factory; -import com.sun.star.lib.uno.helper.PropertySetMixin; -import com.sun.star.lib.uno.helper.WeakBase; -import com.sun.star.registry.XRegistryKey; -import com.sun.star.report.DataSourceFactory; -import com.sun.star.report.JobProperties; -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.ReportJobFactory; -import com.sun.star.report.SDBCReportDataFactory; -import com.sun.star.report.SOImageService; -import com.sun.star.report.StorageRepository; -import com.sun.star.report.XReportDefinition; -import com.sun.star.report.pentaho.SOReportJobFactory._SOReportJobFactory; -import com.sun.star.sdbc.XConnection; -import com.sun.star.sdbc.XRowSet; -import com.sun.star.task.XJob; -import com.sun.star.uno.Exception; -import com.sun.star.uno.Type; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XComponentContext; -import org.jfree.util.Log; - -/** - * This class capsulates the class, that implements the minimal component, a factory for creating the service - * (<CODE>__getComponentFactory</CODE>) and a method, that writes the information into the given registry key - * (<CODE>__writeRegistryServiceInfo</CODE>). - */ -public class SOReportJobFactory -{ - - private SOReportJobFactory() - { - } - - public static class _SOReportJobFactory extends WeakBase implements XInitialization, XServiceInfo, XJob, XPropertySet, ReportJobFactory - { - - /** - * The service name, that must be used to get an instance of this service. - */ - private static final String __serviceName = - "com.sun.star.report.pentaho.SOReportJobFactory"; - private final PropertySetMixin m_prophlp; - /** - * The initial component contextr, that gives access to the service manager, supported singletons, ... It's - * often later used - */ - private final XComponentContext m_cmpCtx; - private XConnection activeConnection; - private XReportDefinition report; - - public _SOReportJobFactory(final XComponentContext xCompContext) - { - m_cmpCtx = xCompContext; - m_prophlp = new PropertySetMixin(m_cmpCtx, this, - new Type(XJob.class), - null); // no optionals - } - - /** - * This method is a member of the interface for initializing an object directly after its creation. - * - * @param object This array of arbitrary objects will be passed to the component after its creation. - * @throws Exception Every exception will not be handled, but will be passed to the caller. - */ - public void initialize(final Object[] object) - throws com.sun.star.uno.Exception - { - /* The component describes what arguments its expected and in which - * order!At this point you can read the objects and can intialize - * your component using these objects. - */ - } - - /** - * This method returns an array of all supported service names. - * - * @return Array of supported service names. - */ - public String[] getSupportedServiceNames() - { - return getServiceNames(); - } - - /** - * This method is a simple helper function to used in the static component initialisation functions as well as - * in getSupportedServiceNames. - */ - public static String[] getServiceNames() - { - return new String[]{__serviceName}; - } - - /** - * This method returns true, if the given service will be supported by the component. - * - * @param sServiceName Service name. - * @return True, if the given service name will be supported. - */ - public boolean supportsService(final String sServiceName) - { - return sServiceName.equals(__serviceName); - } - - /** - * Return the class name of the component. - * - * @return Class name of the component. - */ - public String getImplementationName() - { - return SOReportJobFactory.class.getName(); - } - - public Object execute(final NamedValue[] namedValue) - throws com.sun.star.lang.IllegalArgumentException, com.sun.star.uno.Exception - { - final ClassLoader cl = java.lang.Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); - try - { - final ReportJob job = createReportJob(namedValue); - job.execute(); - } - catch (java.lang.Exception e) - { - Log.error("ReportProcessing failed", e); - throw new com.sun.star.lang.WrappedTargetException(e.getMessage(), this,null); - } - catch (java.lang.IncompatibleClassChangeError e2) - { - Log.error("Detected an IncompatibleClassChangeError"); - throw new com.sun.star.lang.WrappedTargetException("caught a " + e2.getClass().getName(), this, new com.sun.star.uno.Exception(e2.getLocalizedMessage())); - } - Thread.currentThread().setContextClassLoader(cl); - - return null; - } - - public ReportJob createReportJob(final NamedValue[] namedValue) throws IllegalArgumentException, ReportExecutionException, Exception - { - XStorage input = null; - XStorage output = null; - XRowSet rowSet = null; - String mimetype = null; - String author = null; - String title = null; - - for (int i = 0; i < namedValue.length; ++i) - { - final NamedValue aProps = namedValue[i]; - if ("ActiveConnection".equalsIgnoreCase(aProps.Name)) - { - activeConnection = (XConnection) UnoRuntime.queryInterface(XConnection.class, aProps.Value); - } - else if ("ReportDefinition".equalsIgnoreCase(aProps.Name)) - { - report = (XReportDefinition) UnoRuntime.queryInterface(XReportDefinition.class, aProps.Value); - } - else if ("InputStorage".equalsIgnoreCase(aProps.Name)) - { - input = (XStorage) UnoRuntime.queryInterface(XStorage.class, aProps.Value); - } - else if ("OutputStorage".equalsIgnoreCase(aProps.Name)) - { - output = (XStorage) UnoRuntime.queryInterface(XStorage.class, aProps.Value); - } - else if ("RowSet".equalsIgnoreCase(aProps.Name)) - { - rowSet = (XRowSet) UnoRuntime.queryInterface(XRowSet.class, aProps.Value); - } - else if ("mimetype".equalsIgnoreCase(aProps.Name)) - { - mimetype = (String) aProps.Value; - } - else if (ReportEngineParameterNames.AUTHOR.equalsIgnoreCase(aProps.Name)) - { - author = (String) aProps.Value; - } - else if (ReportEngineParameterNames.TITLE.equalsIgnoreCase(aProps.Name)) - { - title = (String) aProps.Value; - } - } - - if (input == null || output == null) - { - throw new com.sun.star.lang.IllegalArgumentException(); - } - - if (rowSet == null) - { - if (report == null || activeConnection == null) - { - throw new com.sun.star.lang.IllegalArgumentException(); - } - mimetype = report.getMimeType(); - } - else - { - XPropertySet set = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, rowSet); - if ( set == null ) - { - throw new com.sun.star.lang.IllegalArgumentException(); - } - activeConnection = (XConnection) UnoRuntime.queryInterface(XConnection.class,set.getPropertyValue("ActiveConnection")); - } - if (mimetype == null) - { - mimetype = PentahoReportEngineMetaData.OPENDOCUMENT_TEXT; - } - - final DataSourceFactory dataFactory = new SDBCReportDataFactory(m_cmpCtx, activeConnection); - final StorageRepository storageRepository = new StorageRepository(input, output); - - final String inputName = "content.xml"; - final String outputName = "content.xml"; - - final PentahoReportEngine engine = new PentahoReportEngine(); - final ReportJobDefinition definition = engine.createJobDefinition(); - final JobProperties procParms = definition.getProcessingParameters(); - procParms.setProperty(ReportEngineParameterNames.INPUT_REPOSITORY, storageRepository); - procParms.setProperty(ReportEngineParameterNames.OUTPUT_REPOSITORY, storageRepository); - procParms.setProperty(ReportEngineParameterNames.INPUT_NAME, inputName); - procParms.setProperty(ReportEngineParameterNames.OUTPUT_NAME, outputName); - procParms.setProperty(ReportEngineParameterNames.CONTENT_TYPE, mimetype); - procParms.setProperty(ReportEngineParameterNames.INPUT_DATASOURCE_FACTORY, dataFactory); - procParms.setProperty(ReportEngineParameterNames.IMAGE_SERVICE, new SOImageService(m_cmpCtx)); - procParms.setProperty(ReportEngineParameterNames.INPUT_REPORTJOB_FACTORY, this); - if ( author != null) - procParms.setProperty(ReportEngineParameterNames.AUTHOR, author); - if ( title != null) - procParms.setProperty(ReportEngineParameterNames.TITLE, title); - - return engine.createJob(definition); - } - - // com.sun.star.beans.XPropertySet: - public com.sun.star.beans.XPropertySetInfo getPropertySetInfo() - { - return m_prophlp.getPropertySetInfo(); - } - - public void setPropertyValue(final String aPropertyName, final Object aValue) - throws UnknownPropertyException, PropertyVetoException, com.sun.star.lang.IllegalArgumentException, - WrappedTargetException - { - m_prophlp.setPropertyValue(aPropertyName, aValue); - } - - public Object getPropertyValue(final String aPropertyName) - throws UnknownPropertyException, WrappedTargetException - { - return m_prophlp.getPropertyValue(aPropertyName); - } - - public void addPropertyChangeListener(final String aPropertyName, final XPropertyChangeListener xListener) - throws UnknownPropertyException, WrappedTargetException - { - m_prophlp.addPropertyChangeListener(aPropertyName, xListener); - } - - public void removePropertyChangeListener(final String aPropertyName, final XPropertyChangeListener xListener) - throws UnknownPropertyException, WrappedTargetException - { - m_prophlp.removePropertyChangeListener(aPropertyName, xListener); - } - - public void addVetoableChangeListener(final String aPropertyName, final XVetoableChangeListener xListener) - throws UnknownPropertyException, WrappedTargetException - { - m_prophlp.addVetoableChangeListener(aPropertyName, xListener); - } - - public void removeVetoableChangeListener(final String aPropertyName, final XVetoableChangeListener xListener) - throws UnknownPropertyException, WrappedTargetException - { - m_prophlp.removeVetoableChangeListener(aPropertyName, xListener); - } - } - - /** - * Gives a factory for creating the service. This method is called by the <code>JavaLoader</code> - * <p/> - * - * @param sImplName the name of the implementation for which a service is desired - * @return returns a <code>XSingleComponentFactory</code> for creating the component - * @see com.sun.star.comp.loader.JavaLoader - */ - public static XSingleComponentFactory __getComponentFactory(final String sImplName) - { - XSingleComponentFactory xFactory = null; - - try - { - if (sImplName.equals(_SOReportJobFactory.class.getName())) - { - xFactory = Factory.createComponentFactory(_SOReportJobFactory.class, - _SOReportJobFactory.getServiceNames()); - } - } - catch (java.lang.IncompatibleClassChangeError e2) - { - } - - return xFactory; - } - - /** - * Writes the service information into the given registry key. This method is called by the <code>JavaLoader</code> - * <p/> - * - * @param regKey the registryKey - * @return returns true if the operation succeeded - * @see com.sun.star.comp.loader.JavaLoader - */ - public static boolean __writeRegistryServiceInfo(final XRegistryKey regKey) - { - return Factory.writeRegistryServiceInfo(_SOReportJobFactory.class.getName(), - _SOReportJobFactory.getServiceNames(), - regKey); - } -} +/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SOReportJobFactory.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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.beans.NamedValue;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.PropertyVetoException;
+import com.sun.star.beans.XPropertyChangeListener;
+import com.sun.star.beans.XVetoableChangeListener;
+import com.sun.star.embed.XStorage;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.XInitialization;
+import com.sun.star.lang.XServiceInfo;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.lang.XSingleComponentFactory;
+import com.sun.star.lib.uno.helper.Factory;
+import com.sun.star.lib.uno.helper.PropertySetMixin;
+import com.sun.star.lib.uno.helper.WeakBase;
+import com.sun.star.registry.XRegistryKey;
+import com.sun.star.report.DataSourceFactory;
+import com.sun.star.report.JobProperties;
+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.ReportJobFactory;
+import com.sun.star.report.SDBCReportDataFactory;
+import com.sun.star.report.SOImageService;
+import com.sun.star.report.StorageRepository;
+import com.sun.star.report.XReportDefinition;
+import com.sun.star.report.pentaho.SOReportJobFactory._SOReportJobFactory;
+import com.sun.star.sdbc.XConnection;
+import com.sun.star.sdbc.XRowSet;
+import com.sun.star.task.XJob;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.Type;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import org.jfree.util.Log;
+
+/**
+ * This class capsulates the class, that implements the minimal component, a factory for creating the service
+ * (<CODE>__getComponentFactory</CODE>) and a method, that writes the information into the given registry key
+ * (<CODE>__writeRegistryServiceInfo</CODE>).
+ */
+public class SOReportJobFactory
+{
+
+ private SOReportJobFactory()
+ {
+ }
+
+ public static class _SOReportJobFactory extends WeakBase implements XInitialization, XServiceInfo, XJob, XPropertySet, ReportJobFactory
+ {
+
+ /**
+ * The service name, that must be used to get an instance of this service.
+ */
+ private static final String __serviceName =
+ "com.sun.star.report.pentaho.SOReportJobFactory";
+ private final PropertySetMixin m_prophlp;
+ /**
+ * The initial component contextr, that gives access to the service manager, supported singletons, ... It's
+ * often later used
+ */
+ private final XComponentContext m_cmpCtx;
+ private XConnection activeConnection;
+ private XReportDefinition report;
+
+ public _SOReportJobFactory( XComponentContext xCompContext)
+ {
+ m_cmpCtx = xCompContext;
+ m_prophlp = new PropertySetMixin(m_cmpCtx, this,
+ new Type(XJob.class),
+ null); // no optionals
+ }
+
+ /**
+ * This method is a member of the interface for initializing an object directly after its creation.
+ *
+ * @param object This array of arbitrary objects will be passed to the component after its creation.
+ * @throws Exception Every exception will not be handled, but will be passed to the caller.
+ */
+ public void initialize(final Object[] object)
+ throws com.sun.star.uno.Exception
+ {
+ /* The component describes what arguments its expected and in which
+ * order!At this point you can read the objects and can intialize
+ * your component using these objects.
+ */
+ }
+
+ /**
+ * This method returns an array of all supported service names.
+ *
+ * @return Array of supported service names.
+ */
+ public String[] getSupportedServiceNames()
+ {
+ return getServiceNames();
+ }
+
+ /**
+ * This method is a simple helper function to used in the static component initialisation functions as well as
+ * in getSupportedServiceNames.
+ */
+ public static String[] getServiceNames()
+ {
+ return new String[]{__serviceName};
+ }
+
+ /**
+ * This method returns true, if the given service will be supported by the component.
+ *
+ * @param sServiceName Service name.
+ * @return True, if the given service name will be supported.
+ */
+ public boolean supportsService(final String sServiceName)
+ {
+ return sServiceName.equals(__serviceName);
+ }
+
+ /**
+ * Return the class name of the component.
+ *
+ * @return Class name of the component.
+ */
+ public String getImplementationName()
+ {
+ return SOReportJobFactory.class.getName();
+ }
+
+ public Object execute(final NamedValue[] namedValue)
+ throws com.sun.star.lang.IllegalArgumentException, com.sun.star.uno.Exception
+ {
+ final ClassLoader cl = java.lang.Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ try
+ {
+ final ReportJob job = createReportJob(namedValue);
+ job.execute();
+ }
+ catch (java.lang.Exception e)
+ {
+ Log.error("ReportProcessing failed", e);
+ throw new com.sun.star.lang.WrappedTargetException(e.getMessage(), this,null);
+ }
+ catch (java.lang.IncompatibleClassChangeError e2)
+ {
+ Log.error("Detected an IncompatibleClassChangeError");
+ throw new com.sun.star.lang.WrappedTargetException("caught a " + e2.getClass().getName(), this, new com.sun.star.uno.Exception(e2.getLocalizedMessage()));
+ }
+ Thread.currentThread().setContextClassLoader(cl);
+
+ return null;
+ }
+
+ public ReportJob createReportJob(final NamedValue[] namedValue) throws IllegalArgumentException, ReportExecutionException, Exception
+ {
+ XStorage input = null;
+ XStorage output = null;
+ XRowSet rowSet = null;
+ String mimetype = null;
+ String author = null;
+ String title = null;
+
+ for (int i = 0; i < namedValue.length; ++i)
+ {
+ final NamedValue aProps = namedValue[i];
+ if ("ActiveConnection".equalsIgnoreCase(aProps.Name))
+ {
+ activeConnection = (XConnection) UnoRuntime.queryInterface(XConnection.class, aProps.Value);
+ }
+ else if ("ReportDefinition".equalsIgnoreCase(aProps.Name))
+ {
+ report = (XReportDefinition) UnoRuntime.queryInterface(XReportDefinition.class, aProps.Value);
+ }
+ else if ("InputStorage".equalsIgnoreCase(aProps.Name))
+ {
+ input = (XStorage) UnoRuntime.queryInterface(XStorage.class, aProps.Value);
+ }
+ else if ("OutputStorage".equalsIgnoreCase(aProps.Name))
+ {
+ output = (XStorage) UnoRuntime.queryInterface(XStorage.class, aProps.Value);
+ }
+ else if ("RowSet".equalsIgnoreCase(aProps.Name))
+ {
+ rowSet = (XRowSet) UnoRuntime.queryInterface(XRowSet.class, aProps.Value);
+ }
+ else if ("mimetype".equalsIgnoreCase(aProps.Name))
+ {
+ mimetype = (String) aProps.Value;
+ }
+ else if (ReportEngineParameterNames.AUTHOR.equalsIgnoreCase(aProps.Name))
+ {
+ author = (String) aProps.Value;
+ }
+ else if (ReportEngineParameterNames.TITLE.equalsIgnoreCase(aProps.Name))
+ {
+ title = (String) aProps.Value;
+ }
+ }
+
+ if (input == null || output == null)
+ {
+ throw new com.sun.star.lang.IllegalArgumentException();
+ }
+
+ if (rowSet == null)
+ {
+ if (report == null || activeConnection == null)
+ {
+ throw new com.sun.star.lang.IllegalArgumentException();
+ }
+ mimetype = report.getMimeType();
+ }
+ else
+ {
+ final XPropertySet set = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, rowSet);
+ if ( set == null )
+ {
+ throw new com.sun.star.lang.IllegalArgumentException();
+ }
+ activeConnection = (XConnection) UnoRuntime.queryInterface(XConnection.class,set.getPropertyValue("ActiveConnection"));
+ }
+ if (mimetype == null)
+ {
+ mimetype = PentahoReportEngineMetaData.OPENDOCUMENT_TEXT;
+ }
+
+ final DataSourceFactory dataFactory = new SDBCReportDataFactory(m_cmpCtx, activeConnection);
+ final StorageRepository storageRepository = new StorageRepository(input, output);
+
+ final String inputName = "content.xml";
+ final String outputName = "content.xml";
+
+ final PentahoReportEngine engine = new PentahoReportEngine();
+ final ReportJobDefinition definition = engine.createJobDefinition();
+ final JobProperties procParms = definition.getProcessingParameters();
+ procParms.setProperty(ReportEngineParameterNames.INPUT_REPOSITORY, storageRepository);
+ procParms.setProperty(ReportEngineParameterNames.OUTPUT_REPOSITORY, storageRepository);
+ procParms.setProperty(ReportEngineParameterNames.INPUT_NAME, inputName);
+ procParms.setProperty(ReportEngineParameterNames.OUTPUT_NAME, outputName);
+ procParms.setProperty(ReportEngineParameterNames.CONTENT_TYPE, mimetype);
+ procParms.setProperty(ReportEngineParameterNames.INPUT_DATASOURCE_FACTORY, dataFactory);
+ procParms.setProperty(ReportEngineParameterNames.IMAGE_SERVICE, new SOImageService(m_cmpCtx));
+ procParms.setProperty(ReportEngineParameterNames.INPUT_REPORTJOB_FACTORY, this);
+ if ( author != null)
+ procParms.setProperty(ReportEngineParameterNames.AUTHOR, author);
+ if ( title != null)
+ procParms.setProperty(ReportEngineParameterNames.TITLE, title);
+
+ return engine.createJob(definition);
+ }
+
+ // com.sun.star.beans.XPropertySet:
+ public com.sun.star.beans.XPropertySetInfo getPropertySetInfo()
+ {
+ return m_prophlp.getPropertySetInfo();
+ }
+
+ public void setPropertyValue(final String aPropertyName, final Object aValue)
+ throws UnknownPropertyException, PropertyVetoException, com.sun.star.lang.IllegalArgumentException,
+ WrappedTargetException
+ {
+ m_prophlp.setPropertyValue(aPropertyName, aValue);
+ }
+
+ public Object getPropertyValue(final String aPropertyName)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ return m_prophlp.getPropertyValue(aPropertyName);
+ }
+
+ public void addPropertyChangeListener(final String aPropertyName, final XPropertyChangeListener xListener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ m_prophlp.addPropertyChangeListener(aPropertyName, xListener);
+ }
+
+ public void removePropertyChangeListener(final String aPropertyName, final XPropertyChangeListener xListener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ m_prophlp.removePropertyChangeListener(aPropertyName, xListener);
+ }
+
+ public void addVetoableChangeListener(final String aPropertyName, final XVetoableChangeListener xListener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ m_prophlp.addVetoableChangeListener(aPropertyName, xListener);
+ }
+
+ public void removeVetoableChangeListener(final String aPropertyName, final XVetoableChangeListener xListener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ m_prophlp.removeVetoableChangeListener(aPropertyName, xListener);
+ }
+ }
+
+ /**
+ * Gives a factory for creating the service. This method is called by the <code>JavaLoader</code>
+ * <p/>
+ *
+ * @param sImplName the name of the implementation for which a service is desired
+ * @return returns a <code>XSingleComponentFactory</code> for creating the component
+ * @see com.sun.star.comp.loader.JavaLoader
+ */
+ public static XSingleComponentFactory __getComponentFactory(final String sImplName)
+ {
+ XSingleComponentFactory xFactory = null;
+
+ try
+ {
+ if (sImplName.equals(_SOReportJobFactory.class.getName()))
+ {
+ xFactory = Factory.createComponentFactory(_SOReportJobFactory.class,_SOReportJobFactory.getServiceNames());
+ }
+ else if (sImplName.equals(SOFunctionManager.class.getName()))
+ {
+ xFactory = Factory.createComponentFactory(SOFunctionManager.class,SOFunctionManager.getServiceNames());
+ }
+ else if (sImplName.equals(SOFormulaParser.class.getName()))
+ {
+ xFactory = Factory.createComponentFactory(SOFormulaParser.class,SOFormulaParser.getServiceNames());
+ }
+ }
+ catch (java.lang.IncompatibleClassChangeError e2)
+ {
+ }
+
+ return xFactory;
+ }
+
+ /**
+ * Writes the service information into the given registry key. This method is called by the <code>JavaLoader</code>
+ * <p/>
+ *
+ * @param regKey the registryKey
+ * @return returns true if the operation succeeded
+ * @see com.sun.star.comp.loader.JavaLoader
+ */
+ public static boolean __writeRegistryServiceInfo(final XRegistryKey regKey)
+ {
+ return Factory.writeRegistryServiceInfo(SOFunctionManager.class.getName(),
+ SOFunctionManager.getServiceNames(),
+ regKey)
+ &&
+ Factory.writeRegistryServiceInfo(_SOReportJobFactory.class.getName(),
+ _SOReportJobFactory.getServiceNames(),
+ regKey)
+ &&
+ Factory.writeRegistryServiceInfo(SOFormulaParser.class.getName(),
+ SOFormulaParser.getServiceNames(),
+ regKey)
+ ;
+ }
+}
diff --git a/reportdesign/java/com/sun/star/report/pentaho/StarFunctionCategory.java b/reportdesign/java/com/sun/star/report/pentaho/StarFunctionCategory.java new file mode 100644 index 000000000000..21883d74bf9d --- /dev/null +++ b/reportdesign/java/com/sun/star/report/pentaho/StarFunctionCategory.java @@ -0,0 +1,162 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: StarFunctionCategory.java,v $ + * + * $Revision: 1.7 $ + * + * 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.uno.XComponentContext; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.uno.Type; +import com.sun.star.lib.uno.helper.PropertySetMixin; +import com.sun.star.report.meta.XFunctionDescription; +import java.util.Locale; +import java.util.MissingResourceException; +import org.jfree.formula.DefaultFormulaContext; +import org.jfree.formula.function.FunctionCategory; +import org.jfree.formula.function.FunctionRegistry; + + +public final class StarFunctionCategory extends WeakBase + implements com.sun.star.report.meta.XFunctionCategory +{ + private final XComponentContext m_xContext; + private final PropertySetMixin m_prophlp; + // attributes + private final int m_Number; + private final FunctionCategory category; + private final FunctionRegistry functionRegistry; + private final String functions[]; + private final DefaultFormulaContext defaultContext; + private final Locale defaultLocale; + + public StarFunctionCategory( DefaultFormulaContext defaultContext,final XComponentContext context,final FunctionRegistry functionRegistry,final int _number,final FunctionCategory category ) + { + this.defaultContext = defaultContext; + m_xContext = context; + m_Number = _number; + this.category = category; + this.functionRegistry = functionRegistry; + Locale locale; + try + { + category.getDisplayName(defaultContext.getLocalizationContext().getLocale()); + locale = defaultContext.getLocalizationContext().getLocale(); + } + catch(MissingResourceException e) + { + locale = Locale.ENGLISH; + } + this.defaultLocale = locale; + + functions = functionRegistry.getFunctionNamesByCategory(category); + // use the last parameter of the PropertySetMixin constructor + // for your optional attributes if necessary. See the documentation + // of the PropertySetMixin helper for further information. + // Ensure that your attributes are initialized correctly! + m_prophlp = new PropertySetMixin(m_xContext, this, + new Type(com.sun.star.report.meta.XFunctionCategory.class), null); + }; + + // com.sun.star.beans.XPropertySet: + public com.sun.star.beans.XPropertySetInfo getPropertySetInfo() + { + return m_prophlp.getPropertySetInfo(); + } + + public void setPropertyValue(String aPropertyName, Object aValue) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.beans.PropertyVetoException, com.sun.star.lang.IllegalArgumentException,com.sun.star.lang.WrappedTargetException + { + m_prophlp.setPropertyValue(aPropertyName, aValue); + } + + public Object getPropertyValue(String aPropertyName) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + return m_prophlp.getPropertyValue(aPropertyName); + } + + public void addPropertyChangeListener(String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.addPropertyChangeListener(aPropertyName, xListener); + } + + public void removePropertyChangeListener(String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.removePropertyChangeListener(aPropertyName, xListener); + } + + public void addVetoableChangeListener(String aPropertyName, com.sun.star.beans.XVetoableChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.addVetoableChangeListener(aPropertyName, xListener); + } + + public void removeVetoableChangeListener(String aPropertyName, com.sun.star.beans.XVetoableChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.removeVetoableChangeListener(aPropertyName, xListener); + } + + // com.sun.star.container.XElementAccess: + public com.sun.star.uno.Type getElementType() + { + return new com.sun.star.uno.Type(XFunctionDescription.class); + } + + public boolean hasElements() + { + return functions.length != 0; + } + + // com.sun.star.container.XIndexAccess: + public int getCount() + { + return functions.length; + } + + public Object getByIndex(int Index) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException + { + return getFunction(Index); + } + + // com.sun.star.report.meta.XFunctionCategory: + public int getNumber() + { + return m_Number; + } + + public String getName() + { + return category.getDisplayName(defaultLocale); + } + + public com.sun.star.report.meta.XFunctionDescription getFunction(int position) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException + { + if ( position >= functions.length ) + throw new IndexOutOfBoundsException(); + return new StarFunctionDescription(defaultContext,m_xContext,this,functionRegistry,functionRegistry.getMetaData(functions[position])); + } + +} diff --git a/reportdesign/java/com/sun/star/report/pentaho/StarFunctionDescription.java b/reportdesign/java/com/sun/star/report/pentaho/StarFunctionDescription.java new file mode 100644 index 000000000000..7ffec217d017 --- /dev/null +++ b/reportdesign/java/com/sun/star/report/pentaho/StarFunctionDescription.java @@ -0,0 +1,191 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: StarFunctionDescription.java,v $ + * + * $Revision: 1.7 $ + * + * 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.uno.XComponentContext; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.uno.Type; +import com.sun.star.lib.uno.helper.PropertySetMixin; +import com.sun.star.report.meta.XFunctionCategory; +import com.sun.star.sheet.FunctionArgument; +import java.util.Locale; +import java.util.MissingResourceException; +import org.jfree.formula.DefaultFormulaContext; +import org.jfree.formula.function.FunctionDescription; +import org.jfree.formula.function.FunctionRegistry; + +public final class StarFunctionDescription extends WeakBase + implements com.sun.star.report.meta.XFunctionDescription +{ + + private final XComponentContext m_xContext; + private final PropertySetMixin m_prophlp; + // attributes +// final private com.sun.star.report.meta.XFunctionCategory m_Category; + private final FunctionDescription functionDescription; + private final FunctionRegistry functionRegistry; + private final XFunctionCategory category; + private final Locale defaultLocale; + + public StarFunctionDescription(final DefaultFormulaContext defaultContext, final XComponentContext context, final XFunctionCategory category, final FunctionRegistry functionRegistry, final FunctionDescription functionDescription) + { + m_xContext = context; + this.category = category; + Locale locale; + try + { + functionDescription.getDisplayName(defaultContext.getLocalizationContext().getLocale()); + locale = defaultContext.getLocalizationContext().getLocale(); + } catch ( MissingResourceException e ) + { + locale = Locale.ENGLISH; + } + this.defaultLocale = locale; + + this.functionDescription = functionDescription; + this.functionRegistry = functionRegistry; + // use the last parameter of the PropertySetMixin constructor + // for your optional attributes if necessary. See the documentation + // of the PropertySetMixin helper for further information. + // Ensure that your attributes are initialized correctly! + m_prophlp = new PropertySetMixin(m_xContext, this, + new Type(com.sun.star.report.meta.XFunctionDescription.class), null); + } + ; + + // com.sun.star.beans.XPropertySet: + public com.sun.star.beans.XPropertySetInfo getPropertySetInfo() + { + return m_prophlp.getPropertySetInfo(); + } + + public void setPropertyValue(String aPropertyName, Object aValue) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.beans.PropertyVetoException, com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.setPropertyValue(aPropertyName, aValue); + } + + public Object getPropertyValue(String aPropertyName) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + return m_prophlp.getPropertyValue(aPropertyName); + } + + public void addPropertyChangeListener(String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.addPropertyChangeListener(aPropertyName, xListener); + } + + public void removePropertyChangeListener(String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.removePropertyChangeListener(aPropertyName, xListener); + } + + public void addVetoableChangeListener(String aPropertyName, com.sun.star.beans.XVetoableChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.addVetoableChangeListener(aPropertyName, xListener); + } + + public void removeVetoableChangeListener(String aPropertyName, com.sun.star.beans.XVetoableChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException + { + m_prophlp.removeVetoableChangeListener(aPropertyName, xListener); + } + + // com.sun.star.report.meta.XFunctionDescription: + public com.sun.star.report.meta.XFunctionCategory getCategory() + { + return category; + } + + public String getName() + { + return functionDescription.getDisplayName(defaultLocale); + } + + public String getDescription() + { + return functionDescription.getDescription(defaultLocale); + } + + public String getSignature() + { + final int count = functionDescription.getParameterCount(); + final StringBuffer signature = new StringBuffer(getName()); + signature.append("("); + for (int i = 0; i < count; i++) + { + signature.append(functionDescription.getParameterDisplayName(i, defaultLocale)); + if ( i != (count - 1) ) + signature.append(";"); + } + signature.append(")"); + return signature.toString(); + } + + public com.sun.star.sheet.FunctionArgument[] getArguments() + { + int count = functionDescription.getParameterCount(); + final boolean infinite = functionDescription.isInfiniteParameterCount(); + if ( infinite ) + { + count = 30; + } + final FunctionArgument[] args = new FunctionArgument[count]; + for (int i = 0; i < args.length; i++) + { + final int pos = infinite ? 0 : i; + args[i] = new FunctionArgument(); + args[i].Description = functionDescription.getParameterDescription(pos, defaultLocale); + args[i].Name = functionDescription.getParameterDisplayName(pos, defaultLocale); + args[i].IsOptional = !functionDescription.isParameterMandatory(pos); + } + return args; + } + + public String createFormula(String[] arguments) throws com.sun.star.lang.DisposedException, com.sun.star.lang.IllegalArgumentException, com.sun.star.uno.Exception + { + final boolean infinite = functionDescription.isInfiniteParameterCount(); + final int count = functionDescription.getParameterCount(); + if ( !infinite && arguments.length > count ) + throw new com.sun.star.lang.IllegalArgumentException(); + + final StringBuffer formula = new StringBuffer(getName()); + formula.append("("); + for (int i = 0; i < arguments.length; ++i) + { + if ( arguments[i].length() == 0 ) + break; + formula.append(arguments[i]); + if ( i < (arguments.length - 1) && arguments[i+1].length() != 0 ) + formula.append(";"); + } + formula.append(")"); + return formula.toString(); + } +} diff --git a/reportdesign/java/com/sun/star/report/pentaho/layoutprocessor/VariablesDeclarationLayoutController.java b/reportdesign/java/com/sun/star/report/pentaho/layoutprocessor/VariablesDeclarationLayoutController.java index 94e39fc90499..c15e72ccf169 100644 --- a/reportdesign/java/com/sun/star/report/pentaho/layoutprocessor/VariablesDeclarationLayoutController.java +++ b/reportdesign/java/com/sun/star/report/pentaho/layoutprocessor/VariablesDeclarationLayoutController.java @@ -1,190 +1,190 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: VariablesDeclarationLayoutController.java,v $ - * $Revision: 1.5 $ - * - * 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.layoutprocessor; - -import com.sun.star.report.pentaho.OfficeNamespaces; -import com.sun.star.report.pentaho.model.FormattedTextElement; -import org.jfree.layouting.util.AttributeMap; -import org.jfree.report.DataSourceException; -import org.jfree.report.JFreeReportInfo; -import org.jfree.report.ReportDataFactoryException; -import org.jfree.report.ReportProcessingException; -import org.jfree.report.expressions.FormulaExpression; -import org.jfree.report.flow.FlowController; -import org.jfree.report.flow.ReportTarget; -import org.jfree.report.flow.layoutprocessor.AbstractLayoutController; -import org.jfree.report.flow.layoutprocessor.LayoutController; -import org.jfree.report.flow.layoutprocessor.LayoutControllerUtil; -import org.jfree.report.structure.Element; -import java.util.Date; -import java.text.SimpleDateFormat; - -/** - * Writes a full variables-declaration section. - * - * @author Thomas Morgner - * @since 20.03.2007 - */ -public class VariablesDeclarationLayoutController - extends AbstractLayoutController -{ - private boolean processed; - - public VariablesDeclarationLayoutController() - { - } - - private OfficeRepeatingStructureLayoutController getRepeatingParent() - { - LayoutController parent = getParent(); - while (parent != null) - { - if (parent instanceof OfficeRepeatingStructureLayoutController) - { - return (OfficeRepeatingStructureLayoutController) parent; - } - parent = parent.getParent(); - } - return null; - } - - /** - * Advances the processing position. - * - * @param target the report target that receives generated events. - * @return the new layout controller instance representing the new state. - * - * @throws org.jfree.report.DataSourceException - * if there was a problem reading data from the datasource. - * @throws org.jfree.report.ReportProcessingException - * if there was a general problem during the report processing. - * @throws org.jfree.report.ReportDataFactoryException - * if a query failed. - */ - public LayoutController advance(final ReportTarget target) - throws DataSourceException, ReportDataFactoryException, - ReportProcessingException - { - if (processed) - { - throw new IllegalStateException("Already processed."); - } - - final VariablesDeclarationLayoutController vlc = - (VariablesDeclarationLayoutController) clone(); - vlc.processed = true; - - final OfficeRepeatingStructureLayoutController orslc = getRepeatingParent(); - if (orslc == null) - { - // There is no repeating parent. What the heck are we doing here .. - return vlc; - } - - final VariablesCollection collection = orslc.getVariablesCollection(); - if (collection.getVariablesCount() == 0) - { - // no processing necessary, as the header or footer contain no variables at all .. - return vlc; - } - - - final Element node = (Element) getNode(); - final AttributeMap vdSection = node.getAttributeMap(); - target.startElement(vdSection); - - final FormattedTextElement[] variables = collection.getVariables(); - for (int i = 0; i < variables.length; i++) - { - final FormattedTextElement variable = variables[i]; - final String varName = collection.getNamePrefix() + (i + 1); - final AttributeMap map = generateVariableSetSection(variable); - map.setAttribute(OfficeNamespaces.TEXT_NS, "name", varName); - target.startElement(map); - target.endElement(map); - - } - target.endElement(vdSection); - return vlc; - } - - private AttributeMap generateVariableSetSection(final FormattedTextElement variable) - throws DataSourceException - { - final AttributeMap variableSection = new AttributeMap(); - variableSection.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.NAMESPACE_ATTRIBUTE, OfficeNamespaces.TEXT_NS); - variableSection.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.TYPE_ATTRIBUTE, "variable-set"); - variableSection.setAttribute(OfficeNamespaces.TEXT_NS, "display", "none"); - - final FormulaExpression valueExpression = variable.getValueExpression(); - final Object value = LayoutControllerUtil.evaluateExpression(getFlowController(), variable, valueExpression); - String formula = FormatValueUtility.applyValueForVariable(value, variableSection); - if ( formula == null ) - formula = "" + value; - if (value instanceof Date) - { - Date date = (Date)value; - final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy;MM;dd"); - formula = "Date(" + dateFormat.format(date) + ")"; - } - variableSection.setAttribute(OfficeNamespaces.TEXT_NS, "formula", "ooow:" + formula); - return variableSection; - } - - /** - * Checks, whether the layout controller would be advanceable. If this method - * returns true, it is generally safe to call the 'advance()' method. - * - * @return true, if the layout controller is advanceable, false otherwise. - */ - public boolean isAdvanceable() - { - return !processed; - } - - /** - * Joins with a delegated process flow. This is generally called from a child - * flow and should *not* (I mean it!) be called from outside. If you do, - * you'll suffer. - * - * @param flowController the flow controller of the parent. - * @return the joined layout controller that incorperates all changes from the - * delegate. - */ - public LayoutController join(final FlowController flowController) - throws DataSourceException, ReportDataFactoryException, - ReportProcessingException - { - throw new UnsupportedOperationException - ("Join is not supported in this layout controller"); - } -} +/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VariablesDeclarationLayoutController.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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.layoutprocessor;
+
+import com.sun.star.report.pentaho.OfficeNamespaces;
+import com.sun.star.report.pentaho.model.FormattedTextElement;
+import org.jfree.layouting.util.AttributeMap;
+import org.jfree.report.DataSourceException;
+import org.jfree.report.JFreeReportInfo;
+import org.jfree.report.ReportDataFactoryException;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.expressions.FormulaExpression;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.AbstractLayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutControllerUtil;
+import org.jfree.report.structure.Element;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+
+/**
+ * Writes a full variables-declaration section.
+ *
+ * @author Thomas Morgner
+ * @since 20.03.2007
+ */
+public class VariablesDeclarationLayoutController
+ extends AbstractLayoutController
+{
+ private boolean processed;
+
+ public VariablesDeclarationLayoutController()
+ {
+ }
+
+ private OfficeRepeatingStructureLayoutController getRepeatingParent()
+ {
+ LayoutController parent = getParent();
+ while (parent != null)
+ {
+ if (parent instanceof OfficeRepeatingStructureLayoutController)
+ {
+ return (OfficeRepeatingStructureLayoutController) parent;
+ }
+ parent = parent.getParent();
+ }
+ return null;
+ }
+
+ /**
+ * Advances the processing position.
+ *
+ * @param target the report target that receives generated events.
+ * @return the new layout controller instance representing the new state.
+ *
+ * @throws org.jfree.report.DataSourceException
+ * if there was a problem reading data from the datasource.
+ * @throws org.jfree.report.ReportProcessingException
+ * if there was a general problem during the report processing.
+ * @throws org.jfree.report.ReportDataFactoryException
+ * if a query failed.
+ */
+ public LayoutController advance(final ReportTarget target)
+ throws DataSourceException, ReportDataFactoryException,
+ ReportProcessingException
+ {
+ if (processed)
+ {
+ throw new IllegalStateException("Already processed.");
+ }
+
+ final VariablesDeclarationLayoutController vlc =
+ (VariablesDeclarationLayoutController) clone();
+ vlc.processed = true;
+
+ final OfficeRepeatingStructureLayoutController orslc = getRepeatingParent();
+ if (orslc == null)
+ {
+ // There is no repeating parent. What the heck are we doing here ..
+ return vlc;
+ }
+
+ final VariablesCollection collection = orslc.getVariablesCollection();
+ if (collection.getVariablesCount() == 0)
+ {
+ // no processing necessary, as the header or footer contain no variables at all ..
+ return vlc;
+ }
+
+
+ final Element node = (Element) getNode();
+ final AttributeMap vdSection = node.getAttributeMap();
+ target.startElement(vdSection);
+
+ final FormattedTextElement[] variables = collection.getVariables();
+ for (int i = 0; i < variables.length; i++)
+ {
+ final FormattedTextElement variable = variables[i];
+ final String varName = collection.getNamePrefix() + (i + 1);
+ final AttributeMap map = generateVariableSetSection(variable);
+ map.setAttribute(OfficeNamespaces.TEXT_NS, "name", varName);
+ target.startElement(map);
+ target.endElement(map);
+
+ }
+ target.endElement(vdSection);
+ return vlc;
+ }
+
+ private AttributeMap generateVariableSetSection(final FormattedTextElement variable)
+ throws DataSourceException
+ {
+ final AttributeMap variableSection = new AttributeMap();
+ variableSection.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.NAMESPACE_ATTRIBUTE, OfficeNamespaces.TEXT_NS);
+ variableSection.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.TYPE_ATTRIBUTE, "variable-set");
+ variableSection.setAttribute(OfficeNamespaces.TEXT_NS, "display", "none");
+
+ final FormulaExpression valueExpression = variable.getValueExpression();
+ final Object value = LayoutControllerUtil.evaluateExpression(getFlowController(), variable, valueExpression);
+ String formula = FormatValueUtility.applyValueForVariable(value, variableSection);
+ if ( formula == null )
+ formula = "" + value;
+ if (value instanceof Date)
+ {
+ final Date date = (Date)value;
+ final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy;MM;dd");
+ formula = "Date(" + dateFormat.format(date) + ")";
+ }
+ variableSection.setAttribute(OfficeNamespaces.TEXT_NS, "formula", "ooow:" + formula);
+ return variableSection;
+ }
+
+ /**
+ * Checks, whether the layout controller would be advanceable. If this method
+ * returns true, it is generally safe to call the 'advance()' method.
+ *
+ * @return true, if the layout controller is advanceable, false otherwise.
+ */
+ public boolean isAdvanceable()
+ {
+ return !processed;
+ }
+
+ /**
+ * Joins with a delegated process flow. This is generally called from a child
+ * flow and should *not* (I mean it!) be called from outside. If you do,
+ * you'll suffer.
+ *
+ * @param flowController the flow controller of the parent.
+ * @return the joined layout controller that incorperates all changes from the
+ * delegate.
+ */
+ public LayoutController join(final FlowController flowController)
+ throws DataSourceException, ReportDataFactoryException,
+ ReportProcessingException
+ {
+ throw new UnsupportedOperationException
+ ("Join is not supported in this layout controller");
+ }
+}
diff --git a/reportdesign/java/com/sun/star/report/pentaho/output/spreadsheet/SpreadsheetRawReportProcessor.java b/reportdesign/java/com/sun/star/report/pentaho/output/spreadsheet/SpreadsheetRawReportProcessor.java index 5f3530a2b3a7..8da7088e304e 100644 --- a/reportdesign/java/com/sun/star/report/pentaho/output/spreadsheet/SpreadsheetRawReportProcessor.java +++ b/reportdesign/java/com/sun/star/report/pentaho/output/spreadsheet/SpreadsheetRawReportProcessor.java @@ -1,122 +1,122 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: SpreadsheetRawReportProcessor.java,v $ - * $Revision: 1.7 $ - * - * 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.output.spreadsheet; - -import com.sun.star.report.DataSourceFactory; -import org.jfree.report.DataSourceException; -import org.jfree.report.ReportDataFactoryException; -import org.jfree.report.ReportProcessingException; -import org.jfree.report.flow.AbstractReportProcessor; -import org.jfree.report.flow.ReportJob; -import org.jfree.report.flow.ReportStructureRoot; -import org.jfree.report.flow.ReportTarget; -import org.jfree.resourceloader.ResourceManager; -import com.sun.star.report.OutputRepository; -import com.sun.star.report.InputRepository; -import com.sun.star.report.ImageService; -import com.sun.star.report.pentaho.PentahoFormulaContext; -import org.jfree.report.data.ReportContextImpl; -import org.jfree.report.flow.ReportContext; - -/** - * @author Michael D'Amour - */ -public class SpreadsheetRawReportProcessor extends AbstractReportProcessor -{ - - private final OutputRepository outputRepository; - private final String targetName; - private final InputRepository inputRepository; - private final ImageService imageService; - private final DataSourceFactory dataSourceFactory; - - public SpreadsheetRawReportProcessor(final InputRepository inputRepository, - final OutputRepository outputRepository, - final String targetName, - final ImageService imageService, - final DataSourceFactory dataSourceFactory) - { - if (outputRepository == null) - { - throw new NullPointerException(); - } - if (targetName == null) - { - throw new NullPointerException(); - } - if (imageService == null) - { - throw new NullPointerException(); - } - if (inputRepository == null) - { - throw new NullPointerException(); - } - if (dataSourceFactory == null) - { - throw new NullPointerException(); - } - - this.targetName = targetName; - this.inputRepository = inputRepository; - this.outputRepository = outputRepository; - this.imageService = imageService; - this.dataSourceFactory = dataSourceFactory; - } - - protected ReportTarget createReportTarget(final ReportJob job) throws ReportProcessingException - { - final ReportStructureRoot report = job.getReportStructureRoot(); - final ResourceManager resourceManager = report.getResourceManager(); - return new SpreadsheetRawReportTarget(job, resourceManager, report.getBaseResource(), inputRepository, outputRepository, targetName, imageService, dataSourceFactory); - } - - public void processReport(final ReportJob job) throws ReportDataFactoryException, DataSourceException, - ReportProcessingException - { - final ReportTarget reportTarget = createReportTarget(job); - // first run: collect table cell sizes for all tables - processReportRun(job, reportTarget); - // second run: uses table cell data to output a single uniform table - processReportRun(job, reportTarget); - } - - protected ReportContext createReportContext(final ReportJob job, - final ReportTarget target) - { - final ReportContext context = super.createReportContext(job, target); - if (context instanceof ReportContextImpl) - { - ReportContextImpl impl = (ReportContextImpl) context; - impl.setFormulaContext(new PentahoFormulaContext(impl.getFormulaContext(),job.getConfiguration())); - } - return context; - } -} +/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SpreadsheetRawReportProcessor.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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.output.spreadsheet;
+
+import com.sun.star.report.DataSourceFactory;
+import org.jfree.report.DataSourceException;
+import org.jfree.report.ReportDataFactoryException;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.flow.AbstractReportProcessor;
+import org.jfree.report.flow.ReportJob;
+import org.jfree.report.flow.ReportStructureRoot;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.resourceloader.ResourceManager;
+import com.sun.star.report.OutputRepository;
+import com.sun.star.report.InputRepository;
+import com.sun.star.report.ImageService;
+import com.sun.star.report.pentaho.PentahoFormulaContext;
+import org.jfree.report.data.ReportContextImpl;
+import org.jfree.report.flow.ReportContext;
+
+/**
+ * @author Michael D'Amour
+ */
+public class SpreadsheetRawReportProcessor extends AbstractReportProcessor
+{
+
+ private final OutputRepository outputRepository;
+ private final String targetName;
+ private final InputRepository inputRepository;
+ private final ImageService imageService;
+ private final DataSourceFactory dataSourceFactory;
+
+ public SpreadsheetRawReportProcessor(final InputRepository inputRepository,
+ final OutputRepository outputRepository,
+ final String targetName,
+ final ImageService imageService,
+ final DataSourceFactory dataSourceFactory)
+ {
+ if (outputRepository == null)
+ {
+ throw new NullPointerException();
+ }
+ if (targetName == null)
+ {
+ throw new NullPointerException();
+ }
+ if (imageService == null)
+ {
+ throw new NullPointerException();
+ }
+ if (inputRepository == null)
+ {
+ throw new NullPointerException();
+ }
+ if (dataSourceFactory == null)
+ {
+ throw new NullPointerException();
+ }
+
+ this.targetName = targetName;
+ this.inputRepository = inputRepository;
+ this.outputRepository = outputRepository;
+ this.imageService = imageService;
+ this.dataSourceFactory = dataSourceFactory;
+ }
+
+ protected ReportTarget createReportTarget(final ReportJob job) throws ReportProcessingException
+ {
+ final ReportStructureRoot report = job.getReportStructureRoot();
+ final ResourceManager resourceManager = report.getResourceManager();
+ return new SpreadsheetRawReportTarget(job, resourceManager, report.getBaseResource(), inputRepository, outputRepository, targetName, imageService, dataSourceFactory);
+ }
+
+ public void processReport(final ReportJob job) throws ReportDataFactoryException, DataSourceException,
+ ReportProcessingException
+ {
+ final ReportTarget reportTarget = createReportTarget(job);
+ // first run: collect table cell sizes for all tables
+ processReportRun(job, reportTarget);
+ // second run: uses table cell data to output a single uniform table
+ processReportRun(job, reportTarget);
+ }
+
+ protected ReportContext createReportContext(final ReportJob job,
+ final ReportTarget target)
+ {
+ final ReportContext context = super.createReportContext(job, target);
+ if (context instanceof ReportContextImpl)
+ {
+ final ReportContextImpl impl = (ReportContextImpl) context;
+ impl.setFormulaContext(new PentahoFormulaContext(impl.getFormulaContext(),job.getConfiguration()));
+ }
+ return context;
+ }
+}
diff --git a/reportdesign/java/com/sun/star/report/pentaho/output/spreadsheet/SpreadsheetRawReportTarget.java b/reportdesign/java/com/sun/star/report/pentaho/output/spreadsheet/SpreadsheetRawReportTarget.java index 3904208a36ba..e0122ed994e4 100644 --- a/reportdesign/java/com/sun/star/report/pentaho/output/spreadsheet/SpreadsheetRawReportTarget.java +++ b/reportdesign/java/com/sun/star/report/pentaho/output/spreadsheet/SpreadsheetRawReportTarget.java @@ -1,942 +1,942 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: SpreadsheetRawReportTarget.java,v $ - * $Revision: 1.8 $ - * - * 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.output.spreadsheet; - -import com.sun.star.report.DataSourceFactory; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; - -import com.sun.star.report.InputRepository; -import com.sun.star.report.OutputRepository; -import com.sun.star.report.ImageService; -import com.sun.star.report.pentaho.OfficeNamespaces; -import com.sun.star.report.OfficeToken; -import com.sun.star.report.pentaho.PentahoReportEngineMetaData; -import com.sun.star.report.pentaho.model.OfficeStyle; -import com.sun.star.report.pentaho.model.OfficeStyles; -import com.sun.star.report.pentaho.model.OfficeStylesCollection; -import com.sun.star.report.pentaho.model.OfficeMasterPage; -import com.sun.star.report.pentaho.model.OfficeMasterStyles; -import com.sun.star.report.pentaho.model.PageSection; -import com.sun.star.report.pentaho.output.OfficeDocumentReportTarget; -import com.sun.star.report.pentaho.output.StyleUtilities; -import com.sun.star.report.pentaho.output.text.MasterPageFactory; -import com.sun.star.report.pentaho.styles.LengthCalculator; -import java.util.Set; -import org.jfree.layouting.util.AttributeMap; -import org.jfree.layouting.input.style.values.CSSNumericValue; -import org.jfree.layouting.input.style.values.CSSNumericType; -import org.jfree.report.DataFlags; -import org.jfree.report.DataSourceException; -import org.jfree.report.ReportProcessingException; -import org.jfree.report.JFreeReportInfo; -import org.jfree.report.flow.ReportJob; -import org.jfree.report.flow.ReportStructureRoot; -import org.jfree.report.flow.ReportTargetUtil; -import org.jfree.report.structure.Element; -import org.jfree.report.structure.Section; -import org.jfree.report.util.IntegerCache; -import org.jfree.report.util.TextUtilities; -import org.jfree.resourceloader.ResourceKey; -import org.jfree.resourceloader.ResourceManager; -import org.jfree.util.Log; -import org.jfree.xmlns.common.AttributeList; -import org.jfree.xmlns.writer.XmlWriter; -import org.jfree.xmlns.writer.XmlWriterSupport; - -/** - * Creation-Date: 03.11.2007 - * - * @author Michael D'Amour - */ -public class SpreadsheetRawReportTarget extends OfficeDocumentReportTarget -{ - - private boolean paragraphFound = false; - private boolean paragraphHandled = false; - - /** - * This class represents a column boundary, not in width, but it's actual boundary location. One of the motivations - * for creating this class was to be able to record the boundaries for each incoming table while consuming as few - * objects/memory as possible. - */ - private static class ColumnBoundary implements Comparable - { - - private final Set tableIndices; - private final float boundary; - - private ColumnBoundary(final float boundary) - { - this.tableIndices = new HashSet(); - this.boundary = boundary; - } - - public void addTableIndex(final int table) - { - tableIndices.add(IntegerCache.getInteger(table)); - } - - public float getBoundary() - { - return boundary; - } - - public boolean isContainedByTable(final int table) - { - final Integer index = IntegerCache.getInteger(table); - return tableIndices.contains(index); - } - - public int compareTo(final Object arg0) - { - if (arg0.equals(this)) - { - return 0; - } - if (arg0 instanceof ColumnBoundary) - { - if (boundary > ((ColumnBoundary) arg0).boundary) - { - return 1; - } - else - { - return -1; - } - } - return 1; - } - - public boolean equals(final Object obj) - { - if (obj instanceof ColumnBoundary) - { - return ((ColumnBoundary) obj).boundary == boundary; - } - return false; - } - } - private String tableBackgroundColor; // null means transparent ... - private static final ColumnBoundary[] EMPTY_COLBOUNDS = new ColumnBoundary[0]; - private boolean elementBoundaryCollectionPass; - private boolean oleHandled; - private final List columnBoundaryList; - private float currentRowBoundaryMarker; - private ColumnBoundary[] sortedBoundaryArray; - private ColumnBoundary[] boundariesForTableArray; - private int tableCounter; - private int columnCounter; - private int columnSpanCounter; - private String unitsOfMeasure; - private ArrayList shapes; - private ArrayList ole; - private ArrayList rowHeights; - - public SpreadsheetRawReportTarget(final ReportJob reportJob, - final ResourceManager resourceManager, - final ResourceKey baseResource, - final InputRepository inputRepository, - final OutputRepository outputRepository, - final String target, - final ImageService imageService, - final DataSourceFactory dataSourceFactory) - throws ReportProcessingException - { - super(reportJob, resourceManager, baseResource, inputRepository, outputRepository, target, imageService, dataSourceFactory); - columnBoundaryList = new ArrayList(); - elementBoundaryCollectionPass = true; - rowHeights = new ArrayList(); - shapes = new ArrayList(); - ole = new ArrayList(); - oleHandled = false; - } - - public void startOther(final AttributeMap attrs) throws DataSourceException, ReportProcessingException - { - if (ReportTargetUtil.isElementOfType(OfficeNamespaces.INTERNAL_NS, OfficeToken.OBJECT_OLE, attrs)) - { - if (isElementBoundaryCollectionPass() && getCurrentRole() != ROLE_TEMPLATE) - { - ole.add(attrs); - } - oleHandled = true; - return; - } - final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs); - if (isRepeatingSection() || isFilteredNamespace(namespace)) - { - return; - } - - final String elementType = ReportTargetUtil.getElemenTypeFromAttribute(attrs); - if (OfficeNamespaces.TEXT_NS.equals(namespace) && OfficeToken.P.equals(elementType) && !paragraphHandled) - { - paragraphFound = true; - return; - } - - if (OfficeNamespaces.DRAWING_NS.equals(namespace) && OfficeToken.FRAME.equals(elementType)) - { - if (isElementBoundaryCollectionPass() && getCurrentRole() != ROLE_TEMPLATE) - { - final LengthCalculator len = new LengthCalculator(); - for (int i = 0; i < rowHeights.size(); i++) - { - len.add((CSSNumericValue) rowHeights.get(i)); - // val += ((CSSNumericValue)rowHeights.get(i)).getValue(); - } - - rowHeights.clear(); - final CSSNumericValue currentRowHeight = len.getResult(); - rowHeights.add(currentRowHeight); - attrs.setAttribute(OfficeNamespaces.DRAWING_NS, "z-index", String.valueOf(shapes.size())); - final String y = (String) attrs.getAttribute(OfficeNamespaces.SVG_NS, "y"); - if (y != null) - { - len.add(parseLength(y)); - final CSSNumericValue currentY = len.getResult(); - attrs.setAttribute(OfficeNamespaces.SVG_NS, "y", currentY.getValue() + currentY.getType().getType()); - } - shapes.add(attrs); - } - return; - } - if (oleHandled) - { - if (isElementBoundaryCollectionPass() && getCurrentRole() != ROLE_TEMPLATE) - { - ole.add(attrs); - } - return; - } - - // if this is the report namespace, write out a table definition .. - if (OfficeNamespaces.TABLE_NS.equals(namespace) && OfficeToken.TABLE.equals(elementType)) - { - // whenever we see a new table, we increment our tableCounter - // this is used to keep tracked of the boundary conditions per table - tableCounter++; - } - - if (isElementBoundaryCollectionPass()) - { - collectBoundaryForElement(attrs); - } - else - // if (!isElementBoundaryCollectionPass()) - { - try - { - processElement(attrs, namespace, elementType); - } - catch (IOException e) - { - throw new ReportProcessingException("Failed", e); - } - } - } - - protected void startReportSection(final AttributeMap attrs, final int role) throws IOException, DataSourceException, ReportProcessingException - { - if ((role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_HEADER || - role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_FOOTER) && - (!PageSection.isPrintWithReportHeader(attrs) || - !PageSection.isPrintWithReportFooter(attrs))) - { - startBuffering(new OfficeStylesCollection(), true); - - } - else - { - super.startReportSection(attrs, role); - } - } - - protected void endReportSection(final AttributeMap attrs, final int role) throws IOException, DataSourceException, ReportProcessingException - { - if ((role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_HEADER || - role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_FOOTER) && - (!PageSection.isPrintWithReportHeader(attrs) || - !PageSection.isPrintWithReportFooter(attrs))) - { - finishBuffering(); - } - else - { - super.endReportSection(attrs, role); - } - } - - private void handleParagraph() - { - if (paragraphFound) - { - try - { - final XmlWriter xmlWriter = getXmlWriter(); - xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, null, XmlWriterSupport.OPEN); - paragraphHandled = true; - paragraphFound = false; - } - catch (IOException ex) - { - Log.error("ReportProcessing failed", ex); - } - } - } - - private void processElement(final AttributeMap attrs, final String namespace, final String elementType) - throws IOException, ReportProcessingException - { - final XmlWriter xmlWriter = getXmlWriter(); - - if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE, attrs)) - { - // a new table means we must clear our "calculated" table boundary array cache - boundariesForTableArray = null; - - final String tableStyle = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME); - if (tableStyle == null) - { - tableBackgroundColor = null; - } - else - { - final Object raw = StyleUtilities.queryStyle(getPredefinedStylesCollection(), OfficeToken.TABLE, tableStyle, - "table-properties", OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR); - if (raw == null || "transparent".equals(raw)) - { - tableBackgroundColor = null; - } - else - { - tableBackgroundColor = String.valueOf(raw); - } - } - return; - } - - if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMN, attrs) || - ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMNS, attrs)) - { - return; - } - - // covered-table-cell elements may appear in the input from row or column spans. In the event that we hit a - // column-span we simply ignore these elements because we are going to adjust the span to fit the uniform table. - if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.COVERED_TABLE_CELL, attrs)) - { - if (columnSpanCounter > 0) - { - columnSpanCounter--; - } - - if (columnSpanCounter == 0) - { - // if we weren't expecting a covered-table-cell, let's use it, it's probably from a row-span - columnCounter++; - final int span = getColumnSpanForCell(tableCounter, columnCounter, 1); - // use the calculated span for the column in the uniform table to create any additional covered-table-cell - // elements - for (int i = 0; i < span; i++) - { - xmlWriter.writeTag(namespace, OfficeToken.COVERED_TABLE_CELL, null, XmlWriter.CLOSE); - } - } - return; - } - - if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_ROW, attrs)) - { - // a new row means our column counter gets reset - columnCounter = 0; - // Lets make sure the color of the table is ok .. - if (tableBackgroundColor != null) - { - final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME); - final OfficeStyle style = deriveStyle(OfficeToken.TABLE_ROW, styleName); - Element tableRowProperties = style.getTableRowProperties(); - if (tableRowProperties == null) - { - tableRowProperties = new Section(); - tableRowProperties.setNamespace(OfficeNamespaces.STYLE_NS); - tableRowProperties.setType("table-row-properties"); - tableRowProperties.setAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR, tableBackgroundColor); - style.addNode(tableRowProperties); - } - else - { - final Object oldValue = tableRowProperties.getAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR); - if (oldValue == null || "transparent".equals(oldValue)) - { - tableRowProperties.setAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR, tableBackgroundColor); - } - } - attrs.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, style.getStyleName()); - } - } - else if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_CELL, attrs)) - { - columnCounter++; - final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME); - if (styleName != null) - { - OfficeStyle cellStyle = getPredefinedStylesCollection().getStyle(OfficeToken.TABLE_CELL, styleName); - if (cellStyle != null) - { - final Element props = cellStyle.getTableCellProperties(); - if (props != null) - { - final Object raw = props.getAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR); - if (raw == null || "transparent".equals(raw)) - { - cellStyle.removeNode(props); - } - } - } - } - - final String numColSpanStr = (String) attrs.getAttribute(namespace, "number-columns-spanned"); - int initialColumnSpan = columnSpanCounter = 1; - if (numColSpanStr != null) - { - initialColumnSpan = Integer.parseInt(numColSpanStr); - columnSpanCounter = initialColumnSpan; - } - final int span = getColumnSpanForCell(tableCounter, columnCounter, initialColumnSpan); - if (initialColumnSpan > 1) - { - // add the initial column span to our column counter index (subtract 1, since it is counted by default) - columnCounter += initialColumnSpan - 1; - } - - // if (span < initialColumnSpan) - // { - // // ColumnBoundary cbs[] = getBoundariesForTable(tableCounter); - // // for (int i = 0; i < cbs.length; i++) - // // { - // // System.out.print(cbs[i].getBoundary() + " "); - // // } - // // System.out.println(); - // - // Log.error("A cell cannot span less than the declared columns: Declared=" + initialColumnSpan + " Computed=" - // + span); - // } - - // there's no point to create number-columns-spanned attributes if we only span 1 column - if (span > 1) - { - attrs.setAttribute(namespace, "number-columns-spanned", "" + span); - } - // we must also generate "covered-table-cell" elements for each column spanned - // but we'll do this in the endElement, after we close this OfficeToken.TABLE_CELL - } - - // All styles have to be processed or you will loose the paragraph-styles and inline text-styles. - // .. - performStyleProcessing(attrs); - - final AttributeList attrList = buildAttributeList(attrs); - xmlWriter.writeTag(namespace, elementType, attrList, XmlWriter.OPEN); - // System.out.println("elementType = " + elementType); - } - - private void collectBoundaryForElement(final AttributeMap attrs) - { - if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMNS, attrs)) - { - // A table row resets the column counter. - resetCurrentRowBoundaryMarker(); - } - else if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMN, attrs)) - { - final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME); - if (styleName == null) - { - // This should not happen, but if it does, we will ignore that cell. - return; - } - - final OfficeStyle style = getPredefinedStylesCollection().getStyle(OfficeToken.TABLE_COLUMN, styleName); - if (style == null) - { - // Now this is very bad. It means that there is no style defined with the given name. - return; - } - - final Element tableColumnProperties = style.getTableColumnProperties(); - String widthStr = (String) tableColumnProperties.getAttribute("column-width"); - widthStr = widthStr.substring(0, widthStr.indexOf(getUnitsOfMeasure(widthStr))); - addColumnWidthToRowBoundaryMarker(Float.parseFloat(widthStr)); - ColumnBoundary currentRowBoundary = new ColumnBoundary(getCurrentRowBoundaryMarker()); - final List columnBoundaryList_ = getColumnBoundaryList(); - final int idx = columnBoundaryList_.indexOf(currentRowBoundary); - if (idx == -1) - { - columnBoundaryList_.add(currentRowBoundary); - } - else - { - currentRowBoundary = (ColumnBoundary) columnBoundaryList_.get(idx); - } - currentRowBoundary.addTableIndex(tableCounter); - } - } - - private String getUnitsOfMeasure(final String str) - { - if (unitsOfMeasure == null || "".equals(unitsOfMeasure)) - { - if (str == null || "".equals(str)) - { - unitsOfMeasure = "cm"; - return unitsOfMeasure; - } - - // build units of measure, set it - int i = str.length() - 1; - for (; i >= 0; i--) - { - final char c = str.charAt(i); - if (Character.isDigit(c) || c == '.' || c == ',') - { - break; - } - } - unitsOfMeasure = str.substring(i + 1); - } - return unitsOfMeasure; - } - - private void createTableShapes() throws ReportProcessingException - { - if (!shapes.isEmpty()) - { - try - { - final XmlWriter xmlWriter = getXmlWriter(); - // at this point we need to generate the table-columns section based on our boundary table - // <table:shapes> - // <draw:frame /> - // .. - // </table:shapes> - xmlWriter.writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.SHAPES, null, XmlWriterSupport.OPEN); - - - for (int i = 0; i < shapes.size(); i++) - { - final AttributeMap attrs = (AttributeMap) shapes.get(i); - final AttributeList attrList = buildAttributeList(attrs); - attrList.removeAttribute(OfficeNamespaces.DRAWING_NS, OfficeToken.STYLE_NAME); - xmlWriter.writeTag(OfficeNamespaces.DRAWING_NS, OfficeToken.FRAME, attrList, XmlWriterSupport.OPEN); - startChartProcessing((AttributeMap) ole.get(i)); - - xmlWriter.writeCloseTag(); - } - xmlWriter.writeCloseTag(); - } - catch (IOException e) - { - throw new ReportProcessingException("Failed", e); - } - } - } - - private void createTableColumns() throws ReportProcessingException - { - try - { - final XmlWriter xmlWriter = getXmlWriter(); - // at this point we need to generate the table-columns section based on our boundary table - // <table-columns> - // <table-column style-name="coX"/> - // .. - // </table-columns> - // the first boundary is '0' which is a placeholder so we will ignore it - xmlWriter.writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMNS, null, XmlWriterSupport.OPEN); - - // blow away current column styles - // start processing at i=1 because we added a boundary for "0" which is virtual - final ColumnBoundary[] cba = getSortedColumnBoundaryArray(); - for (int i = 1; i < cba.length; i++) - { - final ColumnBoundary cb = cba[i]; - float columnWidth = cb.getBoundary(); - if (i > 1) - { - columnWidth -= cba[i - 1].getBoundary(); - } - final OfficeStyle style = deriveStyle(OfficeToken.TABLE_COLUMN, ("co" + i + "_")); - final Section tableColumnProperties = new Section(); - tableColumnProperties.setType("table-column-properties"); - tableColumnProperties.setNamespace(style.getNamespace()); - tableColumnProperties.setAttribute(style.getNamespace(), "column-width", columnWidth + getUnitsOfMeasure(null)); - style.addNode(tableColumnProperties); - - final AttributeList myAttrList = new AttributeList(); - myAttrList.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, style.getStyleName()); - xmlWriter.writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMN, myAttrList, XmlWriterSupport.CLOSE); - } - xmlWriter.writeCloseTag(); - } - catch (IOException e) - { - throw new ReportProcessingException("Failed", e); - } - } - - protected void endOther(final AttributeMap attrs) throws DataSourceException, ReportProcessingException - { - if (ReportTargetUtil.isElementOfType(OfficeNamespaces.INTERNAL_NS, OfficeToken.OBJECT_OLE, attrs) || oleHandled) - { - oleHandled = false; - return; - } - - if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_ROW, attrs) && isElementBoundaryCollectionPass() && getCurrentRole() != ROLE_TEMPLATE) - { - final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME); - rowHeights.add(computeRowHeight(styleName)); - } - - if (isRepeatingSection() || isElementBoundaryCollectionPass()) - { - return; - } - - final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs); - if (isFilteredNamespace(namespace)) - { - return; - } - final String elementType = ReportTargetUtil.getElemenTypeFromAttribute(attrs); - if (OfficeNamespaces.DRAWING_NS.equals(namespace) && OfficeToken.FRAME.equals(elementType)) - { - return; - } - - // if this is the report namespace, write out a table definition .. - if (OfficeNamespaces.TABLE_NS.equals(namespace) && (OfficeToken.TABLE.equals(elementType) || - OfficeToken.COVERED_TABLE_CELL.equals(elementType) || - OfficeToken.TABLE_COLUMN.equals(elementType) || - OfficeToken.TABLE_COLUMNS.equals(elementType))) - { - return; - } - - if ( !paragraphHandled && OfficeNamespaces.TEXT_NS.equals(namespace) && OfficeToken.P.equals(elementType)) - { - if (!paragraphHandled) - { - return; - } - - paragraphHandled = false; - } - try - { - final XmlWriter xmlWriter = getXmlWriter(); - xmlWriter.writeCloseTag(); - // table-cell elements may have a number-columns-spanned attribute which indicates how many - // 'covered-table-cell' elements we need to generate - generateCoveredTableCells(attrs); - } - catch (IOException e) - { - throw new ReportProcessingException("Failed", e); - } - } - - private void generateCoveredTableCells(final AttributeMap attrs) throws IOException - { - if (!ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_CELL, attrs)) - { - return; - } - - // do this after we close the tag - final XmlWriter xmlWriter = getXmlWriter(); - final Object attribute = attrs.getAttribute(OfficeNamespaces.TABLE_NS, "number-columns-spanned"); - final int span = TextUtilities.parseInt((String) attribute, 0); - for (int i = 1; i < span; i++) - { - xmlWriter.writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.COVERED_TABLE_CELL, null, XmlWriter.CLOSE); - } - } - - public String getExportDescriptor() - { - return "raw/" + PentahoReportEngineMetaData.OPENDOCUMENT_SPREADSHEET; - } - - // ///////////////////////////////////////////////////////////////////////// - public void processText(final String text) throws DataSourceException, ReportProcessingException - { - if (!(isRepeatingSection() || isElementBoundaryCollectionPass())) - { - handleParagraph(); - super.processText(text); - } - } - - public void processContent(final DataFlags value) throws DataSourceException, ReportProcessingException - { - if (!(isRepeatingSection() || isElementBoundaryCollectionPass())) - { - handleParagraph(); - super.processContent(value); - } - } - - protected String getStartContent() - { - return "spreadsheet"; - } - - protected void startContent(final AttributeMap attrs) throws IOException, DataSourceException, - ReportProcessingException - { - if (!isElementBoundaryCollectionPass()) - { - final XmlWriter xmlWriter = getXmlWriter(); - xmlWriter.writeTag(OfficeNamespaces.OFFICE_NS, getStartContent(), null, XmlWriterSupport.OPEN); - - final AttributeMap tableAttributes = new AttributeMap(); - tableAttributes.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.NAMESPACE_ATTRIBUTE, OfficeNamespaces.TABLE_NS); - tableAttributes.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.TYPE_ATTRIBUTE, OfficeToken.TABLE); - tableAttributes.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, generateInitialTableStyle()); - tableAttributes.setAttribute(OfficeNamespaces.TABLE_NS, "name", "Report"); - - performStyleProcessing(tableAttributes); - - xmlWriter.writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE, buildAttributeList(tableAttributes), XmlWriterSupport.OPEN); - createTableShapes(); - createTableColumns(); - } - } - - private String generateInitialTableStyle() throws ReportProcessingException - { - final OfficeStylesCollection predefStyles = getPredefinedStylesCollection(); - final OfficeStyles commonStyles = predefStyles.getAutomaticStyles(); - if (!commonStyles.containsStyle(OfficeToken.TABLE, "Initial_Table")) - { - final String masterPageName = createMasterPage(); - - final OfficeStyle tableStyle = new OfficeStyle(); - tableStyle.setStyleFamily(OfficeToken.TABLE); - tableStyle.setStyleName("Initial_Table"); - tableStyle.setAttribute(OfficeNamespaces.STYLE_NS, "master-page-name", masterPageName); - final Element tableProperties = produceFirstChild(tableStyle, OfficeNamespaces.STYLE_NS, "table-properties"); - tableProperties.setAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR, "transparent"); - commonStyles.addStyle(tableStyle); - } - return "Initial_Table"; - } - - private String createMasterPage() throws ReportProcessingException - { - final OfficeStylesCollection predefStyles = getPredefinedStylesCollection(); - final MasterPageFactory masterPageFactory = new MasterPageFactory(predefStyles.getMasterStyles()); - final OfficeMasterPage masterPage; - if (!masterPageFactory.containsMasterPage("Standard", null, null)) - { - masterPage = masterPageFactory.createMasterPage("Standard", null, null); - - final CSSNumericValue zeroLength = CSSNumericValue.createValue(CSSNumericType.CM, 0); - final String pageLayoutTemplate = masterPage.getPageLayout(); - if (pageLayoutTemplate == null) - { - // there is no pagelayout. Create one .. - final String derivedLayout = masterPageFactory.createPageStyle(getGlobalStylesCollection().getAutomaticStyles(), zeroLength, zeroLength); - masterPage.setPageLayout(derivedLayout); - } - else - { - final String derivedLayout = masterPageFactory.derivePageStyle(pageLayoutTemplate, - getPredefinedStylesCollection().getAutomaticStyles(), - getGlobalStylesCollection().getAutomaticStyles(), zeroLength, zeroLength); - masterPage.setPageLayout(derivedLayout); - } - - final OfficeStylesCollection officeStylesCollection = getGlobalStylesCollection(); - final OfficeMasterStyles officeMasterStyles = officeStylesCollection.getMasterStyles(); - officeMasterStyles.addMasterPage(masterPage); - } - else - { - masterPage = masterPageFactory.getMasterPage("Standard", null, null); - } - return masterPage.getStyleName(); - } - - protected void endContent(final AttributeMap attrs) throws IOException, DataSourceException, - ReportProcessingException - { - // todo - if (!isElementBoundaryCollectionPass()) - { - final XmlWriter xmlWriter = getXmlWriter(); - xmlWriter.writeCloseTag(); - xmlWriter.writeCloseTag(); - } - } - - public void endReport(final ReportStructureRoot report) throws DataSourceException, ReportProcessingException - { - super.endReport(report); - setElementBoundaryCollectionPass(false); - resetTableCounter(); - columnCounter = 0; - } - - private boolean isElementBoundaryCollectionPass() - { - return elementBoundaryCollectionPass; - } - - private void setElementBoundaryCollectionPass(final boolean elementBoundaryCollectionPass) - { - this.elementBoundaryCollectionPass = elementBoundaryCollectionPass; - } - - private ColumnBoundary[] getSortedColumnBoundaryArray() - { - if (sortedBoundaryArray == null) - { - getColumnBoundaryList().add(new ColumnBoundary(0)); - sortedBoundaryArray = (ColumnBoundary[]) getColumnBoundaryList().toArray(EMPTY_COLBOUNDS); - Arrays.sort(sortedBoundaryArray); - } - return sortedBoundaryArray; - } - - private List getColumnBoundaryList() - { - return columnBoundaryList; - } - - private void addColumnWidthToRowBoundaryMarker(final float width) - { - currentRowBoundaryMarker += width; - } - - private float getCurrentRowBoundaryMarker() - { - return currentRowBoundaryMarker; - } - - private void resetTableCounter() - { - tableCounter = 0; - } - - private void resetCurrentRowBoundaryMarker() - { - currentRowBoundaryMarker = 0; - } - - private ColumnBoundary[] getBoundariesForTable(final int table) - { - if (boundariesForTableArray == null) - { - final List boundariesForTable = new ArrayList(); - final List boundaryList = getColumnBoundaryList(); - for (int i = 0; i < boundaryList.size(); i++) - { - final ColumnBoundary b = (ColumnBoundary) boundaryList.get(i); - if (b.isContainedByTable(table)) - { - boundariesForTable.add(b); - } - } - boundariesForTableArray = (ColumnBoundary[]) boundariesForTable.toArray(EMPTY_COLBOUNDS); - Arrays.sort(boundariesForTableArray); - } - return boundariesForTableArray; - } - - private int getColumnSpanForCell(final int table, final int col, final int initialColumnSpan) - { - final ColumnBoundary[] globalBoundaries = getSortedColumnBoundaryArray(); - final ColumnBoundary[] tableBoundaries = getBoundariesForTable(table); - // how many column boundaries in the globalBoundaries list fall between the currentRowWidth and the next boundary - // for the current row - - float cellBoundary = tableBoundaries[col - 1].getBoundary(); - float cellWidth = tableBoundaries[col - 1].getBoundary(); - - if (col > 1) - { - cellWidth = cellWidth - tableBoundaries[col - 2].getBoundary(); - } - - if (initialColumnSpan > 1) - { - // ok we've got some additional spanning specified on the input - final int index = (col - 1) + (initialColumnSpan - 1); - cellWidth += tableBoundaries[index].getBoundary() - tableBoundaries[col - 1].getBoundary(); - cellBoundary = tableBoundaries[index].getBoundary(); - } - - int beginBoundaryIndex = 0; - int endBoundaryIndex = globalBoundaries.length - 1; - for (int i = 0; i < globalBoundaries.length; i++) - { - // find beginning boundary - if (globalBoundaries[i].getBoundary() <= cellBoundary - cellWidth) - { - beginBoundaryIndex = i; - } - if (globalBoundaries[i].getBoundary() <= cellBoundary) - { - endBoundaryIndex = i; - } - } - final int span = endBoundaryIndex - beginBoundaryIndex; - // span will be zero for the first column, so we adjust it to 1 - if (span == 0) - { - return 1; - } - // System.out.println("table = " + table + " col = " + col + " rowBoundaries.length = " + tableBoundaries.length + " - // cellWidth = " + cellWidth + " span = " + span); - return span; - } - - protected String getTargetMimeType() - { - return "application/vnd.oasis.opendocument.spreadsheet"; - } -} +/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SpreadsheetRawReportTarget.java,v $
+ * $Revision: 1.8 $
+ *
+ * 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.output.spreadsheet;
+
+import com.sun.star.report.DataSourceFactory;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import com.sun.star.report.InputRepository;
+import com.sun.star.report.OutputRepository;
+import com.sun.star.report.ImageService;
+import com.sun.star.report.pentaho.OfficeNamespaces;
+import com.sun.star.report.OfficeToken;
+import com.sun.star.report.pentaho.PentahoReportEngineMetaData;
+import com.sun.star.report.pentaho.model.OfficeStyle;
+import com.sun.star.report.pentaho.model.OfficeStyles;
+import com.sun.star.report.pentaho.model.OfficeStylesCollection;
+import com.sun.star.report.pentaho.model.OfficeMasterPage;
+import com.sun.star.report.pentaho.model.OfficeMasterStyles;
+import com.sun.star.report.pentaho.model.PageSection;
+import com.sun.star.report.pentaho.output.OfficeDocumentReportTarget;
+import com.sun.star.report.pentaho.output.StyleUtilities;
+import com.sun.star.report.pentaho.output.text.MasterPageFactory;
+import com.sun.star.report.pentaho.styles.LengthCalculator;
+import java.util.Set;
+import org.jfree.layouting.util.AttributeMap;
+import org.jfree.layouting.input.style.values.CSSNumericValue;
+import org.jfree.layouting.input.style.values.CSSNumericType;
+import org.jfree.report.DataFlags;
+import org.jfree.report.DataSourceException;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.JFreeReportInfo;
+import org.jfree.report.flow.ReportJob;
+import org.jfree.report.flow.ReportStructureRoot;
+import org.jfree.report.flow.ReportTargetUtil;
+import org.jfree.report.structure.Element;
+import org.jfree.report.structure.Section;
+import org.jfree.report.util.IntegerCache;
+import org.jfree.report.util.TextUtilities;
+import org.jfree.resourceloader.ResourceKey;
+import org.jfree.resourceloader.ResourceManager;
+import org.jfree.util.Log;
+import org.jfree.xmlns.common.AttributeList;
+import org.jfree.xmlns.writer.XmlWriter;
+import org.jfree.xmlns.writer.XmlWriterSupport;
+
+/**
+ * Creation-Date: 03.11.2007
+ *
+ * @author Michael D'Amour
+ */
+public class SpreadsheetRawReportTarget extends OfficeDocumentReportTarget
+{
+
+ private boolean paragraphFound = false;
+ private boolean paragraphHandled = false;
+
+ /**
+ * This class represents a column boundary, not in width, but it's actual boundary location. One of the motivations
+ * for creating this class was to be able to record the boundaries for each incoming table while consuming as few
+ * objects/memory as possible.
+ */
+ private static class ColumnBoundary implements Comparable
+ {
+
+ private final Set tableIndices;
+ private final float boundary;
+
+ private ColumnBoundary(final float boundary)
+ {
+ this.tableIndices = new HashSet();
+ this.boundary = boundary;
+ }
+
+ public void addTableIndex(final int table)
+ {
+ tableIndices.add(IntegerCache.getInteger(table));
+ }
+
+ public float getBoundary()
+ {
+ return boundary;
+ }
+
+ public boolean isContainedByTable(final int table)
+ {
+ final Integer index = IntegerCache.getInteger(table);
+ return tableIndices.contains(index);
+ }
+
+ public int compareTo(final Object arg0)
+ {
+ if (arg0.equals(this))
+ {
+ return 0;
+ }
+ if (arg0 instanceof ColumnBoundary)
+ {
+ if (boundary > ((ColumnBoundary) arg0).boundary)
+ {
+ return 1;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ return 1;
+ }
+
+ public boolean equals(final Object obj)
+ {
+ if (obj instanceof ColumnBoundary)
+ {
+ return ((ColumnBoundary) obj).boundary == boundary;
+ }
+ return false;
+ }
+ }
+ private String tableBackgroundColor; // null means transparent ...
+ private static final ColumnBoundary[] EMPTY_COLBOUNDS = new ColumnBoundary[0];
+ private boolean elementBoundaryCollectionPass;
+ private boolean oleHandled;
+ private final List columnBoundaryList;
+ private float currentRowBoundaryMarker;
+ private ColumnBoundary[] sortedBoundaryArray;
+ private ColumnBoundary[] boundariesForTableArray;
+ private int tableCounter;
+ private int columnCounter;
+ private int columnSpanCounter;
+ private String unitsOfMeasure;
+ final private ArrayList shapes;
+ final private ArrayList ole;
+ final private ArrayList rowHeights;
+
+ public SpreadsheetRawReportTarget(final ReportJob reportJob,
+ final ResourceManager resourceManager,
+ final ResourceKey baseResource,
+ final InputRepository inputRepository,
+ final OutputRepository outputRepository,
+ final String target,
+ final ImageService imageService,
+ final DataSourceFactory dataSourceFactory)
+ throws ReportProcessingException
+ {
+ super(reportJob, resourceManager, baseResource, inputRepository, outputRepository, target, imageService, dataSourceFactory);
+ columnBoundaryList = new ArrayList();
+ elementBoundaryCollectionPass = true;
+ rowHeights = new ArrayList();
+ shapes = new ArrayList();
+ ole = new ArrayList();
+ oleHandled = false;
+ }
+
+ public void startOther(final AttributeMap attrs) throws DataSourceException, ReportProcessingException
+ {
+ if (ReportTargetUtil.isElementOfType(OfficeNamespaces.INTERNAL_NS, OfficeToken.OBJECT_OLE, attrs))
+ {
+ if (isElementBoundaryCollectionPass() && getCurrentRole() != ROLE_TEMPLATE)
+ {
+ ole.add(attrs);
+ }
+ oleHandled = true;
+ return;
+ }
+ final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs);
+ if (isRepeatingSection() || isFilteredNamespace(namespace))
+ {
+ return;
+ }
+
+ final String elementType = ReportTargetUtil.getElemenTypeFromAttribute(attrs);
+ if (OfficeNamespaces.TEXT_NS.equals(namespace) && OfficeToken.P.equals(elementType) && !paragraphHandled)
+ {
+ paragraphFound = true;
+ return;
+ }
+
+ if (OfficeNamespaces.DRAWING_NS.equals(namespace) && OfficeToken.FRAME.equals(elementType))
+ {
+ if (isElementBoundaryCollectionPass() && getCurrentRole() != ROLE_TEMPLATE)
+ {
+ final LengthCalculator len = new LengthCalculator();
+ for (int i = 0; i < rowHeights.size(); i++)
+ {
+ len.add((CSSNumericValue) rowHeights.get(i));
+ // val += ((CSSNumericValue)rowHeights.get(i)).getValue();
+ }
+
+ rowHeights.clear();
+ final CSSNumericValue currentRowHeight = len.getResult();
+ rowHeights.add(currentRowHeight);
+ attrs.setAttribute(OfficeNamespaces.DRAWING_NS, "z-index", String.valueOf(shapes.size()));
+ final String y = (String) attrs.getAttribute(OfficeNamespaces.SVG_NS, "y");
+ if (y != null)
+ {
+ len.add(parseLength(y));
+ final CSSNumericValue currentY = len.getResult();
+ attrs.setAttribute(OfficeNamespaces.SVG_NS, "y", currentY.getValue() + currentY.getType().getType());
+ }
+ shapes.add(attrs);
+ }
+ return;
+ }
+ if (oleHandled)
+ {
+ if (isElementBoundaryCollectionPass() && getCurrentRole() != ROLE_TEMPLATE)
+ {
+ ole.add(attrs);
+ }
+ return;
+ }
+
+ // if this is the report namespace, write out a table definition ..
+ if (OfficeNamespaces.TABLE_NS.equals(namespace) && OfficeToken.TABLE.equals(elementType))
+ {
+ // whenever we see a new table, we increment our tableCounter
+ // this is used to keep tracked of the boundary conditions per table
+ tableCounter++;
+ }
+
+ if (isElementBoundaryCollectionPass())
+ {
+ collectBoundaryForElement(attrs);
+ }
+ else
+ // if (!isElementBoundaryCollectionPass())
+ {
+ try
+ {
+ processElement(attrs, namespace, elementType);
+ }
+ catch (IOException e)
+ {
+ throw new ReportProcessingException("Failed", e);
+ }
+ }
+ }
+
+ protected void startReportSection(final AttributeMap attrs, final int role) throws IOException, DataSourceException, ReportProcessingException
+ {
+ if ((role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_HEADER ||
+ role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_FOOTER) &&
+ (!PageSection.isPrintWithReportHeader(attrs) ||
+ !PageSection.isPrintWithReportFooter(attrs)))
+ {
+ startBuffering(new OfficeStylesCollection(), true);
+
+ }
+ else
+ {
+ super.startReportSection(attrs, role);
+ }
+ }
+
+ protected void endReportSection(final AttributeMap attrs, final int role) throws IOException, DataSourceException, ReportProcessingException
+ {
+ if ((role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_HEADER ||
+ role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_FOOTER) &&
+ (!PageSection.isPrintWithReportHeader(attrs) ||
+ !PageSection.isPrintWithReportFooter(attrs)))
+ {
+ finishBuffering();
+ }
+ else
+ {
+ super.endReportSection(attrs, role);
+ }
+ }
+
+ private void handleParagraph()
+ {
+ if (paragraphFound)
+ {
+ try
+ {
+ final XmlWriter xmlWriter = getXmlWriter();
+ xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, null, XmlWriterSupport.OPEN);
+ paragraphHandled = true;
+ paragraphFound = false;
+ }
+ catch (IOException ex)
+ {
+ Log.error("ReportProcessing failed", ex);
+ }
+ }
+ }
+
+ private void processElement(final AttributeMap attrs, final String namespace, final String elementType)
+ throws IOException, ReportProcessingException
+ {
+ final XmlWriter xmlWriter = getXmlWriter();
+
+ if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE, attrs))
+ {
+ // a new table means we must clear our "calculated" table boundary array cache
+ boundariesForTableArray = null;
+
+ final String tableStyle = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ if (tableStyle == null)
+ {
+ tableBackgroundColor = null;
+ }
+ else
+ {
+ final Object raw = StyleUtilities.queryStyle(getPredefinedStylesCollection(), OfficeToken.TABLE, tableStyle,
+ "table-properties", OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR);
+ if (raw == null || "transparent".equals(raw))
+ {
+ tableBackgroundColor = null;
+ }
+ else
+ {
+ tableBackgroundColor = String.valueOf(raw);
+ }
+ }
+ return;
+ }
+
+ if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMN, attrs) ||
+ ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMNS, attrs))
+ {
+ return;
+ }
+
+ // covered-table-cell elements may appear in the input from row or column spans. In the event that we hit a
+ // column-span we simply ignore these elements because we are going to adjust the span to fit the uniform table.
+ if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.COVERED_TABLE_CELL, attrs))
+ {
+ if (columnSpanCounter > 0)
+ {
+ columnSpanCounter--;
+ }
+
+ if (columnSpanCounter == 0)
+ {
+ // if we weren't expecting a covered-table-cell, let's use it, it's probably from a row-span
+ columnCounter++;
+ final int span = getColumnSpanForCell(tableCounter, columnCounter, 1);
+ // use the calculated span for the column in the uniform table to create any additional covered-table-cell
+ // elements
+ for (int i = 0; i < span; i++)
+ {
+ xmlWriter.writeTag(namespace, OfficeToken.COVERED_TABLE_CELL, null, XmlWriter.CLOSE);
+ }
+ }
+ return;
+ }
+
+ if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_ROW, attrs))
+ {
+ // a new row means our column counter gets reset
+ columnCounter = 0;
+ // Lets make sure the color of the table is ok ..
+ if (tableBackgroundColor != null)
+ {
+ final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ final OfficeStyle style = deriveStyle(OfficeToken.TABLE_ROW, styleName);
+ Element tableRowProperties = style.getTableRowProperties();
+ if (tableRowProperties == null)
+ {
+ tableRowProperties = new Section();
+ tableRowProperties.setNamespace(OfficeNamespaces.STYLE_NS);
+ tableRowProperties.setType("table-row-properties");
+ tableRowProperties.setAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR, tableBackgroundColor);
+ style.addNode(tableRowProperties);
+ }
+ else
+ {
+ final Object oldValue = tableRowProperties.getAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR);
+ if (oldValue == null || "transparent".equals(oldValue))
+ {
+ tableRowProperties.setAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR, tableBackgroundColor);
+ }
+ }
+ attrs.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, style.getStyleName());
+ }
+ }
+ else if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_CELL, attrs))
+ {
+ columnCounter++;
+ final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ if (styleName != null)
+ {
+ final OfficeStyle cellStyle = getPredefinedStylesCollection().getStyle(OfficeToken.TABLE_CELL, styleName);
+ if (cellStyle != null)
+ {
+ final Element props = cellStyle.getTableCellProperties();
+ if (props != null)
+ {
+ final Object raw = props.getAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR);
+ if (raw == null || "transparent".equals(raw))
+ {
+ cellStyle.removeNode(props);
+ }
+ }
+ }
+ }
+
+ final String numColSpanStr = (String) attrs.getAttribute(namespace, "number-columns-spanned");
+ int initialColumnSpan = columnSpanCounter = 1;
+ if (numColSpanStr != null)
+ {
+ initialColumnSpan = Integer.parseInt(numColSpanStr);
+ columnSpanCounter = initialColumnSpan;
+ }
+ final int span = getColumnSpanForCell(tableCounter, columnCounter, initialColumnSpan);
+ if (initialColumnSpan > 1)
+ {
+ // add the initial column span to our column counter index (subtract 1, since it is counted by default)
+ columnCounter += initialColumnSpan - 1;
+ }
+
+ // if (span < initialColumnSpan)
+ // {
+ // // ColumnBoundary cbs[] = getBoundariesForTable(tableCounter);
+ // // for (int i = 0; i < cbs.length; i++)
+ // // {
+ // // System.out.print(cbs[i].getBoundary() + " ");
+ // // }
+ // // System.out.println();
+ //
+ // Log.error("A cell cannot span less than the declared columns: Declared=" + initialColumnSpan + " Computed="
+ // + span);
+ // }
+
+ // there's no point to create number-columns-spanned attributes if we only span 1 column
+ if (span > 1)
+ {
+ attrs.setAttribute(namespace, "number-columns-spanned", "" + span);
+ }
+ // we must also generate "covered-table-cell" elements for each column spanned
+ // but we'll do this in the endElement, after we close this OfficeToken.TABLE_CELL
+ }
+
+ // All styles have to be processed or you will loose the paragraph-styles and inline text-styles.
+ // ..
+ performStyleProcessing(attrs);
+
+ final AttributeList attrList = buildAttributeList(attrs);
+ xmlWriter.writeTag(namespace, elementType, attrList, XmlWriter.OPEN);
+ // System.out.println("elementType = " + elementType);
+ }
+
+ private void collectBoundaryForElement(final AttributeMap attrs)
+ {
+ if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMNS, attrs))
+ {
+ // A table row resets the column counter.
+ resetCurrentRowBoundaryMarker();
+ }
+ else if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMN, attrs))
+ {
+ final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ if (styleName == null)
+ {
+ // This should not happen, but if it does, we will ignore that cell.
+ return;
+ }
+
+ final OfficeStyle style = getPredefinedStylesCollection().getStyle(OfficeToken.TABLE_COLUMN, styleName);
+ if (style == null)
+ {
+ // Now this is very bad. It means that there is no style defined with the given name.
+ return;
+ }
+
+ final Element tableColumnProperties = style.getTableColumnProperties();
+ String widthStr = (String) tableColumnProperties.getAttribute("column-width");
+ widthStr = widthStr.substring(0, widthStr.indexOf(getUnitsOfMeasure(widthStr)));
+ addColumnWidthToRowBoundaryMarker(Float.parseFloat(widthStr));
+ ColumnBoundary currentRowBoundary = new ColumnBoundary(getCurrentRowBoundaryMarker());
+ final List columnBoundaryList_ = getColumnBoundaryList();
+ final int idx = columnBoundaryList_.indexOf(currentRowBoundary);
+ if (idx == -1)
+ {
+ columnBoundaryList_.add(currentRowBoundary);
+ }
+ else
+ {
+ currentRowBoundary = (ColumnBoundary) columnBoundaryList_.get(idx);
+ }
+ currentRowBoundary.addTableIndex(tableCounter);
+ }
+ }
+
+ private String getUnitsOfMeasure(final String str)
+ {
+ if (unitsOfMeasure == null || "".equals(unitsOfMeasure))
+ {
+ if (str == null || "".equals(str))
+ {
+ unitsOfMeasure = "cm";
+ return unitsOfMeasure;
+ }
+
+ // build units of measure, set it
+ int i = str.length() - 1;
+ for (; i >= 0; i--)
+ {
+ final char c = str.charAt(i);
+ if (Character.isDigit(c) || c == '.' || c == ',')
+ {
+ break;
+ }
+ }
+ unitsOfMeasure = str.substring(i + 1);
+ }
+ return unitsOfMeasure;
+ }
+
+ private void createTableShapes() throws ReportProcessingException
+ {
+ if (!shapes.isEmpty())
+ {
+ try
+ {
+ final XmlWriter xmlWriter = getXmlWriter();
+ // at this point we need to generate the table-columns section based on our boundary table
+ // <table:shapes>
+ // <draw:frame />
+ // ..
+ // </table:shapes>
+ xmlWriter.writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.SHAPES, null, XmlWriterSupport.OPEN);
+
+
+ for (int i = 0; i < shapes.size(); i++)
+ {
+ final AttributeMap attrs = (AttributeMap) shapes.get(i);
+ final AttributeList attrList = buildAttributeList(attrs);
+ attrList.removeAttribute(OfficeNamespaces.DRAWING_NS, OfficeToken.STYLE_NAME);
+ xmlWriter.writeTag(OfficeNamespaces.DRAWING_NS, OfficeToken.FRAME, attrList, XmlWriterSupport.OPEN);
+ startChartProcessing((AttributeMap) ole.get(i));
+
+ xmlWriter.writeCloseTag();
+ }
+ xmlWriter.writeCloseTag();
+ }
+ catch (IOException e)
+ {
+ throw new ReportProcessingException("Failed", e);
+ }
+ }
+ }
+
+ private void createTableColumns() throws ReportProcessingException
+ {
+ try
+ {
+ final XmlWriter xmlWriter = getXmlWriter();
+ // at this point we need to generate the table-columns section based on our boundary table
+ // <table-columns>
+ // <table-column style-name="coX"/>
+ // ..
+ // </table-columns>
+ // the first boundary is '0' which is a placeholder so we will ignore it
+ xmlWriter.writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMNS, null, XmlWriterSupport.OPEN);
+
+ // blow away current column styles
+ // start processing at i=1 because we added a boundary for "0" which is virtual
+ final ColumnBoundary[] cba = getSortedColumnBoundaryArray();
+ for (int i = 1; i < cba.length; i++)
+ {
+ final ColumnBoundary cb = cba[i];
+ float columnWidth = cb.getBoundary();
+ if (i > 1)
+ {
+ columnWidth -= cba[i - 1].getBoundary();
+ }
+ final OfficeStyle style = deriveStyle(OfficeToken.TABLE_COLUMN, ("co" + i + "_"));
+ final Section tableColumnProperties = new Section();
+ tableColumnProperties.setType("table-column-properties");
+ tableColumnProperties.setNamespace(style.getNamespace());
+ tableColumnProperties.setAttribute(style.getNamespace(), "column-width", columnWidth + getUnitsOfMeasure(null));
+ style.addNode(tableColumnProperties);
+
+ final AttributeList myAttrList = new AttributeList();
+ myAttrList.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, style.getStyleName());
+ xmlWriter.writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMN, myAttrList, XmlWriterSupport.CLOSE);
+ }
+ xmlWriter.writeCloseTag();
+ }
+ catch (IOException e)
+ {
+ throw new ReportProcessingException("Failed", e);
+ }
+ }
+
+ protected void endOther(final AttributeMap attrs) throws DataSourceException, ReportProcessingException
+ {
+ if (ReportTargetUtil.isElementOfType(OfficeNamespaces.INTERNAL_NS, OfficeToken.OBJECT_OLE, attrs) || oleHandled)
+ {
+ oleHandled = false;
+ return;
+ }
+
+ if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_ROW, attrs) && isElementBoundaryCollectionPass() && getCurrentRole() != ROLE_TEMPLATE)
+ {
+ final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ rowHeights.add(computeRowHeight(styleName));
+ }
+
+ if (isRepeatingSection() || isElementBoundaryCollectionPass())
+ {
+ return;
+ }
+
+ final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs);
+ if (isFilteredNamespace(namespace))
+ {
+ return;
+ }
+ final String elementType = ReportTargetUtil.getElemenTypeFromAttribute(attrs);
+ if (OfficeNamespaces.DRAWING_NS.equals(namespace) && OfficeToken.FRAME.equals(elementType))
+ {
+ return;
+ }
+
+ // if this is the report namespace, write out a table definition ..
+ if (OfficeNamespaces.TABLE_NS.equals(namespace) && (OfficeToken.TABLE.equals(elementType) ||
+ OfficeToken.COVERED_TABLE_CELL.equals(elementType) ||
+ OfficeToken.TABLE_COLUMN.equals(elementType) ||
+ OfficeToken.TABLE_COLUMNS.equals(elementType)))
+ {
+ return;
+ }
+
+ if ( !paragraphHandled && OfficeNamespaces.TEXT_NS.equals(namespace) && OfficeToken.P.equals(elementType))
+ {
+ if (!paragraphHandled)
+ {
+ return;
+ }
+
+ paragraphHandled = false;
+ }
+ try
+ {
+ final XmlWriter xmlWriter = getXmlWriter();
+ xmlWriter.writeCloseTag();
+ // table-cell elements may have a number-columns-spanned attribute which indicates how many
+ // 'covered-table-cell' elements we need to generate
+ generateCoveredTableCells(attrs);
+ }
+ catch (IOException e)
+ {
+ throw new ReportProcessingException("Failed", e);
+ }
+ }
+
+ private void generateCoveredTableCells(final AttributeMap attrs) throws IOException
+ {
+ if (!ReportTargetUtil.isElementOfType(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_CELL, attrs))
+ {
+ return;
+ }
+
+ // do this after we close the tag
+ final XmlWriter xmlWriter = getXmlWriter();
+ final Object attribute = attrs.getAttribute(OfficeNamespaces.TABLE_NS, "number-columns-spanned");
+ final int span = TextUtilities.parseInt((String) attribute, 0);
+ for (int i = 1; i < span; i++)
+ {
+ xmlWriter.writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.COVERED_TABLE_CELL, null, XmlWriter.CLOSE);
+ }
+ }
+
+ public String getExportDescriptor()
+ {
+ return "raw/" + PentahoReportEngineMetaData.OPENDOCUMENT_SPREADSHEET;
+ }
+
+ // /////////////////////////////////////////////////////////////////////////
+ public void processText(final String text) throws DataSourceException, ReportProcessingException
+ {
+ if (!(isRepeatingSection() || isElementBoundaryCollectionPass()))
+ {
+ handleParagraph();
+ super.processText(text);
+ }
+ }
+
+ public void processContent(final DataFlags value) throws DataSourceException, ReportProcessingException
+ {
+ if (!(isRepeatingSection() || isElementBoundaryCollectionPass()))
+ {
+ handleParagraph();
+ super.processContent(value);
+ }
+ }
+
+ protected String getStartContent()
+ {
+ return "spreadsheet";
+ }
+
+ protected void startContent(final AttributeMap attrs) throws IOException, DataSourceException,
+ ReportProcessingException
+ {
+ if (!isElementBoundaryCollectionPass())
+ {
+ final XmlWriter xmlWriter = getXmlWriter();
+ xmlWriter.writeTag(OfficeNamespaces.OFFICE_NS, getStartContent(), null, XmlWriterSupport.OPEN);
+
+ final AttributeMap tableAttributes = new AttributeMap();
+ tableAttributes.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.NAMESPACE_ATTRIBUTE, OfficeNamespaces.TABLE_NS);
+ tableAttributes.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.TYPE_ATTRIBUTE, OfficeToken.TABLE);
+ tableAttributes.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, generateInitialTableStyle());
+ tableAttributes.setAttribute(OfficeNamespaces.TABLE_NS, "name", "Report");
+
+ performStyleProcessing(tableAttributes);
+
+ xmlWriter.writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE, buildAttributeList(tableAttributes), XmlWriterSupport.OPEN);
+ createTableShapes();
+ createTableColumns();
+ }
+ }
+
+ private String generateInitialTableStyle() throws ReportProcessingException
+ {
+ final OfficeStylesCollection predefStyles = getPredefinedStylesCollection();
+ final OfficeStyles commonStyles = predefStyles.getAutomaticStyles();
+ if (!commonStyles.containsStyle(OfficeToken.TABLE, "Initial_Table"))
+ {
+ final String masterPageName = createMasterPage();
+
+ final OfficeStyle tableStyle = new OfficeStyle();
+ tableStyle.setStyleFamily(OfficeToken.TABLE);
+ tableStyle.setStyleName("Initial_Table");
+ tableStyle.setAttribute(OfficeNamespaces.STYLE_NS, "master-page-name", masterPageName);
+ final Element tableProperties = produceFirstChild(tableStyle, OfficeNamespaces.STYLE_NS, "table-properties");
+ tableProperties.setAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR, "transparent");
+ commonStyles.addStyle(tableStyle);
+ }
+ return "Initial_Table";
+ }
+
+ private String createMasterPage() throws ReportProcessingException
+ {
+ final OfficeStylesCollection predefStyles = getPredefinedStylesCollection();
+ final MasterPageFactory masterPageFactory = new MasterPageFactory(predefStyles.getMasterStyles());
+ final OfficeMasterPage masterPage;
+ if (!masterPageFactory.containsMasterPage("Standard", null, null))
+ {
+ masterPage = masterPageFactory.createMasterPage("Standard", null, null);
+
+ final CSSNumericValue zeroLength = CSSNumericValue.createValue(CSSNumericType.CM, 0);
+ final String pageLayoutTemplate = masterPage.getPageLayout();
+ if (pageLayoutTemplate == null)
+ {
+ // there is no pagelayout. Create one ..
+ final String derivedLayout = masterPageFactory.createPageStyle(getGlobalStylesCollection().getAutomaticStyles(), zeroLength, zeroLength);
+ masterPage.setPageLayout(derivedLayout);
+ }
+ else
+ {
+ final String derivedLayout = masterPageFactory.derivePageStyle(pageLayoutTemplate,
+ getPredefinedStylesCollection().getAutomaticStyles(),
+ getGlobalStylesCollection().getAutomaticStyles(), zeroLength, zeroLength);
+ masterPage.setPageLayout(derivedLayout);
+ }
+
+ final OfficeStylesCollection officeStylesCollection = getGlobalStylesCollection();
+ final OfficeMasterStyles officeMasterStyles = officeStylesCollection.getMasterStyles();
+ officeMasterStyles.addMasterPage(masterPage);
+ }
+ else
+ {
+ masterPage = masterPageFactory.getMasterPage("Standard", null, null);
+ }
+ return masterPage.getStyleName();
+ }
+
+ protected void endContent(final AttributeMap attrs) throws IOException, DataSourceException,
+ ReportProcessingException
+ {
+ // todo
+ if (!isElementBoundaryCollectionPass())
+ {
+ final XmlWriter xmlWriter = getXmlWriter();
+ xmlWriter.writeCloseTag();
+ xmlWriter.writeCloseTag();
+ }
+ }
+
+ public void endReport(final ReportStructureRoot report) throws DataSourceException, ReportProcessingException
+ {
+ super.endReport(report);
+ setElementBoundaryCollectionPass(false);
+ resetTableCounter();
+ columnCounter = 0;
+ }
+
+ private boolean isElementBoundaryCollectionPass()
+ {
+ return elementBoundaryCollectionPass;
+ }
+
+ private void setElementBoundaryCollectionPass(final boolean elementBoundaryCollectionPass)
+ {
+ this.elementBoundaryCollectionPass = elementBoundaryCollectionPass;
+ }
+
+ private ColumnBoundary[] getSortedColumnBoundaryArray()
+ {
+ if (sortedBoundaryArray == null)
+ {
+ getColumnBoundaryList().add(new ColumnBoundary(0));
+ sortedBoundaryArray = (ColumnBoundary[]) getColumnBoundaryList().toArray(EMPTY_COLBOUNDS);
+ Arrays.sort(sortedBoundaryArray);
+ }
+ return sortedBoundaryArray;
+ }
+
+ private List getColumnBoundaryList()
+ {
+ return columnBoundaryList;
+ }
+
+ private void addColumnWidthToRowBoundaryMarker(final float width)
+ {
+ currentRowBoundaryMarker += width;
+ }
+
+ private float getCurrentRowBoundaryMarker()
+ {
+ return currentRowBoundaryMarker;
+ }
+
+ private void resetTableCounter()
+ {
+ tableCounter = 0;
+ }
+
+ private void resetCurrentRowBoundaryMarker()
+ {
+ currentRowBoundaryMarker = 0;
+ }
+
+ private ColumnBoundary[] getBoundariesForTable(final int table)
+ {
+ if (boundariesForTableArray == null)
+ {
+ final List boundariesForTable = new ArrayList();
+ final List boundaryList = getColumnBoundaryList();
+ for (int i = 0; i < boundaryList.size(); i++)
+ {
+ final ColumnBoundary b = (ColumnBoundary) boundaryList.get(i);
+ if (b.isContainedByTable(table))
+ {
+ boundariesForTable.add(b);
+ }
+ }
+ boundariesForTableArray = (ColumnBoundary[]) boundariesForTable.toArray(EMPTY_COLBOUNDS);
+ Arrays.sort(boundariesForTableArray);
+ }
+ return boundariesForTableArray;
+ }
+
+ private int getColumnSpanForCell(final int table, final int col, final int initialColumnSpan)
+ {
+ final ColumnBoundary[] globalBoundaries = getSortedColumnBoundaryArray();
+ final ColumnBoundary[] tableBoundaries = getBoundariesForTable(table);
+ // how many column boundaries in the globalBoundaries list fall between the currentRowWidth and the next boundary
+ // for the current row
+
+ float cellBoundary = tableBoundaries[col - 1].getBoundary();
+ float cellWidth = tableBoundaries[col - 1].getBoundary();
+
+ if (col > 1)
+ {
+ cellWidth = cellWidth - tableBoundaries[col - 2].getBoundary();
+ }
+
+ if (initialColumnSpan > 1)
+ {
+ // ok we've got some additional spanning specified on the input
+ final int index = (col - 1) + (initialColumnSpan - 1);
+ cellWidth += tableBoundaries[index].getBoundary() - tableBoundaries[col - 1].getBoundary();
+ cellBoundary = tableBoundaries[index].getBoundary();
+ }
+
+ int beginBoundaryIndex = 0;
+ int endBoundaryIndex = globalBoundaries.length - 1;
+ for (int i = 0; i < globalBoundaries.length; i++)
+ {
+ // find beginning boundary
+ if (globalBoundaries[i].getBoundary() <= cellBoundary - cellWidth)
+ {
+ beginBoundaryIndex = i;
+ }
+ if (globalBoundaries[i].getBoundary() <= cellBoundary)
+ {
+ endBoundaryIndex = i;
+ }
+ }
+ final int span = endBoundaryIndex - beginBoundaryIndex;
+ // span will be zero for the first column, so we adjust it to 1
+ if (span == 0)
+ {
+ return 1;
+ }
+ // System.out.println("table = " + table + " col = " + col + " rowBoundaries.length = " + tableBoundaries.length + "
+ // cellWidth = " + cellWidth + " span = " + span);
+ return span;
+ }
+
+ protected String getTargetMimeType()
+ {
+ return "application/vnd.oasis.opendocument.spreadsheet";
+ }
+}
diff --git a/reportdesign/java/com/sun/star/report/pentaho/output/text/TextRawReportProcessor.java b/reportdesign/java/com/sun/star/report/pentaho/output/text/TextRawReportProcessor.java index 491a85df4ba4..00eb7b9b5b2d 100644 --- a/reportdesign/java/com/sun/star/report/pentaho/output/text/TextRawReportProcessor.java +++ b/reportdesign/java/com/sun/star/report/pentaho/output/text/TextRawReportProcessor.java @@ -1,117 +1,117 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: TextRawReportProcessor.java,v $ - * $Revision: 1.6 $ - * - * 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.output.text; - -import com.sun.star.report.DataSourceFactory; -import com.sun.star.report.OutputRepository; -import com.sun.star.report.InputRepository; -import com.sun.star.report.ImageService; -import com.sun.star.report.pentaho.PentahoFormulaContext; -import com.sun.star.report.pentaho.PentahoReportJob; -import org.jfree.report.ReportProcessingException; -import org.jfree.report.data.ReportContextImpl; -import org.jfree.report.flow.ReportContext; -import org.jfree.report.flow.ReportJob; -import org.jfree.report.flow.ReportStructureRoot; -import org.jfree.report.flow.ReportTarget; -import org.jfree.report.flow.SinglePassReportProcessor; -import org.jfree.resourceloader.ResourceManager; - -/** - * Creation-Date: 03.07.2006, 17:08:25 - * - * @author Thomas Morgner - */ -public class TextRawReportProcessor extends SinglePassReportProcessor -{ - - private final OutputRepository outputRepository; - private final String targetName; - private final InputRepository inputRepository; - private final ImageService imageService; - private final DataSourceFactory dataSourceFactory; - - public TextRawReportProcessor(final InputRepository inputRepository, - final OutputRepository outputRepository, - final String targetName, - final ImageService imageService, - final DataSourceFactory dataSourceFactory) - { - if (inputRepository == null) - { - throw new NullPointerException(); - } - if (outputRepository == null) - { - throw new NullPointerException(); - } - if (targetName == null) - { - throw new NullPointerException(); - } - if (imageService == null) - { - throw new NullPointerException(); - } - if (dataSourceFactory == null) - { - throw new NullPointerException(); - } - - this.targetName = targetName; - this.inputRepository = inputRepository; - this.outputRepository = outputRepository; - this.imageService = imageService; - this.dataSourceFactory = dataSourceFactory; - } - - protected ReportTarget createReportTarget(final ReportJob job) - throws ReportProcessingException - { - final ReportStructureRoot report = job.getReportStructureRoot(); - final ResourceManager resourceManager = report.getResourceManager(); - - return new TextRawReportTarget(job, resourceManager, report.getBaseResource(), - inputRepository, outputRepository, targetName, imageService, dataSourceFactory); - } - - protected ReportContext createReportContext(final ReportJob job, - final ReportTarget target) - { - final ReportContext context = super.createReportContext(job, target); - if (context instanceof ReportContextImpl) - { - ReportContextImpl impl = (ReportContextImpl) context; - impl.setFormulaContext(new PentahoFormulaContext(impl.getFormulaContext(),job.getConfiguration())); - } - return context; - } -} - +/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: TextRawReportProcessor.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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.output.text;
+
+import com.sun.star.report.DataSourceFactory;
+import com.sun.star.report.OutputRepository;
+import com.sun.star.report.InputRepository;
+import com.sun.star.report.ImageService;
+import com.sun.star.report.pentaho.PentahoFormulaContext;
+import com.sun.star.report.pentaho.PentahoReportJob;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.data.ReportContextImpl;
+import org.jfree.report.flow.ReportContext;
+import org.jfree.report.flow.ReportJob;
+import org.jfree.report.flow.ReportStructureRoot;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.SinglePassReportProcessor;
+import org.jfree.resourceloader.ResourceManager;
+
+/**
+ * Creation-Date: 03.07.2006, 17:08:25
+ *
+ * @author Thomas Morgner
+ */
+public class TextRawReportProcessor extends SinglePassReportProcessor
+{
+
+ private final OutputRepository outputRepository;
+ private final String targetName;
+ private final InputRepository inputRepository;
+ private final ImageService imageService;
+ private final DataSourceFactory dataSourceFactory;
+
+ public TextRawReportProcessor(final InputRepository inputRepository,
+ final OutputRepository outputRepository,
+ final String targetName,
+ final ImageService imageService,
+ final DataSourceFactory dataSourceFactory)
+ {
+ if (inputRepository == null)
+ {
+ throw new NullPointerException();
+ }
+ if (outputRepository == null)
+ {
+ throw new NullPointerException();
+ }
+ if (targetName == null)
+ {
+ throw new NullPointerException();
+ }
+ if (imageService == null)
+ {
+ throw new NullPointerException();
+ }
+ if (dataSourceFactory == null)
+ {
+ throw new NullPointerException();
+ }
+
+ this.targetName = targetName;
+ this.inputRepository = inputRepository;
+ this.outputRepository = outputRepository;
+ this.imageService = imageService;
+ this.dataSourceFactory = dataSourceFactory;
+ }
+
+ protected ReportTarget createReportTarget(final ReportJob job)
+ throws ReportProcessingException
+ {
+ final ReportStructureRoot report = job.getReportStructureRoot();
+ final ResourceManager resourceManager = report.getResourceManager();
+
+ return new TextRawReportTarget(job, resourceManager, report.getBaseResource(),
+ inputRepository, outputRepository, targetName, imageService, dataSourceFactory);
+ }
+
+ protected ReportContext createReportContext(final ReportJob job,
+ final ReportTarget target)
+ {
+ final ReportContext context = super.createReportContext(job, target);
+ if (context instanceof ReportContextImpl)
+ {
+ final ReportContextImpl impl = (ReportContextImpl) context;
+ impl.setFormulaContext(new PentahoFormulaContext(impl.getFormulaContext(),job.getConfiguration()));
+ }
+ return context;
+ }
+}
+
diff --git a/reportdesign/java/com/sun/star/report/pentaho/output/text/TextRawReportTarget.java b/reportdesign/java/com/sun/star/report/pentaho/output/text/TextRawReportTarget.java index 40b6f635d14c..7ef944baef10 100644 --- a/reportdesign/java/com/sun/star/report/pentaho/output/text/TextRawReportTarget.java +++ b/reportdesign/java/com/sun/star/report/pentaho/output/text/TextRawReportTarget.java @@ -1,1518 +1,1518 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: TextRawReportTarget.java,v $ - * $Revision: 1.9 $ - * - * 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.output.text; - -import com.sun.star.report.DataSourceFactory; -import java.io.IOException; -import java.io.OutputStream; -import java.io.InputStream; -import org.jfree.io.IOUtils; -import java.io.OutputStreamWriter; -import java.util.Iterator; -import java.util.Map; - -import com.sun.star.report.ImageService; -import com.sun.star.report.InputRepository; -import com.sun.star.report.OutputRepository; -import com.sun.star.report.pentaho.OfficeNamespaces; -import com.sun.star.report.OfficeToken; -import com.sun.star.report.pentaho.PentahoReportEngineMetaData; -import com.sun.star.report.pentaho.layoutprocessor.FormatValueUtility; -import com.sun.star.report.pentaho.model.OfficeMasterPage; -import com.sun.star.report.pentaho.model.OfficeMasterStyles; -import com.sun.star.report.pentaho.model.OfficeStyle; -import com.sun.star.report.pentaho.model.OfficeStyles; -import com.sun.star.report.pentaho.model.OfficeStylesCollection; -import com.sun.star.report.pentaho.model.PageSection; -import com.sun.star.report.pentaho.output.OfficeDocumentReportTarget; -import com.sun.star.report.pentaho.output.StyleUtilities; -import com.sun.star.report.pentaho.styles.LengthCalculator; -import java.util.ArrayList; -import org.jfree.layouting.input.style.values.CSSNumericValue; -import org.jfree.layouting.util.AttributeMap; -import org.jfree.report.DataSourceException; -import org.jfree.report.ReportProcessingException; -import org.jfree.report.flow.ReportJob; -import org.jfree.report.flow.ReportStructureRoot; -import org.jfree.report.flow.ReportTargetUtil; -import org.jfree.report.structure.Element; -import org.jfree.report.structure.Node; -import org.jfree.report.structure.Section; -import org.jfree.report.util.AttributeNameGenerator; -import org.jfree.report.util.IntegerCache; -import org.jfree.resourceloader.ResourceKey; -import org.jfree.resourceloader.ResourceManager; -import org.jfree.util.FastStack; -import org.jfree.util.ObjectUtilities; -//import org.jfree.util.Log; -import org.jfree.xmlns.common.AttributeList; -import org.jfree.xmlns.writer.XmlWriter; -import org.jfree.xmlns.writer.XmlWriterSupport; - -/** - * Creation-Date: 03.07.2006, 16:28:00 - * - * @author Thomas Morgner - */ -public class TextRawReportTarget extends OfficeDocumentReportTarget -{ - - private static final String ALWAYS = "always"; - private static final String KEEP_TOGETHER = "keep-together"; - private static final String KEEP_WITH_NEXT = "keep-with-next"; - private static final String MAY_BREAK_BETWEEN_ROWS = "may-break-between-rows"; - private static final String NAME = "name"; - private static final String NONE = "none"; - private static final String NORMAL = "normal"; - private static final String PARAGRAPH_PROPERTIES = "paragraph-properties"; - private static final String STANDARD = "Standard"; - private static final String TABLE_PROPERTIES = "table-properties"; - private static final String VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT = "variables_paragraph_with_next"; - private static final String VARIABLES_HIDDEN_STYLE_WITHOUT_KEEPWNEXT = "variables_paragraph_without_next"; - private static final int TABLE_LAYOUT_VARIABLES_PARAGRAPH = 0; - private static final int TABLE_LAYOUT_VARIABLES_IN_FIRST_CELL = 1; - private static final int TABLE_LAYOUT_SINGLE_DETAIL_TABLE = 2; - private static final int CP_SETUP = 0; - private static final int CP_FIRST_TABLE = 1; - private static final int CP_NEXT_TABLE = 2; - - // This is the initial state of the detail-band processing. It states, that we are now waiting for a - // detail-band to be printed. - private static final int DETAIL_SECTION_WAIT = 0; - // The first detail section has started. - private static final int DETAIL_SECTION_FIRST_STARTED = 1; - // The first detail section has been printed. - private static final int DETAIL_SECTION_FIRST_PRINTED = 2; - // An other detail section has started - private static final int DETAIL_SECTION_OTHER_STARTED = 3; - // The other detail section has been printed. - private static final int DETAIL_SECTION_OTHER_PRINTED = 4; - private boolean pageFooterOnReportFooter; - private boolean pageFooterOnReportHeader; - private boolean pageHeaderOnReportFooter; - private boolean pageHeaderOnReportHeader; - private int contentProcessingState; - private OfficeMasterPage currentMasterPage; - private final FastStack activePageContext; - private MasterPageFactory masterPageFactory; - private LengthCalculator sectionHeight; - private String variables; - private PageBreakDefinition pageBreakDefinition; - private VariablesDeclarations variablesDeclarations; - private boolean columnBreakPending; - private boolean sectionKeepTogether; - private final AttributeNameGenerator sectionNames; - private int detailBandProcessingState; - private final int tableLayoutConfig; - private int expectedTableRowCount; - private boolean firstCellSeen; - private boolean cellEmpty; - - public TextRawReportTarget(final ReportJob reportJob, - final ResourceManager resourceManager, - final ResourceKey baseResource, - final InputRepository inputRepository, - final OutputRepository outputRepository, - final String target, - final ImageService imageService, - final DataSourceFactory datasourcefactory) - throws ReportProcessingException - { - super(reportJob, resourceManager, baseResource, inputRepository, outputRepository, target, imageService, datasourcefactory); - activePageContext = new FastStack(); - this.sectionNames = new AttributeNameGenerator(); - - this.tableLayoutConfig = TABLE_LAYOUT_SINGLE_DETAIL_TABLE; - } - - protected String getTargetMimeType() - { - return "application/vnd.oasis.opendocument.text"; - } - - /** - * Checks, whether a manual page break should be inserted at the next possible location. - * - * @return true, if a pagebreak is pending, false otherwise. - */ - private boolean isPagebreakPending() - { - return pageBreakDefinition != null; - } - - private boolean isResetPageNumber() - { - if (pageBreakDefinition == null) - { - return false; - } - return pageBreakDefinition.isResetPageNumber(); - } - - /** - * Defines, whether a manual pagebreak should be inserted at the next possible location. - * - * @param pageBreakDefinition the new flag value. - */ - private void setPagebreakDefinition(final PageBreakDefinition pageBreakDefinition) - { - this.pageBreakDefinition = pageBreakDefinition; - } - - private PageBreakDefinition getPagebreakDefinition() - { - return pageBreakDefinition; - } - - // todo - private boolean isKeepTableWithNext() - { - final int keepTogetherState = getCurrentContext().getKeepTogether(); - if (keepTogetherState == PageContext.KEEP_TOGETHER_GROUP) - { - return true; - } - - final boolean keepWithNext; - if (keepTogetherState == PageContext.KEEP_TOGETHER_FIRST_DETAIL) - { - keepWithNext = (detailBandProcessingState == DETAIL_SECTION_WAIT); - } - else - { - keepWithNext = false; - } - return keepWithNext; - } - - private boolean isSectionPagebreakAfter(final AttributeMap attrs) - { - final Object forceNewPage = - attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, "force-new-page"); - if ("after-section".equals(forceNewPage)) - { - return true; - } - if ("before-after-section".equals(forceNewPage)) - { - return true; - } - return false; - } - - private boolean isSectionPagebreakBefore(final AttributeMap attrs) - { - final Object forceNewPage = - attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, "force-new-page"); - return "before-section".equals(forceNewPage) || "before-after-section".equals(forceNewPage); - } - - private PageContext getCurrentContext() - { - return (PageContext) activePageContext.peek(); - } - - private String createMasterPage(final boolean printHeader, - final boolean printFooter) - throws ReportProcessingException - { - // create the master page for the report-header. - // If there is a page-header or footer in the report that gets - // surpressed on the report-header, we have to insert a pagebreak - // afterwards. - - final String activePageFooter; - // Check, whether the report header can have a page-header - final PageContext context = getCurrentContext(); - if (printFooter) - { - activePageFooter = context.getPageFooterContent(); - } - else - { - activePageFooter = null; - } - final String activePageHeader; - if (printHeader) - { - // we have to insert a manual pagebreak after the report header. - activePageHeader = context.getPageHeaderContent(); - } - else - { - activePageHeader = null; - } - - final String masterPageName; - if (currentMasterPage == null || - !masterPageFactory.containsMasterPage(STANDARD, activePageHeader, activePageFooter)) - { - - final CSSNumericValue headerSize = context.getAllHeaderSize(); - final CSSNumericValue footerSize = context.getAllFooterSize(); - - - currentMasterPage = masterPageFactory.createMasterPage(STANDARD, activePageHeader, activePageFooter); - -// Log.debug("Created a new master-page: " + currentMasterPage.getStyleName()); - - // todo: Store the page-layouts as well. - // The page layouts are derived from a common template, but as the - // header-heights differ, we have to derive these beasts instead - // of copying them - - final OfficeStylesCollection officeStylesCollection = getGlobalStylesCollection(); - final OfficeMasterStyles officeMasterStyles = officeStylesCollection.getMasterStyles(); - final String pageLayoutTemplate = currentMasterPage.getPageLayout(); - if (pageLayoutTemplate == null) - { - // there is no pagelayout. Create one .. - final String derivedLayout = masterPageFactory.createPageStyle(getGlobalStylesCollection().getAutomaticStyles(), headerSize, footerSize); - currentMasterPage.setPageLayout(derivedLayout); - } - else - { - final String derivedLayout = masterPageFactory.derivePageStyle(pageLayoutTemplate, - getPredefinedStylesCollection().getAutomaticStyles(), - getGlobalStylesCollection().getAutomaticStyles(), headerSize, footerSize); - currentMasterPage.setPageLayout(derivedLayout); - } - officeMasterStyles.addMasterPage(currentMasterPage); - masterPageName = currentMasterPage.getStyleName(); - } - else - { - // retrieve the master-page. - final OfficeMasterPage masterPage = masterPageFactory.getMasterPage(STANDARD, activePageHeader, activePageFooter); - if (ObjectUtilities.equal(masterPage.getStyleName(), currentMasterPage.getStyleName())) - { - // They are the same, - masterPageName = null; - } - else - { - // reuse the existing one .. - currentMasterPage = masterPage; - masterPageName = currentMasterPage.getStyleName(); - } - } - - // if either the pageheader or footer are *not* printed with the - // report header, then this implies that we have to insert a manual - // pagebreak at the end of the section. - - if ((!printHeader && context.getHeader() != null) || - (!printFooter && context.getFooter() != null)) - { - setPagebreakDefinition(new PageBreakDefinition(isResetPageNumber())); - } - - return masterPageName; - } - - private boolean isColumnBreakPending() - { - return columnBreakPending; - } - - private void setColumnBreakPending(final boolean columnBreakPending) - { - this.columnBreakPending = columnBreakPending; - } - - private Integer parseInt(final Object value) - { - if (value instanceof Number) - { - final Number n = (Number) value; - return IntegerCache.getInteger(n.intValue()); - } - if (value instanceof String) - { - try - { - return IntegerCache.getInteger(Integer.parseInt((String) value)); - } - catch (NumberFormatException nfe) - { - //return null; // ignore - } - } - return null; - } - - private BufferState applyColumnsToPageBand(final BufferState contents, - final int numberOfColumns) - throws IOException, ReportProcessingException - { - if (numberOfColumns <= 1) - { - return contents; - } - startBuffering(getGlobalStylesCollection(), true); - // derive section style .. - - // This is a rather cheap solution to the problem. In a sane world, we would have to feed the - // footer multiple times. Right now, we simply rely on the balacing, which should make sure that - // the column's content are evenly distributed. - final XmlWriter writer = getXmlWriter(); - final AttributeList attrs = new AttributeList(); - attrs.setAttribute(OfficeNamespaces.TEXT_NS, OfficeToken.STYLE_NAME, generateSectionStyle(numberOfColumns)); - attrs.setAttribute(OfficeNamespaces.TEXT_NS, NAME, sectionNames.generateName("Section")); - writer.writeTag(OfficeNamespaces.TEXT_NS, "section", attrs, XmlWriterSupport.OPEN); - for (int i = 0; i < numberOfColumns; i++) - { - writer.writeStream(contents.getXmlAsReader()); - } - - writer.writeCloseTag(); - return finishBuffering(); - } - - private String generateSectionStyle(final int columnCount) - { - final OfficeStyles automaticStyles = getStylesCollection().getAutomaticStyles(); - final String styleName = getAutoStyleNameGenerator().generateName("auto_section_style"); - - final Section sectionProperties = new Section(); - sectionProperties.setNamespace(OfficeNamespaces.STYLE_NS); - sectionProperties.setType("section-properties"); - sectionProperties.setAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR, "transparent"); - sectionProperties.setAttribute(OfficeNamespaces.TEXT_NS, "dont-balance-text-columns", OfficeToken.FALSE); - sectionProperties.setAttribute(OfficeNamespaces.STYLE_NS, "editable", OfficeToken.FALSE); - - if (columnCount > 1) - { - final Section columns = new Section(); - columns.setNamespace(OfficeNamespaces.STYLE_NS); - columns.setType("columns"); - columns.setAttribute(OfficeNamespaces.FO_NS, "column-count", String.valueOf(columnCount)); - columns.setAttribute(OfficeNamespaces.STYLE_NS, "column-gap", "0cm"); - sectionProperties.addNode(columns); - -// final Section columnSep = new Section(); -// columnSep.setNamespace(OfficeNamespaces.STYLE_NS); -// columnSep.setType("column-sep"); -// columnSep.setAttribute(OfficeNamespaces.STYLE_NS, "width", "0.035cm"); -// columnSep.setAttribute(OfficeNamespaces.STYLE_NS, "color", "#000000"); -// columnSep.setAttribute(OfficeNamespaces.STYLE_NS, "height", "100%"); -// columns.addNode(columnSep); - - for (int i = 0; i < columnCount; i++) - { - final Section column = new Section(); - column.setNamespace(OfficeNamespaces.STYLE_NS); - column.setType("column"); - column.setAttribute(OfficeNamespaces.STYLE_NS, "rel-width", "1*"); - column.setAttribute(OfficeNamespaces.FO_NS, "start-indent", "0cm"); - column.setAttribute(OfficeNamespaces.FO_NS, "end-indent", "0cm"); - columns.addNode(column); - } - } - - final OfficeStyle style = new OfficeStyle(); - style.setNamespace(OfficeNamespaces.STYLE_NS); - style.setType("style"); - style.setAttribute(OfficeNamespaces.STYLE_NS, NAME, styleName); - style.setAttribute(OfficeNamespaces.STYLE_NS, "family", "section"); - style.addNode(sectionProperties); - - automaticStyles.addStyle(style); - return styleName; - } - - /** - * Starts the output of a new office document. This method writes the generic 'office:document-content' tag along with - * all known namespace declarations. - * - * @param report the report object. - * @throws org.jfree.report.DataSourceException - * if there was an error accessing the datasource - * @throws org.jfree.report.ReportProcessingException - * if some other error occured. - */ - public void startReport(final ReportStructureRoot report) - throws DataSourceException, ReportProcessingException - { - super.startReport(report); - variablesDeclarations = new VariablesDeclarations(); - detailBandProcessingState = DETAIL_SECTION_WAIT; - sectionNames.reset(); - - pageFooterOnReportFooter = false; - pageFooterOnReportHeader = false; - pageHeaderOnReportFooter = false; - pageHeaderOnReportHeader = false; - contentProcessingState = TextRawReportTarget.CP_SETUP; - - activePageContext.clear(); - activePageContext.push(new PageContext()); - - final OfficeStylesCollection predefStyles = getPredefinedStylesCollection(); - masterPageFactory = new MasterPageFactory(predefStyles.getMasterStyles()); - - predefStyles.getAutomaticStyles().addStyle(createVariablesStyle(true)); - predefStyles.getAutomaticStyles().addStyle(createVariablesStyle(false)); - } - - private OfficeStyle createVariablesStyle(final boolean keepWithNext) - { - final OfficeStyle variablesSectionStyle = new OfficeStyle(); - variablesSectionStyle.setStyleFamily(OfficeToken.PARAGRAPH); - if (keepWithNext) - { - variablesSectionStyle.setStyleName(TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT); - } - else - { - variablesSectionStyle.setStyleName(TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITHOUT_KEEPWNEXT); - } - - final Section paragraphProps = new Section(); - paragraphProps.setNamespace(OfficeNamespaces.STYLE_NS); - paragraphProps.setType(PARAGRAPH_PROPERTIES); - paragraphProps.setAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR, "transparent"); - paragraphProps.setAttribute(OfficeNamespaces.FO_NS, "text-align", "start"); - paragraphProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_WITH_NEXT, ALWAYS); - paragraphProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_TOGETHER, ALWAYS); - paragraphProps.setAttribute(OfficeNamespaces.STYLE_NS, "vertical-align", "top"); - variablesSectionStyle.addNode(paragraphProps); - - final Section textProps = new Section(); - textProps.setNamespace(OfficeNamespaces.STYLE_NS); - textProps.setType("text-properties"); - textProps.setAttribute(OfficeNamespaces.FO_NS, "font-variant", NORMAL); - textProps.setAttribute(OfficeNamespaces.FO_NS, "text-transform", NONE); - textProps.setAttribute(OfficeNamespaces.FO_NS, "color", "#ffffff"); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-outline", OfficeToken.FALSE); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-blinking", OfficeToken.FALSE); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-line-through-style", NONE); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-line-through-mode", "continuous"); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-position", "0% 100%"); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "font-name", "Tahoma"); - textProps.setAttribute(OfficeNamespaces.FO_NS, "font-size", "1pt"); - textProps.setAttribute(OfficeNamespaces.FO_NS, "letter-spacing", NORMAL); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "letter-kerning", OfficeToken.FALSE); - textProps.setAttribute(OfficeNamespaces.FO_NS, "font-style", NORMAL); - textProps.setAttribute(OfficeNamespaces.FO_NS, "text-shadow", NONE); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-underline-style", NONE); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-underline-mode", "continuous"); - textProps.setAttribute(OfficeNamespaces.FO_NS, "font-weight", NORMAL); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-rotation-angle", "0"); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-emphasize", NONE); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-combine", NONE); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-combine-start-char", ""); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-combine-end-char", ""); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-blinking", OfficeToken.FALSE); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-scale", "100%"); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "font-relief", NONE); - textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-display", NONE); - variablesSectionStyle.addNode(textProps); - return variablesSectionStyle; - } - - protected void startContent(final AttributeMap attrs) - throws IOException, DataSourceException, ReportProcessingException - { - final XmlWriter xmlWriter = getXmlWriter(); - xmlWriter.writeTag(OfficeNamespaces.OFFICE_NS, "text", null, XmlWriterSupport.OPEN); - - // now start the buffering. We have to insert the variables declaration - // later .. - startBuffering(getStylesCollection(), true); - - final Object columnCountRaw = attrs.getAttribute(OfficeNamespaces.FO_NS, "column-count"); - final Integer colCount = parseInt(columnCountRaw); - if (colCount != null) - { - final PageContext pageContext = getCurrentContext(); - pageContext.setColumnCount(colCount); - } - - } - - protected void startOther(final AttributeMap attrs) - throws IOException, DataSourceException, ReportProcessingException - { - final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs); - final String elementType = ReportTargetUtil.getElemenTypeFromAttribute(attrs); - - if (ObjectUtilities.equal(OfficeNamespaces.INTERNAL_NS, namespace)) - { - if (ObjectUtilities.equal(OfficeToken.IMAGE, elementType)) - { - startImageProcessing(attrs); - } - else if (ObjectUtilities.equal(OfficeToken.OBJECT_OLE, elementType) && getCurrentRole() != ROLE_TEMPLATE) - { - startChartProcessing(attrs); - } - return; - } - else if (isFilteredNamespace(namespace)) - { - throw new IllegalStateException("This element should be hidden: " + - namespace + ", " + elementType); - } - - if (isTableMergeActive() && detailBandProcessingState == DETAIL_SECTION_OTHER_PRINTED && ObjectUtilities.equal(OfficeNamespaces.TABLE_NS, namespace) && ObjectUtilities.equal(OfficeToken.TABLE_COLUMNS, elementType)) - { - // Skip the columns section if the tables get merged.. - startBuffering(getStylesCollection(), true); - return; - } - else - { - openSection(); - - final boolean isTableNS = ObjectUtilities.equal(OfficeNamespaces.TABLE_NS, namespace); - if (isTableNS) - { - if (ObjectUtilities.equal(OfficeToken.TABLE, elementType)) - { - startTable(attrs); - return; - } - - if (ObjectUtilities.equal(OfficeToken.TABLE_ROW, elementType)) - { - startRow(attrs); - return; - } - } - - - if (ObjectUtilities.equal(OfficeNamespaces.TEXT_NS, namespace)) - { - if (ObjectUtilities.equal("variable-set", elementType)) - { - // update the variables-declaration thingie .. - final String varName = (String) attrs.getAttribute(OfficeNamespaces.TEXT_NS, NAME); - final String varType = (String) attrs.getAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE); - final String newVarName = variablesDeclarations.produceVariable(varName, varType); - attrs.setAttribute(OfficeNamespaces.TEXT_NS, NAME, newVarName); - } - else if (ObjectUtilities.equal("variable-get", elementType)) - { - final String varName = (String) attrs.getAttribute(OfficeNamespaces.TEXT_NS, NAME); - final String varType = (String) attrs.getAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE); - final String newVarName = variablesDeclarations.produceVariable(varName, varType); - attrs.setAttribute(OfficeNamespaces.TEXT_NS, NAME, newVarName); - // this one must not be written, as the DTD does not declare it. - // attrs.setAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE, null); - } - } - - if (tableLayoutConfig == TABLE_LAYOUT_VARIABLES_PARAGRAPH && variables != null) - { - // This cannot happen as long as the report sections only contain tables. But at some point in the - // future they will be made of paragraphs, and then we are prepared .. - // Log.debug("Variables-Section in own paragraph " + variables); - - StyleUtilities.copyStyle(OfficeToken.PARAGRAPH, - TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, getStylesCollection(), - getGlobalStylesCollection(), getPredefinedStylesCollection()); - final XmlWriter xmlWriter = getXmlWriter(); - xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME, - TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, XmlWriterSupport.OPEN); - xmlWriter.writeText(variables); - xmlWriter.writeCloseTag(); - variables = null; - } - - if (isTableNS && ObjectUtilities.equal(OfficeToken.TABLE_CELL, elementType)) - { - cellEmpty = true; - } - - final boolean keepTogetherOnParagraph = true; - - if (keepTogetherOnParagraph) - { - if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TEXT_NS, OfficeToken.P, attrs)) - { - final int keepTogetherState = getCurrentContext().getKeepTogether(); - cellEmpty = false; - if (!firstCellSeen && (sectionKeepTogether || keepTogetherState == PageContext.KEEP_TOGETHER_GROUP)) - { - OfficeStyle style = null; - final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TEXT_NS, OfficeToken.STYLE_NAME); - if (styleName == null) - { - final boolean keep = (keepTogetherState == PageContext.KEEP_TOGETHER_GROUP || expectedTableRowCount > 0) && isParentKeepTogether(); - final ArrayList propertyNameSpaces = new ArrayList(); - final ArrayList propertyNames = new ArrayList(); - final ArrayList propertyValues = new ArrayList(); - - propertyNameSpaces.add(OfficeNamespaces.FO_NS); - propertyNameSpaces.add(OfficeNamespaces.FO_NS); - propertyNames.add(KEEP_TOGETHER); - propertyValues.add(ALWAYS); - if (keep) - { - propertyNames.add(KEEP_WITH_NEXT); - propertyValues.add(ALWAYS); - } - else - { - propertyNames.add(KEEP_WITH_NEXT); - propertyValues.add(null); - } - style = StyleUtilities.queryStyleByProperties(getStylesCollection(), OfficeToken.PARAGRAPH, PARAGRAPH_PROPERTIES, propertyNameSpaces, propertyNames, propertyValues); - } - if (style == null) - { - style = deriveStyle(OfficeToken.PARAGRAPH, styleName); - // Lets set the 'keep-together' flag.. - - Element paragraphProps = style.getParagraphProperties(); - if (paragraphProps == null) - { - paragraphProps = new Section(); - paragraphProps.setNamespace(OfficeNamespaces.STYLE_NS); - paragraphProps.setType(PARAGRAPH_PROPERTIES); - style.addNode(paragraphProps); - } - paragraphProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_TOGETHER, ALWAYS); - - // We prevent pagebreaks within the two adjacent rows (this one and the next one) if - // either a group-wide keep-together is defined or if we haven't reached the end of the - // current section yet. - if ((keepTogetherState == PageContext.KEEP_TOGETHER_GROUP || expectedTableRowCount > 0) && isParentKeepTogether()) - { - paragraphProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_WITH_NEXT, ALWAYS); - } - } - - attrs.setAttribute(OfficeNamespaces.TEXT_NS, OfficeToken.STYLE_NAME, style.getStyleName()); - } - } - } - - if (ObjectUtilities.equal(OfficeNamespaces.DRAWING_NS, namespace) && ObjectUtilities.equal(OfficeToken.FRAME, elementType)) - { - final String styleName = (String) attrs.getAttribute(OfficeNamespaces.DRAWING_NS, OfficeToken.STYLE_NAME); - final OfficeStyle predefAutoStyle = getPredefinedStylesCollection().getAutomaticStyles().getStyle(OfficeToken.GRAPHIC, styleName); - if (predefAutoStyle != null) - { - // special ole handling - Element graphicProperties = predefAutoStyle.getGraphicProperties(); - graphicProperties.setAttribute(OfficeNamespaces.STYLE_NS, VERTICAL_POS, "from-top"); - graphicProperties.setAttribute(OfficeNamespaces.STYLE_NS, HORIZONTAL_POS, "from-left"); - graphicProperties.setAttribute(OfficeNamespaces.STYLE_NS, "vertical-rel", "paragraph-content"); - graphicProperties.setAttribute(OfficeNamespaces.STYLE_NS, "horizontal-rel", "paragraph"); - graphicProperties.setAttribute(OfficeNamespaces.STYLE_NS, "flow-with-text", "false"); - graphicProperties.setAttribute(OfficeNamespaces.DRAWING_NS, "ole-draw-aspect", "1"); - - // attrs.setAttribute(OfficeNamespaces.DRAWING_NS, OfficeToken.STYLE_NAME, predefAutoStyle.getStyleName()); - } - } - - // process the styles as usual - performStyleProcessing(attrs); - final XmlWriter xmlWriter = getXmlWriter(); - final AttributeList attrList = buildAttributeList(attrs); - xmlWriter.writeTag(namespace, elementType, attrList, XmlWriterSupport.OPEN); - - if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TEXT_NS, OfficeToken.P, attrs)) - { - cellEmpty = false; - if (tableLayoutConfig != TABLE_LAYOUT_VARIABLES_PARAGRAPH && variables != null) - { - //Log.debug("Variables-Section in existing cell " + variables); - xmlWriter.writeText(variables); - variables = null; - } - } - } - } - - private void startRow(final AttributeMap attrs) - throws IOException, ReportProcessingException - { - firstCellSeen = false; - expectedTableRowCount -= 1; - final String rowStyle = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME); - final CSSNumericValue rowHeight = computeRowHeight(rowStyle); - // Log.debug("Adding row-Style: " + rowStyle + " " + rowHeight); - sectionHeight.add(rowHeight); - -// if (expectedTableRowCount > 0) -// { -// // Some other row. Create a keep-together -// -// } -// else -// { -// // This is the last row before the section will end. -// // or (in some weird cases) There is no information when the row will end. -// // Anyway, if we are here, we do not create a keep-together style on the table-row .. -// } - // process the styles as usual - performStyleProcessing(attrs); - - final AttributeList attrList = buildAttributeList(attrs); - getXmlWriter().writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_ROW, attrList, XmlWriterSupport.OPEN); - } - - private void startTable(final AttributeMap attrs) - throws ReportProcessingException, IOException - { - final Integer trc = (Integer) attrs.getAttribute(OfficeNamespaces.INTERNAL_NS, "table-row-count"); - if (trc == null) - { - expectedTableRowCount = -1; - } - else - { - expectedTableRowCount = trc.intValue(); - } - - if (isSectionPagebreakBefore(attrs)) - { - // force a pagebreak .. - setPagebreakDefinition(new PageBreakDefinition(isResetPageNumber())); - } - - // its a table. This means, it is a root-level element - final PageBreakDefinition breakDefinition; - String masterPageName = null; - final int currentRole = getCurrentRole(); - if (contentProcessingState == TextRawReportTarget.CP_FIRST_TABLE) - { - contentProcessingState = TextRawReportTarget.CP_NEXT_TABLE; - - // Processing the report header now. - if (currentRole == OfficeDocumentReportTarget.ROLE_REPORT_HEADER) - { - breakDefinition = new PageBreakDefinition(isResetPageNumber()); - masterPageName = createMasterPage(pageHeaderOnReportHeader, pageFooterOnReportHeader); - if (masterPageName == null) - { - // we should always have a master-page ... - masterPageName = currentMasterPage.getStyleName(); - } - } - else if (currentRole == OfficeDocumentReportTarget.ROLE_REPORT_FOOTER) - { - breakDefinition = new PageBreakDefinition(isResetPageNumber()); - masterPageName = createMasterPage(pageHeaderOnReportFooter, pageFooterOnReportFooter); - if (masterPageName == null && isSectionPagebreakBefore(attrs)) - { - // If we have a manual pagebreak, then activate the current master-page again. - masterPageName = currentMasterPage.getStyleName(); - } - // But we skip this (and therefore the resulting pagebreak) if there is no manual break - // and no other condition that would force an break. - } - else if (currentRole == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_HEADER || currentRole == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_FOOTER) - { - breakDefinition = null; - // no pagebreaks .. - } - else if (currentMasterPage == null || - isPagebreakPending()) - { - // Must be the first table, as we have no master-page yet. - masterPageName = createMasterPage(true, true); - setPagebreakDefinition(null); - if (masterPageName == null) - { - // we should always have a master-page ... - masterPageName = currentMasterPage.getStyleName(); - } - breakDefinition = new PageBreakDefinition(isResetPageNumber()); - } - else - { - breakDefinition = null; - } - } - else if (isPagebreakPending() && - currentRole != OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_HEADER && - currentRole != OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_FOOTER) - { - // Derive an automatic style for the pagebreak. -// Log.debug("Manual pagebreak (within the section): " + getCurrentRole()); - breakDefinition = getPagebreakDefinition(); - setPagebreakDefinition(null); - masterPageName = createMasterPage(true, true); - if (masterPageName == null || isSectionPagebreakBefore(attrs)) - { - // If we have a manual pagebreak, then activate the current master-page again. - masterPageName = currentMasterPage.getStyleName(); - } - } - else - { - breakDefinition = null; - } - - final XmlWriter xmlWriter = getXmlWriter(); - if (detailBandProcessingState == DETAIL_SECTION_OTHER_PRINTED && - masterPageName != null) - { - // close the last table-tag, we will open a new one - xmlWriter.writeCloseTag(); - // Reset the detail-state to 'started' so that the table's columns get printed now. - detailBandProcessingState = DETAIL_SECTION_OTHER_STARTED; - } - - if (tableLayoutConfig == TABLE_LAYOUT_VARIABLES_PARAGRAPH && variables != null) - { - if (masterPageName != null) - { - // write a paragraph that uses the VARIABLES_HIDDEN_STYLE as - // primary style. Derive that one and add the manual pagebreak. - // The predefined style already has the 'keep-together' flags set. -// Log.debug("Variables-Section with new Master-Page " + variables + " " + masterPageName); - - final OfficeStyle style = deriveStyle(OfficeToken.PARAGRAPH, TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT); - style.setAttribute(OfficeNamespaces.STYLE_NS, "master-page-name", masterPageName); - if (breakDefinition.isResetPageNumber()) - { - final Element paragraphProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, PARAGRAPH_PROPERTIES); - paragraphProps.setAttribute(OfficeNamespaces.STYLE_NS, "page-number", "1"); - } - if (isColumnBreakPending()) - { - final Element paragraphProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, PARAGRAPH_PROPERTIES); - paragraphProps.setAttribute(OfficeNamespaces.FO_NS, "break-before", "column"); - setColumnBreakPending(false); - } - xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME, style.getStyleName(), XmlWriterSupport.OPEN); - - masterPageName = null; - //breakDefinition = null; - } - else if (isColumnBreakPending()) - { - setColumnBreakPending(false); - - final OfficeStyle style = deriveStyle(OfficeToken.PARAGRAPH, TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT); - final Element paragraphProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, PARAGRAPH_PROPERTIES); - paragraphProps.setAttribute(OfficeNamespaces.STYLE_NS, "page-number", "1"); - - xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME, style.getStyleName(), XmlWriterSupport.OPEN); - } - else - { - // Write a paragraph without adding the pagebreak. We can reuse the global style, but we have to make - // sure that the style is part of the current 'auto-style' collection. -// Log.debug("Variables-Section " + variables); - - StyleUtilities.copyStyle(OfficeToken.PARAGRAPH, - TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, getStylesCollection(), - getGlobalStylesCollection(), getPredefinedStylesCollection()); - xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME, - TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, XmlWriterSupport.OPEN); - } - xmlWriter.writeText(variables); - xmlWriter.writeCloseTag(); - variables = null; - } - - final boolean keepWithNext = isKeepTableWithNext(); - final boolean localKeepTogether = OfficeToken.TRUE.equals(attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, KEEP_TOGETHER)); - final boolean tableMergeActive = isTableMergeActive(); - if (tableMergeActive) - { - this.sectionKeepTogether = localKeepTogether; - } - else - { - this.sectionKeepTogether = false; - - } - - // Check, whether we have a reason to derive a style... - if (masterPageName != null || - (!tableMergeActive && (localKeepTogether || keepWithNext)) || isColumnBreakPending()) - { - final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME); - final OfficeStyle style = deriveStyle("table", styleName); - - if (masterPageName != null) - { -// Log.debug("Starting a new MasterPage: " + masterPageName); - // Patch the current styles. - // This usually only happens on Table-Styles or Paragraph-Styles - style.setAttribute(OfficeNamespaces.STYLE_NS, "master-page-name", masterPageName); - if (breakDefinition.isResetPageNumber()) - { - final Element paragraphProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, PARAGRAPH_PROPERTIES); - paragraphProps.setAttribute(OfficeNamespaces.STYLE_NS, "page-number", "1"); - } - } - if (isColumnBreakPending()) - { - final Element paragraphProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, PARAGRAPH_PROPERTIES); - paragraphProps.setAttribute(OfficeNamespaces.FO_NS, "break-before", "column"); - setColumnBreakPending(false); - } - - // Inhibit breaks inside the table only if it has been defined and if we do not create one single - // big detail section. In that case, this flag would be invalid and would cause layout-errors. - if (!tableMergeActive) - { - if (localKeepTogether) - { - final Element tableProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, TABLE_PROPERTIES); - tableProps.setAttribute(OfficeNamespaces.STYLE_NS, MAY_BREAK_BETWEEN_ROWS, OfficeToken.FALSE); - } - } - else - { - if (detailBandProcessingState == DETAIL_SECTION_WAIT) - { - detailBandProcessingState = DETAIL_SECTION_FIRST_STARTED; - } - else if (detailBandProcessingState == DETAIL_SECTION_FIRST_PRINTED) - { - detailBandProcessingState = DETAIL_SECTION_OTHER_STARTED; - } - } - if (keepWithNext) - { - boolean addKeepWithNext = true; - if (currentRole == ROLE_GROUP_FOOTER) - { - addKeepWithNext = isParentKeepTogether(); - } - - final Element tableProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, TABLE_PROPERTIES); - tableProps.setAttribute(OfficeNamespaces.STYLE_NS, MAY_BREAK_BETWEEN_ROWS, OfficeToken.FALSE); - if (addKeepWithNext) - { - tableProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_WITH_NEXT, ALWAYS); - // A keep-with-next does not work, if the may-break-betweek rows is not set to false .. - } - } - attrs.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, style.getStyleName()); - // no need to copy the styles, this was done while deriving the - // style .. - } - else - { - // Check, whether we may be able to skip the table. - if (tableMergeActive) - { - if (detailBandProcessingState == DETAIL_SECTION_OTHER_PRINTED) - { - // Skip the whole thing .. - return; - } - else if (detailBandProcessingState == DETAIL_SECTION_WAIT) - { - if (keepWithNext) - { - final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME); - - final OfficeStyle style = deriveStyle(OfficeToken.TABLE, styleName); - final Element tableProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, TABLE_PROPERTIES); - // A keep-with-next does not work, if the may-break-betweek rows is not set to false .. - tableProps.setAttribute(OfficeNamespaces.STYLE_NS, MAY_BREAK_BETWEEN_ROWS, OfficeToken.FALSE); - final String hasGroupFooter = (String) attrs.getAttribute(OfficeNamespaces.INTERNAL_NS, "has-group-footer"); - if (hasGroupFooter != null && hasGroupFooter.equals(OfficeToken.TRUE)) - { - tableProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_WITH_NEXT, ALWAYS); - } - - attrs.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, style.getStyleName()); - } - detailBandProcessingState = DETAIL_SECTION_FIRST_STARTED; - } - else if (detailBandProcessingState == DETAIL_SECTION_FIRST_PRINTED) - { - detailBandProcessingState = DETAIL_SECTION_OTHER_STARTED; - } - } - - // process the styles as usual - performStyleProcessing(attrs); - } - - final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs); - final String elementType = ReportTargetUtil.getElemenTypeFromAttribute(attrs); - final AttributeList attrList = buildAttributeList(attrs); - xmlWriter.writeTag(namespace, elementType, attrList, XmlWriterSupport.OPEN); - } - - private boolean isParentKeepTogether() - { - PageContext context = getCurrentContext(); - if (context != null) - { - context = context.getParent(); - if (context != null) - { - return context.getKeepTogether() == PageContext.KEEP_TOGETHER_GROUP; - } - } - return false; - } - - private boolean isTableMergeActive() - { - return getCurrentRole() == ROLE_DETAIL && - tableLayoutConfig == TABLE_LAYOUT_SINGLE_DETAIL_TABLE; - } - - private void openSection() - throws IOException - { - if (isRepeatingSection()) - { - // repeating sections have other ways of defining columns .. - return; - } - if (getCurrentRole() == ROLE_TEMPLATE || - getCurrentRole() == ROLE_SPREADSHEET_PAGE_HEADER || - getCurrentRole() == ROLE_SPREADSHEET_PAGE_FOOTER) - { - // the template section would break the multi-column stuff and we dont open up sections there - // anyway .. - return; - } - - final PageContext pageContext = getCurrentContext(); - final Integer columnCount = pageContext.getColumnCount(); - if (columnCount != null && !pageContext.isSectionOpen()) - { - final AttributeList attrs = new AttributeList(); - attrs.setAttribute(OfficeNamespaces.TEXT_NS, OfficeToken.STYLE_NAME, generateSectionStyle(columnCount.intValue())); - attrs.setAttribute(OfficeNamespaces.TEXT_NS, NAME, sectionNames.generateName("Section")); - getXmlWriter().writeTag(OfficeNamespaces.TEXT_NS, "section", attrs, XmlWriterSupport.OPEN); - - pageContext.setSectionOpen(true); - } - - } - - protected void startReportSection(final AttributeMap attrs, final int role) - throws IOException, DataSourceException, ReportProcessingException - { - sectionHeight = new LengthCalculator(); - if (role == OfficeDocumentReportTarget.ROLE_TEMPLATE || - role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_HEADER || - role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_FOOTER) - { - // Start buffering with an dummy styles-collection, so that the global styles dont get polluted .. - startBuffering(new OfficeStylesCollection(), true); - } - else if (role == OfficeDocumentReportTarget.ROLE_PAGE_HEADER) - { - startBuffering(getGlobalStylesCollection(), true); - pageHeaderOnReportHeader = PageSection.isPrintWithReportHeader(attrs); - pageHeaderOnReportFooter = PageSection.isPrintWithReportFooter(attrs); - } - else if (role == OfficeDocumentReportTarget.ROLE_PAGE_FOOTER) - { - startBuffering(getGlobalStylesCollection(), true); - pageFooterOnReportHeader = PageSection.isPrintWithReportHeader(attrs); - pageFooterOnReportFooter = PageSection.isPrintWithReportFooter(attrs); - } - else if (role == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_HEADER || role == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_FOOTER) - { - startBuffering(getGlobalStylesCollection(), true); - } - else if (role == OfficeDocumentReportTarget.ROLE_VARIABLES) - { - startBuffering(getGlobalStylesCollection(), false); - } - else - { - contentProcessingState = TextRawReportTarget.CP_FIRST_TABLE; - if (role == OfficeDocumentReportTarget.ROLE_GROUP_HEADER || role == OfficeDocumentReportTarget.ROLE_GROUP_FOOTER) - { - // if we have a repeating header, then skip the first one .. - // if this is a repeating footer, skip the last one. This means, - // we have to buffer all group footers and wait for the next section.. - startBuffering(getContentStylesCollection(), true); - } - - if (role != OfficeDocumentReportTarget.ROLE_DETAIL) - { - // reset the detail-state. The flag will be updated on startTable and endOther(Table) if the - // current role is ROLE_DETAIL - detailBandProcessingState = DETAIL_SECTION_WAIT; - } - } - } - - protected void startGroup(final AttributeMap attrs) - throws IOException, DataSourceException, ReportProcessingException - { - super.startGroup(attrs); - final PageContext pageContext = new PageContext(getCurrentContext()); - activePageContext.push(pageContext); - - final Object resetPageNumber = attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, "reset-page-number"); - if (OfficeToken.TRUE.equals(resetPageNumber)) - { - setPagebreakDefinition(new PageBreakDefinition(true)); - } - - final Object keepTogether = attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, KEEP_TOGETHER); - if ("whole-group".equals(keepTogether)) - { - pageContext.setKeepTogether(PageContext.KEEP_TOGETHER_GROUP); - } - else if ("with-first-detail".equals(keepTogether) && pageContext.getKeepTogether() != PageContext.KEEP_TOGETHER_GROUP) - { - pageContext.setKeepTogether(PageContext.KEEP_TOGETHER_FIRST_DETAIL); - } - - final Object columnCountRaw = attrs.getAttribute(OfficeNamespaces.FO_NS, "column-count"); - final Integer colCount = parseInt(columnCountRaw); - if (colCount != null) - { - pageContext.setColumnCount(colCount); - } - - final Object newColumn = attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, "start-new-column"); - if (OfficeToken.TRUE.equals(newColumn)) - { - setColumnBreakPending(true); - } - } - - protected void startGroupInstance(final AttributeMap attrs) - throws IOException, DataSourceException, ReportProcessingException - { - if (getGroupContext().isGroupWithRepeatingSection()) - { - setPagebreakDefinition(new PageBreakDefinition(isResetPageNumber())); - } - } - - protected void endGroup(final AttributeMap attrs) - throws IOException, DataSourceException, ReportProcessingException - { - if (getGroupContext().isGroupWithRepeatingSection()) - { - setPagebreakDefinition(new PageBreakDefinition(isResetPageNumber())); - } - - super.endGroup(attrs); - finishSection(); - - activePageContext.pop(); - } - - private void finishSection() - throws ReportProcessingException - { - final PageContext pageContext = getCurrentContext(); - if (pageContext.isSectionOpen()) - { - pageContext.setSectionOpen(false); - try - { - getXmlWriter().writeCloseTag(); - } - catch (IOException e) - { - throw new ReportProcessingException("IOError", e); - } - } - } - - protected void endReportSection(final AttributeMap attrs, final int role) - throws IOException, DataSourceException, ReportProcessingException - { - if (role == ROLE_TEMPLATE || - role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_HEADER || - role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_FOOTER) - { - finishBuffering(); - return; - } - - final CSSNumericValue result = sectionHeight.getResult(); - if (role == OfficeDocumentReportTarget.ROLE_PAGE_HEADER) - { - final PageContext pageContext = getCurrentContext(); - pageContext.setHeader(applyColumnsToPageBand(finishBuffering(), pageContext.getActiveColumns()).getXmlBuffer(), result); - } - else if (role == OfficeDocumentReportTarget.ROLE_PAGE_FOOTER) - { - final PageContext pageContext = getCurrentContext(); - pageContext.setFooter(applyColumnsToPageBand(finishBuffering(), pageContext.getActiveColumns()).getXmlBuffer(), result); - } - else if (role == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_HEADER) - { - final PageContext pageContext = getCurrentContext(); - pageContext.setHeader(applyColumnsToPageBand(finishBuffering(), pageContext.getActiveColumns()).getXmlBuffer(), result); - } - else if (role == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_FOOTER) - { - final PageContext pageContext = getCurrentContext(); - pageContext.setFooter(applyColumnsToPageBand(finishBuffering(), pageContext.getActiveColumns()).getXmlBuffer(), result); - } - else if (role == OfficeDocumentReportTarget.ROLE_VARIABLES) - { - if (variables == null) - { - variables = finishBuffering().getXmlBuffer(); - } - else - { - variables += finishBuffering().getXmlBuffer(); - } - } - else if (role == OfficeDocumentReportTarget.ROLE_GROUP_HEADER) - { - final String headerText = finishBuffering().getXmlBuffer(); - final int iterationCount = getGroupContext().getParent().getIterationCount(); - final boolean repeat = OfficeToken.TRUE.equals(attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, "repeat-section")); - if (!repeat || iterationCount > 0) - { - getXmlWriter().writeText(headerText); - } - } - else if (role == OfficeDocumentReportTarget.ROLE_GROUP_FOOTER) - { - final String footerText = finishBuffering().getXmlBuffer(); - // how do we detect whether this is the last group footer? - getXmlWriter().writeText(footerText); - } - - } - - public void endReport(final ReportStructureRoot report) - throws DataSourceException, ReportProcessingException - { - super.endReport(report); - variablesDeclarations = null; - - try - { - // Write the settings .. - final AttributeList rootAttributes = new AttributeList(); - rootAttributes.addNamespaceDeclaration("office", OfficeNamespaces.OFFICE_NS); - rootAttributes.addNamespaceDeclaration("config", OfficeNamespaces.CONFIG); - rootAttributes.addNamespaceDeclaration("ooo", OfficeNamespaces.OO2004_NS); - rootAttributes.setAttribute(OfficeNamespaces.OFFICE_NS, "version", "1.0"); - final OutputStream outputStream = getOutputRepository().createOutputStream("settings.xml", "text/xml"); - final XmlWriter xmlWriter = new XmlWriter(new OutputStreamWriter(outputStream, "UTF-8"), createTagDescription()); - xmlWriter.setAlwaysAddNamespace(true); - xmlWriter.writeXmlDeclaration("UTF-8"); - xmlWriter.writeTag(OfficeNamespaces.OFFICE_NS, "document-settings", rootAttributes, XmlWriterSupport.OPEN); - xmlWriter.writeTag(OfficeNamespaces.OFFICE_NS, "settings", XmlWriterSupport.OPEN); - xmlWriter.writeTag(OfficeNamespaces.CONFIG, "config-item-set", NAME, "ooo:configuration-settings", XmlWriterSupport.OPEN); - - final AttributeList configAttributes = new AttributeList(); - configAttributes.setAttribute(OfficeNamespaces.CONFIG, NAME, "TableRowKeep"); - configAttributes.setAttribute(OfficeNamespaces.CONFIG, "type", "boolean"); - xmlWriter.writeTag(OfficeNamespaces.CONFIG, "config-item", configAttributes, XmlWriterSupport.OPEN); - xmlWriter.writeText(OfficeToken.TRUE); - xmlWriter.writeCloseTag(); - - xmlWriter.writeCloseTag(); - xmlWriter.writeCloseTag(); - xmlWriter.writeCloseTag(); - xmlWriter.close(); - - // now copy the meta.xml - if (getInputRepository().isReadable("meta.xml")) - { - final InputStream inputStream = getInputRepository().createInputStream("meta.xml"); - try - { - final OutputStream outputMetaStream = getOutputRepository().createOutputStream("meta.xml", "text/xml"); - IOUtils.getInstance().copyStreams(inputStream, outputMetaStream); - outputMetaStream.close(); - } finally - { - inputStream.close(); - } - } - } - catch (IOException ioe) - { - throw new ReportProcessingException("Failed to write settings document"); - } - } - - protected void endOther(final AttributeMap attrs) - throws IOException, DataSourceException, ReportProcessingException - { - final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs); - final String elementType = ReportTargetUtil.getElemenTypeFromAttribute(attrs); - - final boolean isInternalNS = ObjectUtilities.equal(OfficeNamespaces.INTERNAL_NS, namespace); - final boolean isTableNs = ObjectUtilities.equal(OfficeNamespaces.TABLE_NS, namespace); - if (isTableMergeActive() && detailBandProcessingState == DETAIL_SECTION_OTHER_PRINTED && isTableNs && ObjectUtilities.equal(OfficeToken.TABLE_COLUMNS, elementType)) - { - finishBuffering(); - return; - } - - if (isInternalNS && (ObjectUtilities.equal(OfficeToken.IMAGE, elementType) || - ObjectUtilities.equal(OfficeToken.OBJECT_OLE, elementType))) - { - return; - } - - final XmlWriter xmlWriter = getXmlWriter(); - if (tableLayoutConfig != TABLE_LAYOUT_VARIABLES_PARAGRAPH && - isTableNs && ObjectUtilities.equal(OfficeToken.TABLE_CELL, elementType)) - { - if (variables != null) - { - // This cannot happen as long as the report sections only contain tables. But at some point in the - // future they will be made of paragraphs, and then we are prepared .. - //Log.debug("Variables-Section " + variables); - final String tag; - if (sectionKeepTogether && expectedTableRowCount > 0) - { - tag = TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT; - } - else - { - tag = TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITHOUT_KEEPWNEXT; - } - StyleUtilities.copyStyle(OfficeToken.PARAGRAPH, - tag, getStylesCollection(), - getGlobalStylesCollection(), getPredefinedStylesCollection()); - xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME, - tag, XmlWriterSupport.OPEN); - xmlWriter.writeText(variables); - xmlWriter.writeCloseTag(); - variables = null; - } - /** - // Only generate the empty paragraph, if we have to add the keep-together .. - else if (cellEmpty && expectedTableRowCount > 0 && - sectionKeepTogether && !firstCellSeen) - { - // we have no variables .. - StyleUtilities.copyStyle(OfficeToken.PARAGRAPH, - TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, getStylesCollection(), - getGlobalStylesCollection(), getPredefinedStylesCollection()); - xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME, - TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, XmlWriterSupport.CLOSE); - } - */ - } - - if (isTableNs && (ObjectUtilities.equal(OfficeToken.TABLE_CELL, elementType) || ObjectUtilities.equal(OfficeToken.COVERED_TABLE_CELL, elementType))) - { - firstCellSeen = true; - } - if (isTableNs && ObjectUtilities.equal(OfficeToken.TABLE, elementType)) - { - if (getCurrentRole() == ROLE_DETAIL) - { - if (!isTableMergeActive()) - { - // We do not merge the detail bands, so an ordinary close will do. - xmlWriter.writeCloseTag(); - } - else if (detailBandProcessingState == DETAIL_SECTION_FIRST_STARTED) - { - final int keepTogetherState = getCurrentContext().getKeepTogether(); - if (keepTogetherState == PageContext.KEEP_TOGETHER_FIRST_DETAIL) - { - xmlWriter.writeCloseTag(); - detailBandProcessingState = DETAIL_SECTION_FIRST_PRINTED; - } - else - { - detailBandProcessingState = DETAIL_SECTION_OTHER_PRINTED; - } - } - else if (detailBandProcessingState == DETAIL_SECTION_OTHER_STARTED) - { - detailBandProcessingState = DETAIL_SECTION_OTHER_PRINTED; - } - } - else - { - xmlWriter.writeCloseTag(); - } - if (isSectionPagebreakAfter(attrs)) - { - setPagebreakDefinition(new PageBreakDefinition(false)); - } - } - else - { - xmlWriter.writeCloseTag(); - } - } - - protected void endGroupBody(final AttributeMap attrs) - throws IOException, DataSourceException, ReportProcessingException - { - if (tableLayoutConfig == TABLE_LAYOUT_SINGLE_DETAIL_TABLE && detailBandProcessingState == DETAIL_SECTION_OTHER_PRINTED) - { - // closes the table .. - final XmlWriter xmlWriter = getXmlWriter(); - xmlWriter.writeCloseTag(); - detailBandProcessingState = DETAIL_SECTION_WAIT; - } - - } - - protected void endContent(final AttributeMap attrs) - throws IOException, DataSourceException, ReportProcessingException - { - finishSection(); - final BufferState bodyText = finishBuffering(); - final XmlWriter writer = getXmlWriter(); - - final Map definedMappings = variablesDeclarations.getDefinedMappings(); - if (!definedMappings.isEmpty()) - { - writer.writeTag(OfficeNamespaces.TEXT_NS, "variable-decls", XmlWriterSupport.OPEN); - final Iterator mappingsIt = definedMappings.entrySet().iterator(); - while (mappingsIt.hasNext()) - { - final Map.Entry entry = (Map.Entry) mappingsIt.next(); - final AttributeList entryList = new AttributeList(); - entryList.setAttribute(OfficeNamespaces.TEXT_NS, NAME, (String) entry.getKey()); - entryList.setAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE, (String) entry.getValue()); - writer.writeTag(OfficeNamespaces.TEXT_NS, "variable-decl", entryList, XmlWriterSupport.CLOSE); - } - writer.writeCloseTag(); - } - - writer.writeStream(bodyText.getXmlAsReader()); - writer.setLineEmpty(true); - writer.writeCloseTag(); - } - - public String getExportDescriptor() - { - return "raw/" + PentahoReportEngineMetaData.OPENDOCUMENT_TEXT; - } -} +/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: TextRawReportTarget.java,v $
+ * $Revision: 1.9 $
+ *
+ * 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.output.text;
+
+import com.sun.star.report.DataSourceFactory;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.InputStream;
+import org.jfree.io.IOUtils;
+import java.io.OutputStreamWriter;
+import java.util.Iterator;
+import java.util.Map;
+
+import com.sun.star.report.ImageService;
+import com.sun.star.report.InputRepository;
+import com.sun.star.report.OutputRepository;
+import com.sun.star.report.pentaho.OfficeNamespaces;
+import com.sun.star.report.OfficeToken;
+import com.sun.star.report.pentaho.PentahoReportEngineMetaData;
+import com.sun.star.report.pentaho.layoutprocessor.FormatValueUtility;
+import com.sun.star.report.pentaho.model.OfficeMasterPage;
+import com.sun.star.report.pentaho.model.OfficeMasterStyles;
+import com.sun.star.report.pentaho.model.OfficeStyle;
+import com.sun.star.report.pentaho.model.OfficeStyles;
+import com.sun.star.report.pentaho.model.OfficeStylesCollection;
+import com.sun.star.report.pentaho.model.PageSection;
+import com.sun.star.report.pentaho.output.OfficeDocumentReportTarget;
+import com.sun.star.report.pentaho.output.StyleUtilities;
+import com.sun.star.report.pentaho.styles.LengthCalculator;
+import java.util.ArrayList;
+import org.jfree.layouting.input.style.values.CSSNumericValue;
+import org.jfree.layouting.util.AttributeMap;
+import org.jfree.report.DataSourceException;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.flow.ReportJob;
+import org.jfree.report.flow.ReportStructureRoot;
+import org.jfree.report.flow.ReportTargetUtil;
+import org.jfree.report.structure.Element;
+import org.jfree.report.structure.Node;
+import org.jfree.report.structure.Section;
+import org.jfree.report.util.AttributeNameGenerator;
+import org.jfree.report.util.IntegerCache;
+import org.jfree.resourceloader.ResourceKey;
+import org.jfree.resourceloader.ResourceManager;
+import org.jfree.util.FastStack;
+import org.jfree.util.ObjectUtilities;
+//import org.jfree.util.Log;
+import org.jfree.xmlns.common.AttributeList;
+import org.jfree.xmlns.writer.XmlWriter;
+import org.jfree.xmlns.writer.XmlWriterSupport;
+
+/**
+ * Creation-Date: 03.07.2006, 16:28:00
+ *
+ * @author Thomas Morgner
+ */
+public class TextRawReportTarget extends OfficeDocumentReportTarget
+{
+
+ private static final String ALWAYS = "always";
+ private static final String KEEP_TOGETHER = "keep-together";
+ private static final String KEEP_WITH_NEXT = "keep-with-next";
+ private static final String MAY_BREAK_BETWEEN_ROWS = "may-break-between-rows";
+ private static final String NAME = "name";
+ private static final String NONE = "none";
+ private static final String NORMAL = "normal";
+ private static final String PARAGRAPH_PROPERTIES = "paragraph-properties";
+ private static final String STANDARD = "Standard";
+ private static final String TABLE_PROPERTIES = "table-properties";
+ private static final String VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT = "variables_paragraph_with_next";
+ private static final String VARIABLES_HIDDEN_STYLE_WITHOUT_KEEPWNEXT = "variables_paragraph_without_next";
+ private static final int TABLE_LAYOUT_VARIABLES_PARAGRAPH = 0;
+ private static final int TABLE_LAYOUT_VARIABLES_IN_FIRST_CELL = 1;
+ private static final int TABLE_LAYOUT_SINGLE_DETAIL_TABLE = 2;
+ private static final int CP_SETUP = 0;
+ private static final int CP_FIRST_TABLE = 1;
+ private static final int CP_NEXT_TABLE = 2;
+
+ // This is the initial state of the detail-band processing. It states, that we are now waiting for a
+ // detail-band to be printed.
+ private static final int DETAIL_SECTION_WAIT = 0;
+ // The first detail section has started.
+ private static final int DETAIL_SECTION_FIRST_STARTED = 1;
+ // The first detail section has been printed.
+ private static final int DETAIL_SECTION_FIRST_PRINTED = 2;
+ // An other detail section has started
+ private static final int DETAIL_SECTION_OTHER_STARTED = 3;
+ // The other detail section has been printed.
+ private static final int DETAIL_SECTION_OTHER_PRINTED = 4;
+ private boolean pageFooterOnReportFooter;
+ private boolean pageFooterOnReportHeader;
+ private boolean pageHeaderOnReportFooter;
+ private boolean pageHeaderOnReportHeader;
+ private int contentProcessingState;
+ private OfficeMasterPage currentMasterPage;
+ private final FastStack activePageContext;
+ private MasterPageFactory masterPageFactory;
+ private LengthCalculator sectionHeight;
+ private String variables;
+ private PageBreakDefinition pageBreakDefinition;
+ private VariablesDeclarations variablesDeclarations;
+ private boolean columnBreakPending;
+ private boolean sectionKeepTogether;
+ private final AttributeNameGenerator sectionNames;
+ private int detailBandProcessingState;
+ private final int tableLayoutConfig;
+ private int expectedTableRowCount;
+ private boolean firstCellSeen;
+ private boolean cellEmpty;
+
+ public TextRawReportTarget(final ReportJob reportJob,
+ final ResourceManager resourceManager,
+ final ResourceKey baseResource,
+ final InputRepository inputRepository,
+ final OutputRepository outputRepository,
+ final String target,
+ final ImageService imageService,
+ final DataSourceFactory datasourcefactory)
+ throws ReportProcessingException
+ {
+ super(reportJob, resourceManager, baseResource, inputRepository, outputRepository, target, imageService, datasourcefactory);
+ activePageContext = new FastStack();
+ this.sectionNames = new AttributeNameGenerator();
+
+ this.tableLayoutConfig = TABLE_LAYOUT_SINGLE_DETAIL_TABLE;
+ }
+
+ protected String getTargetMimeType()
+ {
+ return "application/vnd.oasis.opendocument.text";
+ }
+
+ /**
+ * Checks, whether a manual page break should be inserted at the next possible location.
+ *
+ * @return true, if a pagebreak is pending, false otherwise.
+ */
+ private boolean isPagebreakPending()
+ {
+ return pageBreakDefinition != null;
+ }
+
+ private boolean isResetPageNumber()
+ {
+ if (pageBreakDefinition == null)
+ {
+ return false;
+ }
+ return pageBreakDefinition.isResetPageNumber();
+ }
+
+ /**
+ * Defines, whether a manual pagebreak should be inserted at the next possible location.
+ *
+ * @param pageBreakDefinition the new flag value.
+ */
+ private void setPagebreakDefinition(final PageBreakDefinition pageBreakDefinition)
+ {
+ this.pageBreakDefinition = pageBreakDefinition;
+ }
+
+ private PageBreakDefinition getPagebreakDefinition()
+ {
+ return pageBreakDefinition;
+ }
+
+ // todo
+ private boolean isKeepTableWithNext()
+ {
+ final int keepTogetherState = getCurrentContext().getKeepTogether();
+ if (keepTogetherState == PageContext.KEEP_TOGETHER_GROUP)
+ {
+ return true;
+ }
+
+ final boolean keepWithNext;
+ if (keepTogetherState == PageContext.KEEP_TOGETHER_FIRST_DETAIL)
+ {
+ keepWithNext = (detailBandProcessingState == DETAIL_SECTION_WAIT);
+ }
+ else
+ {
+ keepWithNext = false;
+ }
+ return keepWithNext;
+ }
+
+ private boolean isSectionPagebreakAfter(final AttributeMap attrs)
+ {
+ final Object forceNewPage =
+ attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, "force-new-page");
+ if ("after-section".equals(forceNewPage))
+ {
+ return true;
+ }
+ if ("before-after-section".equals(forceNewPage))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isSectionPagebreakBefore(final AttributeMap attrs)
+ {
+ final Object forceNewPage =
+ attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, "force-new-page");
+ return "before-section".equals(forceNewPage) || "before-after-section".equals(forceNewPage);
+ }
+
+ private PageContext getCurrentContext()
+ {
+ return (PageContext) activePageContext.peek();
+ }
+
+ private String createMasterPage(final boolean printHeader,
+ final boolean printFooter)
+ throws ReportProcessingException
+ {
+ // create the master page for the report-header.
+ // If there is a page-header or footer in the report that gets
+ // surpressed on the report-header, we have to insert a pagebreak
+ // afterwards.
+
+ final String activePageFooter;
+ // Check, whether the report header can have a page-header
+ final PageContext context = getCurrentContext();
+ if (printFooter)
+ {
+ activePageFooter = context.getPageFooterContent();
+ }
+ else
+ {
+ activePageFooter = null;
+ }
+ final String activePageHeader;
+ if (printHeader)
+ {
+ // we have to insert a manual pagebreak after the report header.
+ activePageHeader = context.getPageHeaderContent();
+ }
+ else
+ {
+ activePageHeader = null;
+ }
+
+ final String masterPageName;
+ if (currentMasterPage == null ||
+ !masterPageFactory.containsMasterPage(STANDARD, activePageHeader, activePageFooter))
+ {
+
+ final CSSNumericValue headerSize = context.getAllHeaderSize();
+ final CSSNumericValue footerSize = context.getAllFooterSize();
+
+
+ currentMasterPage = masterPageFactory.createMasterPage(STANDARD, activePageHeader, activePageFooter);
+
+// Log.debug("Created a new master-page: " + currentMasterPage.getStyleName());
+
+ // todo: Store the page-layouts as well.
+ // The page layouts are derived from a common template, but as the
+ // header-heights differ, we have to derive these beasts instead
+ // of copying them
+
+ final OfficeStylesCollection officeStylesCollection = getGlobalStylesCollection();
+ final OfficeMasterStyles officeMasterStyles = officeStylesCollection.getMasterStyles();
+ final String pageLayoutTemplate = currentMasterPage.getPageLayout();
+ if (pageLayoutTemplate == null)
+ {
+ // there is no pagelayout. Create one ..
+ final String derivedLayout = masterPageFactory.createPageStyle(getGlobalStylesCollection().getAutomaticStyles(), headerSize, footerSize);
+ currentMasterPage.setPageLayout(derivedLayout);
+ }
+ else
+ {
+ final String derivedLayout = masterPageFactory.derivePageStyle(pageLayoutTemplate,
+ getPredefinedStylesCollection().getAutomaticStyles(),
+ getGlobalStylesCollection().getAutomaticStyles(), headerSize, footerSize);
+ currentMasterPage.setPageLayout(derivedLayout);
+ }
+ officeMasterStyles.addMasterPage(currentMasterPage);
+ masterPageName = currentMasterPage.getStyleName();
+ }
+ else
+ {
+ // retrieve the master-page.
+ final OfficeMasterPage masterPage = masterPageFactory.getMasterPage(STANDARD, activePageHeader, activePageFooter);
+ if (ObjectUtilities.equal(masterPage.getStyleName(), currentMasterPage.getStyleName()))
+ {
+ // They are the same,
+ masterPageName = null;
+ }
+ else
+ {
+ // reuse the existing one ..
+ currentMasterPage = masterPage;
+ masterPageName = currentMasterPage.getStyleName();
+ }
+ }
+
+ // if either the pageheader or footer are *not* printed with the
+ // report header, then this implies that we have to insert a manual
+ // pagebreak at the end of the section.
+
+ if ((!printHeader && context.getHeader() != null) ||
+ (!printFooter && context.getFooter() != null))
+ {
+ setPagebreakDefinition(new PageBreakDefinition(isResetPageNumber()));
+ }
+
+ return masterPageName;
+ }
+
+ private boolean isColumnBreakPending()
+ {
+ return columnBreakPending;
+ }
+
+ private void setColumnBreakPending(final boolean columnBreakPending)
+ {
+ this.columnBreakPending = columnBreakPending;
+ }
+
+ private Integer parseInt(final Object value)
+ {
+ if (value instanceof Number)
+ {
+ final Number n = (Number) value;
+ return IntegerCache.getInteger(n.intValue());
+ }
+ if (value instanceof String)
+ {
+ try
+ {
+ return IntegerCache.getInteger(Integer.parseInt((String) value));
+ }
+ catch (NumberFormatException nfe)
+ {
+ //return null; // ignore
+ }
+ }
+ return null;
+ }
+
+ private BufferState applyColumnsToPageBand(final BufferState contents,
+ final int numberOfColumns)
+ throws IOException, ReportProcessingException
+ {
+ if (numberOfColumns <= 1)
+ {
+ return contents;
+ }
+ startBuffering(getGlobalStylesCollection(), true);
+ // derive section style ..
+
+ // This is a rather cheap solution to the problem. In a sane world, we would have to feed the
+ // footer multiple times. Right now, we simply rely on the balacing, which should make sure that
+ // the column's content are evenly distributed.
+ final XmlWriter writer = getXmlWriter();
+ final AttributeList attrs = new AttributeList();
+ attrs.setAttribute(OfficeNamespaces.TEXT_NS, OfficeToken.STYLE_NAME, generateSectionStyle(numberOfColumns));
+ attrs.setAttribute(OfficeNamespaces.TEXT_NS, NAME, sectionNames.generateName("Section"));
+ writer.writeTag(OfficeNamespaces.TEXT_NS, "section", attrs, XmlWriterSupport.OPEN);
+ for (int i = 0; i < numberOfColumns; i++)
+ {
+ writer.writeStream(contents.getXmlAsReader());
+ }
+
+ writer.writeCloseTag();
+ return finishBuffering();
+ }
+
+ private String generateSectionStyle(final int columnCount)
+ {
+ final OfficeStyles automaticStyles = getStylesCollection().getAutomaticStyles();
+ final String styleName = getAutoStyleNameGenerator().generateName("auto_section_style");
+
+ final Section sectionProperties = new Section();
+ sectionProperties.setNamespace(OfficeNamespaces.STYLE_NS);
+ sectionProperties.setType("section-properties");
+ sectionProperties.setAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR, "transparent");
+ sectionProperties.setAttribute(OfficeNamespaces.TEXT_NS, "dont-balance-text-columns", OfficeToken.FALSE);
+ sectionProperties.setAttribute(OfficeNamespaces.STYLE_NS, "editable", OfficeToken.FALSE);
+
+ if (columnCount > 1)
+ {
+ final Section columns = new Section();
+ columns.setNamespace(OfficeNamespaces.STYLE_NS);
+ columns.setType("columns");
+ columns.setAttribute(OfficeNamespaces.FO_NS, "column-count", String.valueOf(columnCount));
+ columns.setAttribute(OfficeNamespaces.STYLE_NS, "column-gap", "0cm");
+ sectionProperties.addNode(columns);
+
+// final Section columnSep = new Section();
+// columnSep.setNamespace(OfficeNamespaces.STYLE_NS);
+// columnSep.setType("column-sep");
+// columnSep.setAttribute(OfficeNamespaces.STYLE_NS, "width", "0.035cm");
+// columnSep.setAttribute(OfficeNamespaces.STYLE_NS, "color", "#000000");
+// columnSep.setAttribute(OfficeNamespaces.STYLE_NS, "height", "100%");
+// columns.addNode(columnSep);
+
+ for (int i = 0; i < columnCount; i++)
+ {
+ final Section column = new Section();
+ column.setNamespace(OfficeNamespaces.STYLE_NS);
+ column.setType("column");
+ column.setAttribute(OfficeNamespaces.STYLE_NS, "rel-width", "1*");
+ column.setAttribute(OfficeNamespaces.FO_NS, "start-indent", "0cm");
+ column.setAttribute(OfficeNamespaces.FO_NS, "end-indent", "0cm");
+ columns.addNode(column);
+ }
+ }
+
+ final OfficeStyle style = new OfficeStyle();
+ style.setNamespace(OfficeNamespaces.STYLE_NS);
+ style.setType("style");
+ style.setAttribute(OfficeNamespaces.STYLE_NS, NAME, styleName);
+ style.setAttribute(OfficeNamespaces.STYLE_NS, "family", "section");
+ style.addNode(sectionProperties);
+
+ automaticStyles.addStyle(style);
+ return styleName;
+ }
+
+ /**
+ * Starts the output of a new office document. This method writes the generic 'office:document-content' tag along with
+ * all known namespace declarations.
+ *
+ * @param report the report object.
+ * @throws org.jfree.report.DataSourceException
+ * if there was an error accessing the datasource
+ * @throws org.jfree.report.ReportProcessingException
+ * if some other error occured.
+ */
+ public void startReport(final ReportStructureRoot report)
+ throws DataSourceException, ReportProcessingException
+ {
+ super.startReport(report);
+ variablesDeclarations = new VariablesDeclarations();
+ detailBandProcessingState = DETAIL_SECTION_WAIT;
+ sectionNames.reset();
+
+ pageFooterOnReportFooter = false;
+ pageFooterOnReportHeader = false;
+ pageHeaderOnReportFooter = false;
+ pageHeaderOnReportHeader = false;
+ contentProcessingState = TextRawReportTarget.CP_SETUP;
+
+ activePageContext.clear();
+ activePageContext.push(new PageContext());
+
+ final OfficeStylesCollection predefStyles = getPredefinedStylesCollection();
+ masterPageFactory = new MasterPageFactory(predefStyles.getMasterStyles());
+
+ predefStyles.getAutomaticStyles().addStyle(createVariablesStyle(true));
+ predefStyles.getAutomaticStyles().addStyle(createVariablesStyle(false));
+ }
+
+ private OfficeStyle createVariablesStyle(final boolean keepWithNext)
+ {
+ final OfficeStyle variablesSectionStyle = new OfficeStyle();
+ variablesSectionStyle.setStyleFamily(OfficeToken.PARAGRAPH);
+ if (keepWithNext)
+ {
+ variablesSectionStyle.setStyleName(TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT);
+ }
+ else
+ {
+ variablesSectionStyle.setStyleName(TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITHOUT_KEEPWNEXT);
+ }
+
+ final Section paragraphProps = new Section();
+ paragraphProps.setNamespace(OfficeNamespaces.STYLE_NS);
+ paragraphProps.setType(PARAGRAPH_PROPERTIES);
+ paragraphProps.setAttribute(OfficeNamespaces.FO_NS, OfficeToken.BACKGROUND_COLOR, "transparent");
+ paragraphProps.setAttribute(OfficeNamespaces.FO_NS, "text-align", "start");
+ paragraphProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_WITH_NEXT, ALWAYS);
+ paragraphProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_TOGETHER, ALWAYS);
+ paragraphProps.setAttribute(OfficeNamespaces.STYLE_NS, "vertical-align", "top");
+ variablesSectionStyle.addNode(paragraphProps);
+
+ final Section textProps = new Section();
+ textProps.setNamespace(OfficeNamespaces.STYLE_NS);
+ textProps.setType("text-properties");
+ textProps.setAttribute(OfficeNamespaces.FO_NS, "font-variant", NORMAL);
+ textProps.setAttribute(OfficeNamespaces.FO_NS, "text-transform", NONE);
+ textProps.setAttribute(OfficeNamespaces.FO_NS, "color", "#ffffff");
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-outline", OfficeToken.FALSE);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-blinking", OfficeToken.FALSE);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-line-through-style", NONE);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-line-through-mode", "continuous");
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-position", "0% 100%");
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "font-name", "Tahoma");
+ textProps.setAttribute(OfficeNamespaces.FO_NS, "font-size", "1pt");
+ textProps.setAttribute(OfficeNamespaces.FO_NS, "letter-spacing", NORMAL);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "letter-kerning", OfficeToken.FALSE);
+ textProps.setAttribute(OfficeNamespaces.FO_NS, "font-style", NORMAL);
+ textProps.setAttribute(OfficeNamespaces.FO_NS, "text-shadow", NONE);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-underline-style", NONE);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-underline-mode", "continuous");
+ textProps.setAttribute(OfficeNamespaces.FO_NS, "font-weight", NORMAL);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-rotation-angle", "0");
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-emphasize", NONE);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-combine", NONE);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-combine-start-char", "");
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-combine-end-char", "");
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-blinking", OfficeToken.FALSE);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-scale", "100%");
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "font-relief", NONE);
+ textProps.setAttribute(OfficeNamespaces.STYLE_NS, "text-display", NONE);
+ variablesSectionStyle.addNode(textProps);
+ return variablesSectionStyle;
+ }
+
+ protected void startContent(final AttributeMap attrs)
+ throws IOException, DataSourceException, ReportProcessingException
+ {
+ final XmlWriter xmlWriter = getXmlWriter();
+ xmlWriter.writeTag(OfficeNamespaces.OFFICE_NS, "text", null, XmlWriterSupport.OPEN);
+
+ // now start the buffering. We have to insert the variables declaration
+ // later ..
+ startBuffering(getStylesCollection(), true);
+
+ final Object columnCountRaw = attrs.getAttribute(OfficeNamespaces.FO_NS, "column-count");
+ final Integer colCount = parseInt(columnCountRaw);
+ if (colCount != null)
+ {
+ final PageContext pageContext = getCurrentContext();
+ pageContext.setColumnCount(colCount);
+ }
+
+ }
+
+ protected void startOther(final AttributeMap attrs)
+ throws IOException, DataSourceException, ReportProcessingException
+ {
+ final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs);
+ final String elementType = ReportTargetUtil.getElemenTypeFromAttribute(attrs);
+
+ if (ObjectUtilities.equal(OfficeNamespaces.INTERNAL_NS, namespace))
+ {
+ if (ObjectUtilities.equal(OfficeToken.IMAGE, elementType))
+ {
+ startImageProcessing(attrs);
+ }
+ else if (ObjectUtilities.equal(OfficeToken.OBJECT_OLE, elementType) && getCurrentRole() != ROLE_TEMPLATE)
+ {
+ startChartProcessing(attrs);
+ }
+ return;
+ }
+ else if (isFilteredNamespace(namespace))
+ {
+ throw new IllegalStateException("This element should be hidden: " +
+ namespace + ", " + elementType);
+ }
+
+ if (isTableMergeActive() && detailBandProcessingState == DETAIL_SECTION_OTHER_PRINTED && ObjectUtilities.equal(OfficeNamespaces.TABLE_NS, namespace) && ObjectUtilities.equal(OfficeToken.TABLE_COLUMNS, elementType))
+ {
+ // Skip the columns section if the tables get merged..
+ startBuffering(getStylesCollection(), true);
+ return;
+ }
+ else
+ {
+ openSection();
+
+ final boolean isTableNS = ObjectUtilities.equal(OfficeNamespaces.TABLE_NS, namespace);
+ if (isTableNS)
+ {
+ if (ObjectUtilities.equal(OfficeToken.TABLE, elementType))
+ {
+ startTable(attrs);
+ return;
+ }
+
+ if (ObjectUtilities.equal(OfficeToken.TABLE_ROW, elementType))
+ {
+ startRow(attrs);
+ return;
+ }
+ }
+
+
+ if (ObjectUtilities.equal(OfficeNamespaces.TEXT_NS, namespace))
+ {
+ if (ObjectUtilities.equal("variable-set", elementType))
+ {
+ // update the variables-declaration thingie ..
+ final String varName = (String) attrs.getAttribute(OfficeNamespaces.TEXT_NS, NAME);
+ final String varType = (String) attrs.getAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE);
+ final String newVarName = variablesDeclarations.produceVariable(varName, varType);
+ attrs.setAttribute(OfficeNamespaces.TEXT_NS, NAME, newVarName);
+ }
+ else if (ObjectUtilities.equal("variable-get", elementType))
+ {
+ final String varName = (String) attrs.getAttribute(OfficeNamespaces.TEXT_NS, NAME);
+ final String varType = (String) attrs.getAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE);
+ final String newVarName = variablesDeclarations.produceVariable(varName, varType);
+ attrs.setAttribute(OfficeNamespaces.TEXT_NS, NAME, newVarName);
+ // this one must not be written, as the DTD does not declare it.
+ // attrs.setAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE, null);
+ }
+ }
+
+ if (tableLayoutConfig == TABLE_LAYOUT_VARIABLES_PARAGRAPH && variables != null)
+ {
+ // This cannot happen as long as the report sections only contain tables. But at some point in the
+ // future they will be made of paragraphs, and then we are prepared ..
+ // Log.debug("Variables-Section in own paragraph " + variables);
+
+ StyleUtilities.copyStyle(OfficeToken.PARAGRAPH,
+ TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, getStylesCollection(),
+ getGlobalStylesCollection(), getPredefinedStylesCollection());
+ final XmlWriter xmlWriter = getXmlWriter();
+ xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME,
+ TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, XmlWriterSupport.OPEN);
+ xmlWriter.writeText(variables);
+ xmlWriter.writeCloseTag();
+ variables = null;
+ }
+
+ if (isTableNS && ObjectUtilities.equal(OfficeToken.TABLE_CELL, elementType))
+ {
+ cellEmpty = true;
+ }
+
+ final boolean keepTogetherOnParagraph = true;
+
+ if (keepTogetherOnParagraph)
+ {
+ if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TEXT_NS, OfficeToken.P, attrs))
+ {
+ final int keepTogetherState = getCurrentContext().getKeepTogether();
+ cellEmpty = false;
+ if (!firstCellSeen && (sectionKeepTogether || keepTogetherState == PageContext.KEEP_TOGETHER_GROUP))
+ {
+ OfficeStyle style = null;
+ final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TEXT_NS, OfficeToken.STYLE_NAME);
+ if (styleName == null)
+ {
+ final boolean keep = (keepTogetherState == PageContext.KEEP_TOGETHER_GROUP || expectedTableRowCount > 0) && isParentKeepTogether();
+ final ArrayList propertyNameSpaces = new ArrayList();
+ final ArrayList propertyNames = new ArrayList();
+ final ArrayList propertyValues = new ArrayList();
+
+ propertyNameSpaces.add(OfficeNamespaces.FO_NS);
+ propertyNameSpaces.add(OfficeNamespaces.FO_NS);
+ propertyNames.add(KEEP_TOGETHER);
+ propertyValues.add(ALWAYS);
+ if (keep)
+ {
+ propertyNames.add(KEEP_WITH_NEXT);
+ propertyValues.add(ALWAYS);
+ }
+ else
+ {
+ propertyNames.add(KEEP_WITH_NEXT);
+ propertyValues.add(null);
+ }
+ style = StyleUtilities.queryStyleByProperties(getStylesCollection(), OfficeToken.PARAGRAPH, PARAGRAPH_PROPERTIES, propertyNameSpaces, propertyNames, propertyValues);
+ }
+ if (style == null)
+ {
+ style = deriveStyle(OfficeToken.PARAGRAPH, styleName);
+ // Lets set the 'keep-together' flag..
+
+ Element paragraphProps = style.getParagraphProperties();
+ if (paragraphProps == null)
+ {
+ paragraphProps = new Section();
+ paragraphProps.setNamespace(OfficeNamespaces.STYLE_NS);
+ paragraphProps.setType(PARAGRAPH_PROPERTIES);
+ style.addNode(paragraphProps);
+ }
+ paragraphProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_TOGETHER, ALWAYS);
+
+ // We prevent pagebreaks within the two adjacent rows (this one and the next one) if
+ // either a group-wide keep-together is defined or if we haven't reached the end of the
+ // current section yet.
+ if ((keepTogetherState == PageContext.KEEP_TOGETHER_GROUP || expectedTableRowCount > 0) && isParentKeepTogether())
+ {
+ paragraphProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_WITH_NEXT, ALWAYS);
+ }
+ }
+
+ attrs.setAttribute(OfficeNamespaces.TEXT_NS, OfficeToken.STYLE_NAME, style.getStyleName());
+ }
+ }
+ }
+
+ if (ObjectUtilities.equal(OfficeNamespaces.DRAWING_NS, namespace) && ObjectUtilities.equal(OfficeToken.FRAME, elementType))
+ {
+ final String styleName = (String) attrs.getAttribute(OfficeNamespaces.DRAWING_NS, OfficeToken.STYLE_NAME);
+ final OfficeStyle predefAutoStyle = getPredefinedStylesCollection().getAutomaticStyles().getStyle(OfficeToken.GRAPHIC, styleName);
+ if (predefAutoStyle != null)
+ {
+ // special ole handling
+ final Element graphicProperties = predefAutoStyle.getGraphicProperties();
+ graphicProperties.setAttribute(OfficeNamespaces.STYLE_NS, VERTICAL_POS, "from-top");
+ graphicProperties.setAttribute(OfficeNamespaces.STYLE_NS, HORIZONTAL_POS, "from-left");
+ graphicProperties.setAttribute(OfficeNamespaces.STYLE_NS, "vertical-rel", "paragraph-content");
+ graphicProperties.setAttribute(OfficeNamespaces.STYLE_NS, "horizontal-rel", "paragraph");
+ graphicProperties.setAttribute(OfficeNamespaces.STYLE_NS, "flow-with-text", "false");
+ graphicProperties.setAttribute(OfficeNamespaces.DRAWING_NS, "ole-draw-aspect", "1");
+
+ // attrs.setAttribute(OfficeNamespaces.DRAWING_NS, OfficeToken.STYLE_NAME, predefAutoStyle.getStyleName());
+ }
+ }
+
+ // process the styles as usual
+ performStyleProcessing(attrs);
+ final XmlWriter xmlWriter = getXmlWriter();
+ final AttributeList attrList = buildAttributeList(attrs);
+ xmlWriter.writeTag(namespace, elementType, attrList, XmlWriterSupport.OPEN);
+
+ if (ReportTargetUtil.isElementOfType(OfficeNamespaces.TEXT_NS, OfficeToken.P, attrs))
+ {
+ cellEmpty = false;
+ if (tableLayoutConfig != TABLE_LAYOUT_VARIABLES_PARAGRAPH && variables != null)
+ {
+ //Log.debug("Variables-Section in existing cell " + variables);
+ xmlWriter.writeText(variables);
+ variables = null;
+ }
+ }
+ }
+ }
+
+ private void startRow(final AttributeMap attrs)
+ throws IOException, ReportProcessingException
+ {
+ firstCellSeen = false;
+ expectedTableRowCount -= 1;
+ final String rowStyle = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ final CSSNumericValue rowHeight = computeRowHeight(rowStyle);
+ // Log.debug("Adding row-Style: " + rowStyle + " " + rowHeight);
+ sectionHeight.add(rowHeight);
+
+// if (expectedTableRowCount > 0)
+// {
+// // Some other row. Create a keep-together
+//
+// }
+// else
+// {
+// // This is the last row before the section will end.
+// // or (in some weird cases) There is no information when the row will end.
+// // Anyway, if we are here, we do not create a keep-together style on the table-row ..
+// }
+ // process the styles as usual
+ performStyleProcessing(attrs);
+
+ final AttributeList attrList = buildAttributeList(attrs);
+ getXmlWriter().writeTag(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_ROW, attrList, XmlWriterSupport.OPEN);
+ }
+
+ private void startTable(final AttributeMap attrs)
+ throws ReportProcessingException, IOException
+ {
+ final Integer trc = (Integer) attrs.getAttribute(OfficeNamespaces.INTERNAL_NS, "table-row-count");
+ if (trc == null)
+ {
+ expectedTableRowCount = -1;
+ }
+ else
+ {
+ expectedTableRowCount = trc.intValue();
+ }
+
+ if (isSectionPagebreakBefore(attrs))
+ {
+ // force a pagebreak ..
+ setPagebreakDefinition(new PageBreakDefinition(isResetPageNumber()));
+ }
+
+ // its a table. This means, it is a root-level element
+ final PageBreakDefinition breakDefinition;
+ String masterPageName = null;
+ final int currentRole = getCurrentRole();
+ if (contentProcessingState == TextRawReportTarget.CP_FIRST_TABLE)
+ {
+ contentProcessingState = TextRawReportTarget.CP_NEXT_TABLE;
+
+ // Processing the report header now.
+ if (currentRole == OfficeDocumentReportTarget.ROLE_REPORT_HEADER)
+ {
+ breakDefinition = new PageBreakDefinition(isResetPageNumber());
+ masterPageName = createMasterPage(pageHeaderOnReportHeader, pageFooterOnReportHeader);
+ if (masterPageName == null)
+ {
+ // we should always have a master-page ...
+ masterPageName = currentMasterPage.getStyleName();
+ }
+ }
+ else if (currentRole == OfficeDocumentReportTarget.ROLE_REPORT_FOOTER)
+ {
+ breakDefinition = new PageBreakDefinition(isResetPageNumber());
+ masterPageName = createMasterPage(pageHeaderOnReportFooter, pageFooterOnReportFooter);
+ if (masterPageName == null && isSectionPagebreakBefore(attrs))
+ {
+ // If we have a manual pagebreak, then activate the current master-page again.
+ masterPageName = currentMasterPage.getStyleName();
+ }
+ // But we skip this (and therefore the resulting pagebreak) if there is no manual break
+ // and no other condition that would force an break.
+ }
+ else if (currentRole == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_HEADER || currentRole == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_FOOTER)
+ {
+ breakDefinition = null;
+ // no pagebreaks ..
+ }
+ else if (currentMasterPage == null ||
+ isPagebreakPending())
+ {
+ // Must be the first table, as we have no master-page yet.
+ masterPageName = createMasterPage(true, true);
+ setPagebreakDefinition(null);
+ if (masterPageName == null)
+ {
+ // we should always have a master-page ...
+ masterPageName = currentMasterPage.getStyleName();
+ }
+ breakDefinition = new PageBreakDefinition(isResetPageNumber());
+ }
+ else
+ {
+ breakDefinition = null;
+ }
+ }
+ else if (isPagebreakPending() &&
+ currentRole != OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_HEADER &&
+ currentRole != OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_FOOTER)
+ {
+ // Derive an automatic style for the pagebreak.
+// Log.debug("Manual pagebreak (within the section): " + getCurrentRole());
+ breakDefinition = getPagebreakDefinition();
+ setPagebreakDefinition(null);
+ masterPageName = createMasterPage(true, true);
+ if (masterPageName == null || isSectionPagebreakBefore(attrs))
+ {
+ // If we have a manual pagebreak, then activate the current master-page again.
+ masterPageName = currentMasterPage.getStyleName();
+ }
+ }
+ else
+ {
+ breakDefinition = null;
+ }
+
+ final XmlWriter xmlWriter = getXmlWriter();
+ if (detailBandProcessingState == DETAIL_SECTION_OTHER_PRINTED &&
+ masterPageName != null)
+ {
+ // close the last table-tag, we will open a new one
+ xmlWriter.writeCloseTag();
+ // Reset the detail-state to 'started' so that the table's columns get printed now.
+ detailBandProcessingState = DETAIL_SECTION_OTHER_STARTED;
+ }
+
+ if (tableLayoutConfig == TABLE_LAYOUT_VARIABLES_PARAGRAPH && variables != null)
+ {
+ if (masterPageName != null)
+ {
+ // write a paragraph that uses the VARIABLES_HIDDEN_STYLE as
+ // primary style. Derive that one and add the manual pagebreak.
+ // The predefined style already has the 'keep-together' flags set.
+// Log.debug("Variables-Section with new Master-Page " + variables + " " + masterPageName);
+
+ final OfficeStyle style = deriveStyle(OfficeToken.PARAGRAPH, TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT);
+ style.setAttribute(OfficeNamespaces.STYLE_NS, "master-page-name", masterPageName);
+ if (breakDefinition.isResetPageNumber())
+ {
+ final Element paragraphProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, PARAGRAPH_PROPERTIES);
+ paragraphProps.setAttribute(OfficeNamespaces.STYLE_NS, "page-number", "1");
+ }
+ if (isColumnBreakPending())
+ {
+ final Element paragraphProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, PARAGRAPH_PROPERTIES);
+ paragraphProps.setAttribute(OfficeNamespaces.FO_NS, "break-before", "column");
+ setColumnBreakPending(false);
+ }
+ xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME, style.getStyleName(), XmlWriterSupport.OPEN);
+
+ masterPageName = null;
+ //breakDefinition = null;
+ }
+ else if (isColumnBreakPending())
+ {
+ setColumnBreakPending(false);
+
+ final OfficeStyle style = deriveStyle(OfficeToken.PARAGRAPH, TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT);
+ final Element paragraphProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, PARAGRAPH_PROPERTIES);
+ paragraphProps.setAttribute(OfficeNamespaces.STYLE_NS, "page-number", "1");
+
+ xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME, style.getStyleName(), XmlWriterSupport.OPEN);
+ }
+ else
+ {
+ // Write a paragraph without adding the pagebreak. We can reuse the global style, but we have to make
+ // sure that the style is part of the current 'auto-style' collection.
+// Log.debug("Variables-Section " + variables);
+
+ StyleUtilities.copyStyle(OfficeToken.PARAGRAPH,
+ TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, getStylesCollection(),
+ getGlobalStylesCollection(), getPredefinedStylesCollection());
+ xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME,
+ TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, XmlWriterSupport.OPEN);
+ }
+ xmlWriter.writeText(variables);
+ xmlWriter.writeCloseTag();
+ variables = null;
+ }
+
+ final boolean keepWithNext = isKeepTableWithNext();
+ final boolean localKeepTogether = OfficeToken.TRUE.equals(attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, KEEP_TOGETHER));
+ final boolean tableMergeActive = isTableMergeActive();
+ if (tableMergeActive)
+ {
+ this.sectionKeepTogether = localKeepTogether;
+ }
+ else
+ {
+ this.sectionKeepTogether = false;
+
+ }
+
+ // Check, whether we have a reason to derive a style...
+ if (masterPageName != null ||
+ (!tableMergeActive && (localKeepTogether || keepWithNext)) || isColumnBreakPending())
+ {
+ final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ final OfficeStyle style = deriveStyle("table", styleName);
+
+ if (masterPageName != null)
+ {
+// Log.debug("Starting a new MasterPage: " + masterPageName);
+ // Patch the current styles.
+ // This usually only happens on Table-Styles or Paragraph-Styles
+ style.setAttribute(OfficeNamespaces.STYLE_NS, "master-page-name", masterPageName);
+ if (breakDefinition.isResetPageNumber())
+ {
+ final Element paragraphProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, PARAGRAPH_PROPERTIES);
+ paragraphProps.setAttribute(OfficeNamespaces.STYLE_NS, "page-number", "1");
+ }
+ }
+ if (isColumnBreakPending())
+ {
+ final Element paragraphProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, PARAGRAPH_PROPERTIES);
+ paragraphProps.setAttribute(OfficeNamespaces.FO_NS, "break-before", "column");
+ setColumnBreakPending(false);
+ }
+
+ // Inhibit breaks inside the table only if it has been defined and if we do not create one single
+ // big detail section. In that case, this flag would be invalid and would cause layout-errors.
+ if (!tableMergeActive)
+ {
+ if (localKeepTogether)
+ {
+ final Element tableProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, TABLE_PROPERTIES);
+ tableProps.setAttribute(OfficeNamespaces.STYLE_NS, MAY_BREAK_BETWEEN_ROWS, OfficeToken.FALSE);
+ }
+ }
+ else
+ {
+ if (detailBandProcessingState == DETAIL_SECTION_WAIT)
+ {
+ detailBandProcessingState = DETAIL_SECTION_FIRST_STARTED;
+ }
+ else if (detailBandProcessingState == DETAIL_SECTION_FIRST_PRINTED)
+ {
+ detailBandProcessingState = DETAIL_SECTION_OTHER_STARTED;
+ }
+ }
+ if (keepWithNext)
+ {
+ boolean addKeepWithNext = true;
+ if (currentRole == ROLE_GROUP_FOOTER)
+ {
+ addKeepWithNext = isParentKeepTogether();
+ }
+
+ final Element tableProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, TABLE_PROPERTIES);
+ tableProps.setAttribute(OfficeNamespaces.STYLE_NS, MAY_BREAK_BETWEEN_ROWS, OfficeToken.FALSE);
+ if (addKeepWithNext)
+ {
+ tableProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_WITH_NEXT, ALWAYS);
+ // A keep-with-next does not work, if the may-break-betweek rows is not set to false ..
+ }
+ }
+ attrs.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, style.getStyleName());
+ // no need to copy the styles, this was done while deriving the
+ // style ..
+ }
+ else
+ {
+ // Check, whether we may be able to skip the table.
+ if (tableMergeActive)
+ {
+ if (detailBandProcessingState == DETAIL_SECTION_OTHER_PRINTED)
+ {
+ // Skip the whole thing ..
+ return;
+ }
+ else if (detailBandProcessingState == DETAIL_SECTION_WAIT)
+ {
+ if (keepWithNext)
+ {
+ final String styleName = (String) attrs.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+
+ final OfficeStyle style = deriveStyle(OfficeToken.TABLE, styleName);
+ final Element tableProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, TABLE_PROPERTIES);
+ // A keep-with-next does not work, if the may-break-betweek rows is not set to false ..
+ tableProps.setAttribute(OfficeNamespaces.STYLE_NS, MAY_BREAK_BETWEEN_ROWS, OfficeToken.FALSE);
+ final String hasGroupFooter = (String) attrs.getAttribute(OfficeNamespaces.INTERNAL_NS, "has-group-footer");
+ if (hasGroupFooter != null && hasGroupFooter.equals(OfficeToken.TRUE))
+ {
+ tableProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_WITH_NEXT, ALWAYS);
+ }
+
+ attrs.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, style.getStyleName());
+ }
+ detailBandProcessingState = DETAIL_SECTION_FIRST_STARTED;
+ }
+ else if (detailBandProcessingState == DETAIL_SECTION_FIRST_PRINTED)
+ {
+ detailBandProcessingState = DETAIL_SECTION_OTHER_STARTED;
+ }
+ }
+
+ // process the styles as usual
+ performStyleProcessing(attrs);
+ }
+
+ final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs);
+ final String elementType = ReportTargetUtil.getElemenTypeFromAttribute(attrs);
+ final AttributeList attrList = buildAttributeList(attrs);
+ xmlWriter.writeTag(namespace, elementType, attrList, XmlWriterSupport.OPEN);
+ }
+
+ private boolean isParentKeepTogether()
+ {
+ PageContext context = getCurrentContext();
+ if (context != null)
+ {
+ context = context.getParent();
+ if (context != null)
+ {
+ return context.getKeepTogether() == PageContext.KEEP_TOGETHER_GROUP;
+ }
+ }
+ return false;
+ }
+
+ private boolean isTableMergeActive()
+ {
+ return getCurrentRole() == ROLE_DETAIL &&
+ tableLayoutConfig == TABLE_LAYOUT_SINGLE_DETAIL_TABLE;
+ }
+
+ private void openSection()
+ throws IOException
+ {
+ if (isRepeatingSection())
+ {
+ // repeating sections have other ways of defining columns ..
+ return;
+ }
+ if (getCurrentRole() == ROLE_TEMPLATE ||
+ getCurrentRole() == ROLE_SPREADSHEET_PAGE_HEADER ||
+ getCurrentRole() == ROLE_SPREADSHEET_PAGE_FOOTER)
+ {
+ // the template section would break the multi-column stuff and we dont open up sections there
+ // anyway ..
+ return;
+ }
+
+ final PageContext pageContext = getCurrentContext();
+ final Integer columnCount = pageContext.getColumnCount();
+ if (columnCount != null && !pageContext.isSectionOpen())
+ {
+ final AttributeList attrs = new AttributeList();
+ attrs.setAttribute(OfficeNamespaces.TEXT_NS, OfficeToken.STYLE_NAME, generateSectionStyle(columnCount.intValue()));
+ attrs.setAttribute(OfficeNamespaces.TEXT_NS, NAME, sectionNames.generateName("Section"));
+ getXmlWriter().writeTag(OfficeNamespaces.TEXT_NS, "section", attrs, XmlWriterSupport.OPEN);
+
+ pageContext.setSectionOpen(true);
+ }
+
+ }
+
+ protected void startReportSection(final AttributeMap attrs, final int role)
+ throws IOException, DataSourceException, ReportProcessingException
+ {
+ sectionHeight = new LengthCalculator();
+ if (role == OfficeDocumentReportTarget.ROLE_TEMPLATE ||
+ role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_HEADER ||
+ role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_FOOTER)
+ {
+ // Start buffering with an dummy styles-collection, so that the global styles dont get polluted ..
+ startBuffering(new OfficeStylesCollection(), true);
+ }
+ else if (role == OfficeDocumentReportTarget.ROLE_PAGE_HEADER)
+ {
+ startBuffering(getGlobalStylesCollection(), true);
+ pageHeaderOnReportHeader = PageSection.isPrintWithReportHeader(attrs);
+ pageHeaderOnReportFooter = PageSection.isPrintWithReportFooter(attrs);
+ }
+ else if (role == OfficeDocumentReportTarget.ROLE_PAGE_FOOTER)
+ {
+ startBuffering(getGlobalStylesCollection(), true);
+ pageFooterOnReportHeader = PageSection.isPrintWithReportHeader(attrs);
+ pageFooterOnReportFooter = PageSection.isPrintWithReportFooter(attrs);
+ }
+ else if (role == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_HEADER || role == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_FOOTER)
+ {
+ startBuffering(getGlobalStylesCollection(), true);
+ }
+ else if (role == OfficeDocumentReportTarget.ROLE_VARIABLES)
+ {
+ startBuffering(getGlobalStylesCollection(), false);
+ }
+ else
+ {
+ contentProcessingState = TextRawReportTarget.CP_FIRST_TABLE;
+ if (role == OfficeDocumentReportTarget.ROLE_GROUP_HEADER || role == OfficeDocumentReportTarget.ROLE_GROUP_FOOTER)
+ {
+ // if we have a repeating header, then skip the first one ..
+ // if this is a repeating footer, skip the last one. This means,
+ // we have to buffer all group footers and wait for the next section..
+ startBuffering(getContentStylesCollection(), true);
+ }
+
+ if (role != OfficeDocumentReportTarget.ROLE_DETAIL)
+ {
+ // reset the detail-state. The flag will be updated on startTable and endOther(Table) if the
+ // current role is ROLE_DETAIL
+ detailBandProcessingState = DETAIL_SECTION_WAIT;
+ }
+ }
+ }
+
+ protected void startGroup(final AttributeMap attrs)
+ throws IOException, DataSourceException, ReportProcessingException
+ {
+ super.startGroup(attrs);
+ final PageContext pageContext = new PageContext(getCurrentContext());
+ activePageContext.push(pageContext);
+
+ final Object resetPageNumber = attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, "reset-page-number");
+ if (OfficeToken.TRUE.equals(resetPageNumber))
+ {
+ setPagebreakDefinition(new PageBreakDefinition(true));
+ }
+
+ final Object keepTogether = attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, KEEP_TOGETHER);
+ if ("whole-group".equals(keepTogether))
+ {
+ pageContext.setKeepTogether(PageContext.KEEP_TOGETHER_GROUP);
+ }
+ else if ("with-first-detail".equals(keepTogether) && pageContext.getKeepTogether() != PageContext.KEEP_TOGETHER_GROUP)
+ {
+ pageContext.setKeepTogether(PageContext.KEEP_TOGETHER_FIRST_DETAIL);
+ }
+
+ final Object columnCountRaw = attrs.getAttribute(OfficeNamespaces.FO_NS, "column-count");
+ final Integer colCount = parseInt(columnCountRaw);
+ if (colCount != null)
+ {
+ pageContext.setColumnCount(colCount);
+ }
+
+ final Object newColumn = attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, "start-new-column");
+ if (OfficeToken.TRUE.equals(newColumn))
+ {
+ setColumnBreakPending(true);
+ }
+ }
+
+ protected void startGroupInstance(final AttributeMap attrs)
+ throws IOException, DataSourceException, ReportProcessingException
+ {
+ if (getGroupContext().isGroupWithRepeatingSection())
+ {
+ setPagebreakDefinition(new PageBreakDefinition(isResetPageNumber()));
+ }
+ }
+
+ protected void endGroup(final AttributeMap attrs)
+ throws IOException, DataSourceException, ReportProcessingException
+ {
+ if (getGroupContext().isGroupWithRepeatingSection())
+ {
+ setPagebreakDefinition(new PageBreakDefinition(isResetPageNumber()));
+ }
+
+ super.endGroup(attrs);
+ finishSection();
+
+ activePageContext.pop();
+ }
+
+ private void finishSection()
+ throws ReportProcessingException
+ {
+ final PageContext pageContext = getCurrentContext();
+ if (pageContext.isSectionOpen())
+ {
+ pageContext.setSectionOpen(false);
+ try
+ {
+ getXmlWriter().writeCloseTag();
+ }
+ catch (IOException e)
+ {
+ throw new ReportProcessingException("IOError", e);
+ }
+ }
+ }
+
+ protected void endReportSection(final AttributeMap attrs, final int role)
+ throws IOException, DataSourceException, ReportProcessingException
+ {
+ if (role == ROLE_TEMPLATE ||
+ role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_HEADER ||
+ role == OfficeDocumentReportTarget.ROLE_SPREADSHEET_PAGE_FOOTER)
+ {
+ finishBuffering();
+ return;
+ }
+
+ final CSSNumericValue result = sectionHeight.getResult();
+ if (role == OfficeDocumentReportTarget.ROLE_PAGE_HEADER)
+ {
+ final PageContext pageContext = getCurrentContext();
+ pageContext.setHeader(applyColumnsToPageBand(finishBuffering(), pageContext.getActiveColumns()).getXmlBuffer(), result);
+ }
+ else if (role == OfficeDocumentReportTarget.ROLE_PAGE_FOOTER)
+ {
+ final PageContext pageContext = getCurrentContext();
+ pageContext.setFooter(applyColumnsToPageBand(finishBuffering(), pageContext.getActiveColumns()).getXmlBuffer(), result);
+ }
+ else if (role == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_HEADER)
+ {
+ final PageContext pageContext = getCurrentContext();
+ pageContext.setHeader(applyColumnsToPageBand(finishBuffering(), pageContext.getActiveColumns()).getXmlBuffer(), result);
+ }
+ else if (role == OfficeDocumentReportTarget.ROLE_REPEATING_GROUP_FOOTER)
+ {
+ final PageContext pageContext = getCurrentContext();
+ pageContext.setFooter(applyColumnsToPageBand(finishBuffering(), pageContext.getActiveColumns()).getXmlBuffer(), result);
+ }
+ else if (role == OfficeDocumentReportTarget.ROLE_VARIABLES)
+ {
+ if (variables == null)
+ {
+ variables = finishBuffering().getXmlBuffer();
+ }
+ else
+ {
+ variables += finishBuffering().getXmlBuffer();
+ }
+ }
+ else if (role == OfficeDocumentReportTarget.ROLE_GROUP_HEADER)
+ {
+ final String headerText = finishBuffering().getXmlBuffer();
+ final int iterationCount = getGroupContext().getParent().getIterationCount();
+ final boolean repeat = OfficeToken.TRUE.equals(attrs.getAttribute(OfficeNamespaces.OOREPORT_NS, "repeat-section"));
+ if (!repeat || iterationCount > 0)
+ {
+ getXmlWriter().writeText(headerText);
+ }
+ }
+ else if (role == OfficeDocumentReportTarget.ROLE_GROUP_FOOTER)
+ {
+ final String footerText = finishBuffering().getXmlBuffer();
+ // how do we detect whether this is the last group footer?
+ getXmlWriter().writeText(footerText);
+ }
+
+ }
+
+ public void endReport(final ReportStructureRoot report)
+ throws DataSourceException, ReportProcessingException
+ {
+ super.endReport(report);
+ variablesDeclarations = null;
+
+ try
+ {
+ // Write the settings ..
+ final AttributeList rootAttributes = new AttributeList();
+ rootAttributes.addNamespaceDeclaration("office", OfficeNamespaces.OFFICE_NS);
+ rootAttributes.addNamespaceDeclaration("config", OfficeNamespaces.CONFIG);
+ rootAttributes.addNamespaceDeclaration("ooo", OfficeNamespaces.OO2004_NS);
+ rootAttributes.setAttribute(OfficeNamespaces.OFFICE_NS, "version", "1.0");
+ final OutputStream outputStream = getOutputRepository().createOutputStream("settings.xml", "text/xml");
+ final XmlWriter xmlWriter = new XmlWriter(new OutputStreamWriter(outputStream, "UTF-8"), createTagDescription());
+ xmlWriter.setAlwaysAddNamespace(true);
+ xmlWriter.writeXmlDeclaration("UTF-8");
+ xmlWriter.writeTag(OfficeNamespaces.OFFICE_NS, "document-settings", rootAttributes, XmlWriterSupport.OPEN);
+ xmlWriter.writeTag(OfficeNamespaces.OFFICE_NS, "settings", XmlWriterSupport.OPEN);
+ xmlWriter.writeTag(OfficeNamespaces.CONFIG, "config-item-set", NAME, "ooo:configuration-settings", XmlWriterSupport.OPEN);
+
+ final AttributeList configAttributes = new AttributeList();
+ configAttributes.setAttribute(OfficeNamespaces.CONFIG, NAME, "TableRowKeep");
+ configAttributes.setAttribute(OfficeNamespaces.CONFIG, "type", "boolean");
+ xmlWriter.writeTag(OfficeNamespaces.CONFIG, "config-item", configAttributes, XmlWriterSupport.OPEN);
+ xmlWriter.writeText(OfficeToken.TRUE);
+ xmlWriter.writeCloseTag();
+
+ xmlWriter.writeCloseTag();
+ xmlWriter.writeCloseTag();
+ xmlWriter.writeCloseTag();
+ xmlWriter.close();
+
+ // now copy the meta.xml
+ if (getInputRepository().isReadable("meta.xml"))
+ {
+ final InputStream inputStream = getInputRepository().createInputStream("meta.xml");
+ try
+ {
+ final OutputStream outputMetaStream = getOutputRepository().createOutputStream("meta.xml", "text/xml");
+ IOUtils.getInstance().copyStreams(inputStream, outputMetaStream);
+ outputMetaStream.close();
+ } finally
+ {
+ inputStream.close();
+ }
+ }
+ }
+ catch (IOException ioe)
+ {
+ throw new ReportProcessingException("Failed to write settings document");
+ }
+ }
+
+ protected void endOther(final AttributeMap attrs)
+ throws IOException, DataSourceException, ReportProcessingException
+ {
+ final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs);
+ final String elementType = ReportTargetUtil.getElemenTypeFromAttribute(attrs);
+
+ final boolean isInternalNS = ObjectUtilities.equal(OfficeNamespaces.INTERNAL_NS, namespace);
+ final boolean isTableNs = ObjectUtilities.equal(OfficeNamespaces.TABLE_NS, namespace);
+ if (isTableMergeActive() && detailBandProcessingState == DETAIL_SECTION_OTHER_PRINTED && isTableNs && ObjectUtilities.equal(OfficeToken.TABLE_COLUMNS, elementType))
+ {
+ finishBuffering();
+ return;
+ }
+
+ if (isInternalNS && (ObjectUtilities.equal(OfficeToken.IMAGE, elementType) ||
+ ObjectUtilities.equal(OfficeToken.OBJECT_OLE, elementType)))
+ {
+ return;
+ }
+
+ final XmlWriter xmlWriter = getXmlWriter();
+ if (tableLayoutConfig != TABLE_LAYOUT_VARIABLES_PARAGRAPH &&
+ isTableNs && ObjectUtilities.equal(OfficeToken.TABLE_CELL, elementType))
+ {
+ if (variables != null)
+ {
+ // This cannot happen as long as the report sections only contain tables. But at some point in the
+ // future they will be made of paragraphs, and then we are prepared ..
+ //Log.debug("Variables-Section " + variables);
+ final String tag;
+ if (sectionKeepTogether && expectedTableRowCount > 0)
+ {
+ tag = TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT;
+ }
+ else
+ {
+ tag = TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITHOUT_KEEPWNEXT;
+ }
+ StyleUtilities.copyStyle(OfficeToken.PARAGRAPH,
+ tag, getStylesCollection(),
+ getGlobalStylesCollection(), getPredefinedStylesCollection());
+ xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME,
+ tag, XmlWriterSupport.OPEN);
+ xmlWriter.writeText(variables);
+ xmlWriter.writeCloseTag();
+ variables = null;
+ }
+ /**
+ // Only generate the empty paragraph, if we have to add the keep-together ..
+ else if (cellEmpty && expectedTableRowCount > 0 &&
+ sectionKeepTogether && !firstCellSeen)
+ {
+ // we have no variables ..
+ StyleUtilities.copyStyle(OfficeToken.PARAGRAPH,
+ TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, getStylesCollection(),
+ getGlobalStylesCollection(), getPredefinedStylesCollection());
+ xmlWriter.writeTag(OfficeNamespaces.TEXT_NS, OfficeToken.P, OfficeToken.STYLE_NAME,
+ TextRawReportTarget.VARIABLES_HIDDEN_STYLE_WITH_KEEPWNEXT, XmlWriterSupport.CLOSE);
+ }
+ */
+ }
+
+ if (isTableNs && (ObjectUtilities.equal(OfficeToken.TABLE_CELL, elementType) || ObjectUtilities.equal(OfficeToken.COVERED_TABLE_CELL, elementType)))
+ {
+ firstCellSeen = true;
+ }
+ if (isTableNs && ObjectUtilities.equal(OfficeToken.TABLE, elementType))
+ {
+ if (getCurrentRole() == ROLE_DETAIL)
+ {
+ if (!isTableMergeActive())
+ {
+ // We do not merge the detail bands, so an ordinary close will do.
+ xmlWriter.writeCloseTag();
+ }
+ else if (detailBandProcessingState == DETAIL_SECTION_FIRST_STARTED)
+ {
+ final int keepTogetherState = getCurrentContext().getKeepTogether();
+ if (keepTogetherState == PageContext.KEEP_TOGETHER_FIRST_DETAIL)
+ {
+ xmlWriter.writeCloseTag();
+ detailBandProcessingState = DETAIL_SECTION_FIRST_PRINTED;
+ }
+ else
+ {
+ detailBandProcessingState = DETAIL_SECTION_OTHER_PRINTED;
+ }
+ }
+ else if (detailBandProcessingState == DETAIL_SECTION_OTHER_STARTED)
+ {
+ detailBandProcessingState = DETAIL_SECTION_OTHER_PRINTED;
+ }
+ }
+ else
+ {
+ xmlWriter.writeCloseTag();
+ }
+ if (isSectionPagebreakAfter(attrs))
+ {
+ setPagebreakDefinition(new PageBreakDefinition(false));
+ }
+ }
+ else
+ {
+ xmlWriter.writeCloseTag();
+ }
+ }
+
+ protected void endGroupBody(final AttributeMap attrs)
+ throws IOException, DataSourceException, ReportProcessingException
+ {
+ if (tableLayoutConfig == TABLE_LAYOUT_SINGLE_DETAIL_TABLE && detailBandProcessingState == DETAIL_SECTION_OTHER_PRINTED)
+ {
+ // closes the table ..
+ final XmlWriter xmlWriter = getXmlWriter();
+ xmlWriter.writeCloseTag();
+ detailBandProcessingState = DETAIL_SECTION_WAIT;
+ }
+
+ }
+
+ protected void endContent(final AttributeMap attrs)
+ throws IOException, DataSourceException, ReportProcessingException
+ {
+ finishSection();
+ final BufferState bodyText = finishBuffering();
+ final XmlWriter writer = getXmlWriter();
+
+ final Map definedMappings = variablesDeclarations.getDefinedMappings();
+ if (!definedMappings.isEmpty())
+ {
+ writer.writeTag(OfficeNamespaces.TEXT_NS, "variable-decls", XmlWriterSupport.OPEN);
+ final Iterator mappingsIt = definedMappings.entrySet().iterator();
+ while (mappingsIt.hasNext())
+ {
+ final Map.Entry entry = (Map.Entry) mappingsIt.next();
+ final AttributeList entryList = new AttributeList();
+ entryList.setAttribute(OfficeNamespaces.TEXT_NS, NAME, (String) entry.getKey());
+ entryList.setAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE, (String) entry.getValue());
+ writer.writeTag(OfficeNamespaces.TEXT_NS, "variable-decl", entryList, XmlWriterSupport.CLOSE);
+ }
+ writer.writeCloseTag();
+ }
+
+ writer.writeStream(bodyText.getXmlAsReader());
+ writer.setLineEmpty(true);
+ writer.writeCloseTag();
+ }
+
+ public String getExportDescriptor()
+ {
+ return "raw/" + PentahoReportEngineMetaData.OPENDOCUMENT_TEXT;
+ }
+}
|