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 * http://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.multiset; 018 019import java.io.IOException; 020import java.io.ObjectInputStream; 021import java.io.ObjectOutputStream; 022import java.util.Collection; 023import java.util.Iterator; 024import java.util.Set; 025 026import org.apache.commons.collections4.MultiSet; 027import org.apache.commons.collections4.Unmodifiable; 028import org.apache.commons.collections4.iterators.UnmodifiableIterator; 029import org.apache.commons.collections4.set.UnmodifiableSet; 030 031/** 032 * Decorates another {@link MultiSet} to ensure it can't be altered. 033 * <p> 034 * Attempts to modify it will result in an UnsupportedOperationException. 035 * 036 * @param <E> the type held in the multiset 037 * @since 4.1 038 */ 039public final class UnmodifiableMultiSet<E> 040 extends AbstractMultiSetDecorator<E> implements Unmodifiable { 041 042 /** Serialization version */ 043 private static final long serialVersionUID = 20150611L; 044 045 /** 046 * Factory method to create an unmodifiable multiset. 047 * <p> 048 * If the multiset passed in is already unmodifiable, it is returned. 049 * 050 * @param <E> the type of the elements in the multiset 051 * @param multiset the multiset to decorate, may not be null 052 * @return an unmodifiable MultiSet 053 * @throws NullPointerException if multiset is null 054 */ 055 public static <E> MultiSet<E> unmodifiableMultiSet(final MultiSet<? extends E> multiset) { 056 if (multiset instanceof Unmodifiable) { 057 @SuppressWarnings("unchecked") // safe to upcast 058 final MultiSet<E> tmpMultiSet = (MultiSet<E>) multiset; 059 return tmpMultiSet; 060 } 061 return new UnmodifiableMultiSet<>(multiset); 062 } 063 064 //----------------------------------------------------------------------- 065 /** 066 * Constructor that wraps (not copies). 067 * 068 * @param multiset the multiset to decorate, may not be null 069 * @throws NullPointerException if multiset is null 070 */ 071 @SuppressWarnings("unchecked") // safe to upcast 072 private UnmodifiableMultiSet(final MultiSet<? extends E> multiset) { 073 super((MultiSet<E>) multiset); 074 } 075 076 //----------------------------------------------------------------------- 077 /** 078 * Write the collection out using a custom routine. 079 * 080 * @param out the output stream 081 * @throws IOException if an error occurs while writing to the stream 082 */ 083 private void writeObject(final ObjectOutputStream out) throws IOException { 084 out.defaultWriteObject(); 085 out.writeObject(decorated()); 086 } 087 088 /** 089 * Read the collection in using a custom routine. 090 * 091 * @param in the input stream 092 * @throws IOException if an error occurs while reading from the stream 093 * @throws ClassNotFoundException if an object read from the stream can not be loaded 094 * @throws ClassCastException if deserialised object has wrong type 095 */ 096 @SuppressWarnings("unchecked") // will throw CCE, see Javadoc 097 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { 098 in.defaultReadObject(); 099 setCollection((Collection<E>) in.readObject()); 100 } 101 102 //----------------------------------------------------------------------- 103 @Override 104 public Iterator<E> iterator() { 105 return UnmodifiableIterator.<E> unmodifiableIterator(decorated().iterator()); 106 } 107 108 @Override 109 public boolean add(final E object) { 110 throw new UnsupportedOperationException(); 111 } 112 113 @Override 114 public boolean addAll(final Collection<? extends E> coll) { 115 throw new UnsupportedOperationException(); 116 } 117 118 @Override 119 public void clear() { 120 throw new UnsupportedOperationException(); 121 } 122 123 @Override 124 public boolean remove(final Object object) { 125 throw new UnsupportedOperationException(); 126 } 127 128 @Override 129 public boolean removeAll(final Collection<?> coll) { 130 throw new UnsupportedOperationException(); 131 } 132 133 @Override 134 public boolean retainAll(final Collection<?> coll) { 135 throw new UnsupportedOperationException(); 136 } 137 138 //----------------------------------------------------------------------- 139 @Override 140 public int setCount(final E object, final int count) { 141 throw new UnsupportedOperationException(); 142 } 143 144 @Override 145 public int add(final E object, final int count) { 146 throw new UnsupportedOperationException(); 147 } 148 149 @Override 150 public int remove(final Object object, final int count) { 151 throw new UnsupportedOperationException(); 152 } 153 154 @Override 155 public Set<E> uniqueSet() { 156 final Set<E> set = decorated().uniqueSet(); 157 return UnmodifiableSet.unmodifiableSet(set); 158 } 159 160 @Override 161 public Set<MultiSet.Entry<E>> entrySet() { 162 final Set<MultiSet.Entry<E>> set = decorated().entrySet(); 163 return UnmodifiableSet.unmodifiableSet(set); 164 } 165 166}