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.xbean.finder.util;
018
019import java.lang.reflect.Array;
020import java.util.Collection;
021import java.util.Iterator;
022import java.util.List;
023import java.util.ListIterator;
024import java.util.NoSuchElementException;
025
026public class SingleLinkedList<E> implements List<E> {
027
028    private Entry<E> entry;
029    private int size = 0;
030
031    private class Entry<E> {
032
033        private E value;
034        private Entry next;
035
036        private Entry(E value, Entry next) {
037            this.value = value;
038            this.next = next;
039        }
040    }
041
042
043    public int size() {
044        return size;
045    }
046
047    public boolean isEmpty() {
048        return size() == 0;
049    }
050
051    public boolean contains(Object o) {
052        if (o == null) {
053            for (E e : this) {
054                if (null == e) return true;
055            }
056        } else {
057            for (E e : this) {
058                if (o.equals(e)) return true;
059            }
060        }
061
062        return false;
063    }
064
065    public Iterator<E> iterator() {
066        return values();
067    }
068
069    public Object[] toArray() {
070        final Object[] array = new Object[size];
071        return toArray(array);
072    }
073
074    public <T> T[] toArray(T[] a) {
075        if (a.length < size) a = (T[]) Array.newInstance(a.getClass().getComponentType(), size);
076        
077        Object[] array = a;
078        int i = 0;
079
080        for (E e : this) {
081            array[i++] = e;
082        }
083        
084        return (T[]) array;
085    }
086
087    public boolean add(E e) {
088        this.entry = new Entry(e, this.entry); 
089        size++;
090        return true;
091    }
092
093    public boolean remove(Object o) {
094        throw new UnsupportedOperationException("remove");
095    }
096
097    public boolean containsAll(Collection<?> c) {
098        throw new UnsupportedOperationException("containsAll");
099    }
100
101    public boolean addAll(Collection<? extends E> c) {
102        throw new UnsupportedOperationException("addAll");
103    }
104
105    public boolean addAll(int index, Collection<? extends E> c) {
106        throw new UnsupportedOperationException("addAll");
107    }
108
109    public boolean removeAll(Collection<?> c) {
110        throw new UnsupportedOperationException("removeAll");
111    }
112
113    public boolean retainAll(Collection<?> c) {
114        throw new UnsupportedOperationException("retainAll");
115    }
116
117    public void clear() {
118        this.entry = null;
119        this.size = 0; 
120    }
121
122    public E get(int index) {
123        bounds(index);
124        int i = size;
125        for (E e : this) {
126            if (--i == index) return e;
127        }
128
129        throw new IllegalStateException("statement should not be reachable");
130    }
131
132    public E set(int index, E element) {
133        bounds(index);
134        int i = size;
135
136        for (Entry<E> entry : entries()) {
137            if (--i == index) {
138                final E old = entry.value;
139                entry.value = element;
140                return old;
141            }
142        }
143
144        throw new IllegalStateException("statement should not be reachable");
145    }
146
147    public void add(int index, E element) {
148        throw new UnsupportedOperationException("add");
149    }
150
151    public E remove(int index) {
152        throw new UnsupportedOperationException("remove");
153    }
154
155    public int indexOf(Object o) {
156        throw new UnsupportedOperationException("indexOf");
157    }
158
159    public int lastIndexOf(Object o) {
160        throw new UnsupportedOperationException("lastIndexOf");
161    }
162
163    public ListIterator<E> listIterator() {
164        throw new UnsupportedOperationException("listIterator");
165    }
166
167    public ListIterator<E> listIterator(int index) {
168        throw new UnsupportedOperationException("listIterator");
169    }
170
171    public List<E> subList(int fromIndex, int toIndex) {
172        throw new UnsupportedOperationException("subList");
173    }
174
175    private void bounds(int index) {
176        if (index >= size) throw new IndexOutOfBoundsException(index + " [size " + size + "]");
177        if (index < 0) throw new IndexOutOfBoundsException(index + " [size " + size + "]");
178    }
179
180
181    private Iterator<E> values() {
182        return new Values<E>(this.entry);
183    }
184
185    private Entries entries() {
186        return new Entries(this.entry);
187    }
188    
189
190    private class Values<E> implements Iterator<E> {
191
192        private Entry<E> current;
193
194        private Values(Entry<E> current) {
195            this.current = current;
196        }
197
198        public boolean hasNext() {
199            return current != null;
200        }
201
202        public E next() {
203            if (current == null) throw new NoSuchElementException();
204            
205            final E v = current.value;
206
207            this.current = current.next;
208
209            return v;
210        }
211
212        public void remove() {
213            throw new UnsupportedOperationException("remove");
214        }
215    }
216
217    private class Entries implements Iterator<Entry<E>>, Iterable<Entry<E>> {
218        private Entry<E> current;
219
220        private Entries(Entry<E> current) {
221            this.current = current;
222        }
223
224        public Iterator<Entry<E>> iterator() {
225            return this;
226        }
227
228        public boolean hasNext() {
229            return current != null;
230        }
231
232        public Entry<E> next() {
233            if (current == null) throw new NoSuchElementException();
234
235            final Entry<E> value = this.current;
236
237            this.current = current.next;
238
239            return value;
240        }
241
242        public void remove() {
243            throw new UnsupportedOperationException("remove");
244        }
245    }
246}