001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.hadoop.hdfs.util;
019    
020    import java.util.Collection;
021    import java.util.Collections;
022    import java.util.Iterator;
023    import java.util.List;
024    import java.util.ListIterator;
025    
026    import org.apache.hadoop.classification.InterfaceAudience;
027    
028    /**
029     * A {@link ReadOnlyList} is a unmodifiable list,
030     * which supports read-only operations.
031     * 
032     * @param <E> The type of the list elements.
033     */
034    @InterfaceAudience.Private
035    public interface ReadOnlyList<E> extends Iterable<E> {
036      /**
037       * Is this an empty list?
038       */
039      boolean isEmpty();
040    
041      /**
042       * @return the size of this list.
043       */
044      int size();
045    
046      /**
047       * @return the i-th element.
048       */
049      E get(int i);
050      
051      /**
052       * Utilities for {@link ReadOnlyList}
053       */
054      public static class Util {
055        /** @return an empty list. */
056        public static <E> ReadOnlyList<E> emptyList() {
057          return ReadOnlyList.Util.asReadOnlyList(Collections.<E>emptyList());
058        }
059    
060        /**
061         * The same as {@link Collections#binarySearch(List, Object)}
062         * except that the list is a {@link ReadOnlyList}.
063         *
064         * @return the insertion point defined
065         *         in {@link Collections#binarySearch(List, Object)}.
066         */
067        public static <K, E extends Comparable<K>> int binarySearch(
068            final ReadOnlyList<E> list, final K key) {
069          int lower = 0;
070          for(int upper = list.size() - 1; lower <= upper; ) {
071            final int mid = (upper + lower) >>> 1;
072    
073            final int d = list.get(mid).compareTo(key);
074            if (d == 0) {
075              return mid;
076            } else if (d > 0) {
077              upper = mid - 1;
078            } else {
079              lower = mid + 1;
080            }
081          }
082          return -(lower + 1);
083        }
084    
085        /**
086         * @return a {@link ReadOnlyList} view of the given list.
087         */
088        public static <E> ReadOnlyList<E> asReadOnlyList(final List<E> list) {
089          return new ReadOnlyList<E>() {
090            @Override
091            public Iterator<E> iterator() {
092              return list.iterator();
093            }
094    
095            @Override
096            public boolean isEmpty() {
097              return list.isEmpty();
098            }
099    
100            @Override
101            public int size() {
102              return list.size();
103            }
104    
105            @Override
106            public E get(int i) {
107              return list.get(i);
108            }
109          };
110        }
111    
112        /**
113         * @return a {@link List} view of the given list.
114         */
115        public static <E> List<E> asList(final ReadOnlyList<E> list) {
116          return new List<E>() {
117            @Override
118            public Iterator<E> iterator() {
119              return list.iterator();
120            }
121    
122            @Override
123            public boolean isEmpty() {
124              return list.isEmpty();
125            }
126    
127            @Override
128            public int size() {
129              return list.size();
130            }
131    
132            @Override
133            public E get(int i) {
134              return list.get(i);
135            }
136    
137            @Override
138            public Object[] toArray() {
139              final Object[] a = new Object[size()];
140              for(int i = 0; i < a.length; i++) {
141                a[i] = get(i);
142              }
143              return a;
144            }
145    
146            //All methods below are not supported.
147    
148            @Override
149            public boolean add(E e) {
150              throw new UnsupportedOperationException();
151            }
152    
153            @Override
154            public void add(int index, E element) {
155              throw new UnsupportedOperationException();
156            }
157    
158            @Override
159            public boolean addAll(Collection<? extends E> c) {
160              throw new UnsupportedOperationException();
161            }
162    
163            @Override
164            public boolean addAll(int index, Collection<? extends E> c) {
165              throw new UnsupportedOperationException();
166            }
167    
168            @Override
169            public void clear() {
170              throw new UnsupportedOperationException();
171            }
172    
173            @Override
174            public boolean contains(Object o) {
175              throw new UnsupportedOperationException();
176            }
177    
178            @Override
179            public boolean containsAll(Collection<?> c) {
180              throw new UnsupportedOperationException();
181            }
182    
183            @Override
184            public int indexOf(Object o) {
185              throw new UnsupportedOperationException();
186            }
187    
188            @Override
189            public int lastIndexOf(Object o) {
190              throw new UnsupportedOperationException();
191            }
192    
193            @Override
194            public ListIterator<E> listIterator() {
195              throw new UnsupportedOperationException();
196            }
197    
198            @Override
199            public ListIterator<E> listIterator(int index) {
200              throw new UnsupportedOperationException();
201            }
202    
203            @Override
204            public boolean remove(Object o) {
205              throw new UnsupportedOperationException();
206            }
207    
208            @Override
209            public E remove(int index) {
210              throw new UnsupportedOperationException();
211            }
212    
213            @Override
214            public boolean removeAll(Collection<?> c) {
215              throw new UnsupportedOperationException();
216            }
217    
218            @Override
219            public boolean retainAll(Collection<?> c) {
220              throw new UnsupportedOperationException();
221            }
222    
223            @Override
224            public E set(int index, E element) {
225              throw new UnsupportedOperationException();
226            }
227    
228            @Override
229            public List<E> subList(int fromIndex, int toIndex) {
230              throw new UnsupportedOperationException();
231            }
232    
233            @Override
234            public <T> T[] toArray(T[] a) {
235              throw new UnsupportedOperationException();
236            }
237          };
238        }
239      }
240    }