001/*
002 * Copyright (C) 2007 The Guava Authors
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
017package com.google.common.collect.testing;
018
019import static java.lang.System.arraycopy;
020import static java.util.Arrays.asList;
021
022import com.google.common.annotations.GwtCompatible;
023import java.util.AbstractCollection;
024import java.util.Collection;
025import java.util.Iterator;
026import org.checkerframework.checker.nullness.qual.NonNull;
027import org.checkerframework.checker.nullness.qual.Nullable;
028
029/**
030 * A simplistic collection which implements only the bare minimum allowed by the spec, and throws
031 * exceptions whenever it can.
032 *
033 * @author Kevin Bourrillion
034 */
035@GwtCompatible
036@ElementTypesAreNonnullByDefault
037public class MinimalCollection<E extends @Nullable Object> extends AbstractCollection<E> {
038  // TODO: expose allow nulls parameter?
039
040  public static <E extends @Nullable Object> MinimalCollection<E> of(E... contents) {
041    return new MinimalCollection<>(Object.class, true, contents);
042  }
043
044  // TODO: use this
045  public static <E extends @Nullable Object> MinimalCollection<E> ofClassAndContents(
046      Class<? super @NonNull E> type, E... contents) {
047    return new MinimalCollection<>(type, true, contents);
048  }
049
050  private final E[] contents;
051  private final Class<? super @NonNull E> type;
052  private final boolean allowNulls;
053
054  // Package-private so that it can be extended.
055  MinimalCollection(Class<? super @NonNull E> type, boolean allowNulls, E... contents) {
056    // TODO: consider making it shuffle the contents to test iteration order.
057    this.contents = Platform.clone(contents);
058    this.type = type;
059    this.allowNulls = allowNulls;
060
061    if (!allowNulls) {
062      for (Object element : contents) {
063        if (element == null) {
064          throw new NullPointerException();
065        }
066      }
067    }
068  }
069
070  @Override
071  public int size() {
072    return contents.length;
073  }
074
075  @Override
076  public boolean contains(@Nullable Object object) {
077    if (!allowNulls) {
078      // behave badly
079      if (object == null) {
080        throw new NullPointerException();
081      }
082    }
083    Platform.checkCast(type, object); // behave badly
084    return asList(contents).contains(object);
085  }
086
087  @Override
088  public boolean containsAll(Collection<?> collection) {
089    if (!allowNulls) {
090      for (Object object : collection) {
091        // behave badly
092        if (object == null) {
093          throw new NullPointerException();
094        }
095      }
096    }
097    return super.containsAll(collection);
098  }
099
100  @Override
101  public Iterator<E> iterator() {
102    return asList(contents).iterator();
103  }
104
105  @Override
106  public @Nullable Object[] toArray() {
107    @Nullable Object[] result = new @Nullable Object[contents.length];
108    arraycopy(contents, 0, result, 0, contents.length);
109    return result;
110  }
111
112  /*
113   * a "type A" unmodifiable collection freaks out proactively, even if there
114   * wasn't going to be any actual work to do anyway
115   */
116
117  @Override
118  public boolean addAll(Collection<? extends E> elementsToAdd) {
119    throw up();
120  }
121
122  @Override
123  public boolean removeAll(Collection<?> elementsToRemove) {
124    throw up();
125  }
126
127  @Override
128  public boolean retainAll(Collection<?> elementsToRetain) {
129    throw up();
130  }
131
132  @Override
133  public void clear() {
134    throw up();
135  }
136
137  private static UnsupportedOperationException up() {
138    throw new UnsupportedOperationException();
139  }
140}