Package com.google.gwt.junit.client.impl

Source Code of com.google.gwt.junit.client.impl.PermutationIterator$Permutation

/*
* Copyright 2007 Google Inc.
* Licensed 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.
*/
package com.google.gwt.junit.client.impl;

import com.google.gwt.junit.client.Range;

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

/**
* Iterates over all the possible permutations available in a list of
* {@link com.google.gwt.junit.client.Range}s.
*
* <p>The simplest way to iterate over the permutations of multiple iterators
* is in a nested for loop. The PermutationIterator turns that for loop inside
* out into a single iterator, which enables you to access each permutation
* in a piecemeal fashion.</p>
*
*/
public class PermutationIterator implements Iterator {

  /**
   * A single permutation of all the iterators. Contains the current value
   * of each iterator for the permutation.
   *
   */
  public static class Permutation {
    private List values;
    public Permutation( List values ) {
      this.values = new ArrayList( values );
    }
    public List getValues() {
      return values;
    }
    public String toString() {
      return values.toString();
    }
  }

  private static class ListRange implements Range {
    private List list;
    public ListRange( List list ) {
      this.list = list;
    }
    public Iterator iterator() {
      return list.iterator();
    }
  }
  public static void main( String[] args ) {
    List ranges = Arrays.asList(
      new Range[] {
        new ListRange( Arrays.asList( new String[] {"a", "b", "c" } ) ),
        new ListRange( Arrays.asList( new String[] {"1", "2", "3" } ) ),
        new ListRange( Arrays.asList( new String[] {"alpha", "beta", "gamma", "delta" } ) ),
      }
    );

    System.out.println("Testing normal iteration.");
    for ( Iterator it = new PermutationIterator(ranges); it.hasNext(); ) {
      Permutation p = (Permutation) it.next();
      System.out.println(p);
    }

    System.out.println("\nTesting skipping iteration.");

    Iterator skipIterator = Arrays.asList( new String[] {"alpha", "beta", "gamma", "delta" } ).iterator();
    boolean skipped = true;
    String skipValue = null;
    for ( PermutationIterator it = new PermutationIterator(ranges); it.hasNext(); ) {
      Permutation p = (Permutation) it.next();

      if ( skipped ) {
        if ( skipIterator.hasNext() ) {
          skipValue = (String) skipIterator.next();
          skipped = false;
        }
      }

      System.out.println(p);

      String value = (String) p.getValues().get(p.getValues().size() - 1);

      if ( value.equals(skipValue) ) {
        it.skipCurrentRange();
        skipped = true;
      }
    }
  }
  private boolean firstRun = true;
  private List iterators;
  private boolean maybeHaveMore = true;
  private List ranges;

  private boolean rangeSkipped = false;

  private List values;

  /**
   * Constructs a new PermutationIterator that provides the values for each
   * possible permutation of <code>ranges</code>.
   *
   * @param ranges non-null. Each {@link com.google.gwt.junit.client.Range}
   * must have at least one element. ranges.size() must be > 1
   *
   * TODO(tobyr) Consider if empty Ranges ever make sense in the context of
   * permutations.
   *
   */
  public PermutationIterator( List ranges ) {
    this.ranges = ranges;

    iterators = new ArrayList();

    for ( int i = 0; i < ranges.size(); ++i ) {
      Range r = ( Range ) ranges.get( i );
      iterators.add( r.iterator() );
    }

    values = new ArrayList();
  }

  /**
   * Returns a new <code>Permutation</code> containing the values of the next
   * permutation.
   *
   * @return a non-null <code>Permutation</code>
   */
  public boolean hasNext() {

    if ( ! maybeHaveMore ) {
      return false;
    }

    // Walk the iterators from bottom to top checking to see if any still have
    // any available values

    for ( int currentIterator = iterators.size() - 1; currentIterator >= 0; --currentIterator ) {
      Iterator it = (Iterator) iterators.get( currentIterator );
      if ( it.hasNext() ) {
        return true;
      }
    }

    return false;
  }

  public Object next() {
    assert hasNext() : "No more available permutations in this iterator.";

    if ( firstRun ) {

      // Initialize all of our iterators and values on the first run
      for ( int i = 0; i < iterators.size(); ++i ) {
        Iterator it = ( Iterator ) iterators.get( i );
        values.add( it.next() );
      }
      firstRun = false;
      return new Permutation( values );
    }

    if ( rangeSkipped ) {
      rangeSkipped = false;
      return new Permutation( values );
    }

    // Walk through the iterators from bottom to top, finding the first one
    // which has a value available. Increment it, reset all of the subsequent
    // iterators, and then return the current permutation.
    for ( int currentIteratorIndex = iterators.size() - 1; currentIteratorIndex >= 0; --currentIteratorIndex ) {
      Iterator it = (Iterator) iterators.get( currentIteratorIndex );
      if ( it.hasNext() ) {
        values.set( currentIteratorIndex, it.next() );
        for ( int i = currentIteratorIndex + 1; i < iterators.size(); ++i ) {
          Range resetRange = (Range) ranges.get( i );
          Iterator resetIterator = resetRange.iterator();
          iterators.set(i, resetIterator);
          values.set( i, resetIterator.next() );
        }

        return new Permutation( values );
      }
    }

    throw new AssertionError( "Assertion failed - Couldn't find a non-empty iterator." );
  }

  public void remove() {
    throw new UnsupportedOperationException();
  }

  /**
   * Skips the remaining set of values in the bottom
   * {@link com.google.gwt.junit.client.Range}. This method affects the results
   * of both hasNext() and next().
   *
   */
  public void skipCurrentRange() {

    rangeSkipped = true;

    for ( int currentIteratorIndex = iterators.size() - 2; currentIteratorIndex >= 0; --currentIteratorIndex ) {
      Iterator it = (Iterator) iterators.get( currentIteratorIndex );
      if ( it.hasNext() ) {
        values.set( currentIteratorIndex, it.next() );
        for ( int i = currentIteratorIndex + 1; i < iterators.size(); ++i ) {
          Range resetRange = (Range) ranges.get( i );
          Iterator resetIterator = resetRange.iterator();
          iterators.set( i, resetIterator );
          values.set( i, resetIterator.next() );
        }
        return;
      }
    }

    maybeHaveMore = false;
  }
}
TOP

Related Classes of com.google.gwt.junit.client.impl.PermutationIterator$Permutation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.