All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javolution.util.internal.collection.CollectionView Maven / Gradle / Ivy

The newest version!
/*
 * 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 extends FastCollection implements CollectionService {
//public abstract class CollectionView implements CollectionService {

    private static final long serialVersionUID = 0x600L; // Version.
    private CollectionService target;

    /**
     * The view constructor or root class constructor if target is {@code null}.
     */
    public CollectionView(CollectionService target) {
        this.target = target;
    }

    @Override
    public abstract boolean add(E element);

    @Override
    public boolean addAll(Collection c) {
        boolean changed = false;
        Iterator it = c.iterator();
        while (it.hasNext()) {
            if (add(it.next())) changed = true;
        }
        return changed;
    }

    @Override
    public void clear() {
        Iterator it = iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public CollectionView clone() {
        try {
            CollectionView copy = (CollectionView) 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 comparator();

    @Override
    @SuppressWarnings("unchecked")
    public boolean contains(Object obj) {
        Iterator it = iterator();
        Equality cmp = (Equality) comparator();
        while (it.hasNext()) {
            if (cmp.areEqual(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) {
        // Follow Collection.equals specification if this comparator is standard.        
        if (this == o) return true;
        // Check comparators consistency.
        if (o instanceof CollectionService) {
            if (!comparator().equals(((CollectionService) o).comparator())) return false; // Different comparators.
        } else {
            if (!comparator().equals(Equalities.STANDARD)) return false;
        }
        // Collection.equals contract.
        if (this instanceof Set) {
            if (!(o instanceof Set)) return false;
            Set set = (Set) o;
            return (size() == set.size()) && containsAll(set);
        } else if (this instanceof List) {
            if (!(o instanceof List)) return false;
            List list = (List) o;
            if (size() != list.size()) return false; // Short-cut.
            Equality cmp = comparator();
            Iterator it1 = this.iterator();
            Iterator it2 = list.iterator();
            while (it1.hasNext()) {
                if (!it2.hasNext()) return false;
                if (!cmp.areEqual(it1.next(), it2.next())) return false;
            }
            if (it2.hasNext()) return false;
            return true;
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        // Follow Collection.equals specification if this comparator is standard.        
        Equality cmp = comparator();
        Iterator it = this.iterator();
        int hash = 0;
        if (this instanceof Set) {
            while (it.hasNext()) {
                hash += cmp.hashCodeOf(it.next());
            }
        } else if (this instanceof List) {
            while (it.hasNext()) {
                hash += 31 * hash + cmp.hashCodeOf(it.next());
            }
        } else {
            hash = super.hashCode();
        }
        return hash;
    }

    @Override
    public boolean isEmpty() {
        return iterator().hasNext();
    }

    @Override
    public abstract Iterator iterator();

    @Override
    public void perform(Consumer> action, CollectionService view) {
        if (target == null) {
            action.accept(view);
        } else {
            target.perform(action, view);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public boolean remove(Object obj) {
        Iterator it = iterator();
        Equality cmp = (Equality) comparator();
        while (it.hasNext()) {
            if (cmp.areEqual(obj, it.next())) {
                it.remove();
                return true;
            }
        }
        return false;
    }
    
    @Override
    public boolean removeAll(Collection c) {
        boolean changed = false;
        Iterator 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 it = iterator();
        while (it.hasNext()) {
            if (!c.contains(it.next())) {
                it.remove();
                changed = true;
            }
        }
        return changed;
    }

    @Override
    public int size() {
        int count = 0;
        Iterator it = iterator();
        while (it.hasNext()) {
            count++;
            it.next();
        }
        return count;
    }

    @SuppressWarnings("unchecked")
    @Override
    public CollectionService[] split(int n) {
        if (target == null) return new CollectionService[] { this }; // No split.
        CollectionService[] subTargets = target.split(n);
        CollectionService[] result = new CollectionService[subTargets.length];
        for (int i = 0; i < subTargets.length; i++) {
            CollectionView copy = this.clone();
            copy.target = subTargets[i];
            result[i] = copy;
        }
        return result;
    }

    @Override
    public CollectionService threadSafe() {
        // We use shared collection as default (they can split).
        return new SharedCollectionImpl(this); 
    }

    @Override
    public Object[] toArray() {
        return toArray(new Object[size()]);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  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 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> action, CollectionService view) {
        if (target == null) {
            action.accept(view);
        } else {
            target.perform(action, view);
        }
    }
    
    protected CollectionService service() {
        return this;
    }
    
    /** Returns the actual target */
    protected CollectionService target() {
        return target;
    }
}