001 /*
002 * Copyright 2001-2010 Stephen Colebourne
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.joda.primitives.list.impl;
017
018 import org.joda.primitives.CharUtils;
019 import org.joda.primitives.list.CharList;
020
021 /**
022 * Unmodifiable CharList wrapped around a String.
023 * <p>
024 * This class implements {@link java.util.List List} allowing
025 * seamless integration with other APIs.
026 *
027 * @author Stephen Colebourne
028 * @since 1.0
029 */
030 public class StringCharList extends AbstractCharList implements Cloneable {
031
032 /** The String being wrapped */
033 protected final String string;
034
035 /**
036 * Constructor that uses an empty string as the datasource.
037 */
038 public StringCharList() {
039 super();
040 this.string = "";
041 }
042
043 /**
044 * Constructor that copies the specified list.
045 *
046 * @param list the list to copy, must not be null
047 * @throws IllegalArgumentException if the list is null
048 */
049 public StringCharList(CharList list) {
050 super();
051 if (list == null) {
052 throw new IllegalArgumentException("List must not be null");
053 }
054 this.string = new String(list.toCharArray());
055 }
056
057 /**
058 * Constructor that uses the specified string as the datasource.
059 *
060 * @param str the string to wrap in a list, must not be null
061 * @throws IllegalArgumentException if the string is null
062 */
063 public StringCharList(String str) {
064 super();
065 if (str == null) {
066 throw new IllegalArgumentException("String must not be null");
067 }
068 this.string = str;
069 }
070
071 // Implementation
072 //-----------------------------------------------------------------------
073 /**
074 * Gets the character at the specified index.
075 *
076 * @param index the index to retrieve
077 * @return the character at the specified index
078 */
079 public char getChar(int index) {
080 return string.charAt(index);
081 }
082
083 /**
084 * Gets the size of the list, which is the string length.
085 *
086 * @return the string length
087 */
088 public int size() {
089 return string.length();
090 }
091
092 // Optimisation
093 //-----------------------------------------------------------------------
094 /**
095 * Checks whether this collection contains a specified primitive value.
096 * <p>
097 * This implementation uses <code>String.indexOf(char)</code>.
098 *
099 * @param value the value to search for
100 * @return <code>true</code> if the value is found
101 */
102 public boolean contains(char value) {
103 return (string.indexOf(value) >= 0);
104 }
105
106 /**
107 * Gets the first index of the specified primitive value.
108 * <p>
109 * This implementation uses <code>String.indexOf(char)</code>.
110 *
111 * @param value the value to search for
112 * @return the zero-based index, or <code>-1</code> if not found
113 */
114 public int indexOf(char value) {
115 return string.indexOf(value);
116 }
117
118 /**
119 * Gets the first index of the specified primitive value from an index.
120 * <p>
121 * This method follows the conventions of <code>String</code> in that a
122 * negative index is treated as zero, and an index greater than the list
123 * size will simply return <code>-1</code>.
124 * <p>
125 * This implementation uses <code>String.indexOf(char, int)</code>.
126 *
127 * @param value the value to search for
128 * @param fromIndexInclusive the index to start searching from, inclusive
129 * @return the zero-based index, or <code>-1</code> if not found
130 */
131 public int indexOf(char value, int fromIndexInclusive) {
132 return string.indexOf(value, fromIndexInclusive);
133 }
134
135 /**
136 * Gets the last index of the specified primitive value.
137 * <p>
138 * This implementation uses <code>String.lastIndexOf(char)</code>.
139 *
140 * @param value the value to search for
141 * @return the zero-based index, or <code>-1</code> if not found
142 */
143 public int lastIndexOf(char value) {
144 return string.lastIndexOf(value);
145 }
146
147 /**
148 * Gets the first index of the specified primitive value from an index.
149 * <p>
150 * This method follows the conventions of <code>String</code> in that an
151 * index greater than the list size will start searching at the list size,
152 * and a negative index simply returns <code>-1</code>.
153 * <p>
154 * This implementation uses <code>String.lastIndexOf(char, int)</code>.
155 *
156 * @param value the value to search for
157 * @param fromIndexInclusive the index to start searching from, inclusive
158 * @return the zero-based index, or <code>-1</code> if not found
159 */
160 public int lastIndexOf(char value, int fromIndexInclusive) {
161 return string.lastIndexOf(value, fromIndexInclusive);
162 }
163
164 /**
165 * Gets the String underlying the list.
166 *
167 * @return the underlying string, not null
168 */
169 public String toStringContents() {
170 return string;
171 }
172
173 /**
174 * Gets the elements of this collection as an array.
175 * <p>
176 * This implementation uses <code>String.toCharArray()</code>.
177 *
178 * @return a new array containing a copy of the elements of this collection, not null
179 */
180 public char[] toCharArray() {
181 if (size() == 0) {
182 return CharUtils.EMPTY_CHAR_ARRAY;
183 }
184 return string.toCharArray();
185 }
186
187 /**
188 * Gets a range view of part of this list.
189 * <p>
190 * This method allows operations to work on a range within the greater list.
191 * StringCharList is unmodifiable, thus so is the view.
192 *
193 * @param fromIndexInclusive the index to start from, inclusive
194 * @param toIndexExclusive the index to end at, exclusive
195 * @return a new CharList for the subList, not null
196 * @throws IndexOutOfBoundsException if either index is invalid
197 */
198 public CharList subList(int fromIndexInclusive, int toIndexExclusive) {
199 checkRange(fromIndexInclusive, toIndexExclusive);
200 return new StringCharList(string.substring(fromIndexInclusive, toIndexExclusive));
201 }
202
203 }