/* * 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; import org.pentaho.reporting.engine.classic.core.style.ElementStyleSheet; import org.pentaho.reporting.engine.classic.core.style.ReportSectionDefaultStyleSheet; import org.pentaho.reporting.engine.classic.core.util.InstanceID; import java.util.Iterator; import java.util.NoSuchElementException; /** * A section is a small-scale band that allows to access the child elements but does not define how childs get added or * organized in the section. Defining a sensible order is left to the subclass-implementation. * * @author Thomas Morgner */ public abstract class Section extends Element implements Iterable<Element> { private class SectionIterator implements Iterator<Element> { private int pos; private SectionIterator() { } public boolean hasNext() { return pos < getElementCount(); } public Element next() { if ( pos >= getElementCount() ) { throw new NoSuchElementException(); } final Element e = getElement( pos ); pos += 1; return e; } public void remove() { throw new UnsupportedOperationException(); } } /** * Default Constructor. */ protected Section() { } protected Section( final InstanceID id ) { super( id ); } /** * Creates the global stylesheet for this element type. The global stylesheet is an immutable stylesheet that provides * reasonable default values for some of the style keys. * <p/> * The global default stylesheet is always the last stylesheet that will be queried for values. * * @return the global stylesheet. */ public ElementStyleSheet getDefaultStyleSheet() { return ReportSectionDefaultStyleSheet.getSectionDefault(); } /** * Returns the element stored add the given index. * * @param index * the element position within this section * @return the element * @throws IndexOutOfBoundsException * if the index is invalid. */ public abstract Element getElement( int index ); /** * Returns the number of elements in this section. * * @return the number of elements of this section. */ public abstract int getElementCount(); /** * Unregisters the given element from its parent. If the element is already a direct child of this section, this * operation does nothing and returns 'true' to indicate that all the work is already done. * <p/> * This is a helper function and not meant to be used by the grand public. * * @param element * the element to be unregistered from its current parent. * @return true, if the element is a child of this section, false otherwise. */ protected boolean unregisterParent( final Element element ) { // remove the element from its old parent .. // this is the default AWT behaviour when adding Components to Container final Section parentSection = element.getParentSection(); if ( parentSection != null ) { if ( parentSection == this ) { // already a child, wont add twice ... return true; } parentSection.removeElement( element ); } return false; } /** * Checks whether the element given is a parent of this section. Adding that element to the section would cause * infinite loops later, so we prevent it early in the game. * * @param element * the element to be checked for loops. */ protected void validateLooping( final Element element ) { // check for component loops ... if ( element instanceof Section ) { Section band = this; while ( band != null ) { if ( band == element ) { throw new IllegalArgumentException( "adding container's parent to itself" ); } band = band.getParentSection(); } } } public abstract void setElementAt( final int position, final Element element ); /** * Removes an element from the section. * * @param element * the element to be section. * @throws NullPointerException * if the given element is null. */ protected abstract void removeElement( final Element element ); protected void unregisterAsChild( final Element element ) { element.setParent( null ); } protected void registerAsChild( final Element element ) { element.setParent( this ); } public Iterator<Element> iterator() { return new SectionIterator(); } public Section derive( final boolean preserveElementInstanceIds ) { return (Section) super.derive( preserveElementInstanceIds ); } public Section clone() { return (Section) super.clone(); } }