001    /*
002     * Created on Jan 11, 2011
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     *
013     * Copyright @2011 the original author or authors.
014     */
015    package org.fest.assertions;
016    
017    import static org.fest.util.ToString.toStringOf;
018    
019    import java.util.*;
020    
021    import org.fest.util.VisibleForTesting;
022    
023    /**
024     * Assertions for <code>{@link Iterator}</code>s.
025     * <p>
026     * To create a new instance of this class invoke <code>{@link Assertions#assertThat(Iterator)}</code>.
027     * </p>
028     *
029     * @author Alex Ruiz
030     *
031     * @since 1.4
032     */
033    public class IteratorAssert extends ObjectGroupAssert<IteratorAssert, Iterator<?>> {
034    
035      /**
036       * Creates a new </code>{@link IteratorAssert}</code>.
037       * @param actual the target to verify.
038       */
039      protected IteratorAssert(Iterator<?> actual) {
040        super(IteratorAssert.class, wrap(actual));
041      }
042    
043      private static Iterator<?> wrap(Iterator<?> actual) {
044        if (actual == null) return null;
045        return new PrettyPrintIterator(actual);
046      }
047    
048      /** {@inheritDoc} */
049      @Override protected IteratorAssert onProperty(String propertyName) {
050        isNotNull();
051        List<Object> subset = PropertySupport.instance().propertyValues(propertyName, contentOfActual());
052        return new IteratorAssert(subset.iterator());
053      }
054    
055      /** {@inheritDoc} */
056      @Override protected Set<Object> actualAsSet() {
057        return new LinkedHashSet<Object>(contentOfActual());
058      }
059    
060      /** {@inheritDoc} */
061      @Override protected List<Object> actualAsList() {
062        return new ArrayList<Object>(contentOfActual());
063      }
064    
065      /** {@inheritDoc} */
066      @Override protected int actualGroupSize() {
067        isNotNull();
068        return contentOfActual().size();
069      }
070    
071      private List<Object> contentOfActual() {
072        PrettyPrintIterator wrapped = (PrettyPrintIterator) actual;
073        return wrapped.contents();
074      }
075    
076      @VisibleForTesting static class PrettyPrintIterator implements Iterator<Object> {
077        private final Iterator<?> wrapped;
078    
079        boolean wrappedWasConsumed;
080        List<Object> wrappedContents;
081        Iterator<Object> iterator;
082    
083        PrettyPrintIterator(Iterator<?> wrapped) {
084          this.wrapped = wrapped;
085        }
086    
087        List<Object> contents() {
088          consumeIterator();
089          return wrappedContents;
090        }
091    
092        /** {@inheritDoc} */
093        public boolean hasNext() {
094          consumeIterator();
095          return iterator.hasNext();
096        }
097    
098        /** {@inheritDoc} */
099        public Object next() {
100          consumeIterator();
101          return iterator.next();
102        }
103    
104        private synchronized void consumeIterator() {
105          if (wrappedWasConsumed) return;
106          wrappedContents = new ArrayList<Object>();
107          while (wrapped.hasNext()) wrappedContents.add(wrapped.next());
108          wrappedWasConsumed = true;
109          iterator = wrappedContents.iterator();
110        }
111    
112        /** {@inheritDoc} */
113        public void remove() {
114          throw new UnsupportedOperationException();
115        }
116    
117        /** {@inheritDoc} */
118        @Override public String toString() {
119          consumeIterator();
120          return toStringOf(wrappedContents);
121        }
122      }
123    }