001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.internal; 014 015import java.lang.reflect.*; 016import java.util.*; 017 018/** 019 * Simple read-only wrapper around an object array. 020 * 021 * <p> 022 * Allows for forward or reverse access to elements of an array without being able to modify the array and without 023 * involving copying the array. 024 * 025 * @param <T> Array element type. 026 */ 027public class UnmodifiableArray<T> implements List<T> { 028 029 final T[] array; 030 final int length; 031 private final boolean reversed; 032 033 /** 034 * Constructor. 035 * 036 * @param array The array being wrapped. 037 */ 038 public UnmodifiableArray(T[] array) { 039 this(array, false); 040 } 041 042 /** 043 * Constructor. 044 * 045 * @param array The array being wrapped. 046 * @param reversed <jk>true</jk> if elements of array should be addressed in reverse. 047 */ 048 @SuppressWarnings("unchecked") 049 public UnmodifiableArray(T[] array, boolean reversed) { 050 this.array = array == null ? (T[])new Object[0] : array; 051 this.length = this.array.length; 052 this.reversed = reversed; 053 } 054 055 @Override 056 public int size() { 057 return array.length; 058 } 059 060 @Override 061 public boolean isEmpty() { 062 return array.length == 0; 063 } 064 065 @Override 066 public boolean contains(Object o) { 067 return indexOf(o) != -1; 068 } 069 070 @Override 071 public Iterator<T> iterator() { 072 if (reversed) { 073 return new Iterator<T>() { 074 int i = length-1; 075 076 @Override 077 public boolean hasNext() { 078 return i > -1; 079 } 080 081 @Override 082 public T next() { 083 return array[i--]; 084 } 085 }; 086 } 087 return new Iterator<T>() { 088 int i = 0; 089 090 @Override 091 public boolean hasNext() { 092 return i < length; 093 } 094 095 @Override 096 public T next() { 097 return array[i++]; 098 } 099 }; 100 } 101 102 @Override 103 public Object[] toArray() { 104 Object[] o2 = (Object[])Array.newInstance(array.getClass().getComponentType(), array.length); 105 for (int i = 0; i < array.length; i++) 106 o2[i] = reversed ? array[length-i-1] : array[i]; 107 return o2; 108 } 109 110 @Override 111 @SuppressWarnings({ "unchecked", "hiding" }) 112 public <T> T[] toArray(T[] a) { 113 if (a.length < length) 114 return (T[])toArray(); 115 for (int i = 0; i < array.length; i++) 116 a[i] = reversed ? (T)array[length-i-1] : (T)array[i]; 117 return a; 118 } 119 120 @Override 121 public boolean add(T e) { 122 throw new UnsupportedOperationException("Cannot modify read-only list."); 123 } 124 125 @Override 126 public boolean remove(Object o) { 127 throw new UnsupportedOperationException("Cannot modify read-only list."); 128 } 129 130 @Override 131 public boolean containsAll(Collection<?> c) { 132 for (Object o : c) 133 if (! contains(o)) 134 return false; 135 return true; 136 } 137 138 @Override 139 public boolean addAll(Collection<? extends T> c) { 140 throw new UnsupportedOperationException("Cannot modify read-only list."); 141 } 142 143 @Override 144 public boolean addAll(int index, Collection<? extends T> c) { 145 throw new UnsupportedOperationException("Cannot modify read-only list."); 146 } 147 148 @Override 149 public boolean removeAll(Collection<?> c) { 150 throw new UnsupportedOperationException("Cannot modify read-only list."); 151 } 152 153 @Override 154 public boolean retainAll(Collection<?> c) { 155 throw new UnsupportedOperationException("Cannot modify read-only list."); 156 } 157 158 @Override 159 public void clear() { 160 throw new UnsupportedOperationException("Cannot modify read-only list."); 161 } 162 163 @Override 164 public T get(int index) { 165 return reversed ? array[length-index-1] : array[index]; 166 } 167 168 @Override 169 public T set(int index, T element) { 170 throw new UnsupportedOperationException("Cannot modify read-only list."); 171 } 172 173 @Override 174 public void add(int index, T element) { 175 throw new UnsupportedOperationException("Cannot modify read-only list."); 176 } 177 178 @Override 179 public T remove(int index) { 180 throw new UnsupportedOperationException("Cannot modify read-only list."); 181 } 182 183 @Override 184 public int indexOf(Object o) { 185 for (int i = 0; i < length; i++) { 186 int j = reversed ? length-i-1 : i; 187 T t = array[j]; 188 if ((o == t) || (o != null && o.equals(t))) 189 return j; 190 } 191 return -1; 192 } 193 194 @Override 195 public int lastIndexOf(Object o) { 196 for (int i = length-1; i >= 0; i--) { 197 int j = reversed ? length-i-1 : i; 198 T t = array[j]; 199 if ((o == t) || (o != null && o.equals(t))) 200 return j; 201 } 202 return -1; 203 } 204 205 @Override 206 public ListIterator<T> listIterator() { 207 throw new UnsupportedOperationException("Unsupported method on ReadOnlyArrayList class."); 208 } 209 210 @Override 211 public ListIterator<T> listIterator(int index) { 212 throw new UnsupportedOperationException("Unsupported method on ReadOnlyArrayList class."); 213 } 214 215 @Override 216 public List<T> subList(int fromIndex, int toIndex) { 217 if (reversed) { 218 List<T> l = Arrays.asList(array); 219 Collections.reverse(l); 220 return l.subList(fromIndex, toIndex); 221 } 222 return Arrays.asList(array).subList(fromIndex, toIndex); 223 } 224}