/* * 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) 2001 - 2013 Object Refinery Ltd, Pentaho Corporation and Contributors.. All rights reserved. */ package org.pentaho.reporting.engine.classic.core.function; import org.pentaho.reporting.engine.classic.core.AttributeNames; import org.pentaho.reporting.engine.classic.core.Band; import org.pentaho.reporting.engine.classic.core.CrosstabCell; import org.pentaho.reporting.engine.classic.core.CrosstabCellBody; import org.pentaho.reporting.engine.classic.core.CrosstabColumnGroup; 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.event.ReportEvent; import org.pentaho.reporting.engine.classic.core.states.LayoutProcess; import org.pentaho.reporting.engine.classic.core.states.ReportState; import org.pentaho.reporting.engine.classic.core.util.InstanceID; import org.pentaho.reporting.libraries.base.util.ObjectUtilities; import java.util.ArrayList; /** * A collection of utility methods relating to functions. * * @author Thomas Morgner. */ public final class FunctionUtilities { /** * Default Constructor. */ private FunctionUtilities() { } /** * Try to find the first element with the given name in the last active root-band. * * @param band * the band that is suspected to contain the element. * @param element * the element name. * @return the found element or null, if no element could be found. */ public static Element findElement( final Band band, final String element ) { if ( element == null ) { throw new NullPointerException( "Element name must not be null" ); } if ( band == null ) { throw new NullPointerException( "Band must not be null" ); } if ( band.getName().equals( element ) ) { return band; } final Element[] elements = band.getElementArray(); for ( int i = 0; i < elements.length; i++ ) { final Element e = elements[i]; if ( element.equals( e.getName() ) ) { return e; } if ( e instanceof Band ) { final Element retval = findElement( (Band) e, element ); if ( retval != null ) { return retval; } } } return null; } public static ReportElement findElementById( final ReportDefinition reportDefinition, final String id ) { if ( reportDefinition == null ) { throw new NullPointerException( "Element name must not be null" ); } if ( id == null ) { return null; } return findElementById( (Section) reportDefinition, id ); } public static ReportElement findElementByInstanceId( final ReportDefinition reportDefinition, final InstanceID id ) { if ( reportDefinition == null ) { throw new NullPointerException( "Element name must not be null" ); } if ( id == null ) { return null; } return findElementByInstanceId( (Section) reportDefinition, id ); } /** * Try to find the defined element in the last active root-band. * * @param band * the band that is suspected to contain the element. * @param id * the element's unique id. * @return the found element or null, if no element could be found. */ public static ReportElement findElementById( final Section band, final String id ) { return findElementByAttribute( band, AttributeNames.Xml.NAMESPACE, AttributeNames.Xml.ID, id ); } /** * Try to find the defined element in the last active root-band. * * @param band * the band that is suspected to contain the element. * @param id * the element's unique id. * @return the found element or null, if no element could be found. */ public static ReportElement findElementByInstanceId( final Section band, final InstanceID id ) { if ( band == null ) { throw new NullPointerException( "Element name must not be null" ); } if ( id == null ) { return null; } if ( band.getObjectID() == id ) { return band; } for ( int i = 0; i < band.getElementCount(); i++ ) { final ReportElement e = band.getElement( i ); if ( id == e.getObjectID() ) { return e; } if ( e instanceof Section ) { final ReportElement retval = findElementByInstanceId( (Section) e, id ); if ( retval != null ) { return retval; } } } if ( band instanceof RootLevelBand ) { final RootLevelBand rootLevelBand = (RootLevelBand) band; final SubReport[] reports = rootLevelBand.getSubReports(); for ( int i = 0; i < reports.length; i++ ) { final SubReport report = reports[i]; if ( report.getObjectID() == id ) { return report; } } } return null; } public static ReportElement findElementByName( final Section band, final String name ) { return findElementByAttribute( band, AttributeNames.Core.NAMESPACE, AttributeNames.Core.NAME, name ); } /** * Try to find the defined element in the last active root-band. * * @param band * the band that is suspected to contain the element. * @param attributeNamespace * the namespace of the attribute, never null. * @param attributeName * the attribute name, never null. * @param attributeValue * the value, never null. * @return the found element or null, if no element could be found. */ public static ReportElement findElementByAttribute( final Section band, final String attributeNamespace, final String attributeName, final String attributeValue ) { if ( band == null ) { throw new NullPointerException( "Element must not be null" ); } if ( attributeNamespace == null ) { throw new NullPointerException( "Attribute name must not be null" ); } if ( attributeName == null ) { throw new NullPointerException( "Attribute namespace must not be null" ); } if ( attributeValue == null ) { throw new NullPointerException( "Attribute value must not be null" ); } if ( attributeValue.equals( band.getAttribute( attributeNamespace, attributeName ) ) ) { return band; } for ( int i = 0; i < band.getElementCount(); i++ ) { final ReportElement e = band.getElement( i ); if ( attributeValue.equals( e.getAttribute( attributeNamespace, attributeName ) ) ) { return e; } if ( e instanceof Section ) { final ReportElement retval = findElementByAttribute( (Section) e, attributeNamespace, attributeName, attributeValue ); if ( retval != null ) { return retval; } } } return null; } /** * Try to find all element with the given name in the last active root-band. * * @param band * the band that is suspected to contain the element. * @param element * the element name. * @return the found element or null, if no element could be found. */ public static Element[] findAllElements( final Band band, final String element ) { if ( element == null ) { throw new NullPointerException( "Element name must not be null" ); } if ( band == null ) { throw new NullPointerException( "Band must not be null" ); } final ArrayList<Element> collector = new ArrayList<Element>(); if ( band.getName().equals( element ) ) { collector.add( band ); } performFindElement( band, element, collector ); return collector.toArray( new Element[collector.size()] ); } /** * Try to find all element with the given name in the last active root-band. * * @param band * the band that is suspected to contain the element. * @param element * the element name. * @return the found element or null, if no element could be found. */ public static Element[] findAllElements( final CrosstabCellBody band, final String element ) { if ( element == null ) { throw new NullPointerException( "Element name must not be null" ); } if ( band == null ) { throw new NullPointerException( "Band must not be null" ); } final ArrayList<Element> collector = new ArrayList<Element>(); if ( band.getName().equals( element ) ) { collector.add( band ); } for ( int i = 1; i < band.getElementCount(); i += 1 ) { final CrosstabCell b = (CrosstabCell) band.getElement( i ); if ( b.getName().equals( element ) ) { collector.add( band ); } performFindElement( b, element, collector ); } return collector.toArray( new Element[collector.size()] ); } /** * Internal function that collects all elements of a given band with a given name. * * @param band * the band from which elements should be collected. * @param element * the name of the element to collect. * @param collector * the list of results. */ private static void performFindElement( final Band band, final String element, final ArrayList<Element> collector ) { final int count = band.getElementCount(); final Element[] buffer = band.getElementArray(); for ( int i = 0; i < count; i++ ) { final Element e = buffer[i]; if ( e.getName().equals( element ) ) { collector.add( e ); } if ( e instanceof Band ) { performFindElement( (Band) e, element, collector ); } } } /** * Returns true if the events current groupname is equal to the group name. * * @param groupName * the group name. * @param event * the report event. * @return A boolean. */ public static boolean isDefinedGroup( final String groupName, final ReportEvent event ) { if ( groupName == null ) { return false; } final int groupIndex = event.getState().getCurrentGroupIndex(); final Group group = event.getReport().getGroup( groupIndex ); if ( groupName.equals( group.getName() ) ) { return true; } if ( groupName.equals( group.getGeneratedName() ) ) { return true; } return false; } /** * Returns true, if the current run level is defined for the given function and this is a prepare run. The prepare run * is used to compute the function values. * * @param f * the function. * @param event * the event. * @return A boolean. */ public static boolean isDefinedPrepareRunLevel( final Function f, final ReportEvent event ) { if ( f == null ) { throw new NullPointerException( "Function is null" ); } if ( event == null ) { throw new NullPointerException( "ReportEvent is null" ); } final ReportState state = event.getState(); if ( state.isPrepareRun() == false ) { return false; } return ( state.getLevel() == f.getDependencyLevel() ); } /** * Returns true or false. * * @param event * the report event. * @return A boolean. */ public static boolean isLayoutLevel( final ReportEvent event ) { if ( event == null ) { throw new NullPointerException( "ReportEvent is null" ); } return ( event.getState().getLevel() == LayoutProcess.LEVEL_PAGINATE ); } /** * Returns the current group instance, based on the given report event. * * @param event * the event which is base for the action. * @return the current group of the event, never null. */ public static Group getCurrentGroup( final ReportEvent event ) { if ( event == null ) { throw new NullPointerException( "ReportEvent is null" ); } final int index = event.getState().getCurrentGroupIndex(); if ( index == -1 ) { throw new IllegalStateException(); } return event.getReport().getGroup( index ); } /** * Returns the current group instance, based on the given report event. * * @param event * the event which is base for the action. * @return the current group of the event, or null if the event is a deep traversing event. */ public static Group getCurrentDeepTraverseGroup( final ReportEvent event ) { if ( event == null ) { throw new NullPointerException( "ReportEvent is null" ); } if ( event.isDeepTraversing() ) { final int index = event.getOriginatingState().getCurrentGroupIndex(); return event.getOriginatingState().getReport().getGroup( index ); } else { return getCurrentGroup( event ); } } public static boolean isCrosstabFilterValid( ReportDefinition def, String filterName ) { if ( filterName == null ) { return true; } for ( int i = 0; i < def.getGroupCount(); i++ ) { final Group group = def.getGroup( i ); if ( group instanceof CrosstabColumnGroup ) { final CrosstabColumnGroup columnGroup = (CrosstabColumnGroup) group; if ( ObjectUtilities.equal( columnGroup.getName(), filterName ) ) { return true; } } } return false; } public static boolean isCrosstabDefined( final ReportEvent event ) { return event.getReport().getCrosstabCellBody() != null; } public static String computeElementLocation( ReportElement e ) { final StringBuilder b = new StringBuilder(); computeElementLocationInternal( e, b ); return b.toString(); } private static void computeElementLocationInternal( final ReportElement e, final StringBuilder b ) { final Section parentSection = e.getParentSection(); if ( parentSection != null ) { computeElementLocationInternal( parentSection, b ); b.append( "->" ); } final String typeName = e.getElementType().getMetaData().getName(); b.append( typeName ); if ( parentSection != null ) { final int elementCount = parentSection.getElementCount(); for ( int i = 0; i < elementCount; i += 1 ) { if ( parentSection.getElement( i ) == e ) { b.append( "[" ); b.append( i ); b.append( "]" ); break; } } } } }