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