summaryrefslogtreecommitdiff
path: root/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor
diff options
context:
space:
mode:
Diffstat (limited to 'reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor')
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/AbstractReportElementLayoutController.java269
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FixedTextLayoutController.java85
-rwxr-xr-xreportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FormatValueUtility.java241
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FormattedTextLayoutController.java229
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ImageElementContext.java90
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ImageElementLayoutController.java325
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ObjectOleLayoutController.java124
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeDetailLayoutController.java159
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupInstanceSectionLayoutController.java153
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupLayoutController.java204
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupSectionLayoutController.java109
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficePageSectionLayoutController.java30
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeRepeatingStructureLayoutController.java43
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeReportLayoutController.java270
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeTableLayoutController.java79
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeTableTemplateLayoutController.java189
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/TableCellLayoutController.java216
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/VariablesCollection.java97
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/VariablesDeclarationLayoutController.java191
19 files changed, 3103 insertions, 0 deletions
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/AbstractReportElementLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/AbstractReportElementLayoutController.java
new file mode 100644
index 000000000000..85f841a11338
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/AbstractReportElementLayoutController.java
@@ -0,0 +1,269 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.pentaho.model.OfficeGroupSection;
+import com.sun.star.report.pentaho.model.ReportElement;
+
+import org.jfree.report.DataFlags;
+import org.jfree.report.DataRow;
+import org.jfree.report.DataSourceException;
+import org.jfree.report.ReportDataFactoryException;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.expressions.Expression;
+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.flow.layoutprocessor.SectionLayoutController;
+import org.jfree.report.structure.Element;
+import org.jfree.report.structure.Group;
+
+import org.pentaho.reporting.libraries.formula.lvalues.ContextLookup;
+import org.pentaho.reporting.libraries.formula.lvalues.LValue;
+
+/**
+ * Todo: Document me!
+ *
+ * @author Thomas Morgner
+ * @since 05.03.2007
+ * @noinspection CloneableClassWithoutClone
+ */
+public abstract class AbstractReportElementLayoutController
+ extends AbstractLayoutController
+{
+
+ public static final int NOT_STARTED = 0;
+ public static final int FINISHED = 2;
+ private int state;
+
+ protected AbstractReportElementLayoutController()
+ {
+ }
+
+ /**
+ * 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 (state != AbstractReportElementLayoutController.NOT_STARTED)
+ {
+ throw new IllegalStateException();
+ }
+
+ boolean isPrintableContent = true;
+ final ReportElement text = (ReportElement) getNode();
+ // Tests we have to perform:
+ // 1. Print when group changes. We can know whether a group changed by
+ // looking at the newly introduced iteration counter.
+ //
+ // Whether we use the next one or the one after that depends on whether
+ // this element is a child of a group-header or group-footer.
+
+ // 2. Print repeated values. This never applies to static text or static
+ // elements.
+ if ((text.isPrintWhenGroupChanges() && !isGroupChanged()) || (!text.isPrintRepeatedValues() && !isValueChanged()))
+ {
+ // if this is set to true, then we print the element only if this is the
+ // first occurrence in this group.
+ // or
+ // If this is set to true, we evaluate the formula of the element and
+ // try to derive whether there was a change.
+ isPrintableContent = false;
+ }
+
+ // 3. Evaluate the Display Condition
+ final Expression dc = text.getDisplayCondition();
+ if (dc != null)
+ {
+ final Object o = LayoutControllerUtil.evaluateExpression(getFlowController(), text, dc);
+ if (Boolean.FALSE.equals(o))
+ {
+// LOGGER.debug ("DISPLAY Condition forbids printing");
+ isPrintableContent = false;
+ }
+ }
+
+ if (!isPrintableContent)
+ {
+ // There is no printable content at all. Set the state to FINISHED
+ return join(getFlowController());
+ }
+ else
+ {
+ // delegate to the handler ..
+ return delegateContentGeneration(target);
+ }
+
+ }
+
+ protected abstract boolean isValueChanged();
+
+ protected boolean isGroupChanged()
+ {
+ // search the group.
+ final SectionLayoutController slc = findGroup();
+ if (slc == null)
+ {
+ // Always print the content of the report header and footer and
+ // the page header and footer.
+ return true;
+ }
+
+ // we are in the first iteration, so yes, the group has changed recently.
+ return slc.getIterationCount() == 0;
+ }
+
+ private SectionLayoutController findGroup()
+ {
+ LayoutController parent = getParent();
+ boolean skipNext = false;
+ while (parent != null)
+ {
+ if (!(parent instanceof SectionLayoutController))
+ {
+ parent = parent.getParent();
+ }
+ else
+ {
+ final SectionLayoutController slc = (SectionLayoutController) parent;
+ final Element element = slc.getElement();
+ if (element instanceof OfficeGroupSection)
+ {
+ // This is a header or footer. So we take the next group instead.
+ skipNext = true;
+ parent = parent.getParent();
+ }
+ else if (!(element instanceof Group))
+ {
+ parent = parent.getParent();
+ }
+ else if (skipNext)
+ {
+ skipNext = false;
+ parent = parent.getParent();
+ }
+ else
+ {
+ return (SectionLayoutController) parent;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 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
+ {
+ final AbstractReportElementLayoutController alc =
+ (AbstractReportElementLayoutController) clone();
+ alc.state = AbstractReportElementLayoutController.FINISHED;
+ return alc;
+ }
+
+ protected abstract LayoutController delegateContentGeneration(final ReportTarget target)
+ throws ReportProcessingException, ReportDataFactoryException,
+ DataSourceException;
+
+ /**
+ * 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 state != AbstractReportElementLayoutController.FINISHED;
+ }
+
+ protected boolean isReferenceChanged(final LValue lValue)
+ {
+ if (lValue instanceof ContextLookup)
+ {
+ final ContextLookup rval = (ContextLookup) lValue;
+ final String s = rval.getName();
+ final DataRow view = getFlowController().getMasterRow().getGlobalView();
+ try
+ {
+ final DataFlags flags = view.getFlags(s);
+ if (flags != null && flags.isChanged())
+ {
+// LOGGER.debug ("Reference " + s + " is changed");
+ return true;
+ }
+// LOGGER.debug ("Reference " + s + " is unchanged");
+ }
+ catch (DataSourceException e)
+ {
+ // ignore .. assume that the reference has not changed.
+ }
+ }
+ final LValue[] childValues = lValue.getChildValues();
+ for (int i = 0; i < childValues.length; i++)
+ {
+ final LValue value = childValues[i];
+ if (isReferenceChanged(value))
+ {
+ return true;
+ }
+ }
+// LOGGER.debug ("Unchanged.");
+ return false;
+ }
+
+ public int getState()
+ {
+ return state;
+ }
+
+ protected void setState(final int state)
+ {
+ this.state = state;
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FixedTextLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FixedTextLayoutController.java
new file mode 100644
index 000000000000..6ac7b7551bec
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FixedTextLayoutController.java
@@ -0,0 +1,85 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.pentaho.model.FixedTextElement;
+
+import org.jfree.report.DataSourceException;
+import org.jfree.report.ReportDataFactoryException;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.data.GlobalMasterRow;
+import org.jfree.report.data.ReportDataRow;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.ReportContext;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutControllerFactory;
+import org.jfree.report.structure.Section;
+
+/**
+ * Processes a fixed-text element of the OpenOffice reporting specifciation.
+ * The element itself contains a single paragraph which contains the content.
+ * After checking, whether this element should be printed, this layout
+ * controller simply delegates the dirty work to a suitable handler.
+ *
+ * @author Thomas Morgner
+ * @noinspection CloneableClassWithoutClone
+ * @since 05.03.2007
+ */
+public class FixedTextLayoutController
+ extends AbstractReportElementLayoutController
+{
+
+ public FixedTextLayoutController()
+ {
+ }
+
+ protected boolean isValueChanged()
+ {
+ final FlowController controller = getFlowController();
+ final GlobalMasterRow masterRow = controller.getMasterRow();
+ final ReportDataRow reportDataRow = masterRow.getReportDataRow();
+ return reportDataRow.getCursor() == 0;
+ }
+
+ protected LayoutController delegateContentGeneration(final ReportTarget target)
+ throws ReportProcessingException, ReportDataFactoryException,
+ DataSourceException
+ {
+ final FixedTextElement fte = (FixedTextElement) getNode();
+ final Section content = fte.getContent();
+
+ final FlowController flowController = getFlowController();
+ final ReportContext reportContext = flowController.getReportContext();
+ final LayoutControllerFactory layoutControllerFactory =
+ reportContext.getLayoutControllerFactory();
+
+ final FixedTextLayoutController flc = (FixedTextLayoutController) clone();
+ flc.setState(AbstractReportElementLayoutController.FINISHED);
+ return layoutControllerFactory.create(flowController, content, flc);
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FormatValueUtility.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FormatValueUtility.java
new file mode 100755
index 000000000000..76ee85b52aba
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FormatValueUtility.java
@@ -0,0 +1,241 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.OfficeToken;
+import com.sun.star.report.pentaho.OfficeNamespaces;
+import com.sun.star.report.pentaho.model.FormattedTextElement;
+import java.math.BigDecimal;
+
+import java.sql.Time;
+
+import java.text.SimpleDateFormat;
+
+import java.util.Date;
+
+import org.jfree.layouting.util.AttributeMap;
+import org.jfree.report.DataFlags;
+import org.jfree.report.DataSourceException;
+import org.jfree.report.data.DefaultDataFlags;
+import org.jfree.report.expressions.FormulaExpression;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.layoutprocessor.LayoutControllerUtil;
+
+import org.pentaho.reporting.libraries.formula.util.HSSFDateUtil;
+
+/**
+ * Creation-Date: 06.06.2007, 17:03:30
+ *
+ * @author Thomas Morgner
+ */
+public class FormatValueUtility
+{
+
+ private static final String BOOLEAN_VALUE = "boolean-value";
+ private static final String STRING_VALUE = "string-value";
+ public static final String VALUE_TYPE = "value-type";
+ public static final String VALUE = "value";
+ private static SimpleDateFormat dateFormat;
+ private static SimpleDateFormat timeFormat;
+
+ private FormatValueUtility()
+ {
+ }
+
+ public static String applyValueForVariable(final Object value, final AttributeMap variableSection)
+ {
+ String ret = null;
+ if (value instanceof Time)
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE_TYPE, "time");
+ ret = formatTime((Time) value);
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, "time-value", ret);
+ }
+ else if (value instanceof java.sql.Date)
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE_TYPE, "date");
+ ret = formatDate((Date) value);
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, "date-value", ret);
+ }
+ else if (value instanceof Date)
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE_TYPE, "float");
+ ret = HSSFDateUtil.getExcelDate((Date) value, false, 2).toString();
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE, ret);
+ }
+ else if (value instanceof Number)
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE_TYPE, "float");
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE, String.valueOf(value));
+ }
+ else if (value instanceof Boolean)
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE_TYPE, "boolean");
+ if (Boolean.TRUE.equals(value))
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, BOOLEAN_VALUE, OfficeToken.TRUE);
+ }
+ else
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, BOOLEAN_VALUE, OfficeToken.FALSE);
+ }
+ }
+ else if (value != null)
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE_TYPE, "string");
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, STRING_VALUE, String.valueOf(value));
+ }
+ else
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE_TYPE, "string");
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, STRING_VALUE, "");
+ }
+ return ret;
+ }
+
+ public static void applyValueForCell(final Object value, final AttributeMap variableSection, final String valueType)
+ {
+ if (value instanceof Time)
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, "time-value", formatTime((Time) value));
+ }
+ else if (value instanceof java.sql.Date)
+ {
+ if ("float".equals(valueType))//@see http://qa.openoffice.org/issues/show_bug.cgi?id=108954
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE, HSSFDateUtil.getExcelDate((Date) value, false, 2).toString());
+ }
+ else
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, "date-value", formatDate((Date) value));
+ }
+ }
+ else if (value instanceof Date)
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE_TYPE, "float");
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE, HSSFDateUtil.getExcelDate((Date) value, false, 2).toString());
+ }
+ else if (value instanceof BigDecimal)
+ {
+ if ("date".equals(valueType))
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, "date-value", formatDate(HSSFDateUtil.getJavaDate((BigDecimal) value, false, 0)));
+ }
+ else
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE, String.valueOf(value));
+ }
+ }
+ else if (value instanceof Number)
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE, String.valueOf(value));
+ }
+ else if (value instanceof Boolean)
+ {
+ if ("float".equals(valueType))
+ {
+ float fvalue = Boolean.TRUE.equals(value) ? 1 : 0;
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE, String.valueOf(fvalue));
+ }
+ else
+ {
+ if (Boolean.TRUE.equals(value))
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, BOOLEAN_VALUE, OfficeToken.TRUE);
+ }
+ else
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, BOOLEAN_VALUE, OfficeToken.FALSE);
+ }
+ }
+ }
+ else if (value != null)
+ {
+ try
+ {
+ final Float number = Float.valueOf(String.valueOf(value));
+ applyValueForCell(number, variableSection, valueType);
+ return;
+ }
+ catch (NumberFormatException e)
+ {
+ }
+ if (!"string".equals(valueType))
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE_TYPE, "string");
+ //variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, VALUE, String.valueOf(value));
+ }
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, STRING_VALUE, String.valueOf(value));
+ }
+ else
+ {
+ variableSection.setAttribute(OfficeNamespaces.OFFICE_NS, STRING_VALUE, "");
+ }
+ }
+
+ private static synchronized String formatDate(final Date date)
+ {
+ if (dateFormat == null)
+ {
+ dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.'S'Z'");
+ }
+ return dateFormat.format(date);
+ }
+
+ private static synchronized String formatTime(final Date date)
+ {
+ if (timeFormat == null)
+ {
+ timeFormat = new SimpleDateFormat("'PT'HH'H'mm'M'ss'S'");
+ }
+ return timeFormat.format(date);
+ }
+
+ public static DataFlags computeDataFlag(final FormattedTextElement element,
+ final FlowController flowController)
+ throws DataSourceException
+ {
+ // here it is relatively easy. We have to evaluate the expression, convert
+ // the result into a string, and print that string.
+ final FormulaExpression formulaExpression = element.getValueExpression();
+ final Object result = LayoutControllerUtil.evaluateExpression(flowController, element, formulaExpression);
+ if (result == null)
+ {
+ // ignore it. Ignoring it is much better than printing 'null'.
+ // LOGGER.debug("Formula '" + formulaExpression.getFormula() + "' evaluated to null.");
+ return null;
+ }
+ else if (result instanceof DataFlags)
+ {
+ return (DataFlags) result;
+ }
+ else
+ {
+ return new DefaultDataFlags(null, result, true);
+ }
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FormattedTextLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FormattedTextLayoutController.java
new file mode 100644
index 000000000000..5a6b8f948372
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/FormattedTextLayoutController.java
@@ -0,0 +1,229 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.OfficeToken;
+import com.sun.star.report.pentaho.OfficeNamespaces;
+import com.sun.star.report.pentaho.model.FormattedTextElement;
+import com.sun.star.report.pentaho.model.OfficeDocument;
+import com.sun.star.report.pentaho.model.OfficeStyle;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.jfree.layouting.util.AttributeMap;
+import org.jfree.report.DataFlags;
+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.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.structure.Element;
+
+import org.pentaho.reporting.libraries.formula.Formula;
+import org.pentaho.reporting.libraries.formula.lvalues.LValue;
+import org.pentaho.reporting.libraries.formula.parser.ParseException;
+
+/**
+ * Todo: Document me!
+ *
+ * @author Thomas Morgner
+ * @since 05.03.2007
+ */
+public class FormattedTextLayoutController
+ extends AbstractReportElementLayoutController
+{
+
+ private static final Log LOGGER = LogFactory.getLog(FormattedTextLayoutController.class);
+
+ public FormattedTextLayoutController()
+ {
+ }
+
+ private VariablesCollection getVariablesCollection()
+ {
+ LayoutController parent = getParent();
+ while (parent != null)
+ {
+ if (parent instanceof OfficeRepeatingStructureLayoutController)
+ {
+ final OfficeRepeatingStructureLayoutController orslc =
+ (OfficeRepeatingStructureLayoutController) parent;
+ if (orslc.isNormalFlowProcessing())
+ {
+ return null;
+ }
+
+ return orslc.getVariablesCollection();
+ }
+ parent = parent.getParent();
+ }
+ return null;
+ }
+
+ protected boolean isValueChanged()
+ {
+ try
+ {
+ final FormattedTextElement element = (FormattedTextElement) getNode();
+ final FormulaExpression formulaExpression = element.getValueExpression();
+ final Formula formula = formulaExpression.getCompiledFormula();
+ final LValue lValue = formula.getRootReference();
+ return isReferenceChanged(lValue);
+ }
+ catch (final ParseException e)
+ {
+ LOGGER.debug("Parse Exception", e);
+ return false;
+ }
+ }
+
+ protected LayoutController delegateContentGeneration(final ReportTarget target)
+ throws ReportProcessingException, ReportDataFactoryException,
+ DataSourceException
+ {
+ final FormattedTextElement element = (FormattedTextElement) getNode();
+ final VariablesCollection vc = getVariablesCollection();
+ if (vc != null)
+ {
+ final String name = vc.addVariable(element);
+ final AttributeMap variablesGet = new AttributeMap();
+ variablesGet.setAttribute(JFreeReportInfo.REPORT_NAMESPACE,
+ Element.TYPE_ATTRIBUTE, "variable-get");
+ variablesGet.setAttribute(JFreeReportInfo.REPORT_NAMESPACE,
+ Element.NAMESPACE_ATTRIBUTE, OfficeNamespaces.TEXT_NS);
+ variablesGet.setAttribute(OfficeNamespaces.TEXT_NS, "name", name);
+ //variablesGet.setAttribute(OfficeNamespaces.TEXT_NS, "display", "value");
+
+ final String dataStyleName = computeValueStyle();
+ if (dataStyleName != null)
+ {
+ variablesGet.setAttribute(OfficeNamespaces.STYLE_NS, "data-style-name", dataStyleName);
+ }
+
+ final String valueType = computeValueType();
+ variablesGet.setAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE, valueType);
+ target.startElement(variablesGet);
+
+ target.endElement(variablesGet);
+ }
+ else
+ {
+ final DataFlags df = FormatValueUtility.computeDataFlag(element, getFlowController());
+ if (df != null)
+ {
+ if (df.getValue() instanceof String)
+ {
+ target.processContent(df);
+ }
+ else //@see http://qa.openoffice.org/issues/show_bug.cgi?id=108954
+ {
+ Element cell = getParentTableCell();
+ if (cell != null && "string".equals(cell.getAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE)))
+ {
+ target.processContent(df);
+ }
+ }
+ }
+ }
+
+ return join(getFlowController());
+ }
+
+ private OfficeDocument getDocument()
+ {
+ LayoutController parent = getParent();
+ while (parent != null)
+ {
+ final Object node = parent.getNode();
+ if (node instanceof OfficeDocument)
+ {
+ return (OfficeDocument) node;
+ }
+ parent = parent.getParent();
+ }
+ return null;
+ }
+
+ private Element getParentTableCell()
+ {
+ LayoutController parent = getParent();
+ while (parent != null)
+ {
+ if (parent instanceof TableCellLayoutController)
+ {
+ final TableCellLayoutController cellController = (TableCellLayoutController) parent;
+ return cellController.getElement();
+ }
+ parent = parent.getParent();
+ }
+ return null;
+ }
+
+ private String computeValueStyle()
+ {
+ final Element tce = getParentTableCell();
+ if (tce == null)
+ {
+ return null;
+ }
+
+ final String cellStyleName = (String) tce.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ if (cellStyleName == null)
+ {
+ return null;
+ }
+ final OfficeDocument document = getDocument();
+ if (document == null)
+ {
+ return null;
+ }
+
+ final OfficeStyle style = document.getStylesCollection().getStyle("table-cell", cellStyleName);
+ return (String) style.getAttribute(OfficeNamespaces.STYLE_NS, "data-style-name");
+ }
+
+ private String computeValueType()
+ {
+ final Element tce = getParentTableCell();
+ if (tce == null)
+ {
+ // NO particular format means: Fallback to string and hope and pray ..
+ throw new IllegalStateException("A formatted text element must be a child of a Table-Cell.");
+ }
+
+ final String type = (String) tce.getAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE);
+ if (type == null)
+ {
+ LOGGER.error("The Table-Cell does not have a office:value attribute defined. Your content will be messed up.");
+ return "string";
+ }
+ return type;
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ImageElementContext.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ImageElementContext.java
new file mode 100644
index 000000000000..9a2def45d32c
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ImageElementContext.java
@@ -0,0 +1,90 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+/**
+ * Todo: Document me!
+ *
+ * @author Thomas Morgner
+ * @since 30.03.2007
+ */
+public class ImageElementContext
+{
+
+ private final int colSpan;
+ private final int rowSpan;
+ private String[] rowStyles;
+ private String[] colStyles;
+
+ public ImageElementContext(final int colSpan, final int rowSpan)
+ {
+ this.colSpan = colSpan;
+ this.rowSpan = rowSpan;
+ this.colStyles = new String[colSpan];
+ this.rowStyles = new String[rowSpan];
+ }
+
+ public int getColSpan()
+ {
+ return colSpan;
+ }
+
+ public int getRowSpan()
+ {
+ return rowSpan;
+ }
+
+ public String[] getRowStyles()
+ {
+ return rowStyles;
+ }
+
+ public String[] getColStyles()
+ {
+ return colStyles;
+ }
+
+ public void setRowStyle(final int pos, final String styleName)
+ {
+ rowStyles[pos] = styleName;
+ }
+
+ public void setColStyle(final int pos, final String styleName)
+ {
+ colStyles[pos] = styleName;
+ }
+
+ public String getRowStyle(final int pos)
+ {
+ return rowStyles[pos];
+ }
+
+ public String getColStyle(final int pos)
+ {
+ return colStyles[pos];
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ImageElementLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ImageElementLayoutController.java
new file mode 100644
index 000000000000..78f504107348
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ImageElementLayoutController.java
@@ -0,0 +1,325 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.OfficeToken;
+import com.sun.star.report.pentaho.OfficeNamespaces;
+import com.sun.star.report.pentaho.model.ImageElement;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+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.data.GlobalMasterRow;
+import org.jfree.report.data.ReportDataRow;
+import org.jfree.report.expressions.FormulaExpression;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutControllerUtil;
+import org.jfree.report.structure.Element;
+import org.jfree.report.structure.Node;
+import org.jfree.report.structure.Section;
+import org.jfree.report.util.TextUtilities;
+
+import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
+import org.pentaho.reporting.libraries.formula.Formula;
+import org.pentaho.reporting.libraries.formula.lvalues.LValue;
+import org.pentaho.reporting.libraries.formula.parser.ParseException;
+
+/**
+ * Produces an image. The image-structures itself (draw:frame and so on) are not generated here. This element produces a
+ * place-holder element and relies on the output target to compute a sensible position for the element. The report
+ * definition does not give any hints about the size of the image, so we have to derive this from the surrounding
+ * context.
+ *
+ * @author Thomas Morgner
+ * @since 05.03.2007
+ */
+public class ImageElementLayoutController
+ extends AbstractReportElementLayoutController
+{
+
+ private static final Log LOGGER = LogFactory.getLog(ImageElementLayoutController.class);
+ private ImageElementContext context;
+
+ public ImageElementLayoutController()
+ {
+ }
+
+ protected LayoutController delegateContentGeneration(final ReportTarget target)
+ throws ReportProcessingException, ReportDataFactoryException,
+ DataSourceException
+ {
+ final ImageElement imageElement = (ImageElement) getNode();
+ final FormulaExpression formulaExpression = imageElement.getFormula();
+ if (formulaExpression == null)
+ {
+ // A static image is easy. At least at this level. Dont ask about the weird things we have to do in the
+ // output targets ...
+ final String linkTarget = imageElement.getImageData();
+ generateImage(target, linkTarget, imageElement.getScaleMode(), imageElement.isPreserveIRI());
+ }
+ else
+ {
+ final Object value =
+ LayoutControllerUtil.evaluateExpression(getFlowController(), imageElement, formulaExpression);
+ generateImage(target, value, imageElement.getScaleMode(), imageElement.isPreserveIRI());
+ }
+ return join(getFlowController());
+ }
+
+ private void generateImage(final ReportTarget target,
+ final Object linkTarget,
+ final String scale,
+ final boolean preserveIri)
+ throws ReportProcessingException, DataSourceException
+ {
+ if (linkTarget == null)
+ {
+ return;
+ }
+
+ final AttributeMap image = new AttributeMap();
+ image.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.NAMESPACE_ATTRIBUTE, JFreeReportInfo.REPORT_NAMESPACE);
+ image.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.TYPE_ATTRIBUTE, OfficeToken.IMAGE);
+ image.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, OfficeToken.SCALE, scale);
+ image.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, OfficeToken.PRESERVE_IRI, String.valueOf(preserveIri));
+ image.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, "image-context", createContext());
+ image.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, OfficeToken.IMAGE_DATA, linkTarget);
+ target.startElement(image);
+ target.endElement(image);
+ }
+
+ protected ImageElementContext createContext()
+ {
+ if (context == null)
+ {
+
+ // Step 1: Find the parent cell.
+ final LayoutController cellController = findParentCell();
+ if (cellController == null)
+ {
+ LOGGER.warn("Image is not contained in a table. Unable to calculate the image-size.");
+ return null;
+ }
+ final Element tableCell = (Element) cellController.getNode();
+ final int rowSpan = TextUtilities.parseInt((String) tableCell.getAttribute(OfficeNamespaces.TABLE_NS, "number-rows-spanned"), 1);
+ final int colSpan = TextUtilities.parseInt((String) tableCell.getAttribute(OfficeNamespaces.TABLE_NS, "number-columns-spanned"), 1);
+ if (rowSpan < 1 || colSpan < 1)
+ {
+ LOGGER.warn("Rowspan or colspan for image-size calculation was invalid.");
+ return null;
+ }
+
+ final LayoutController rowController = cellController.getParent();
+ if (rowController == null)
+ {
+ LOGGER.warn("Table-Cell has no parent. Unable to calculate the image-size.");
+ return null;
+ }
+ final Section tableRow = (Section) rowController.getNode();
+ // we are now making the assumption, that the row is a section, that contains the table-cell.
+ // This breaks the ability to return nodes or to construct reports on the fly, but the OO-report format
+ // is weird anyway and wont support such advanced techniques for the next few centuries ..
+ final int columnPos = findNodeInSection(tableRow, tableCell, OfficeToken.COVERED_TABLE_CELL);
+ if (columnPos == -1)
+ {
+ LOGGER.warn("Table-Cell is not a direct child of the table-row. Unable to calculate the image-size.");
+ return null;
+ }
+
+ final LayoutController tableController = rowController.getParent();
+ if (tableController == null)
+ {
+ LOGGER.warn("Table-Row has no Table. Unable to calculate the image-size.");
+ return null;
+ }
+
+ final Section table = (Section) tableController.getNode();
+ // ok, we got a table, so as next we have to search for the columns now.
+ final Section columns = (Section) table.findFirstChild(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMNS);
+ if (columns.getNodeCount() <= columnPos + colSpan)
+ {
+ // the colspan is to large. The table definition is therefore invalid. We do not try to fix this.
+ LOGGER.warn(
+ "The Table's defined columns do not match the col-span or col-position. Unable to calculate the image-size.");
+ return null;
+ }
+
+ final ImageElementContext context = new ImageElementContext(colSpan, rowSpan);
+ addColumnStyles(context, columns, columnPos, colSpan);
+ // finally search the styles for the row now.
+ final int rowPos = findNodeInSection(table, tableRow, null);
+ if (rowPos == -1)
+ {
+ LOGGER.warn("Table-Cell is not a direct child of the table-row. Unable to calculate the image-size.");
+ return null;
+ }
+
+ addRowStyles(context, table, rowPos, rowSpan);
+ this.context = context;
+ }
+ return this.context;
+ }
+
+ private int findNodeInSection(final Section tableRow,
+ final Element tableCell,
+ final String secondType)
+ {
+ int retval = 0;
+ final Node[] nodes = tableRow.getNodeArray();
+ final String namespace = tableCell.getNamespace();
+ final String type = tableCell.getType();
+ for (final Node node : nodes)
+ {
+ if (!(node instanceof Element))
+ {
+ continue;
+ }
+ final Element child = (Element) node;
+ /*
+ if (! OfficeToken.COVERED_TABLE_CELL.equals(child.getType()) &&
+ (ObjectUtilities.equal(child.getNamespace(), namespace) == false ||
+ ObjectUtilities.equal(child.getType(), type) == false))
+ */
+ if (!ObjectUtilities.equal(child.getNamespace(), namespace) || (!ObjectUtilities.equal(child.getType(), type) && (secondType == null || !ObjectUtilities.equal(child.getType(), secondType))))
+ {
+ continue;
+ }
+
+ if (node == tableCell)
+ {
+ return retval;
+ }
+ retval += 1;
+ }
+ return -1;
+ }
+
+ private LayoutController findParentCell()
+ {
+ LayoutController parent = getParent();
+ while (parent != null)
+ {
+ final Object node = parent.getNode();
+ if (node instanceof Element)
+ {
+ final Element element = (Element) node;
+ if (OfficeNamespaces.TABLE_NS.equals(element.getNamespace()) && "table-cell".equals(element.getType()))
+ {
+ return parent;
+ }
+ }
+ parent = parent.getParent();
+ }
+ return null;
+ }
+
+ protected boolean isValueChanged()
+ {
+ final ImageElement imageElement = (ImageElement) getNode();
+ final FormulaExpression formulaExpression = imageElement.getFormula();
+ if (formulaExpression == null)
+ {
+ final FlowController controller = getFlowController();
+ final GlobalMasterRow masterRow = controller.getMasterRow();
+ final ReportDataRow reportDataRow = masterRow.getReportDataRow();
+ return reportDataRow.getCursor() == 0;
+ }
+
+ try
+ {
+ final Formula formula = formulaExpression.getCompiledFormula();
+ final LValue lValue = formula.getRootReference();
+ return isReferenceChanged(lValue);
+ }
+ catch (ParseException e)
+ {
+ return false;
+ }
+ }
+
+ void addColumnStyles(final ImageElementContext context, final Section columns, final int columnPos, final int colSpan)
+ {
+ final Node[] columnDefs = columns.getNodeArray();
+ int columnCounter = 0;
+ for (Node columnDef : columnDefs)
+ {
+ final Element column = (Element) columnDef;
+
+ if (!ObjectUtilities.equal(column.getNamespace(), OfficeNamespaces.TABLE_NS) || !ObjectUtilities.equal(column.getType(), OfficeToken.TABLE_COLUMN))
+ {
+ continue;
+ }
+ if (columnCounter >= columnPos)
+ {
+ final String colStyle = (String) column.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ context.setColStyle(columnCounter - columnPos, colStyle);
+ }
+
+ columnCounter += 1;
+
+ if (columnCounter >= (columnPos + colSpan))
+ {
+ break;
+ }
+
+ }
+ }
+
+ void addRowStyles(final ImageElementContext context, final Section table, final int rowPos, final int rowSpan)
+ {
+ final Node[] rows = table.getNodeArray();
+ int rowCounter = 0;
+ for (Node row1 : rows)
+ {
+ final Element row = (Element) row1;
+
+ if (!ObjectUtilities.equal(row.getNamespace(), OfficeNamespaces.TABLE_NS) || !ObjectUtilities.equal(row.getType(), OfficeToken.TABLE_ROW))
+ {
+ continue;
+ }
+ if (rowCounter >= rowPos)
+ {
+ final String rowStyle = (String) row.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ context.setRowStyle(rowCounter - rowPos, rowStyle);
+ }
+
+ rowCounter += 1;
+
+ if (rowCounter >= (rowPos + rowSpan))
+ {
+ break;
+ }
+ }
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ObjectOleLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ObjectOleLayoutController.java
new file mode 100644
index 000000000000..1fcb1b67ec81
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/ObjectOleLayoutController.java
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.OfficeToken;
+import com.sun.star.report.SDBCReportDataFactory;
+import com.sun.star.report.pentaho.model.ObjectOleElement;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jfree.layouting.util.AttributeMap;
+import org.jfree.report.DataFlags;
+import org.jfree.report.DataRow;
+import org.jfree.report.DataSourceException;
+import org.jfree.report.JFreeReportInfo;
+import org.jfree.report.ReportDataFactoryException;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.structure.Element;
+
+/**
+ *
+ * @author Ocke Janssen
+ */
+public class ObjectOleLayoutController extends AbstractReportElementLayoutController
+{
+
+ public ObjectOleLayoutController()
+ {
+ }
+
+ protected boolean isValueChanged()
+ {
+ final ObjectOleElement element = (ObjectOleElement) getNode();
+ final List masterfields = element.getMasterfields();
+ final DataRow view = getFlowController().getMasterRow().getGlobalView();
+ for (final Iterator iter = masterfields.iterator(); iter.hasNext();)
+ {
+ final String master = (String) iter.next();
+ try
+ {
+ final DataFlags flags = view.getFlags(master);
+ if (flags != null && flags.isChanged())
+ {
+ return true;
+ }
+ }
+ catch (DataSourceException e)
+ {
+ // ignore .. assume that the reference has not changed.
+ }
+ }
+ return false;
+ }
+
+ protected LayoutController delegateContentGeneration(final ReportTarget target) throws ReportProcessingException, ReportDataFactoryException, DataSourceException
+ {
+ final ObjectOleElement element = (ObjectOleElement) getNode();
+ final String url = element.getUrl();
+ if (url != null)
+ {
+ final AttributeMap ole = new AttributeMap();
+ ole.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.NAMESPACE_ATTRIBUTE, JFreeReportInfo.REPORT_NAMESPACE);
+ ole.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, Element.TYPE_ATTRIBUTE, OfficeToken.OBJECT_OLE);
+ ole.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, "href", url);
+ ole.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, "class-id", element.getClassid());
+ final List masterfields = element.getMasterfields();
+ final List values = new ArrayList();
+ final DataRow view = getFlowController().getMasterRow().getGlobalView();
+ for (final Iterator iter = masterfields.iterator(); iter.hasNext();)
+ {
+ final String master = (String) iter.next();
+ try
+ {
+ final DataFlags flags = view.getFlags(master);
+ if (flags != null)
+ {
+ values.add(flags.getValue());
+ }
+ }
+ catch (DataSourceException e)
+ {
+ // ignore .. assume that the reference has not changed.
+ }
+ }
+ ole.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, SDBCReportDataFactory.MASTER_COLUMNS, masterfields);
+ ole.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, SDBCReportDataFactory.MASTER_VALUES, values);
+ ole.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, SDBCReportDataFactory.DETAIL_COLUMNS, element.getDetailfields());
+
+ target.startElement(ole);
+ target.endElement(ole);
+ }
+
+ return join(getFlowController());
+ }
+}
+
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeDetailLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeDetailLayoutController.java
new file mode 100644
index 000000000000..b5f77d2a2971
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeDetailLayoutController.java
@@ -0,0 +1,159 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.pentaho.model.VariablesDeclarationSection;
+
+import org.jfree.report.DataSourceException;
+import org.jfree.report.ReportData;
+import org.jfree.report.ReportDataFactoryException;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.data.GlobalMasterRow;
+import org.jfree.report.data.ReportDataRow;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.ElementLayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.flow.layoutprocessor.SectionLayoutController;
+
+/**
+ * Creation-Date: 11.04.2007, 11:04:02
+ *
+ * @author Thomas Morgner
+ */
+public class OfficeDetailLayoutController extends SectionLayoutController
+{
+
+ public static final int STATE_PROCESS_VARIABLES = 2;
+ public static final int STATE_PROCESS_NORMAL_FLOW = 3;
+ private boolean waitForJoin;
+ private int state;
+
+ public OfficeDetailLayoutController()
+ {
+ }
+
+ /**
+ * Initializes the layout controller. This method is called exactly once. It
+ * is the creators responsibility to call this method.
+ * <p/>
+ * Calling initialize after the first advance must result in a
+ * IllegalStateException.
+ *
+ * @param node the currently processed object or layout node.
+ * @param flowController the current flow controller.
+ * @param parent the parent layout controller that was responsible for
+ * instantiating this controller.
+ * @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 void initialize(final Object node,
+ final FlowController flowController,
+ final LayoutController parent)
+ throws DataSourceException, ReportDataFactoryException,
+ ReportProcessingException
+ {
+ super.initialize(node, flowController, parent);
+ state = OfficeDetailLayoutController.STATE_PROCESS_VARIABLES;
+ }
+
+ /**
+ * This method is called for each newly instantiated layout controller. The returned layout controller instance should
+ * have a processing state of either 'OPEN' or 'FINISHING' depending on whether there is any content or any child
+ * nodes to process.
+ *
+ * @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.
+ */
+ protected LayoutController startElement(final ReportTarget target)
+ throws DataSourceException, ReportProcessingException, ReportDataFactoryException
+ {
+ final FlowController fc = getFlowController();
+ final GlobalMasterRow masterRow = fc.getMasterRow();
+ final ReportDataRow reportDataRow = masterRow.getReportDataRow();
+ final ReportData reportData = reportDataRow.getReportData();
+ if (!reportData.isReadable())
+ {
+ reportData.isReadable();
+ // If this report has no data, then do not print the detail section. The detail section
+ // is the only section that behaves this way, and for now this is only done in the OO-implementation
+ final SectionLayoutController derived = (SectionLayoutController) clone();
+ derived.setProcessingState(ElementLayoutController.FINISHED);
+ derived.setFlowController(fc);
+ return derived;
+ }
+
+ if (state == OfficeDetailLayoutController.STATE_PROCESS_VARIABLES)
+ {
+ final VariablesDeclarationSection variables = new VariablesDeclarationSection();
+ final OfficeDetailLayoutController controller = (OfficeDetailLayoutController) clone();
+ controller.state = OfficeDetailLayoutController.STATE_PROCESS_NORMAL_FLOW;
+ controller.waitForJoin = true;
+ return processChild(controller, variables, fc);
+ }
+
+ return super.startElement(target);
+ }
+
+ protected void resetSectionForRepeat()
+ {
+ super.resetSectionForRepeat();
+ state = STATE_PROCESS_VARIABLES;
+ }
+
+ /**
+ * 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)
+ {
+ if (waitForJoin)
+ {
+ final OfficeDetailLayoutController derived = (OfficeDetailLayoutController) clone();
+ derived.setProcessingState(ElementLayoutController.NOT_STARTED);
+ derived.setFlowController(flowController);
+ derived.waitForJoin = false;
+ return derived;
+ }
+ return super.join(flowController);
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupInstanceSectionLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupInstanceSectionLayoutController.java
new file mode 100644
index 000000000000..1be93d70d7d1
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupInstanceSectionLayoutController.java
@@ -0,0 +1,153 @@
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.pentaho.model.OfficeGroupSection;
+import com.sun.star.report.pentaho.model.VariablesDeclarationSection;
+
+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.Expression;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.ReportContext;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.ElementLayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutControllerFactory;
+import org.jfree.report.flow.layoutprocessor.LayoutControllerUtil;
+import org.jfree.report.flow.layoutprocessor.SectionLayoutController;
+import org.jfree.report.structure.Element;
+import org.jfree.report.structure.Node;
+
+/**
+ * Creation-Date: 25.07.2007, 14:50:45
+ *
+ * @author Thomas Morgner
+ */
+public class OfficeGroupInstanceSectionLayoutController extends SectionLayoutController
+{
+
+ public static final int STATE_PROCESS_VARIABLES = 2;
+ public static final int STATE_PROCESS_NORMAL_FLOW = 3;
+ private int state;
+ private boolean waitForJoin;
+
+ public OfficeGroupInstanceSectionLayoutController()
+ {
+ }
+
+ public void initialize(final Object node, final FlowController flowController, final LayoutController parent)
+ throws DataSourceException, ReportDataFactoryException, ReportProcessingException
+ {
+ super.initialize(node, flowController, parent);
+ state = STATE_PROCESS_VARIABLES;
+ }
+
+ protected LayoutController processContent(final ReportTarget target)
+ throws DataSourceException, ReportProcessingException, ReportDataFactoryException
+ {
+ if (state == OfficeGroupInstanceSectionLayoutController.STATE_PROCESS_VARIABLES)
+ {
+ // todo: Fill the variables section with something sensible ..
+ final VariablesDeclarationSection variables = new VariablesDeclarationSection();
+ final OfficeGroupInstanceSectionLayoutController controller =
+ (OfficeGroupInstanceSectionLayoutController) clone();
+ controller.state =
+ OfficeGroupLayoutController.STATE_PROCESS_NORMAL_FLOW;
+ controller.waitForJoin = true;
+ return processChild(controller, variables, getFlowController());
+ }
+ return super.processContent(target);
+ }
+
+ // isDisplayable is private in version 0.9.1, so until the upgrade we keep this copy of the method
+ // todo: Delete it unce the sun-cvs contains version 0.9.2.
+ protected LayoutController processChild(final SectionLayoutController derived,
+ final Node node,
+ final FlowController flowController)
+ throws DataSourceException, ReportProcessingException,
+ ReportDataFactoryException
+ {
+ final ReportContext reportContext = flowController.getReportContext();
+ final LayoutControllerFactory layoutControllerFactory = reportContext.getLayoutControllerFactory();
+ if (isDisplayable(node))
+ {
+ derived.setProcessingState(ElementLayoutController.WAITING_FOR_JOIN);
+ return layoutControllerFactory.create(flowController, node, derived);
+ }
+ else
+ {
+ derived.setProcessingState(ElementLayoutController.WAITING_FOR_JOIN);
+ final LayoutController childLc = layoutControllerFactory.create(flowController, node, derived);
+ return LayoutControllerUtil.skipInvisibleElement(childLc);
+ }
+ }
+
+ protected boolean isDisplayable(final Node node) throws DataSourceException
+ {
+ if (!(node instanceof OfficeGroupSection))
+ {
+ return _isDisplayable(node);
+ }
+
+ final OfficeGroupSection section = (OfficeGroupSection) node;
+ return !section.isRepeatSection() && _isDisplayable(node);
+ }
+
+ protected boolean _isDisplayable(final Node node)
+ throws DataSourceException
+ {
+ // temp method until the pending upgrade to 0.9.2. Later we just call super.isDisplayable(..) instead.
+ if (!node.isEnabled())
+ {
+ return false;
+ }
+
+ final Expression expression = node.getDisplayCondition();
+ if (expression == null)
+ {
+ return true;
+ }
+
+ final Object result = LayoutControllerUtil.evaluateExpression(getFlowController(), node, expression);
+ return Boolean.TRUE.equals(result);
+ }
+
+ protected void resetSectionForRepeat()
+ {
+ super.resetSectionForRepeat();
+ state = STATE_PROCESS_VARIABLES;
+ }
+
+ /**
+ * 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)
+ {
+ if (waitForJoin)
+ {
+ final OfficeGroupInstanceSectionLayoutController derived = (OfficeGroupInstanceSectionLayoutController) clone();
+ derived.setProcessingState(ElementLayoutController.OPENED);
+ derived.setFlowController(flowController);
+ derived.waitForJoin = false;
+ return derived;
+ }
+ return super.join(flowController);
+ }
+
+ protected AttributeMap computeAttributes(final FlowController fc, final Element element, final ReportTarget target)
+ throws DataSourceException
+ {
+ final AttributeMap map = new AttributeMap(super.computeAttributes(fc, element, target));
+ map.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, "iteration-count", getIterationCount());
+ map.makeReadOnly();
+ return map;
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupLayoutController.java
new file mode 100644
index 000000000000..9055c2a5bdd1
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupLayoutController.java
@@ -0,0 +1,204 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.pentaho.model.OfficeGroup;
+import com.sun.star.report.pentaho.model.OfficeGroupSection;
+
+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.flow.FlowController;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.ElementLayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.flow.layoutprocessor.SectionLayoutController;
+import org.jfree.report.structure.Element;
+
+/**
+ * Todo: Document me!
+ *
+ * @author Thomas Morgner
+ * @since 15.03.2007
+ */
+public class OfficeGroupLayoutController extends SectionLayoutController
+ implements OfficeRepeatingStructureLayoutController
+{
+
+ public static final int STATE_PROCESS_REPEATING_HEADER = 0;
+ public static final int STATE_PROCESS_REPEATING_FOOTER = 1;
+ public static final int STATE_PROCESS_NORMAL_FLOW = 3;
+ private boolean waitForJoin;
+ private int state;
+ private VariablesCollection variablesCollection;
+ private boolean repeatHeader;
+ private boolean repeatFooter;
+
+ public OfficeGroupLayoutController()
+ {
+ }
+
+ /**
+ * Initializes the layout controller. This method is called exactly once. It
+ * is the creators responsibility to call this method.
+ * <p/>
+ * Calling initialize after the first advance must result in a
+ * IllegalStateException.
+ *
+ * @param node the currently processed object or layout node.
+ * @param flowController the current flow controller.
+ * @param parent the parent layout controller that was responsible for
+ * instantiating this controller.
+ * @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 void initialize(final Object node,
+ final FlowController flowController,
+ final LayoutController parent)
+ throws DataSourceException, ReportDataFactoryException,
+ ReportProcessingException
+ {
+ super.initialize(node, flowController, parent);
+ state = OfficeGroupLayoutController.STATE_PROCESS_REPEATING_HEADER;
+ variablesCollection = new VariablesCollection(computeVariablesPrefix());
+
+
+ final OfficeGroup group = (OfficeGroup) getElement();
+ final OfficeGroupSection header = group.getHeader();
+ repeatHeader = (header != null && header.isRepeatSection());
+
+ final OfficeGroupSection footer = group.getFooter();
+ repeatFooter = (footer != null && footer.isRepeatSection());
+ }
+
+ protected LayoutController processContent(final ReportTarget target)
+ throws DataSourceException, ReportProcessingException,
+ ReportDataFactoryException
+ {
+ if (state == OfficeGroupLayoutController.STATE_PROCESS_REPEATING_HEADER)
+ {
+
+ final OfficeGroupLayoutController controller =
+ (OfficeGroupLayoutController) clone();
+ controller.state =
+ OfficeGroupLayoutController.STATE_PROCESS_REPEATING_FOOTER;
+
+ if (!repeatHeader)
+ {
+ return controller;
+ }
+
+ final OfficeGroup group = (OfficeGroup) getElement();
+ final OfficeGroupSection header = group.getHeader();
+ controller.waitForJoin = true;
+ return processChild(controller, header, getFlowController());
+ }
+
+ if (state == OfficeGroupLayoutController.STATE_PROCESS_REPEATING_FOOTER)
+ {
+
+ final OfficeGroupLayoutController controller =
+ (OfficeGroupLayoutController) clone();
+ controller.state = OfficeGroupLayoutController.STATE_PROCESS_NORMAL_FLOW;
+
+ if (!repeatFooter)
+ {
+ return controller;
+ }
+
+ final OfficeGroup group = (OfficeGroup) getElement();
+ final OfficeGroupSection footer = group.getFooter();
+ controller.waitForJoin = true;
+ return processChild(controller, footer, getFlowController());
+ }
+
+ return super.processContent(target);
+ }
+
+ /**
+ * 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)
+ {
+ if (waitForJoin)
+ {
+ final OfficeGroupLayoutController derived = (OfficeGroupLayoutController) clone();
+ derived.setProcessingState(ElementLayoutController.OPENED);
+ derived.setFlowController(flowController);
+ derived.waitForJoin = false;
+ return derived;
+ }
+ return super.join(flowController);
+ }
+
+ public boolean isNormalFlowProcessing()
+ {
+ return state == OfficeGroupLayoutController.STATE_PROCESS_NORMAL_FLOW;
+ }
+
+ private String computeVariablesPrefix()
+ {
+ int count = 0;
+ LayoutController lc = this;
+ while (lc != null)
+ {
+ if (lc instanceof OfficeGroupLayoutController)
+ {
+ count++;
+ }
+ lc = lc.getParent();
+ }
+ return "auto_group_" + count + "_";
+ }
+
+ public VariablesCollection getVariablesCollection()
+ {
+ return variablesCollection;
+ }
+
+ protected AttributeMap computeAttributes(final FlowController fc, final Element element, final ReportTarget target)
+ throws DataSourceException
+ {
+ final AttributeMap map = new AttributeMap(super.computeAttributes(fc, element, target));
+ final String value = String.valueOf(repeatHeader || repeatFooter);
+ map.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, "repeating-header-or-footer", value);
+ map.makeReadOnly();
+ return map;
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupSectionLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupSectionLayoutController.java
new file mode 100644
index 000000000000..21086d6584d9
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeGroupSectionLayoutController.java
@@ -0,0 +1,109 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.OfficeToken;
+import com.sun.star.report.pentaho.model.OfficeGroupSection;
+
+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.flow.FlowController;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.ElementLayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.flow.layoutprocessor.SectionLayoutController;
+import org.jfree.report.structure.Element;
+
+/**
+ * This layoutcontroller simply checks, whether the parent layout controller
+ * is a OfficeGroupLayoutController and whether this layout controller is
+ * processing the normal flow or an repeating section. If a repeating section
+ * is being processed, an marker attribute is added to the element's call
+ * to OutputProcessor.startElement() and OutputProcessor.endElement().
+ *
+ * @author Thomas Morgner
+ * @since 19.03.2007
+ */
+public class OfficeGroupSectionLayoutController extends SectionLayoutController
+{
+
+ public OfficeGroupSectionLayoutController()
+ {
+ }
+
+ protected LayoutController startElement(final ReportTarget target)
+ throws DataSourceException, ReportProcessingException, ReportDataFactoryException
+ {
+ final OfficeGroupSection section = (OfficeGroupSection) getElement();
+ if (!section.isRepeatSection())
+ {
+ return super.startElement(target);
+ }
+
+ final LayoutController controller = getParent();
+ if (!(controller instanceof OfficeGroupLayoutController))
+ {
+ return super.startElement(target);
+ }
+ final OfficeGroupLayoutController oglc = (OfficeGroupLayoutController) controller;
+ if (!oglc.isNormalFlowProcessing())
+ {
+ return super.startElement(target);
+ }
+
+ // Skip the processing if the section is a repeating header or footer and we are processing the normal flow ..
+ final ElementLayoutController clone = (ElementLayoutController) this.clone();
+ clone.setProcessingState(ElementLayoutController.FINISHED);
+ return clone;
+ }
+
+ protected AttributeMap computeAttributes(final FlowController fc,
+ final Element element,
+ final ReportTarget target)
+ throws DataSourceException
+ {
+ final AttributeMap attrs = super.computeAttributes(fc, element, target);
+ final LayoutController controller = getParent();
+ if (!(controller instanceof OfficeGroupLayoutController))
+ {
+ return attrs;
+ }
+ final OfficeGroupLayoutController oglc = (OfficeGroupLayoutController) controller;
+ if (oglc.isNormalFlowProcessing())
+ {
+ return attrs;
+ }
+
+ final AttributeMap retval = new AttributeMap(attrs);
+ retval.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, "repeated-section", OfficeToken.TRUE);
+ retval.makeReadOnly();
+ return retval;
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficePageSectionLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficePageSectionLayoutController.java
new file mode 100644
index 000000000000..2eb3dd363f91
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficePageSectionLayoutController.java
@@ -0,0 +1,30 @@
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import org.jfree.layouting.util.AttributeMap;
+import org.jfree.report.DataSourceException;
+import org.jfree.report.JFreeReportInfo;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.SectionLayoutController;
+import org.jfree.report.structure.Element;
+
+/**
+ * Todo: Document Me
+ *
+ * @author Thomas Morgner
+ */
+public class OfficePageSectionLayoutController extends SectionLayoutController
+{
+
+ public OfficePageSectionLayoutController()
+ {
+ }
+
+ protected AttributeMap computeAttributes(final FlowController flowController, final Element element, final ReportTarget reportTarget) throws DataSourceException
+ {
+ final AttributeMap map = new AttributeMap(super.computeAttributes(flowController, element, reportTarget));
+ map.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, "role", "spreadsheet-section");
+ map.makeReadOnly();
+ return map;
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeRepeatingStructureLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeRepeatingStructureLayoutController.java
new file mode 100644
index 000000000000..790d18527f14
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeRepeatingStructureLayoutController.java
@@ -0,0 +1,43 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+
+/**
+ * Todo: Document me!
+ *
+ * @author Thomas Morgner
+ * @since 22.03.2007
+ */
+public interface OfficeRepeatingStructureLayoutController extends LayoutController
+{
+
+ public boolean isNormalFlowProcessing();
+
+ public VariablesCollection getVariablesCollection();
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeReportLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeReportLayoutController.java
new file mode 100644
index 000000000000..2ad88388b347
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeReportLayoutController.java
@@ -0,0 +1,270 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.pentaho.model.OfficeReport;
+import com.sun.star.report.pentaho.model.VariablesDeclarationSection;
+
+import org.jfree.report.DataSourceException;
+import org.jfree.report.ReportDataFactoryException;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.ReportContext;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.ElementLayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.flow.layoutprocessor.LayoutControllerFactory;
+import org.jfree.report.structure.Node;
+
+/**
+ * Todo: Document me!
+ *
+ * @author Thomas Morgner
+ * @since 06.03.2007
+ */
+public class OfficeReportLayoutController extends ElementLayoutController
+ implements OfficeRepeatingStructureLayoutController
+{
+
+ private static final int STATE_NOT_STARTED = 0;
+ private static final int STATE_TEMPLATES = 1;
+ private static final int STATE_PAGE_HEADER_DONE = 2;
+ private static final int STATE_PAGE_FOOTER_DONE = 3;
+ private static final int STATE_SPREADSHEET_PAGE_HEADER_DONE = 4;
+ private static final int STATE_SPREADSHEET_PAGE_FOOTER_DONE = 5;
+ private static final int STATE_COLUMN_HEADER_DONE = 6;
+ private static final int STATE_COLUMN_FOOTER_DONE = 7;
+ private static final int STATE_INITIAL_VARIABLES_DONE = 8;
+ private static final int STATE_REPORT_HEADER_DONE = 9;
+ private static final int STATE_REPORT_BODY_DONE = 10;
+ private static final int STATE_REPORT_FOOTER_VARIABLES = 11;
+ private static final int STATE_REPORT_FOOTER_DONE = 12;
+ private int state;
+ private VariablesCollection variablesCollection;
+
+ public OfficeReportLayoutController()
+ {
+ }
+
+ /**
+ * Initializes the layout controller. This method is called exactly once. It
+ * is the creators responsibility to call this method.
+ * <p/>
+ * Calling initialize after the first advance must result in a
+ * IllegalStateException.
+ *
+ * @param node the currently processed object or layout node.
+ * @param flowController the current flow controller.
+ * @param parent the parent layout controller that was responsible for
+ * instantiating this controller.
+ * @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 void initialize(final Object node, final FlowController flowController,
+ final LayoutController parent)
+ throws DataSourceException, ReportDataFactoryException,
+ ReportProcessingException
+ {
+ super.initialize(node, flowController, parent);
+ variablesCollection = new VariablesCollection("auto_report_");
+ }
+
+ /**
+ * Processes any content in this element. This method is called when the
+ * processing state is 'OPENED'. The returned layout controller will retain
+ * the 'OPENED' state as long as there is more content available. Once all
+ * content has been processed, the returned layout controller should carry a
+ * 'FINISHED' state.
+ *
+ * @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.
+ */
+ protected LayoutController processContent(final ReportTarget target)
+ throws DataSourceException, ReportProcessingException,
+ ReportDataFactoryException
+ {
+ final OfficeReport or = (OfficeReport) getElement();
+
+ switch (state)
+ {
+ case OfficeReportLayoutController.STATE_NOT_STARTED:
+ {
+ return delegateToTemplates(OfficeReportLayoutController.STATE_TEMPLATES);
+ }
+ case OfficeReportLayoutController.STATE_TEMPLATES:
+ {
+ return delegateSection(or.getPageHeader(),
+ OfficeReportLayoutController.STATE_PAGE_HEADER_DONE);
+ }
+ case OfficeReportLayoutController.STATE_PAGE_HEADER_DONE:
+ {
+ return delegateSpreadsheetSection(or.getPageHeader(),
+ OfficeReportLayoutController.STATE_SPREADSHEET_PAGE_HEADER_DONE);
+ }
+ case OfficeReportLayoutController.STATE_SPREADSHEET_PAGE_HEADER_DONE:
+ {
+ return delegateSection(or.getPageFooter(),
+ OfficeReportLayoutController.STATE_PAGE_FOOTER_DONE);
+ }
+ case OfficeReportLayoutController.STATE_PAGE_FOOTER_DONE:
+ {
+ return delegateSection(or.getColumnHeader(),
+ OfficeReportLayoutController.STATE_COLUMN_HEADER_DONE);
+ }
+ case OfficeReportLayoutController.STATE_COLUMN_HEADER_DONE:
+ {
+ return delegateSection(or.getColumnFooter(),
+ OfficeReportLayoutController.STATE_COLUMN_FOOTER_DONE);
+ }
+ case OfficeReportLayoutController.STATE_COLUMN_FOOTER_DONE:
+ {
+ return delegateSection(new VariablesDeclarationSection(),
+ OfficeReportLayoutController.STATE_INITIAL_VARIABLES_DONE);
+ }
+ case OfficeReportLayoutController.STATE_INITIAL_VARIABLES_DONE:
+ {
+ return delegateSection(or.getReportHeader(),
+ OfficeReportLayoutController.STATE_REPORT_HEADER_DONE);
+ }
+ case OfficeReportLayoutController.STATE_REPORT_HEADER_DONE:
+ {
+ return delegateSection(or.getBodySection(),
+ OfficeReportLayoutController.STATE_REPORT_BODY_DONE);
+ }
+ case OfficeReportLayoutController.STATE_REPORT_BODY_DONE:
+ {
+ return delegateSection(new VariablesDeclarationSection(),
+ OfficeReportLayoutController.STATE_REPORT_FOOTER_VARIABLES);
+ }
+ case OfficeReportLayoutController.STATE_REPORT_FOOTER_VARIABLES:
+ {
+ return delegateSection(or.getReportFooter(),
+ OfficeReportLayoutController.STATE_REPORT_FOOTER_DONE);
+ }
+ case OfficeReportLayoutController.STATE_REPORT_FOOTER_DONE:
+ {
+ return delegateSpreadsheetSection(or.getPageFooter(),
+ OfficeReportLayoutController.STATE_SPREADSHEET_PAGE_FOOTER_DONE);
+ }
+ case OfficeReportLayoutController.STATE_SPREADSHEET_PAGE_FOOTER_DONE:
+ {
+ final OfficeReportLayoutController olc = (OfficeReportLayoutController) clone();
+ olc.setProcessingState(ElementLayoutController.FINISHING);
+ return olc;
+ }
+ default:
+ {
+ throw new IllegalStateException("Invalid processing state encountered.");
+ }
+ }
+ }
+
+ private LayoutController delegateSpreadsheetSection(final Node node, final int nextState)
+ throws DataSourceException, ReportProcessingException, ReportDataFactoryException
+ {
+ final OfficeReportLayoutController olc = (OfficeReportLayoutController) clone();
+ olc.state = nextState;
+
+ if (node == null)
+ {
+ return olc;
+ }
+
+ final OfficePageSectionLayoutController templateLc = new OfficePageSectionLayoutController();
+ templateLc.initialize(node, getFlowController(), olc);
+ return templateLc;
+ }
+
+ private LayoutController delegateToTemplates(final int nextState)
+ throws ReportProcessingException, ReportDataFactoryException,
+ DataSourceException
+ {
+ final OfficeReportLayoutController olc = (OfficeReportLayoutController) clone();
+ olc.state = nextState;
+
+ final OfficeTableTemplateLayoutController templateLc = new OfficeTableTemplateLayoutController();
+ templateLc.initialize(getElement(), getFlowController(), olc);
+ return templateLc;
+
+ }
+
+ private LayoutController delegateSection(final Node n, final int nextState)
+ throws ReportProcessingException, ReportDataFactoryException,
+ DataSourceException
+ {
+ final OfficeReportLayoutController olc = (OfficeReportLayoutController) clone();
+ olc.state = nextState;
+ if (n == null)
+ {
+ return olc;
+ }
+
+ final FlowController flowController = getFlowController();
+ final ReportContext reportContext = flowController.getReportContext();
+ final LayoutControllerFactory layoutControllerFactory =
+ reportContext.getLayoutControllerFactory();
+ return layoutControllerFactory.create(flowController, n, olc);
+
+ }
+
+ /**
+ * 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)
+ {
+ final OfficeReportLayoutController derived = (OfficeReportLayoutController) clone();
+ derived.setFlowController(flowController);
+ return derived;
+ }
+
+ public boolean isNormalFlowProcessing()
+ {
+ return state != OfficeReportLayoutController.STATE_PAGE_HEADER_DONE && state != OfficeReportLayoutController.STATE_PAGE_FOOTER_DONE;
+ }
+
+ public VariablesCollection getVariablesCollection()
+ {
+ return variablesCollection;
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeTableLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeTableLayoutController.java
new file mode 100644
index 000000000000..9ce1be656b53
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeTableLayoutController.java
@@ -0,0 +1,79 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.OfficeToken;
+import com.sun.star.report.pentaho.OfficeNamespaces;
+
+import org.jfree.layouting.util.AttributeMap;
+import org.jfree.report.DataSourceException;
+import org.jfree.report.JFreeReportInfo;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.SectionLayoutController;
+import org.jfree.report.structure.Element;
+import org.jfree.report.structure.Node;
+import org.jfree.report.structure.Section;
+import org.jfree.report.util.IntegerCache;
+
+/**
+ * Creation-Date: 24.04.2007, 14:40:20
+ *
+ * @author Thomas Morgner
+ */
+public class OfficeTableLayoutController extends SectionLayoutController
+{
+
+ public OfficeTableLayoutController()
+ {
+ }
+
+ protected AttributeMap computeAttributes(final FlowController fc, final Element element, final ReportTarget target)
+ throws DataSourceException
+ {
+ final AttributeMap attributeMap = new AttributeMap(super.computeAttributes(fc, element, target));
+ final Section s = (Section) element;
+ int rowCount = 0;
+ final Node[] nodeArray = s.getNodeArray();
+ for (int i = 0; i < nodeArray.length; i++)
+ {
+ final Node node = nodeArray[i];
+ if (node instanceof Element)
+ {
+ final Element child = (Element) node;
+ if (OfficeNamespaces.TABLE_NS.equals(child.getNamespace()) && OfficeToken.TABLE_ROW.equals(child.getType()))
+ {
+ rowCount += 1;
+ }
+ }
+ }
+
+ attributeMap.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, "table-row-count", IntegerCache.getInteger(rowCount));
+ attributeMap.makeReadOnly();
+ return attributeMap;
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeTableTemplateLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeTableTemplateLayoutController.java
new file mode 100644
index 000000000000..6c6f997d84aa
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/OfficeTableTemplateLayoutController.java
@@ -0,0 +1,189 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.pentaho.OfficeNamespaces;
+import com.sun.star.report.pentaho.model.OfficeGroup;
+import com.sun.star.report.pentaho.model.OfficeReport;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jfree.report.DataSourceException;
+import org.jfree.report.JFreeReportInfo;
+import org.jfree.report.ReportDataFactoryException;
+import org.jfree.report.ReportProcessingException;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.layoutprocessor.LayoutController;
+import org.jfree.report.flow.layoutprocessor.SectionLayoutController;
+import org.jfree.report.structure.Element;
+import org.jfree.report.structure.Node;
+import org.jfree.report.structure.Section;
+
+
+/**
+ * Creation-Date: 24.04.2007, 16:06:52
+ *
+ * @author Thomas Morgner
+ */
+public class OfficeTableTemplateLayoutController extends SectionLayoutController
+{
+
+ private Node[] nodes;
+
+ public OfficeTableTemplateLayoutController()
+ {
+ }
+
+ /**
+ * Initializes the layout controller. This method is called exactly once. It is the creators responsibility to call
+ * this method.
+ * <p/>
+ * Calling initialize after the first advance must result in a IllegalStateException.
+ *
+ * @param node the currently processed object or layout node.
+ * @param flowController the current flow controller.
+ * @param parent the parent layout controller that was responsible for instantiating this controller.
+ * @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 void initialize(final Object node, final FlowController flowController, final LayoutController parent)
+ throws DataSourceException, ReportDataFactoryException, ReportProcessingException
+ {
+ final Section section = new Section();
+ section.setNamespace(JFreeReportInfo.REPORT_NAMESPACE);
+ section.setType("template");
+ super.initialize(section, flowController, parent);
+
+ final OfficeReport report = (OfficeReport) node;
+ final ArrayList tables = new ArrayList();
+ if (report.getPageHeader() != null)
+ {
+ addFromSection(tables, (Section) report.getPageHeader());
+ }
+ if (report.getReportHeader() != null)
+ {
+ addFromSection(tables, (Section) report.getReportHeader());
+ }
+ addPBody(tables, (Section) report.getPreBodySection());
+ addFromBody(tables, (Section) report.getBodySection());
+ addPBody(tables, (Section) report.getPostBodySection());
+ if (report.getReportFooter() != null)
+ {
+ addFromSection(tables, (Section) report.getReportFooter());
+ }
+ if (report.getPageFooter() != null)
+ {
+ addFromSection(tables, (Section) report.getPageFooter());
+ }
+
+ this.nodes = (Node[]) tables.toArray(new Node[tables.size()]);
+ }
+
+ private void addPBody(final List tables, final Section section)
+ {
+ if (section != null)
+ {
+ // tables.add(section);
+ final Node[] nodeArray = section.getNodeArray();
+ for (int i = 0; i < nodeArray.length; i++)
+ {
+ final Node node = nodeArray[i];
+ tables.add(node);
+ }
+
+ }
+ }
+
+ private void addFromBody(final List tables, final Section section)
+ {
+ final Node[] nodeArray = section.getNodeArray();
+ for (int i = 0; i < nodeArray.length; i++)
+ {
+ final Node node = nodeArray[i];
+ if (node instanceof Section)
+ {
+ final Section child = (Section) node;
+ if (node instanceof OfficeGroup)
+ {
+ addFromGroup(tables, child);
+ }
+ else
+ {
+ addFromSection(tables, child);
+ }
+ }
+ }
+ }
+
+ private void addFromGroup(final List tables, final Section section)
+ {
+ final Node[] nodeArray = section.getNodeArray();
+ for (int i = 0; i < nodeArray.length; i++)
+ {
+ final Node node = nodeArray[i];
+ if (node instanceof Section)
+ {
+ final Section element = (Section) node;
+ if (JFreeReportInfo.REPORT_NAMESPACE.equals(element.getNamespace()) && "group-body".equals(element.getType()))
+ {
+ addFromBody(tables, element);
+ }
+ else
+ {
+ addFromSection(tables, element);
+ }
+ }
+ }
+ }
+
+ private void addFromSection(final List tables, final Section section)
+ {
+ final Node[] nodeArray = section.getNodeArray();
+ for (int i = 0; i < nodeArray.length; i++)
+ {
+ final Node node = nodeArray[i];
+ if (node instanceof Element)
+ {
+ final Element element = (Element) node;
+ if (OfficeNamespaces.TABLE_NS.equals(element.getNamespace()) && "table".equals(element.getType()))
+ {
+ tables.add(element);
+ }
+ }
+ }
+ }
+
+ public Node[] getNodes()
+ {
+ return nodes;
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/TableCellLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/TableCellLayoutController.java
new file mode 100644
index 000000000000..e575831ebf2a
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/TableCellLayoutController.java
@@ -0,0 +1,216 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.OfficeToken;
+import com.sun.star.report.pentaho.OfficeNamespaces;
+import com.sun.star.report.pentaho.model.FormatCondition;
+import com.sun.star.report.pentaho.model.FormattedTextElement;
+import com.sun.star.report.pentaho.model.ReportElement;
+
+import org.jfree.layouting.util.AttributeMap;
+import org.jfree.report.DataFlags;
+import org.jfree.report.DataSourceException;
+import org.jfree.report.expressions.Expression;
+import org.jfree.report.flow.FlowController;
+import org.jfree.report.flow.ReportTarget;
+import org.jfree.report.flow.layoutprocessor.LayoutControllerUtil;
+import org.jfree.report.flow.layoutprocessor.SectionLayoutController;
+import org.jfree.report.structure.Element;
+import org.jfree.report.structure.Node;
+import org.jfree.report.structure.Section;
+
+import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
+
+/**
+ * Before writing the table cell, we have to evaluate the childs of the cell. The cell itself can either be empty or it
+ * has a one ore more paragraphs inside. The paragraph contains a single report element, but may contain additional
+ * other content.
+ *
+ * @author Thomas Morgner
+ * @noinspection CloneableClassWithoutClone
+ * @since 05.03.2007
+ */
+public class TableCellLayoutController extends SectionLayoutController
+{
+
+ public TableCellLayoutController()
+ {
+ }
+
+ protected AttributeMap computeAttributes(final FlowController fc,
+ final Element element,
+ final ReportTarget target)
+ throws DataSourceException
+ {
+ final AttributeMap attributeMap = new AttributeMap(super.computeAttributes(fc, element, target));
+ final String definedStyle = (String) attributeMap.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
+ attributeMap.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, getDisplayStyleName((Section) element, definedStyle));
+
+ try
+ {
+ final DataFlags value = computeValue(attributeMap);
+ final String valueType = (String) attributeMap.getAttribute(OfficeNamespaces.OFFICE_NS, FormatValueUtility.VALUE_TYPE);
+ if (value != null)
+ {
+ FormatValueUtility.applyValueForCell(value.getValue(), attributeMap, valueType);
+ }
+ else if ( "float".equals(valueType))
+ {
+ attributeMap.setAttribute(OfficeNamespaces.OFFICE_NS,
+ FormatValueUtility.VALUE, "NaN");
+ }
+ // #i114108#: except on form elements, the only value-type that can
+ // occur without an accomanying value attribute is "string"
+ else if (!"string".equals(valueType))
+ {
+ attributeMap.setAttribute(OfficeNamespaces.OFFICE_NS,
+ FormatValueUtility.VALUE_TYPE, "string");
+ }
+ }
+ catch (Exception e)
+ {
+ // ignore ..
+ }
+ attributeMap.makeReadOnly();
+ return attributeMap;
+ }
+
+ private DataFlags computeValue(final AttributeMap attributeMap) throws DataSourceException
+ {
+ // Search for the first FormattedTextElement
+ final Section cell = (Section) getElement();
+ final FormattedTextElement element = findFormattedTextElement(cell);
+ if (element == null)
+ {
+ return null;
+ }
+ final Expression dc = element.getDisplayCondition();
+ if (dc != null)
+ {
+ final Object o = LayoutControllerUtil.evaluateExpression(getFlowController(), element, dc);
+ if (Boolean.FALSE.equals(o))
+ {
+ attributeMap.setAttribute(OfficeNamespaces.OFFICE_NS,
+ FormatValueUtility.VALUE_TYPE, "string");
+ return null;
+ }
+ }
+ return FormatValueUtility.computeDataFlag(element, getFlowController());
+ }
+
+ private FormattedTextElement findFormattedTextElement(final Section section)
+ {
+ final Node[] nodeArray = section.getNodeArray();
+ for (int i = 0; i < nodeArray.length; i++)
+ {
+ final Node node = nodeArray[i];
+ if (node instanceof FormattedTextElement)
+ {
+ return (FormattedTextElement) node;
+ }
+ else if (node instanceof Section)
+ {
+ final FormattedTextElement retval = findFormattedTextElement((Section) node);
+ if (retval != null)
+ {
+ return retval;
+ }
+ }
+ }
+ return null;
+ }
+
+ private String getDisplayStyleName(final Section section,
+ final String defaultStyle)
+ {
+ if (!section.isEnabled() || section.getNodeCount() == 0)
+ {
+ return defaultStyle;
+ }
+
+ final Node[] nodes = section.getNodeArray();
+ for (int i = 0; i < nodes.length; i++)
+ {
+ final Node child = nodes[i];
+ if (child instanceof ReportElement && child.isEnabled())
+ {
+ final ReportElement element = (ReportElement) child;
+ if (element.getFormatConditionCount() > 0)
+ {
+ final Expression displayCond = element.getDisplayCondition();
+ if (displayCond != null)
+ {
+ try
+ {
+ if (Boolean.FALSE.equals(LayoutControllerUtil.evaluateExpression(getFlowController(), element, displayCond)))
+ {
+ continue;
+ }
+ }
+ catch (DataSourceException e)
+ {
+ // ignore silently ..
+ }
+ }
+
+ final FormatCondition[] conditions = element.getFormatConditions();
+ for (int j = 0; j < conditions.length; j++)
+ {
+ final FormatCondition formCond = conditions[j];
+ if (formCond.isEnabled())
+ {
+ try
+ {
+ final Object o = LayoutControllerUtil.evaluateExpression(getFlowController(), element, formCond.getFormula());
+ if (Boolean.TRUE.equals(o))
+ {
+ return formCond.getStyleName();
+ }
+ }
+ catch (DataSourceException e)
+ {
+ // ignore silently ..
+ }
+ }
+ }
+ }
+ }
+
+ if (child instanceof Section)
+ {
+ final String childFormatCondition =
+ getDisplayStyleName((Section) child, defaultStyle);
+ if (!ObjectUtilities.equal(childFormatCondition, defaultStyle))
+ {
+ return childFormatCondition;
+ }
+ }
+ }
+ return defaultStyle;
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/VariablesCollection.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/VariablesCollection.java
new file mode 100644
index 000000000000..a0ca9d8c98b6
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/VariablesCollection.java
@@ -0,0 +1,97 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.pentaho.model.FormattedTextElement;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * A variables collection is used to collect all FormattedTextElement objects
+ * of a repeated header or footer. Later, for each of these elements a variable
+ * setter is inserted into a hidden (in fact just very small) paragraph. These
+ * variables can later be read using the 'variable-get' construct.
+ *
+ * From the idea, this is equal to the 'strings' declaration of CSS3, although
+ * this code is explicit instead of declarative.
+ *
+ * @author Thomas Morgner
+ * @since 22.03.2007
+ */
+public class VariablesCollection
+{
+
+ private VariablesCollection parent;
+ private String namePrefix;
+ private List variables;
+
+ public VariablesCollection(final String namePrefix)
+ {
+ this(namePrefix, null);
+ }
+
+ public VariablesCollection(final String namePrefix, final VariablesCollection parent)
+ {
+ if (namePrefix == null)
+ {
+ throw new NullPointerException("NamePrefix cannot be null");
+ }
+
+ this.namePrefix = namePrefix;
+ this.parent = parent;
+ this.variables = new ArrayList();
+ }
+
+ public VariablesCollection getParent()
+ {
+ return parent;
+ }
+
+ public String getNamePrefix()
+ {
+ return namePrefix;
+ }
+
+ public String addVariable(final FormattedTextElement element)
+ {
+ variables.add(element);
+ final int size = variables.size();
+ return namePrefix + size;
+ }
+
+ public FormattedTextElement[] getVariables()
+ {
+ return (FormattedTextElement[]) variables.toArray(new FormattedTextElement[variables.size()]);
+ }
+
+ public int getVariablesCount()
+ {
+ return variables.size();
+ }
+}
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/VariablesDeclarationLayoutController.java b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/VariablesDeclarationLayoutController.java
new file mode 100644
index 000000000000..ba54e200f652
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/layoutprocessor/VariablesDeclarationLayoutController.java
@@ -0,0 +1,191 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho.layoutprocessor;
+
+import com.sun.star.report.pentaho.OfficeNamespaces;
+import com.sun.star.report.pentaho.model.FormattedTextElement;
+
+import java.text.SimpleDateFormat;
+
+import java.util.Date;
+
+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;
+
+/**
+ * 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 java.sql.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");
+ }
+}