18b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira/*
28b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Copyright (C) 2009 Google Inc.
38b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
48b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License");
58b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * you may not use this file except in compliance with the License.
68b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * You may obtain a copy of the License at
78b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
88b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0
98b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Unless required by applicable law or agreed to in writing, software
118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * See the License for the specific language governing permissions and
148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * limitations under the License.
158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */
168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1730e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangpackage com.android.mail.lib.base;
188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1930e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport static com.android.mail.lib.base.Preconditions.checkArgument;
2030e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport static com.android.mail.lib.base.Preconditions.checkNotNull;
2130e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport static com.android.mail.lib.base.Preconditions.checkState;
228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereiraimport com.google.common.base.Joiner;
248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereiraimport java.util.Iterator;
268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereiraimport java.util.NoSuchElementException;
278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereiraimport java.util.StringTokenizer;
288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereiraimport java.util.regex.Matcher;
298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereiraimport java.util.regex.Pattern;
308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereiraimport java.util.regex.PatternSyntaxException;
318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira/**
338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * An object that divides strings (or other instances of {@code CharSequence})
348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * into substrings, by recognizing a <i>separator</i> (a.k.a. "delimiter")
358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * which can be expressed as a single character, literal string, regular
368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * expression, {@code CharMatcher}, or by using a fixed substring length. This
378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * class provides the complementary functionality to {@link Joiner}.
388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>Here is the most basic example of {@code Splitter} usage: <pre>   {@code
408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *   Splitter.on(',').split("foo,bar")}</pre>
428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * This invocation returns an {@code Iterable<String>} containing {@code "foo"}
448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * and {@code "bar"}, in that order.
458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>By default {@code Splitter}'s behavior is very simplistic: <pre>   {@code
478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *   Splitter.on(',').split("foo,,bar,  quux")}</pre>
498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * This returns an iterable containing {@code ["foo", "", "bar", "  quux"]}.
518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Notice that the splitter does not assume that you want empty strings removed,
528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * or that you wish to trim whitespace. If you want features like these, simply
538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * ask for them: <pre> {@code
548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *   private static final Splitter MY_SPLITTER = Splitter.on(',')
568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *       .trimResults()
578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *       .omitEmptyStrings();}</pre>
588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Now {@code MY_SPLITTER.split("foo, ,bar,  quux,")} returns an iterable
608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * containing just {@code ["foo", "bar", "quux"]}. Note that the order in which
618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * the configuration methods are called is never significant; for instance,
628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * trimming is always applied first before checking for an empty result,
638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * regardless of the order in which the {@link #trimResults()} and
648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@link #omitEmptyStrings()} methods were invoked.
658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Warning: splitter instances are always immutable</b>; a configuration
678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * method such as {@code omitEmptyStrings} has no effect on the instance it
688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * is invoked on! You must store and use the new splitter instance returned by
698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * the method. This makes splitters thread-safe, and safe to store as {@code
708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * static final} constants (as illustrated above). <pre>   {@code
718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *   // Bad! Do not do this!
738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *   Splitter splitter = Splitter.on('/');
748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *   splitter.trimResults(); // does nothing!
758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *   return splitter.split("wrong / wrong / wrong");}</pre>
768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * The separator recognized by the splitter does not have to be a single
788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * literal character as in the examples above. See the methods {@link
798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * #on(String)}, {@link #on(Pattern)} and {@link #on(CharMatcher)} for examples
808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * of other ways to specify separators.
818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note:</b> this class does not mimic any of the quirky behaviors of
838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * similar JDK methods; for instance, it does not silently discard trailing
848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * separators, as does {@link String#split(String)}, nor does it have a default
858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * behavior of using five particular whitespace characters as separators, like
868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@link StringTokenizer}.
878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @author Julien Silland
898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @author Jesse Wilson
908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @author Kevin Bourrillion
918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @since 2009.09.15 <b>tentative</b>
928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */
938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereirapublic final class Splitter {
948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private final CharMatcher trimmer;
958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private final boolean omitEmptyStrings;
968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private final Strategy strategy;
978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private Splitter(Strategy strategy) {
998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    this(strategy, false, CharMatcher.NONE);
1008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private Splitter(Strategy strategy, boolean omitEmptyStrings,
1038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      CharMatcher trimmer) {
1048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    this.strategy = strategy;
1058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    this.omitEmptyStrings = omitEmptyStrings;
1068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    this.trimmer = trimmer;
1078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
1108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Returns a splitter that uses the given single-character separator. For
1118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * example, {@code Splitter.on(',').split("foo,,bar")} returns an iterable
1128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * containing {@code ["foo", "", "bar"]}.
1138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
1148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param separator the character to recognize as a separator
1158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return a splitter, with default settings, that recognizes that separator
1168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
1178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static Splitter on(char separator) {
1188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return on(CharMatcher.is(separator));
1198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
1228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Returns a splitter that considers any single character matched by the
1238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * given {@code CharMatcher} to be a separator. For example, {@code
1248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Splitter.on(CharMatcher.anyOf(";,")).split("foo,;bar,quux")} returns an
1258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * iterable containing {@code ["foo", "", "bar", "quux"]}.
1268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
1278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param separatorMatcher a {@link CharMatcher} that determines whether a
1288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     character is a separator
1298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return a splitter, with default settings, that uses this matcher
1308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
1318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static Splitter on(final CharMatcher separatorMatcher) {
1328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    checkNotNull(separatorMatcher);
1338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return new Splitter(new Strategy() {
1358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      /*@Override*/ public SplittingIterator iterator(
1368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          Splitter splitter, final CharSequence toSplit) {
1378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        return new SplittingIterator(splitter, toSplit) {
1388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          @Override int separatorStart(int start) {
1398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            return separatorMatcher.indexIn(toSplit, start);
1408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          }
1418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          @Override int separatorEnd(int separatorPosition) {
1438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            return separatorPosition + 1;
1448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          }
1458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        };
1468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
1478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    });
1488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
1518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Returns a splitter that uses the given fixed string as a separator. For
1528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * example, {@code Splitter.on(", ").split("foo, bar, baz,qux")} returns an
1538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * iterable containing {@code ["foo", "bar", "baz,qux"]}.
1548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
1558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param separator the literal, nonempty string to recognize as a separator
1568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return a splitter, with default settings, that recognizes that separator
1578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
1588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static Splitter on(final String separator) {
1598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    checkArgument(separator.length() != 0,
1608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        "The separator may not be the empty string.");
1618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return new Splitter(new Strategy() {
1638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      /*@Override*/ public SplittingIterator iterator(
1648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          Splitter splitter, CharSequence toSplit) {
1658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        return new SplittingIterator(splitter, toSplit) {
1668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          @Override public int separatorStart(int start) {
1678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            int delimeterLength = separator.length();
1688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            positions:
1708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            for (int p = start, last = toSplit.length() - delimeterLength;
1718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira                p <= last; p++) {
1728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira              for (int i = 0; i < delimeterLength; i++) {
1738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira                if (toSplit.charAt(i + p) != separator.charAt(i)) {
1748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira                  continue positions;
1758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira                }
1768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira              }
1778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira              return p;
1788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            }
1798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            return -1;
1808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          }
1818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          @Override public int separatorEnd(int separatorPosition) {
1838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            return separatorPosition + separator.length();
1848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          }
1858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        };
1868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
1878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    });
1888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
1918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Returns a splitter that considers any subsequence matching {@code
1928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * pattern} to be a separator. For example, {@code
1938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Splitter.on(Pattern.compile("\r?\n")).split(entireFile)} splits a string
1948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * into lines whether it uses DOS-style or UNIX-style line terminators.
1958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
1968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param separatorPattern the pattern that determines whether a subsequence
1978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     is a separator. This pattern may not match the empty string.
1988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return a splitter, with default settings, that uses this pattern
1998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalArgumentException if {@code separatorPattern} matches the
2008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     empty string
2018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
2028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static Splitter on(final Pattern separatorPattern) {
2038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    checkNotNull(separatorPattern);
2048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    checkArgument(!separatorPattern.matcher("").matches(),
2058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        "The pattern may not match the empty string: %s", separatorPattern);
2068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return new Splitter(new Strategy() {
2088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      /*@Override*/ public SplittingIterator iterator(
2098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          final Splitter splitter, CharSequence toSplit) {
2108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        final Matcher matcher = separatorPattern.matcher(toSplit);
2118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        return new SplittingIterator(splitter, toSplit) {
2128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          @Override public int separatorStart(int start) {
2138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            return matcher.find(start) ? matcher.start() : -1;
2148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          }
2158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          @Override public int separatorEnd(int separatorPosition) {
2178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            return matcher.end();
2188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          }
2198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        };
2208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
2218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    });
2228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
2238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
2258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Returns a splitter that considers any subsequence matching a given
2268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * pattern (regular expression) to be a separator. For example, {@code
2278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Splitter.onPattern("\r?\n").split(entireFile)} splits a string into lines
2288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * whether it uses DOS-style or UNIX-style line terminators. This is
2298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * equivalent to {@code Splitter.on(Pattern.compile(pattern))}.
2308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param separatorPattern the pattern that determines whether a subsequence
2328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     is a separator. This pattern may not match the empty string.
2338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return a splitter, with default settings, that uses this pattern
2348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws PatternSyntaxException if {@code separatorPattern} is a malformed
2358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     expression
2368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalArgumentException if {@code separatorPattern} matches the
2378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     empty string
2388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
2398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static Splitter onPattern(String separatorPattern) {
2408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return on(Pattern.compile(separatorPattern));
2418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
2428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
2448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Returns a splitter that divides strings into pieces of the given length.
2458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * For example, {@code Splitter.atEach(2).split("abcde")} returns an
2468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * iterable containing {@code ["ab", "cd", "e"]}. The last piece can be
2478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * smaller than {@code length} but will never be empty.
2488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param length the desired length of pieces after splitting
2508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return a splitter, with default settings, that can split into fixed sized
2518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     pieces
2528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
2538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static Splitter fixedLength(final int length) {
2548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    checkArgument(length > 0, "The length may not be less than 1");
2558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return new Splitter(new Strategy() {
2578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      /*@Override*/ public SplittingIterator iterator(
2588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          final Splitter splitter, CharSequence toSplit) {
2598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        return new SplittingIterator(splitter, toSplit) {
2608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          @Override public int separatorStart(int start) {
2618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            int nextChunkStart = start + length;
2628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            return (nextChunkStart < toSplit.length() ? nextChunkStart : -1);
2638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          }
2648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          @Override public int separatorEnd(int separatorPosition) {
2668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira            return separatorPosition;
2678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          }
2688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        };
2698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
2708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    });
2718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
2728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
2748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Returns a splitter that behaves equivalently to {@code this} splitter, but
2758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * automatically omits empty strings from the results. For example, {@code
2768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Splitter.on(',').omitEmptyStrings().split(",a,,,b,c,,")} returns an
2778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * iterable containing only {@code ["a", "b", "c"]}.
2788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * <p>If either {@code trimResults} option is also specified when creating a
2808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * splitter, that splitter always trims results first before checking for
2818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * emptiness. So, for example, {@code
2828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Splitter.on(':').omitEmptyStrings().trimResults().split(": : : ")} returns
2838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * an empty iterable.
2848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * <p>Note that it is ordinarily not possible for {@link #split(CharSequence)}
2868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * to return an empty iterable, but when using this option, it can (if the
2878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * input sequence consists of nothing but separators).
2888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return a splitter with the desired configuration
2908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
2918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public Splitter omitEmptyStrings() {
2928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return new Splitter(strategy, true, trimmer);
2938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
2948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
2968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Returns a splitter that behaves equivalently to {@code this} splitter, but
2978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * automatically removes leading and trailing {@linkplain
2988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * CharMatcher#WHITESPACE whitespace} from each returned substring; equivalent
2998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * to {@code trimResults(CharMatcher.WHITESPACE)}. For example, {@code
3008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Splitter.on(',').trimResults().split(" a, b  ,c  ")} returns an iterable
3018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * containing {@code ["a", "b", "c"]}.
3028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
3038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return a splitter with the desired configuration
3048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
3058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public Splitter trimResults() {
3068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return trimResults(CharMatcher.WHITESPACE);
3078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
3088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
3108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Returns a splitter that behaves equivalently to {@code this} splitter, but
3118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * removes all leading or trailing characters matching the given {@code
3128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * CharMatcher} from each returned substring. For example, {@code
3138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Splitter.on(',').trimResults(CharMatcher.is('_')).split("_a ,_b_ ,c__")}
3148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * returns an iterable containing {@code ["a ", "b_ ", "c"]}.
3158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
3168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param trimmer a {@link CharMatcher} that determines whether a character
3178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     should be removed from the beginning/end of a subsequence
3188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return a splitter with the desired configuration
3198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
3208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public Splitter trimResults(CharMatcher trimmer) {
3218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    checkNotNull(trimmer);
3228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return new Splitter(strategy, omitEmptyStrings, trimmer);
3238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
3248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
3268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Splits the {@link CharSequence} passed in parameter.
3278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
3288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param sequence the sequence of characters to split
3298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return an iteration over the segments split from the parameter.
3308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
3318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public Iterable<String> split(final CharSequence sequence) {
3328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    checkNotNull(sequence);
3338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return new Iterable<String>() {
3358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      /*@Override*/ public Iterator<String> iterator() {
3368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        return strategy.iterator(Splitter.this, sequence);
3378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
3388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    };
3398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
3408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private interface Strategy {
3428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    Iterator<String> iterator(Splitter splitter, CharSequence toSplit);
3438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
3448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private abstract static class SplittingIterator
3468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      extends AbstractIterator<String> {
3478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    final CharSequence toSplit;
3488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    final CharMatcher trimmer;
3498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    final boolean omitEmptyStrings;
3508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    /**
3528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira     * Returns the first index in {@code toSplit} at or after {@code start}
3538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira     * that contains the separator.
3548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira     */
3558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    abstract int separatorStart(int start);
3568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    /**
3588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira     * Returns the first index in {@code toSplit} after {@code
3598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira     * separatorPosition} that does not contain a separator. This method is only
3608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira     * invoked after a call to {@code separatorStart}.
3618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira     */
3628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    abstract int separatorEnd(int separatorPosition);
3638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    int offset = 0;
3658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    protected SplittingIterator(Splitter splitter, CharSequence toSplit) {
3678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      this.trimmer = splitter.trimmer;
3688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      this.omitEmptyStrings = splitter.omitEmptyStrings;
3698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      this.toSplit = toSplit;
3708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
3718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    @Override protected String computeNext() {
3738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      while (offset != -1) {
3748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        int start = offset;
3758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        int end;
3768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        int separatorPosition = separatorStart(offset);
3788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        if (separatorPosition == -1) {
3798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          end = toSplit.length();
3808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          offset = -1;
3818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        } else {
3828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          end = separatorPosition;
3838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          offset = separatorEnd(separatorPosition);
3848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        }
3858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        while (start < end && trimmer.matches(toSplit.charAt(start))) {
3878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          start++;
3888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        }
3898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        while (end > start && trimmer.matches(toSplit.charAt(end - 1))) {
3908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          end--;
3918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        }
3928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        if (omitEmptyStrings && start == end) {
3948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          continue;
3958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        }
3968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        return toSplit.subSequence(start, end).toString();
3988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
3998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return endOfData();
4008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
4018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
4028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /*
4048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Copied from common.collect.AbstractIterator. TODO: un-fork once these
4058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * packages have been combined into a single library.
4068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
4078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private static abstract class AbstractIterator<T> implements Iterator<T> {
4088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    State state = State.NOT_READY;
4098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    enum State {
4118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      READY, NOT_READY, DONE, FAILED,
4128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
4138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    T next;
4158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    protected abstract T computeNext();
4178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    protected final T endOfData() {
4198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      state = State.DONE;
4208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return null;
4218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
4228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    public final boolean hasNext() {
4248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      checkState(state != State.FAILED);
4258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      switch (state) {
4268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        case DONE:
4278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          return false;
4288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        case READY:
4298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          return true;
4308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        default:
4318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
4328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return tryToComputeNext();
4338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
4348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    boolean tryToComputeNext() {
4368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      state = State.FAILED; // temporary pessimism
4378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      next = computeNext();
4388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      if (state != State.DONE) {
4398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        state = State.READY;
4408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        return true;
4418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
4428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return false;
4438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
4448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    public final T next() {
4468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      if (!hasNext()) {
4478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        throw new NoSuchElementException();
4488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
4498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      state = State.NOT_READY;
4508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return next;
4518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
4528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    /*@Override*/ public void remove() {
4548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new UnsupportedOperationException();
4558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
4568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
4578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira}
458