/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package org.apache.tools.ant.util;

import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.Vector;

/**
 * Subclass of Vector that won't store duplicate entries and shows
 * HashSet's constant time performance characteristics for the
 * contains method.
 *
 * <p>This is not a general purpose class but has been written because
 * the protected members of {@link
 * org.apache.tools.ant.DirectoryScanner DirectoryScanner} prohibited
 * later revisions from using a more efficient collection.</p>
 *
 * <p>Methods are synchronized to keep Vector's contract.</p>
 *
 * @since Ant 1.8.0
 */
public final class VectorSet<E> extends Vector<E> {
    private static final long serialVersionUID = 1L;

    private final HashSet<E> set = new HashSet<E>();

    public VectorSet() { super(); }

    public VectorSet(int initialCapacity) { super(initialCapacity); }

    public VectorSet(int initialCapacity, int capacityIncrement) {
        super(initialCapacity, capacityIncrement);
    }

    public VectorSet(Collection<? extends E> c) {
        if (c != null) {
            for (E e : c) {
                add(e);
            }
        }
    }

    public synchronized boolean add(E o) {
        if (!set.contains(o)) {
            doAdd(size(), o);
            return true;
        }
        return false;
    }

    /**
     * This implementation may not add the element at the given index
     * if it is already contained in the collection.
     */
    public void add(int index, E o) {
        doAdd(index, o);
    }

    private synchronized void doAdd(int index, E o) {
        // Vector.add seems to delegate to insertElementAt, but this
        // is not documented so we may better implement it ourselves
        if (set.add(o)) {
            int count = size();
            ensureCapacity(count + 1);
            if (index != count) {
                System.arraycopy(elementData, index, elementData, index + 1,
                                 count - index);
            }
            elementData[index] = o;
            elementCount++;
        }
    }

    public synchronized void addElement(E o) {
        doAdd(size(), o);
    }

    public synchronized boolean addAll(Collection<? extends E> c) {
        boolean changed = false;
        for (E e : c) {
            changed |= add(e);
        }
        return changed;
    }

    /**
     * This implementation may not add all elements at the given index
     * if any of them are already contained in the collection.
     */
    public synchronized boolean addAll(int index, Collection<? extends E> c) {
        LinkedList toAdd = new LinkedList();
        for (E e : c) {
            if (set.add(e)) {
                toAdd.add(e);
            }
        }
        if (toAdd.isEmpty()) {
            return false;
        }
        int count = size();
        ensureCapacity(count + toAdd.size());
        if (index != count) {
            System.arraycopy(elementData, index, elementData, index + toAdd.size(),
                             count - index);
        }
        for (Object o : toAdd) {
            elementData[index++] = o;
        }
        elementCount += toAdd.size();
        return true;
    }

    public synchronized void clear() {
        super.clear();
        set.clear();
    }

    public Object clone() {
        @SuppressWarnings("unchecked")
        final VectorSet<E> vs = (VectorSet<E>) super.clone();
        vs.set.addAll(set);
        return vs;
    }

    public synchronized boolean contains(Object o) {
        return set.contains(o);
    }

    public synchronized boolean containsAll(Collection<?> c) {
        return set.containsAll(c);
    }

    public void insertElementAt(E o, int index) {
        doAdd(index, o);
    }

    public synchronized E remove(int index) {
        E o = get(index);
        remove(o);
        return o;
    }

    public boolean remove(Object o) {
        return doRemove(o);
    }

    private synchronized boolean doRemove(Object o) {
        // again, remove seems to delegate to removeElement, but we
        // shouldn't trust it
        if (set.remove(o)) {
            int index = indexOf(o);
            if (index < elementData.length - 1) {
                System.arraycopy(elementData, index + 1, elementData, index,
                                 elementData.length - index - 1);
            }
            elementCount--;
            return true;
        }
        return false;
    }

    public synchronized boolean removeAll(Collection<?> c) {
        boolean changed = false;
        for (Object o : c) {
            changed |= remove(o);
        }
        return changed;
    }

    public synchronized void removeAllElements() {
        set.clear();
        super.removeAllElements();
    }

    public boolean removeElement(Object o) {
        return doRemove(o);
    }

    public synchronized void removeElementAt(int index) {
        remove(get(index));
    }

    public synchronized void removeRange(final int fromIndex, int toIndex) {
        while (toIndex > fromIndex) {
            remove(--toIndex);
        }
    }

    public synchronized boolean retainAll(Collection<?> c) {
        if (!(c instanceof Set)) {
            c = new HashSet<Object>(c);
        }
        LinkedList<E> l = new LinkedList<E>();
        for (E o : this) {
            if (!c.contains(o)) {
                l.addLast(o);
            }
        }
        if (!l.isEmpty()) {
            removeAll(l);
            return true;
        }
        return false;
    }

    public synchronized E set(int index, E o) {
        E orig = get(index);
        if (set.add(o)) {
            elementData[index] = o;
            set.remove(orig);
        } else {
            int oldIndexOfO = indexOf(o);
            remove(o);
            remove(orig);
            add(oldIndexOfO > index ? index : index - 1, o);
        }
        return orig;
    }

    public void setElementAt(E o, int index) {
        set(index, o);
    }

}
