1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.collections4.multiset;
18
19 import java.util.Set;
20
21 import org.apache.commons.collections4.MultiSet;
22 import org.apache.commons.collections4.collection.SynchronizedCollection;
23
24 /**
25 * Decorates another {@link MultiSet} to synchronize its behavior
26 * for a multithreaded environment.
27 * <p>
28 * Methods are synchronized, then forwarded to the decorated multiset.
29 * Iterators must be separately synchronized around the loop.
30 * </p>
31 *
32 * @param <E> the type held in the multiset.
33 * @since 4.1
34 */
35 public class SynchronizedMultiSet<E> extends SynchronizedCollection<E> implements MultiSet<E> {
36
37 /**
38 * Synchronized Set for the MultiSet class.
39 *
40 * @param <T> the type held in this Set.
41 */
42 static class SynchronizedSet<T> extends SynchronizedCollection<T> implements Set<T> {
43 /** Serialization version */
44 private static final long serialVersionUID = 20150629L;
45
46 /**
47 * Constructs a new instance.
48 * @param set the set to decorate
49 * @param lock the lock to use, shared with the multiset
50 */
51 SynchronizedSet(final Set<T> set, final Object lock) {
52 super(set, lock);
53 }
54 }
55
56 /** Serialization version */
57 private static final long serialVersionUID = 20150629L;
58
59 /**
60 * Factory method to create a synchronized multiset.
61 *
62 * @param <E> the type of the elements in the multiset
63 * @param multiset the multiset to decorate, must not be null
64 * @return a new synchronized MultiSet
65 * @throws NullPointerException if multiset is null
66 */
67 public static <E> SynchronizedMultiSet<E> synchronizedMultiSet(final MultiSet<E> multiset) {
68 return new SynchronizedMultiSet<>(multiset);
69 }
70
71 /**
72 * Constructor that wraps (not copies).
73 *
74 * @param multiset the multiset to decorate, must not be null
75 * @throws NullPointerException if multiset is null
76 */
77 protected SynchronizedMultiSet(final MultiSet<E> multiset) {
78 super(multiset);
79 }
80
81 /**
82 * Constructor that wraps (not copies).
83 *
84 * @param multiset the multiset to decorate, must not be null
85 * @param lock the lock to use, must not be null
86 * @throws NullPointerException if multiset or lock is null
87 */
88 protected SynchronizedMultiSet(final MultiSet<E> multiset, final Object lock) {
89 super(multiset, lock);
90 }
91
92 @Override
93 public int add(final E object, final int count) {
94 synchronized (lock) {
95 return decorated().add(object, count);
96 }
97 }
98
99 /**
100 * Gets the multiset being decorated.
101 *
102 * @return the decorated multiset
103 */
104 @Override
105 protected MultiSet<E> decorated() {
106 return (MultiSet<E>) super.decorated();
107 }
108
109 @Override
110 public Set<Entry<E>> entrySet() {
111 synchronized (lock) {
112 final Set<MultiSet.Entry<E>> set = decorated().entrySet();
113 return new SynchronizedSet<>(set, lock);
114 }
115 }
116
117 @Override
118 public boolean equals(final Object object) {
119 if (object == this) {
120 return true;
121 }
122 synchronized (lock) {
123 return decorated().equals(object);
124 }
125 }
126
127 @Override
128 public int getCount(final Object object) {
129 synchronized (lock) {
130 return decorated().getCount(object);
131 }
132 }
133
134 @Override
135 public int hashCode() {
136 synchronized (lock) {
137 return decorated().hashCode();
138 }
139 }
140
141 @Override
142 public int remove(final Object object, final int count) {
143 synchronized (lock) {
144 return decorated().remove(object, count);
145 }
146 }
147
148 @Override
149 public int setCount(final E object, final int count) {
150 synchronized (lock) {
151 return decorated().setCount(object, count);
152 }
153 }
154
155 @Override
156 public Set<E> uniqueSet() {
157 synchronized (lock) {
158 final Set<E> set = decorated().uniqueSet();
159 return new SynchronizedSet<>(set, lock);
160 }
161 }
162
163 }