001/* 002 * @author Francesco.Kriegel@gmx.de 003 */ 004package conexp.fx.core.collections.setlist; 005 006/* 007 * #%L 008 * Concept Explorer FX 009 * %% 010 * Copyright (C) 2010 - 2019 Francesco Kriegel 011 * %% 012 * This program is free software: you can redistribute it and/or modify 013 * it under the terms of the GNU General Public License as 014 * published by the Free Software Foundation, either version 3 of the 015 * License, or (at your option) any later version. 016 * 017 * This program is distributed in the hope that it will be useful, 018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 020 * GNU General Public License for more details. 021 * 022 * You should have received a copy of the GNU General Public 023 * License along with this program. If not, see 024 * <http://www.gnu.org/licenses/gpl-3.0.html>. 025 * #L% 026 */ 027 028import java.lang.reflect.Array; 029import java.util.Collection; 030import java.util.Iterator; 031import java.util.ListIterator; 032 033import com.google.common.base.Function; 034import com.google.common.base.Predicate; 035import com.google.common.base.Predicates; 036import com.google.common.collect.Collections2; 037import com.google.common.collect.Iterators; 038 039import conexp.fx.core.collections.BitSetFX; 040import conexp.fx.core.collections.GuavaFunctions; 041 042public abstract class AbstractSetList<E> implements SetList<E> { 043 044 public AbstractSetList() { 045 super(); 046 } 047 048 public AbstractSetList(final Collection<? extends E> c) { 049 super(); 050 addAll(c); 051 } 052 053 public boolean add(final E e) { 054 try { 055 add(size(), e); 056 return true; 057 } catch (IllegalArgumentException x) { 058 return false; 059 } 060 } 061 062 public void add(final int i, final E e) { 063 listIterator(i).add(e); 064 } 065 066 public boolean addAll(final Collection<? extends E> c) { 067 return addAll(size(), c); 068 } 069 070 public boolean addAll(final int i, final Collection<? extends E> c) { 071 boolean changed = false; 072 final ListIterator<E> it = listIterator(i); 073 for (E e : c) 074 try { 075 it.add(e); 076 changed = true; 077 } catch (IllegalArgumentException x) {} 078 return changed; 079 } 080 081 public boolean set(final Object o, final E e) { 082 if ((o == null && e == null) || o.equals(e)) 083 return false; 084 final ListIterator<E> it = listIterator(); 085 while (it.hasNext()) 086 if (it.next().equals(o)) { 087 it.set(e); 088 return true; 089 } 090 return false; 091 } 092 093 public E set(final int i, final E e) { 094 final ListIterator<E> it = listIterator(i); 095 if (it.hasNext()) { 096 final E oldElement = it.next(); 097 it.set(e); 098 return oldElement; 099 } 100 throw new IndexOutOfBoundsException(); 101 } 102 103 public E remove(int i) { 104 final ListIterator<E> it = listIterator(i); 105 if (it.hasNext()) { 106 final E e = it.next(); 107 it.remove(); 108 return e; 109 } 110 throw new IndexOutOfBoundsException(); 111 } 112 113 public boolean remove(final Object o) { 114 final Iterator<E> it = iterator(); 115 while (it.hasNext()) 116 if (it.next().equals(o)) { 117 it.remove(); 118 return true; 119 } 120 return false; 121 } 122 123 public boolean removeAll(final Collection<?> c) { 124 boolean changed = false; 125 final Iterator<E> it = iterator(); 126 while (it.hasNext()) 127 if (c.contains(it.next())) { 128 it.remove(); 129 changed = true; 130 } 131 return changed; 132 } 133 134 public boolean retainAll(final Collection<?> c) { 135 boolean changed = false; 136 final Iterator<E> it = iterator(); 137 while (it.hasNext()) 138 if (!c.contains(it.next())) { 139 it.remove(); 140 changed = true; 141 } 142 return changed; 143 } 144 145 public boolean contains(final Object o) { 146 return indexOf(o) != -1; 147 } 148 149 public boolean containsAll(final Collection<?> c) { 150 for (Object o : c) 151 if (!contains(o)) 152 return false; 153 return true; 154 } 155 156 public E get(final int i) { 157 return listIterator(i).next(); 158 } 159 160 public final Collection<E> getAll(final Collection<Integer> c, final boolean includeNull) { 161 if (includeNull) 162 return Collections2.transform(c, new Function<Integer, E>() { 163 164 public final E apply(final Integer i) { 165 return get(i); 166 } 167 }); 168 else 169 return Collections2.filter(Collections2.transform(c, new Function<Integer, E>() { 170 171 public final E apply(final Integer i) { 172 return get(i); 173 } 174 }), Predicates.notNull()); 175 } 176 177 public int indexOf(final Object o) { 178 int i = 0; 179 for (E e : this) { 180 if (e.equals(o)) 181 return i; 182 i++; 183 } 184 return -1; 185 } 186 187 public final Collection<Integer> indicesOf(final Collection<?> c, final boolean includeMinusOne) { 188 if (includeMinusOne) 189 return Collections2.transform(c, GuavaFunctions.toGuavaFunction(this::indexOf)); 190 else 191 return Collections2.filter( 192 Collections2.transform(c, GuavaFunctions.toGuavaFunction(this::indexOf)), 193 Predicates.not(Predicates.equalTo(-1))); 194 } 195 196 @Deprecated 197 public final int lastIndexOf(final Object o) { 198 return indexOf(o); 199 } 200 201 public final SetList<E> subList(final int from, final int to) { 202 return filter(new Predicate<E>() { 203 204 public final boolean apply(final E e) { 205 final int i = indexOf(e); 206 return from <= i && i < to; 207 } 208 }); 209 } 210 211 public final BitSetFX subBitSet(final Collection<?> c) { 212 final BitSetFX b = new BitSetFX(size()); 213 for (int i : indicesOf(c, true)) 214 b.flip(i); 215 return b; 216 } 217 218 public final SetList<E> filter(final Predicate<? super E> p) { 219 return SetLists.filter(this, p); 220 } 221 222 public final Iterator<E> iterator() { 223 return listIterator(); 224 } 225 226 public final ListIterator<E> listIterator() { 227 return listIterator(0); 228 } 229 230 public abstract ListIterator<E> listIterator(final int i); 231 232 public boolean isEmpty() { 233 return iterator().hasNext(); 234 } 235 236 public int size() { 237 return Iterators.size(iterator()); 238 } 239 240 public void clear() { 241 final Iterator<E> it = iterator(); 242 while (it.hasNext()) { 243 it.next(); 244 it.remove(); 245 } 246 } 247 248 public final HashSetArrayList<E> clone() { 249 return new HashSetArrayList<E>(this); 250 } 251 252 public final boolean equals(final Object o) { 253 return o != null 254 && (this == o || (o instanceof SetList && size() == ((SetList<?>) o).size() && containsAll((SetList<?>) o))); 255 } 256 257 public int hashCode() { 258 int hashCode = 1; 259 for (E e : this) 260 hashCode = 23 * hashCode + (e == null ? 0 : e.hashCode()); 261 return hashCode; 262 } 263 264 public Object[] toArray() { 265 final Object[] a = new Object[size()]; 266 int i = 0; 267 for (E e : this) 268 a[i++] = e; 269 return a; 270 } 271 272 @SuppressWarnings("unchecked") 273 public <T> T[] toArray(T[] a) { 274 if (a == null) 275 throw new NullPointerException(); 276 try { 277 if (a.length < size()) 278 a = (T[]) Array.newInstance(a.getClass().getComponentType(), size()); 279 int i = 0; 280 for (E e : this) 281 a[i++] = (T) e; 282 if (a.length > size()) 283 a[size()] = null; 284 return a; 285 } catch (ClassCastException x) { 286 throw new ArrayStoreException(); 287 } 288 } 289 290 public final String toString() { 291 final StringBuilder s = new StringBuilder(); 292 s.append("{"); 293 final Iterator<E> it = iterator(); 294 if (it.hasNext()) 295 s.append(it.next().toString()); 296 while (it.hasNext()) 297 s.append(", " + it.next().toString()); 298 s.append("}"); 299 return s.toString(); 300 } 301}