/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.designer.core.model;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import org.pentaho.reporting.designer.core.ReportDesignerBoot;
import org.pentaho.reporting.designer.core.model.lineal.LinealModel;
import org.pentaho.reporting.designer.core.model.lineal.LinealModelEvent;
import org.pentaho.reporting.designer.core.model.lineal.LinealModelListener;
import org.pentaho.reporting.engine.classic.core.AbstractReportDefinition;
import org.pentaho.reporting.engine.classic.core.CompoundDataFactory;
import org.pentaho.reporting.engine.classic.core.DataFactory;
import org.pentaho.reporting.engine.classic.core.Element;
import org.pentaho.reporting.engine.classic.core.Group;
import org.pentaho.reporting.engine.classic.core.ReportDefinition;
import org.pentaho.reporting.engine.classic.core.ReportElement;
import org.pentaho.reporting.engine.classic.core.RootLevelBand;
import org.pentaho.reporting.engine.classic.core.Section;
import org.pentaho.reporting.engine.classic.core.SubReport;
import org.pentaho.reporting.engine.classic.core.function.FunctionUtilities;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderNode;
import org.pentaho.reporting.engine.classic.core.util.InstanceID;
import org.pentaho.reporting.engine.classic.extensions.parsers.reportdesigner.ReportDesignerParserModule;
import org.pentaho.reporting.libraries.base.config.Configuration;
/**
* Todo: Document Me
*
* @author Thomas Morgner
*/
public class ModelUtility
{
private static final String CACHED_LAYOUT_DATA = "CachedLayoutData";
private static final String NUMBER_FORMAT_CONFIG_PREFIX = "NumberFormat.String.";
private static final String DATE_FORMAT_CONFIG_PREFIX = "DateFormat.String.";
private ModelUtility()
{
}
private static class LinealUpdateHandler implements LinealModelListener
{
private Element element;
private LinealModel model;
private String attribute;
private LinealUpdateHandler(final Element element,
final LinealModel model,
final String attribute)
{
this.element = element;
this.model = model;
this.attribute = attribute;
}
public void modelChanged(final LinealModelEvent event)
{
element.setAttribute(ReportDesignerParserModule.NAMESPACE, attribute, model.externalize(), false);
}
}
public static boolean isHideInLayoutGui(final RenderNode node)
{
final Object attribute = node.getAttributes().getAttribute(ReportDesignerParserModule.NAMESPACE,
ReportDesignerParserModule.HIDE_IN_LAYOUT_GUI_ATTRIBUTE);
return attribute != null && Boolean.TRUE.equals(attribute);
}
public static boolean isHideInLayoutGui(final ReportElement element)
{
final Object attribute = element.getAttribute(ReportDesignerParserModule.NAMESPACE,
ReportDesignerParserModule.HIDE_IN_LAYOUT_GUI_ATTRIBUTE);
return attribute != null && Boolean.TRUE.equals(attribute);
}
public static LinealModel getVerticalLinealModel(final Element rootBand)
{
final Object maybeLinealModel = rootBand.getAttribute(ReportDesignerParserModule.NAMESPACE,
ReportDesignerBoot.DESIGNER_LINEAL_MODEL_OBJECT);
if (maybeLinealModel instanceof LinealModel)
{
return (LinealModel) maybeLinealModel;
}
final LinealModel verticalLinealModel = new LinealModel();
final Object attribute = rootBand.getAttribute(ReportDesignerParserModule.NAMESPACE,
ReportDesignerParserModule.VERTICAL_GUIDE_LINES_ATTRIBUTE);
if (attribute instanceof String)
{
verticalLinealModel.parse(attribute.toString());
}
verticalLinealModel.addLinealModelListener(new LinealUpdateHandler
(rootBand, verticalLinealModel, ReportDesignerParserModule.VERTICAL_GUIDE_LINES_ATTRIBUTE));
rootBand.setAttribute(ReportDesignerParserModule.NAMESPACE,
ReportDesignerBoot.DESIGNER_LINEAL_MODEL_OBJECT, verticalLinealModel, false);
return verticalLinealModel;
}
public static LinealModel getHorizontalLinealModel(final AbstractReportDefinition rootBand)
{
final Object maybeLinealModel = rootBand.getAttribute(ReportDesignerParserModule.NAMESPACE,
ReportDesignerBoot.DESIGNER_LINEAL_MODEL_OBJECT);
if (maybeLinealModel instanceof LinealModel)
{
return (LinealModel) maybeLinealModel;
}
final LinealModel linealModel = new LinealModel();
final Object attribute = rootBand.getAttribute(ReportDesignerParserModule.NAMESPACE,
ReportDesignerParserModule.HORIZONTAL_GUIDE_LINES_ATTRIBUTE);
if (attribute instanceof String)
{
linealModel.parse(attribute.toString());
}
linealModel.addLinealModelListener(new LinealUpdateHandler
(rootBand, linealModel, ReportDesignerParserModule.HORIZONTAL_GUIDE_LINES_ATTRIBUTE));
rootBand.setAttribute(ReportDesignerParserModule.NAMESPACE,
ReportDesignerBoot.DESIGNER_LINEAL_MODEL_OBJECT, linealModel, false);
return linealModel;
}
public static CachedLayoutData getCachedLayoutData(final Element element)
{
final Object attribute = element.getAttribute(ReportDesignerParserModule.NAMESPACE, CACHED_LAYOUT_DATA);
if (attribute instanceof CachedLayoutData)
{
return (CachedLayoutData) attribute;
}
final CachedLayoutData retval = new CachedLayoutData();
element.setAttribute(ReportDesignerParserModule.NAMESPACE, CACHED_LAYOUT_DATA, retval, false);
return retval;
}
public static boolean isDescendant(final Section definition, final ReportElement element)
{
ReportElement band = element;
while (band != null)
{
if (band == definition)
{
return true;
}
band = band.getParentSection();
}
return false;
}
public static List<Element> filterParents(final List<Element> elements)
{
if (elements.size() == 1)
{
return elements;
}
final ArrayList<Element> retval = new ArrayList<Element>(elements.size());
for (Element element : elements)
{
if (element instanceof Section)
{
final Section s = (Section) element;
if (isParentSection(s, elements))
{
continue;
}
}
retval.add(element);
}
return retval;
}
private static boolean isParentSection(final Section s, final List<Element> elements)
{
for (Element potentialChild: elements)
{
if (potentialChild != s)
{
if (ModelUtility.isDescendant(s, potentialChild))
{
return true;
}
}
}
return false;
}
public static SubReport[] findSubReports(final Section section)
{
final ArrayList<SubReport> result = new ArrayList<SubReport>();
findSubReportsInteral(section, result);
return result.toArray(new SubReport[result.size()]);
}
private static void findSubReportsInteral(final Section section, final ArrayList<SubReport> result)
{
final int count = section.getElementCount();
for (int i = 0; i < count; i++)
{
final ReportElement element = section.getElement(i);
if (element instanceof Section)
{
findSubReportsInteral((Section) element, result);
}
}
if (section instanceof SubReport)
{
result.add((SubReport) section);
}
}
public static ReportElement findElementById(final AbstractReportDefinition definition, final InstanceID id)
{
return FunctionUtilities.findElementByInstanceId((ReportDefinition) definition, id);
}
public static int findIndexOf(final Section parent, final Element visualElement)
{
final int count = parent.getElementCount();
for (int i = 0; i < count; i++)
{
final ReportElement element = parent.getElement(i);
if (element == visualElement)
{
return i;
}
}
return -1;
}
public static int findSubreportIndexOf(final RootLevelBand parent, final SubReport visualElement)
{
final int count = parent.getSubReportCount();
for (int i = 0; i < count; i++)
{
final ReportElement element = parent.getSubReport(i);
if (element == visualElement)
{
return i;
}
}
return -1;
}
public static String[] getGroups(final AbstractReportDefinition reportDefinition)
{
final LinkedHashSet<String> groups = new LinkedHashSet<String>();
final int count = reportDefinition.getGroupCount();
for (int i = 0; i < count; i++)
{
final Group g = reportDefinition.getGroup(i);
final String groupName = g.getName();
if (groupName != null)
{
groups.add(groupName);
}
}
for (int i = 0; i < count; i++)
{
final Group g = reportDefinition.getGroup(i);
final String groupName = g.getGeneratedName();
if (groupName != null)
{
groups.add(groupName);
}
}
return groups.toArray(new String[groups.size()]);
}
public static String[] getNumberFormats()
{
return getMessageSeries(NUMBER_FORMAT_CONFIG_PREFIX);
}
public static String[] getDateFormats()
{
return getMessageSeries(DATE_FORMAT_CONFIG_PREFIX);
}
private static String[] getMessageSeries(final String seriesPrefix)
{
final ArrayList<String> stringSeries = new ArrayList<String>();
int index = 0;
final Configuration configuration = ReportDesignerBoot.getInstance().getGlobalConfig();
String message = configuration.getConfigProperty(seriesPrefix + index);
while (message != null)
{
stringSeries.add(message);
index++;
message = configuration.getConfigProperty(seriesPrefix + index);
}
return stringSeries.toArray(new String[stringSeries.size()]);
}
public static DataFactory findDataFactoryForQuery(AbstractReportDefinition definition,
final String query)
{
while (definition != null)
{
final DataFactory dataFactory = definition.getDataFactory();
if (dataFactory instanceof CompoundDataFactory)
{
final CompoundDataFactory cdf = (CompoundDataFactory) dataFactory;
final DataFactory factoryForQuery = cdf.getDataFactoryForQuery(query);
if (factoryForQuery != null)
{
return factoryForQuery;
}
}
final Section parentSection = definition.getParentSection();
if (parentSection == null)
{
definition = null;
}
else
{
definition = (AbstractReportDefinition) parentSection.getReportDefinition();
}
}
return null;
}
}