/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.wicket.util.string;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
/**
* A typesafe, mutable list of strings supporting a variety of convenient operations as well as
* expected operations from List such as add(), size(), remove(), iterator(), get(int index) and
* toArray(). Instances of the class are not threadsafe.
* <p>
* StringList objects can be constructed empty or they can be created using any of several static
* factory methods:
* <ul>
* <li>valueOf(String[])
* <li>valueOf(String)
* <li>valueOf(Collection)
* <li>valueOf(Object[])
* </ul>
* In the case of the Collection and Object[] factory methods, each Object in the collection or
* array is converted to a String via toString() before being added to the StringList.
* <p>
* The tokenize() factory methods allow easy creation of StringLists via StringTokenizer. The
* repeat() static factory method creates a StringList that repeats a given String a given number of
* times.
* <p>
* The prepend() method adds a String to the beginning of the StringList. The removeLast() method
* pops a String off the end of the list. The sort() method sorts strings in the List using
* Collections.sort(). The class also inherits useful methods from AbstractStringList that include
* join() methods ala Perl and a toString() method which joins the list of strings with comma
* separators for easy viewing.
*
* @author Jonathan Locke
*/
public final class StringList extends AbstractStringList
{
private static final long serialVersionUID = 1L;
// The underlying list of strings
private final List<String> strings;
// The total length of all strings in the list
private int totalLength;
/**
* Returns a list of a string repeated a given number of times.
*
* @param count
* The number of times to repeat the string
* @param string
* The string to repeat
* @return The list of strings
*/
public static StringList repeat(final int count, final String string)
{
final StringList list = new StringList(count);
for (int i = 0; i < count; i++)
{
list.add(string);
}
return list;
}
/**
* Extracts tokens from a comma and space delimited string.
*
* @param string
* The string
* @return The string tokens as a list
*/
public static StringList tokenize(final String string)
{
return tokenize(string, ", ");
}
/**
* Extracts tokens from a delimited string.
*
* @param string
* The string
* @param delimiters
* The delimiters
* @return The string tokens as a list
*/
public static StringList tokenize(final String string, final String delimiters)
{
final StringTokenizer tokenizer = new StringTokenizer(string, delimiters);
final StringList strings = new StringList();
while (tokenizer.hasMoreTokens())
{
strings.add(tokenizer.nextToken());
}
return strings;
}
/**
* Converts a collection of objects into a list of string values by using the conversion methods
* of the StringValue class.
*
* @param collection
* The collection to add as strings
* @return The list
*/
public static StringList valueOf(final Collection<?> collection)
{
if (collection != null)
{
final StringList strings = new StringList(collection.size());
for (Object object : collection)
{
strings.add(StringValue.valueOf(object));
}
return strings;
}
else
{
return new StringList();
}
}
/**
* Converts an array of objects into a list of strings by using the object to string conversion
* method of the StringValue class.
*
* @param objects
* The objects to convert
* @return The list of strings
*/
public static StringList valueOf(final Object[] objects)
{
// check for null parameter
int length = (objects == null) ? 0 : objects.length;
final StringList strings = new StringList(length);
for (int i = 0; i < length; i++)
{
strings.add(StringValue.valueOf(objects[i]));
}
return strings;
}
/**
* Returns a string list with just one string in it.
*
* @param string
* The string
* @return The list of one string
*/
public static StringList valueOf(final String string)
{
final StringList strings = new StringList();
if (string != null)
{
strings.add(string);
}
return strings;
}
/**
* Converts a string array to a string list.
*
* @param array
* The array
* @return The list
*/
public static StringList valueOf(final String[] array)
{
int length = (array == null) ? 0 : array.length;
final StringList strings = new StringList(length);
for (int i = 0; i < length; i++)
{
strings.add(array[i]);
}
return strings;
}
/**
* Constructor.
*/
public StringList()
{
strings = new ArrayList<>();
}
/**
* Constructor.
*
* @param size
* Number of elements to preallocate
*/
public StringList(final int size)
{
strings = new ArrayList<>(size);
}
/**
* Adds a string to the back of this list.
*
* @param string
* String to add
*/
public void add(final String string)
{
// Add to list
add(size(), string);
}
/**
* Adds the string to the stringlist at position pos.
*
* @param pos
* the position to add the string at
* @param string
* the string to add.
*/
public void add(final int pos, final String string)
{
strings.add(pos, string == null ? "" : string);
// Increase total length
totalLength += string == null ? 0 : string.length();
}
/**
* Adds a string value to this list as a string.
*
* @param value
* The value to add
*/
public void add(final StringValue value)
{
add(value.toString());
}
/**
* @param string
* The string to look for
* @return True if the list contains the string
*/
public boolean contains(final String string)
{
return strings.contains(string);
}
/**
* Gets the string at the given index.
*
* @param index
* The index
* @return The string at the index
* @throws IndexOutOfBoundsException
*/
@Override
public String get(final int index)
{
return strings.get(index);
}
/**
* @return List value (not a copy of this list)
*/
public List<String> getList()
{
return strings;
}
/**
* Returns a typesafe iterator over this collection of strings.
*
* @return Typesafe string iterator
*/
@Override
public IStringIterator iterator()
{
return new IStringIterator()
{
private final Iterator<String> iterator = strings.iterator();
@Override
public boolean hasNext()
{
return iterator.hasNext();
}
@Override
public String next()
{
return iterator.next();
}
};
}
/**
* Adds the given string to the front of the list.
*
* @param string
* The string to add
*/
public void prepend(final String string)
{
add(0, string);
}
/**
* Removes the string at the given index.
*
* @param index
* The index
*/
public void remove(final int index)
{
String string = strings.remove(index);
totalLength = totalLength - string.length();
}
/**
* Removes the last string in this list.
*/
public void removeLast()
{
remove(size() - 1);
}
/**
* @return The number of strings in this list.
*/
@Override
public int size()
{
return strings.size();
}
/**
* Sorts this string list alphabetically.
*/
public void sort()
{
Collections.sort(strings);
}
/**
* Converts this string list to a string array.
*
* @return The string array
*/
@Override
public String[] toArray()
{
return strings.toArray(new String[0]);
}
/**
* @return The total length of all strings in this list.
*/
@Override
public int totalLength()
{
return totalLength;
}
}