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 */ 016package org.joda.primitives.list.impl; 017 018import org.joda.primitives.CharUtils; 019import 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 */ 030public 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}