001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.util.string; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.Collections; 022import java.util.Iterator; 023import java.util.List; 024import java.util.StringTokenizer; 025 026/** 027 * A typesafe, mutable list of strings supporting a variety of convenient operations as well as 028 * expected operations from List such as add(), size(), remove(), iterator(), get(int index) and 029 * toArray(). Instances of the class are not threadsafe. 030 * <p> 031 * StringList objects can be constructed empty or they can be created using any of several static 032 * factory methods: 033 * <ul> 034 * <li>valueOf(String[]) 035 * <li>valueOf(String) 036 * <li>valueOf(Collection) 037 * <li>valueOf(Object[]) 038 * </ul> 039 * In the case of the Collection and Object[] factory methods, each Object in the collection or 040 * array is converted to a String via toString() before being added to the StringList. 041 * <p> 042 * The tokenize() factory methods allow easy creation of StringLists via StringTokenizer. The 043 * repeat() static factory method creates a StringList that repeats a given String a given number of 044 * times. 045 * <p> 046 * The prepend() method adds a String to the beginning of the StringList. The removeLast() method 047 * pops a String off the end of the list. The sort() method sorts strings in the List using 048 * Collections.sort(). The class also inherits useful methods from AbstractStringList that include 049 * join() methods ala Perl and a toString() method which joins the list of strings with comma 050 * separators for easy viewing. 051 * 052 * @author Jonathan Locke 053 */ 054public final class StringList extends AbstractStringList 055{ 056 private static final long serialVersionUID = 1L; 057 058 // The underlying list of strings 059 private final List<String> strings; 060 061 // The total length of all strings in the list 062 private int totalLength; 063 064 /** 065 * Returns a list of a string repeated a given number of times. 066 * 067 * @param count 068 * The number of times to repeat the string 069 * @param string 070 * The string to repeat 071 * @return The list of strings 072 */ 073 public static StringList repeat(final int count, final String string) 074 { 075 final StringList list = new StringList(count); 076 077 for (int i = 0; i < count; i++) 078 { 079 list.add(string); 080 } 081 082 return list; 083 } 084 085 /** 086 * Extracts tokens from a comma and space delimited string. 087 * 088 * @param string 089 * The string 090 * @return The string tokens as a list 091 */ 092 public static StringList tokenize(final String string) 093 { 094 return tokenize(string, ", "); 095 } 096 097 /** 098 * Extracts tokens from a delimited string. 099 * 100 * @param string 101 * The string 102 * @param delimiters 103 * The delimiters 104 * @return The string tokens as a list 105 */ 106 public static StringList tokenize(final String string, final String delimiters) 107 { 108 final StringTokenizer tokenizer = new StringTokenizer(string, delimiters); 109 final StringList strings = new StringList(); 110 111 while (tokenizer.hasMoreTokens()) 112 { 113 strings.add(tokenizer.nextToken()); 114 } 115 116 return strings; 117 } 118 119 /** 120 * Converts a collection of objects into a list of string values by using the conversion methods 121 * of the StringValue class. 122 * 123 * @param collection 124 * The collection to add as strings 125 * @return The list 126 */ 127 public static StringList valueOf(final Collection<?> collection) 128 { 129 if (collection != null) 130 { 131 final StringList strings = new StringList(collection.size()); 132 133 for (Object object : collection) 134 { 135 strings.add(StringValue.valueOf(object)); 136 } 137 138 return strings; 139 } 140 else 141 { 142 return new StringList(); 143 } 144 } 145 146 /** 147 * Converts an array of objects into a list of strings by using the object to string conversion 148 * method of the StringValue class. 149 * 150 * @param objects 151 * The objects to convert 152 * @return The list of strings 153 */ 154 public static StringList valueOf(final Object[] objects) 155 { 156 // check for null parameter 157 int length = (objects == null) ? 0 : objects.length; 158 final StringList strings = new StringList(length); 159 160 for (int i = 0; i < length; i++) 161 { 162 strings.add(StringValue.valueOf(objects[i])); 163 } 164 165 return strings; 166 } 167 168 /** 169 * Returns a string list with just one string in it. 170 * 171 * @param string 172 * The string 173 * @return The list of one string 174 */ 175 public static StringList valueOf(final String string) 176 { 177 final StringList strings = new StringList(); 178 179 if (string != null) 180 { 181 strings.add(string); 182 } 183 184 return strings; 185 } 186 187 /** 188 * Converts a string array to a string list. 189 * 190 * @param array 191 * The array 192 * @return The list 193 */ 194 public static StringList valueOf(final String[] array) 195 { 196 int length = (array == null) ? 0 : array.length; 197 final StringList strings = new StringList(length); 198 199 for (int i = 0; i < length; i++) 200 { 201 strings.add(array[i]); 202 } 203 204 return strings; 205 } 206 207 /** 208 * Constructor. 209 */ 210 public StringList() 211 { 212 strings = new ArrayList<>(); 213 } 214 215 /** 216 * Constructor. 217 * 218 * @param size 219 * Number of elements to preallocate 220 */ 221 public StringList(final int size) 222 { 223 strings = new ArrayList<>(size); 224 } 225 226 /** 227 * Adds a string to the back of this list. 228 * 229 * @param string 230 * String to add 231 */ 232 public void add(final String string) 233 { 234 // Add to list 235 add(size(), string); 236 } 237 238 /** 239 * Adds the string to the stringlist at position pos. 240 * 241 * @param pos 242 * the position to add the string at 243 * @param string 244 * the string to add. 245 */ 246 public void add(final int pos, final String string) 247 { 248 strings.add(pos, string == null ? "" : string); 249 250 // Increase total length 251 totalLength += string == null ? 0 : string.length(); 252 } 253 254 /** 255 * Adds a string value to this list as a string. 256 * 257 * @param value 258 * The value to add 259 */ 260 public void add(final StringValue value) 261 { 262 add(value.toString()); 263 } 264 265 /** 266 * @param string 267 * The string to look for 268 * @return True if the list contains the string 269 */ 270 public boolean contains(final String string) 271 { 272 return strings.contains(string); 273 } 274 275 /** 276 * Gets the string at the given index. 277 * 278 * @param index 279 * The index 280 * @return The string at the index 281 * @throws IndexOutOfBoundsException 282 */ 283 @Override 284 public String get(final int index) 285 { 286 return strings.get(index); 287 } 288 289 /** 290 * @return List value (not a copy of this list) 291 */ 292 public List<String> getList() 293 { 294 return strings; 295 } 296 297 /** 298 * Returns a typesafe iterator over this collection of strings. 299 * 300 * @return Typesafe string iterator 301 */ 302 @Override 303 public IStringIterator iterator() 304 { 305 return new IStringIterator() 306 { 307 private final Iterator<String> iterator = strings.iterator(); 308 309 @Override 310 public boolean hasNext() 311 { 312 return iterator.hasNext(); 313 } 314 315 @Override 316 public String next() 317 { 318 return iterator.next(); 319 } 320 }; 321 } 322 323 /** 324 * Adds the given string to the front of the list. 325 * 326 * @param string 327 * The string to add 328 */ 329 public void prepend(final String string) 330 { 331 add(0, string); 332 } 333 334 /** 335 * Removes the string at the given index. 336 * 337 * @param index 338 * The index 339 */ 340 public void remove(final int index) 341 { 342 String string = strings.remove(index); 343 totalLength = totalLength - string.length(); 344 } 345 346 /** 347 * Removes the last string in this list. 348 */ 349 public void removeLast() 350 { 351 remove(size() - 1); 352 } 353 354 /** 355 * @return The number of strings in this list. 356 */ 357 @Override 358 public int size() 359 { 360 return strings.size(); 361 } 362 363 /** 364 * Sorts this string list alphabetically. 365 */ 366 public void sort() 367 { 368 Collections.sort(strings); 369 } 370 371 /** 372 * Converts this string list to a string array. 373 * 374 * @return The string array 375 */ 376 @Override 377 public String[] toArray() 378 { 379 return strings.toArray(new String[0]); 380 } 381 382 /** 383 * @return The total length of all strings in this list. 384 */ 385 @Override 386 public int totalLength() 387 { 388 return totalLength; 389 } 390}