1bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2009 The Guava Authors 3bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 4bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Licensed under the Apache License, Version 2.0 (the "License"); 5bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * you may not use this file except in compliance with the License. 6bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * You may obtain a copy of the License at 7bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 8bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * http://www.apache.org/licenses/LICENSE-2.0 9bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 10bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Unless required by applicable law or agreed to in writing, software 11bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * distributed under the License is distributed on an "AS IS" BASIS, 12bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * See the License for the specific language governing permissions and 14bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * limitations under the License. 15bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 16bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 17bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorpackage com.google.common.base; 18bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 19bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport static com.google.common.base.Preconditions.checkArgument; 20bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport static com.google.common.base.Preconditions.checkNotNull; 21bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collections; 26bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.Iterator; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.LinkedHashMap; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map; 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.CheckReturnValue; 31bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 32bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor/** 33bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * An object that divides strings (or other instances of {@code CharSequence}) 34bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * into substrings, by recognizing a <i>separator</i> (a.k.a. "delimiter") 35bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * which can be expressed as a single character, literal string, regular 36bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * expression, {@code CharMatcher}, or by using a fixed substring length. This 37bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * class provides the complementary functionality to {@link Joiner}. 38bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 39bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>Here is the most basic example of {@code Splitter} usage: <pre> {@code 40bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 41bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Splitter.on(',').split("foo,bar")}</pre> 42bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 43bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * This invocation returns an {@code Iterable<String>} containing {@code "foo"} 44bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * and {@code "bar"}, in that order. 45bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 46bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>By default {@code Splitter}'s behavior is very simplistic: <pre> {@code 47bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Splitter.on(',').split("foo,,bar, quux")}</pre> 49bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * This returns an iterable containing {@code ["foo", "", "bar", " quux"]}. 51bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Notice that the splitter does not assume that you want empty strings removed, 52bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * or that you wish to trim whitespace. If you want features like these, simply 53bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * ask for them: <pre> {@code 54bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 55bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * private static final Splitter MY_SPLITTER = Splitter.on(',') 56bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * .trimResults() 57bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * .omitEmptyStrings();}</pre> 58bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Now {@code MY_SPLITTER.split("foo, ,bar, quux,")} returns an iterable 60bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * containing just {@code ["foo", "bar", "quux"]}. Note that the order in which 61bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * the configuration methods are called is never significant; for instance, 62bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * trimming is always applied first before checking for an empty result, 63bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * regardless of the order in which the {@link #trimResults()} and 64bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * {@link #omitEmptyStrings()} methods were invoked. 65bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 66bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p><b>Warning: splitter instances are always immutable</b>; a configuration 67bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * method such as {@code omitEmptyStrings} has no effect on the instance it 68bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * is invoked on! You must store and use the new splitter instance returned by 69bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * the method. This makes splitters thread-safe, and safe to store as {@code 70bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * static final} constants (as illustrated above). <pre> {@code 71bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 72bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * // Bad! Do not do this! 73bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Splitter splitter = Splitter.on('/'); 74bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * splitter.trimResults(); // does nothing! 75bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * return splitter.split("wrong / wrong / wrong");}</pre> 76bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 77bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * The separator recognized by the splitter does not have to be a single 78bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * literal character as in the examples above. See the methods {@link 79bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * #on(String)}, {@link #on(Pattern)} and {@link #on(CharMatcher)} for examples 80bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * of other ways to specify separators. 81bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 82bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p><b>Note:</b> this class does not mimic any of the quirky behaviors of 83bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * similar JDK methods; for instance, it does not silently discard trailing 84bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * separators, as does {@link String#split(String)}, nor does it have a default 85bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * behavior of using five particular whitespace characters as separators, like 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link java.util.StringTokenizer}. 87bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 88bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @author Julien Silland 89bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @author Jesse Wilson 90bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @author Kevin Bourrillion 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Louis Wasserman 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 1.0 93bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(emulated = true) 95bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorpublic final class Splitter { 96bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private final CharMatcher trimmer; 97bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private final boolean omitEmptyStrings; 98bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private final Strategy strategy; 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final int limit; 100bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 101bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private Splitter(Strategy strategy) { 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this(strategy, false, CharMatcher.NONE, Integer.MAX_VALUE); 103bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 104bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 105bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private Splitter(Strategy strategy, boolean omitEmptyStrings, 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert CharMatcher trimmer, int limit) { 107bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor this.strategy = strategy; 108bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor this.omitEmptyStrings = omitEmptyStrings; 109bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor this.trimmer = trimmer; 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.limit = limit; 111bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 112bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 113bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 114bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a splitter that uses the given single-character separator. For 115bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * example, {@code Splitter.on(',').split("foo,,bar")} returns an iterable 116bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * containing {@code ["foo", "", "bar"]}. 117bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 118bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param separator the character to recognize as a separator 119bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a splitter, with default settings, that recognizes that separator 120bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 121bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static Splitter on(char separator) { 122bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return on(CharMatcher.is(separator)); 123bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 124bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 125bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 126bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a splitter that considers any single character matched by the 127bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * given {@code CharMatcher} to be a separator. For example, {@code 128bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Splitter.on(CharMatcher.anyOf(";,")).split("foo,;bar,quux")} returns an 129bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * iterable containing {@code ["foo", "", "bar", "quux"]}. 130bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 131bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param separatorMatcher a {@link CharMatcher} that determines whether a 132bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * character is a separator 133bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a splitter, with default settings, that uses this matcher 134bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 135bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static Splitter on(final CharMatcher separatorMatcher) { 136bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor checkNotNull(separatorMatcher); 137bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 138bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new Splitter(new Strategy() { 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public SplittingIterator iterator( 140bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Splitter splitter, final CharSequence toSplit) { 141bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new SplittingIterator(splitter, toSplit) { 142bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor @Override int separatorStart(int start) { 143bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return separatorMatcher.indexIn(toSplit, start); 144bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 145bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 146bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor @Override int separatorEnd(int separatorPosition) { 147bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return separatorPosition + 1; 148bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 149bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }; 150bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 151bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }); 152bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 153bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 154bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 155bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a splitter that uses the given fixed string as a separator. For 156bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * example, {@code Splitter.on(", ").split("foo, bar, baz,qux")} returns an 157bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * iterable containing {@code ["foo", "bar", "baz,qux"]}. 158bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 159bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param separator the literal, nonempty string to recognize as a separator 160bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a splitter, with default settings, that recognizes that separator 161bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 162bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static Splitter on(final String separator) { 163bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor checkArgument(separator.length() != 0, 164bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor "The separator may not be the empty string."); 165bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 166bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new Splitter(new Strategy() { 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public SplittingIterator iterator( 168bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Splitter splitter, CharSequence toSplit) { 169bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new SplittingIterator(splitter, toSplit) { 170bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor @Override public int separatorStart(int start) { 171bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor int delimeterLength = separator.length(); 172bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 173bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor positions: 174bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor for (int p = start, last = toSplit.length() - delimeterLength; 175bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor p <= last; p++) { 176bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor for (int i = 0; i < delimeterLength; i++) { 177bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (toSplit.charAt(i + p) != separator.charAt(i)) { 178bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor continue positions; 179bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 180bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 181bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return p; 182bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 183bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return -1; 184bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 185bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 186bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor @Override public int separatorEnd(int separatorPosition) { 187bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return separatorPosition + separator.length(); 188bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 189bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }; 190bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 191bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }); 192bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 193bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 194bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 195bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a splitter that divides strings into pieces of the given length. 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * For example, {@code Splitter.fixedLength(2).split("abcde")} returns an 197bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * iterable containing {@code ["ab", "cd", "e"]}. The last piece can be 198bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * smaller than {@code length} but will never be empty. 199bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 200bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param length the desired length of pieces after splitting 201bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a splitter, with default settings, that can split into fixed sized 202bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * pieces 203bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 204bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static Splitter fixedLength(final int length) { 205bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor checkArgument(length > 0, "The length may not be less than 1"); 206bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 207bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new Splitter(new Strategy() { 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public SplittingIterator iterator( 209bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor final Splitter splitter, CharSequence toSplit) { 210bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new SplittingIterator(splitter, toSplit) { 211bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor @Override public int separatorStart(int start) { 212bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor int nextChunkStart = start + length; 213bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return (nextChunkStart < toSplit.length() ? nextChunkStart : -1); 214bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 215bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 216bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor @Override public int separatorEnd(int separatorPosition) { 217bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return separatorPosition; 218bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 219bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }; 220bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 221bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }); 222bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 223bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 224bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 225bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a splitter that behaves equivalently to {@code this} splitter, but 226bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * automatically omits empty strings from the results. For example, {@code 227bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Splitter.on(',').omitEmptyStrings().split(",a,,,b,c,,")} returns an 228bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * iterable containing only {@code ["a", "b", "c"]}. 229bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 230bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>If either {@code trimResults} option is also specified when creating a 231bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * splitter, that splitter always trims results first before checking for 232bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * emptiness. So, for example, {@code 233bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Splitter.on(':').omitEmptyStrings().trimResults().split(": : : ")} returns 234bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * an empty iterable. 235bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 236bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>Note that it is ordinarily not possible for {@link #split(CharSequence)} 237bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * to return an empty iterable, but when using this option, it can (if the 238bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * input sequence consists of nothing but separators). 239bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 240bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a splitter with the desired configuration 241bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @CheckReturnValue 243bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public Splitter omitEmptyStrings() { 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Splitter(strategy, true, trimmer, limit); 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a splitter that behaves equivalently to {@code this} splitter but 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * stops splitting after it reaches the limit. 2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The limit defines the maximum number of items returned by the iterator. 2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>For example, 2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Splitter.on(',').limit(3).split("a,b,c,d")} returns an iterable 2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * containing {@code ["a", "b", "c,d"]}. When omitting empty strings, the 2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * omitted strings do no count. Hence, 2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Splitter.on(',').limit(3).omitEmptyStrings().split("a,,,b,,,c,d")} 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * returns an iterable containing {@code ["a", "b", "c,d"}. 2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * When trim is requested, all entries, including the last are trimmed. Hence 2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Splitter.on(',').limit(3).trimResults().split(" a , b , c , d ")} 2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * results in @{code ["a", "b", "c , d"]}. 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param limit the maximum number of items returns 2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @return a splitter with the desired configuration 2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 9.0 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @CheckReturnValue 2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public Splitter limit(int limit) { 2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(limit > 0, "must be greater than zero: %s", limit); 2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Splitter(strategy, omitEmptyStrings, trimmer, limit); 270bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 271bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 272bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 273bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a splitter that behaves equivalently to {@code this} splitter, but 274bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * automatically removes leading and trailing {@linkplain 275bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * CharMatcher#WHITESPACE whitespace} from each returned substring; equivalent 276bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * to {@code trimResults(CharMatcher.WHITESPACE)}. For example, {@code 2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Splitter.on(',').trimResults().split(" a, b ,c ")} returns an iterable 278bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * containing {@code ["a", "b", "c"]}. 279bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 280bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a splitter with the desired configuration 281bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @CheckReturnValue 283bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public Splitter trimResults() { 284bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return trimResults(CharMatcher.WHITESPACE); 285bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 286bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 287bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 288bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a splitter that behaves equivalently to {@code this} splitter, but 289bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * removes all leading or trailing characters matching the given {@code 290bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * CharMatcher} from each returned substring. For example, {@code 291bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Splitter.on(',').trimResults(CharMatcher.is('_')).split("_a ,_b_ ,c__")} 292bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * returns an iterable containing {@code ["a ", "b_ ", "c"]}. 293bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 294bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param trimmer a {@link CharMatcher} that determines whether a character 295bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * should be removed from the beginning/end of a subsequence 296bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a splitter with the desired configuration 297bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // TODO(kevinb): throw if a trimmer was already specified! 2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @CheckReturnValue 300bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public Splitter trimResults(CharMatcher trimmer) { 301bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor checkNotNull(trimmer); 3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Splitter(strategy, omitEmptyStrings, trimmer, limit); 303bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 304bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 305bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Splits {@code sequence} into string components and makes them available 3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * through an {@link Iterator}, which may be lazily evaluated. 308bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 309bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param sequence the sequence of characters to split 310bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return an iteration over the segments split from the parameter. 311bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 312bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public Iterable<String> split(final CharSequence sequence) { 313bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor checkNotNull(sequence); 314bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 315bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new Iterable<String>() { 3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public Iterator<String> iterator() { 3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return spliterator(sequence); 318bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 319bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }; 320bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 321bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Iterator<String> spliterator(CharSequence sequence) { 3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return strategy.iterator(this, sequence); 3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a {@code MapSplitter} which splits entries based on this splitter, 3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * and splits entries into keys and values using the specified separator. 3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0 3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @CheckReturnValue 3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapSplitter withKeyValueSeparator(String separator) { 3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return withKeyValueSeparator(on(separator)); 3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a {@code MapSplitter} which splits entries based on this splitter, 3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * and splits entries into keys and values using the specified key-value 3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * splitter. 3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0 3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @CheckReturnValue 3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapSplitter withKeyValueSeparator(Splitter keyValueSplitter) { 3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new MapSplitter(this, keyValueSplitter); 3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * An object that splits strings into maps as {@code Splitter} splits 3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * iterables and lists. Like {@code Splitter}, it is thread-safe and 3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * immutable. 3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0 3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static final class MapSplitter { 3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final String INVALID_ENTRY_MESSAGE = 3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "Chunk [%s] is not a valid entry"; 3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final Splitter outerSplitter; 3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final Splitter entrySplitter; 3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private MapSplitter(Splitter outerSplitter, Splitter entrySplitter) { 3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.outerSplitter = outerSplitter; // only "this" is passed 3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.entrySplitter = checkNotNull(entrySplitter); 3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Splits {@code sequence} into substrings, splits each substring into 3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * an entry, and returns an unmodifiable map with each of the entries. For 3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * example, <code> 3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Splitter.on(';').trimResults().withKeyValueSeparator("=>") 3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * .split("a=>b ; c=>b") 3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * </code> will return a mapping from {@code "a"} to {@code "b"} and 3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code "c"} to {@code b}. 3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The returned map preserves the order of the entries from 3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code sequence}. 3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalArgumentException if the specified sequence does not split 3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * into valid map entries, or if there are duplicate keys 3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public Map<String, String> split(CharSequence sequence) { 3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Map<String, String> map = new LinkedHashMap<String, String>(); 3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (String entry : outerSplitter.split(sequence)) { 3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Iterator<String> entryFields = entrySplitter.spliterator(entry); 3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry); 3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String key = entryFields.next(); 3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(!map.containsKey(key), "Duplicate key [%s] found.", key); 3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry); 3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String value = entryFields.next(); 3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert map.put(key, value); 3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(!entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry); 3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Collections.unmodifiableMap(map); 4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 404bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private interface Strategy { 405bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Iterator<String> iterator(Splitter splitter, CharSequence toSplit); 406bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 407bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 408bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private abstract static class SplittingIterator 409bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor extends AbstractIterator<String> { 410bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor final CharSequence toSplit; 411bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor final CharMatcher trimmer; 412bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor final boolean omitEmptyStrings; 413bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 414bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 415bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns the first index in {@code toSplit} at or after {@code start} 416bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * that contains the separator. 417bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 418bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor abstract int separatorStart(int start); 419bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 420bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 421bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns the first index in {@code toSplit} after {@code 422bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * separatorPosition} that does not contain a separator. This method is only 423bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * invoked after a call to {@code separatorStart}. 424bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 425bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor abstract int separatorEnd(int separatorPosition); 426bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 427bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor int offset = 0; 4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int limit; 429bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 430bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor protected SplittingIterator(Splitter splitter, CharSequence toSplit) { 431bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor this.trimmer = splitter.trimmer; 432bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor this.omitEmptyStrings = splitter.omitEmptyStrings; 4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.limit = splitter.limit; 434bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor this.toSplit = toSplit; 435bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 436bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 437bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor @Override protected String computeNext() { 438bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor while (offset != -1) { 439bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor int start = offset; 440bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor int end; 441bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 442bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor int separatorPosition = separatorStart(offset); 443bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (separatorPosition == -1) { 444bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor end = toSplit.length(); 445bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor offset = -1; 446bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } else { 447bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor end = separatorPosition; 448bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor offset = separatorEnd(separatorPosition); 449bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 450bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 451bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor while (start < end && trimmer.matches(toSplit.charAt(start))) { 452bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor start++; 453bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 454bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor while (end > start && trimmer.matches(toSplit.charAt(end - 1))) { 455bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor end--; 456bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 457bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 458bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (omitEmptyStrings && start == end) { 459bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor continue; 460bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 461bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (limit == 1) { 4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // The limit has been reached, return the rest of the string as the 4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // final item. This is tested after empty string removal so that 4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // empty strings do not count towards the limit. 4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert end = toSplit.length(); 4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert offset = -1; 4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Since we may have changed the end, we need to trim it again. 4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (end > start && trimmer.matches(toSplit.charAt(end - 1))) { 4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert end--; 4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } else { 4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert limit--; 4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 476bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return toSplit.subSequence(start, end).toString(); 477bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 478bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return endOfData(); 479bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 480bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 481bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor} 482