001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4.bag;
018
019import java.io.IOException;
020import java.io.ObjectInputStream;
021import java.io.ObjectOutputStream;
022import java.util.Collection;
023import java.util.Iterator;
024
025import org.apache.commons.collections4.SortedBag;
026import org.apache.commons.collections4.SortedMultiSet;
027
028/**
029 * Decorates another {@link SortedBag} to comply with the Collection contract.
030 *
031 * @param <E> The type of elements in this bag
032 * @since 4.0
033 * @deprecated Since 4.6.0, no longer needed; a {@link SortedMultiSet} already complies with the {@link Collection} contract.
034 */
035@Deprecated
036public final class CollectionSortedBag<E> extends AbstractSortedBagDecorator<E> {
037
038    /** Serialization version */
039    private static final long serialVersionUID = -2560033712679053143L;
040
041    /**
042     * Factory method to create a sorted bag that complies to the Collection contract.
043     *
044     * @param <E> The type of the elements in the bag
045     * @param bag  The sorted bag to decorate, must not be null
046     * @return A SortedBag that complies to the Collection contract
047     * @throws NullPointerException if bag is null
048     */
049    public static <E> SortedBag<E> collectionSortedBag(final SortedBag<E> bag) {
050        return new CollectionSortedBag<>(bag);
051    }
052
053    /**
054     * Constructor that wraps (not copies).
055     *
056     * @param bag  The sorted bag to decorate, must not be null
057     * @throws NullPointerException if bag is null
058     */
059    public CollectionSortedBag(final SortedBag<E> bag) {
060        super(bag);
061    }
062
063    @Override
064    public boolean add(final E object) {
065        return add(object, 1);
066    }
067
068    @Override
069    public boolean add(final E object, final int count) {
070        decorated().add(object, count);
071        return true;
072    }
073
074    // Collection interface
075
076    @Override
077    public boolean addAll(final Collection<? extends E> coll) {
078        boolean changed = false;
079        for (final E current : coll) {
080            final boolean added = add(current, 1);
081            changed = changed || added;
082        }
083        return changed;
084    }
085
086    @Override
087    public boolean containsAll(final Collection<?> coll) {
088        return coll.stream().allMatch(this::contains);
089    }
090
091    /**
092     * Deserializes the collection in using a custom routine.
093     *
094     * @param in  The input stream
095     * @throws IOException Thrown if an error occurs while reading from the stream
096     * @throws ClassNotFoundException if an object read from the stream cannot be loaded
097     * @throws ClassCastException if deserialized object has wrong type
098     */
099    @SuppressWarnings("unchecked") // will throw CCE, see Javadoc
100    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
101        in.defaultReadObject();
102        setCollection((Collection<E>) in.readObject());
103    }
104
105    @Override
106    public boolean remove(final Object object) {
107        return remove(object, 1);
108    }
109
110    @Override
111    public boolean removeAll(final Collection<?> coll) {
112        if (coll != null) {
113            boolean result = false;
114            for (final Object obj : coll) {
115                final boolean changed = remove(obj, getCount(obj));
116                result = result || changed;
117            }
118            return result;
119        }
120        // let the decorated bag handle the case of null argument
121        return decorated().removeAll(null);
122    }
123
124    @Override
125    public boolean retainAll(final Collection<?> coll) {
126        if (coll != null) {
127            boolean modified = false;
128            final Iterator<E> e = iterator();
129            while (e.hasNext()) {
130                if (!coll.contains(e.next())) {
131                    e.remove();
132                    modified = true;
133                }
134            }
135            return modified;
136        }
137        // let the decorated bag handle the case of null argument
138        return decorated().retainAll(null);
139    }
140
141    /**
142     * Serializes this object to an ObjectOutputStream.
143     *
144     * @param out The target ObjectOutputStream.
145     * @throws IOException thrown when an I/O errors occur writing to the target stream.
146     */
147    private void writeObject(final ObjectOutputStream out) throws IOException {
148        out.defaultWriteObject();
149        out.writeObject(decorated());
150    }
151
152}