/* * Javolution - Java(TM) Solution for Real-Time and Embedded Systems * Copyright (C) 2012 - Javolution (http://javolution.org/) * All rights reserved. * * Permission to use, copy, modify, and distribute this software is * freely granted, provided that this notice is preserved. */ package javolution.util.internal.collection; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Set; import javolution.util.FastCollection; import javolution.util.function.Consumer; import javolution.util.function.Equalities; import javolution.util.function.Equality; import javolution.util.service.CollectionService; /** * Collection view implementation; can be used as root class for implementations * if target is {@code null}. * When possible sub-classes should forward to the actual target for the methods * clear, remove, contains, size and isEmpty rather than using the default * implementation. */ public abstract class CollectionView<E> extends FastCollection<E> implements CollectionService<E> { //public abstract class CollectionView<E> implements CollectionService<E> { private static final long serialVersionUID = 0x600L; // Version. private CollectionService<E> target; /** * The view constructor or root class constructor if target is {@code null}. */ public CollectionView(CollectionService<E> target) { this.target = target; } @Override public abstract boolean add(E element); @Override public boolean addAll(Collection<? extends E> c) { boolean changed = false; Iterator<? extends E> it = c.iterator(); while (it.hasNext()) { if (add(it.next())) changed = true; } return changed; } @Override public void clear() { Iterator<? extends E> it = iterator(); while (it.hasNext()) { it.next(); it.remove(); } } @SuppressWarnings("unchecked") @Override public CollectionView<E> clone() { try { CollectionView<E> copy = (CollectionView<E>) super.clone(); if (target != null) { // Not a root class. copy.target = target.clone(); } return copy; } catch (CloneNotSupportedException e) { throw new Error("Should not happen since target is cloneable"); } } @Override public abstract Equality<? super E> comparator(); @Override @SuppressWarnings("unchecked") public boolean contains(Object obj) { Iterator<? extends E> it = iterator(); Equality<Object> cmp = (Equality<Object>) comparator(); while (it.hasNext()) { if (cmp.equal(obj, it.next())) return true; } return false; } @Override public boolean containsAll(Collection<?> c) { for (Object e : c) { if (!contains(e)) return false; } return true; } @SuppressWarnings("unchecked") @Override public boolean equals(Object o) { if (this == o) return true; if (this instanceof Set) { if (!(o instanceof Set)) return false; Set<E> set = (Set<E>) o; return (size() == set.size()) && containsAll(set); } else if (this instanceof List) { if (!(o instanceof List)) return false; List<E> list = (List<E>) o; if (size() != list.size()) return false; // Short-cut. Equality<? super E> cmp = Equalities.STANDARD; Iterator<E> it1 = this.iterator(); Iterator<E> it2 = list.iterator(); while (it1.hasNext()) { if (!it2.hasNext()) return false; if (!cmp.equal(it1.next(), it2.next())) return false; } if (it2.hasNext()) return false; return true; } else { return false; } } @Override public int hashCode() { Equality<? super E> cmp = Equalities.STANDARD; Iterator<E> it = this.iterator(); int hash = 0; if (this instanceof Set) { while (it.hasNext()) { hash += cmp.hashOf(it.next()); } } else if (this instanceof List) { while (it.hasNext()) { hash += 31 * hash + cmp.hashOf(it.next()); } } else { hash = super.hashCode(); } return hash; } @Override public boolean isEmpty() { return !iterator().hasNext(); } @Override public abstract Iterator<E> iterator(); @Override public void perform(Consumer<CollectionService<E>> action, CollectionService<E> view) { if (target == null) { action.accept(view); } else { target.perform(action, view); } } @Override @SuppressWarnings("unchecked") public boolean remove(Object obj) { Iterator<? extends E> it = iterator(); Equality<Object> cmp = (Equality<Object>) comparator(); while (it.hasNext()) { if (cmp.equal(obj, it.next())) { it.remove(); return true; } } return false; } @Override public boolean removeAll(Collection<?> c) { boolean changed = false; Iterator<? extends E> it = iterator(); while (it.hasNext()) { if (c.contains(it.next())) { it.remove(); changed = true; } } return changed; } @Override public boolean retainAll(Collection<?> c) { boolean changed = false; Iterator<? extends E> it = iterator(); while (it.hasNext()) { if (!c.contains(it.next())) { it.remove(); changed = true; } } return changed; } @Override public int size() { int count = 0; Iterator<? extends E> it = iterator(); while (it.hasNext()) { count++; it.next(); } return count; } @SuppressWarnings("unchecked") @Override public CollectionService<E>[] split(int n, boolean updateable) { return new CollectionService[] { this }; // Split not supported. } @Override public Object[] toArray() { return toArray(new Object[size()]); } @Override @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { final int size = size(); final T[] result = (size <= a.length) ? a : (T[]) java.lang.reflect.Array.newInstance(a.getClass() .getComponentType(), size); int i = 0; Iterator<E> it = iterator(); while (it.hasNext()) { result[i++] = (T) it.next(); } if (result.length > size) { result[size] = null; // As per Collection contract. } return result; } @Override public void update(Consumer<CollectionService<E>> action, CollectionService<E> view) { if (target == null) { action.accept(view); } else { target.perform(action, view); } } protected CollectionService<E> service() { return this; } /** Returns the actual target */ protected CollectionService<E> target() { return target; } }