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