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}