| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* $Id$ */ |
| |
| package org.apache.fop.layoutmgr; |
| |
| import java.util.Iterator; |
| import java.util.NoSuchElementException; |
| |
| /** |
| * An iterator over {@link Position} instances, that is wrapped around |
| * another 'parent' {@link Iterator}. The parent can be either another |
| * {@code PositionIterator}, or an iterator over {@link KnuthElement}s, |
| * for example.<br/> |
| * The {@link #next()} method always returns a {@link Position}. The |
| * {@link #getPos(Object)} method can be overridden in subclasses |
| * to take care of obtaining the {@link LayoutManager} or {@link Position} |
| * from the object returned by the parent iterator's {@code next()} method. |
| */ |
| public class PositionIterator implements Iterator<Position> { |
| |
| private Iterator parentIter; |
| private Object nextObj; |
| private LayoutManager childLM; |
| private boolean hasNext; |
| |
| /** |
| * Construct position iterator. |
| * @param parentIter an iterator to use as parent |
| */ |
| public PositionIterator(Iterator parentIter) { |
| this.parentIter = parentIter; |
| lookAhead(); |
| //checkNext(); |
| } |
| |
| /** @return layout manager of next child layout manager or null */ |
| public LayoutManager getNextChildLM() { |
| // Move to next "segment" of iterator, ie: new childLM |
| if (childLM == null && nextObj != null) { |
| childLM = getLM(nextObj); |
| hasNext = true; |
| } |
| return childLM; |
| } |
| |
| /** |
| * @param nextObj next object from which to obtain position |
| * @return layout manager |
| */ |
| protected LayoutManager getLM(Object nextObj) { |
| return getPos(nextObj).getLM(); |
| } |
| |
| /** |
| * Default implementation assumes that the passed |
| * {@code nextObj} is itself a {@link Position}, and just returns it. |
| * Subclasses for which this is not the case, <em>must</em> provide a |
| * suitable override this method. |
| * @param nextObj next object from which to obtain position |
| * @return position of next object. |
| */ |
| protected Position getPos(Object nextObj) { |
| if (nextObj instanceof Position) { |
| return (Position)nextObj; |
| } |
| throw new IllegalArgumentException( |
| "Cannot obtain Position from the given object."); |
| } |
| |
| private void lookAhead() { |
| if (parentIter.hasNext()) { |
| hasNext = true; |
| nextObj = parentIter.next(); |
| } else { |
| endIter(); |
| } |
| } |
| |
| /** @return true if not at end of sub-sequence with same child layout manager */ |
| protected boolean checkNext() { |
| LayoutManager lm = getLM(nextObj); |
| if (childLM == null) { |
| childLM = lm; |
| } else if (childLM != lm && lm != null) { |
| // End of this sub-sequence with same child LM |
| hasNext = false; |
| childLM = null; |
| return false; |
| } |
| return true; |
| } |
| |
| /** end (reset) iterator */ |
| protected void endIter() { |
| hasNext = false; |
| nextObj = null; |
| childLM = null; |
| } |
| |
| /** {@inheritDoc} */ |
| public boolean hasNext() { |
| return (hasNext && checkNext()); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public Position next() throws NoSuchElementException { |
| if (hasNext) { |
| Position retPos = getPos(nextObj); |
| lookAhead(); |
| return retPos; |
| } else { |
| throw new NoSuchElementException("PosIter"); |
| } |
| } |
| |
| /** @return peek at next object */ |
| public Object peekNext() { |
| return nextObj; |
| } |
| |
| /** {@inheritDoc} */ |
| public void remove() throws UnsupportedOperationException { |
| throw new UnsupportedOperationException("PositionIterator doesn't support remove"); |
| } |
| } |