-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
EventCache.java
255 lines (235 loc) · 9.41 KB
/
EventCache.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.event.internal;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.hibernate.AssertionFailure;
/**
* EventCache is a Map implementation that can be used by an event
* listener to keep track of entities involved in the operation
* being performed. This implementation allows entities to be added
* to the EventCache before the operation has cascaded to that
* entity.
* <p/>
* The following methods can be used by event listeners (and other
* classes) in the same package to add entities to an EventCache
* and indicate if the operation is being performed on the entity:<p/>
* {@link EventCache#put(Object entity, Object copy, boolean isOperatedOn)}
* <p/>
* The following method can be used by event listeners (and other
* classes) in the same package to indicate that the operation is being
* performed on an entity already in the EventCache:
* {@link EventCache#setOperatedOn(Object entity, boolean isOperatedOn)
*
* @author Gail Badner
*/
class EventCache implements Map {
private Map entityToCopyMap = new IdentityHashMap(10);
// key is an entity involved with the operation performed by the listener;
// value can be either a copy of the entity or the entity itself
private Map entityToOperatedOnFlagMap = new IdentityHashMap( 10 );
// key is an entity involved with the operation performed by the listener;
// value is a flag indicating if the listener explicitly operates on the entity
/**
* Clears the EventCache.
*/
public void clear() {
entityToCopyMap.clear();
entityToOperatedOnFlagMap.clear();
}
/**
* Returns true if this EventCache contains a mapping for the specified entity.
* @param entity must be non-null
* @return true if this EventCache contains a mapping for the specified entity
* @throws NullPointerException if entity is null
*/
public boolean containsKey(Object entity) {
if ( entity == null ) {
throw new NullPointerException( "null entities are not supported by " + getClass().getName() );
}
return entityToCopyMap.containsKey( entity );
}
/**
* Returns true if this EventCache maps one or more entities to the specified copy.
* @param copy must be non-null
* @return true if this EventCache maps one or more entities to the specified copy
* @throws NullPointerException if copy is null
*/
public boolean containsValue(Object copy) {
if ( copy == null ) {
throw new NullPointerException( "null copies are not supported by " + getClass().getName() );
}
return entityToCopyMap.containsValue( copy );
}
/**
* Returns a set view of the entity-to-copy mappings contained in this EventCache.
* @return set view of the entity-to-copy mappings contained in this EventCache
*/
public Set entrySet() {
return entityToCopyMap.entrySet();
}
/**
* Returns the copy to which this EventCache maps the specified entity.
* @param entity must be non-null
* @return the copy to which this EventCache maps the specified entity
* @throws NullPointerException if entity is null
*/
public Object get(Object entity) {
if ( entity == null ) {
throw new NullPointerException( "null entities are not supported by " + getClass().getName() );
}
return entityToCopyMap.get( entity );
}
/**
* Returns true if this EventCache contains no entity-copy mappings.
* @return true if this EventCache contains no entity-copy mappings
*/
public boolean isEmpty() {
return entityToCopyMap.isEmpty();
}
/**
* Returns a set view of the entities contained in this EventCache
* @return a set view of the entities contained in this EventCache
*/
public Set keySet() {
return entityToCopyMap.keySet();
}
/**
* Associates the specified entity with the specified copy in this EventCache;
* @param entity must be non-null
* @param copy must be non- null
* @return previous copy associated with specified entity, or null if
* there was no mapping for entity.
* @throws NullPointerException if entity or copy is null
*/
public Object put(Object entity, Object copy) {
if ( entity == null || copy == null ) {
throw new NullPointerException( "null entities and copies are not supported by " + getClass().getName() );
}
entityToOperatedOnFlagMap.put( entity, Boolean.FALSE );
return entityToCopyMap.put( entity, copy );
}
/**
* Associates the specified entity with the specified copy in this EventCache;
* @param entity must be non-null
* @param copy must be non- null
* @param isOperatedOn indicates if the operation is performed on the entity
*
* @return previous copy associated with specified entity, or null if
* there was no mapping for entity.
* @throws NullPointerException if entity or copy is null
*/
/* package-private */ Object put(Object entity, Object copy, boolean isOperatedOn) {
if ( entity == null || copy == null ) {
throw new NullPointerException( "null entities and copies are not supported by " + getClass().getName() );
}
entityToOperatedOnFlagMap.put( entity, Boolean.valueOf( isOperatedOn ) );
return entityToCopyMap.put( entity, copy );
}
/**
* Copies all of the mappings from the specified map to this EventCache
* @param map keys and values must be non-null
* @throws NullPointerException if any map keys or values are null
*/
public void putAll(Map map) {
for ( Iterator it=map.entrySet().iterator(); it.hasNext(); ) {
Map.Entry entry = ( Map.Entry ) it.next();
if ( entry.getKey() == null || entry.getValue() == null ) {
throw new NullPointerException( "null entities and copies are not supported by " + getClass().getName() );
}
entityToCopyMap.put( entry.getKey(), entry.getValue() );
entityToOperatedOnFlagMap.put( entry.getKey(), Boolean.FALSE );
}
}
/**
* Removes the mapping for this entity from this EventCache if it is present
* @param entity must be non-null
* @return previous value associated with specified entity, or null if there was no mapping for entity.
* @throws NullPointerException if entity is null
*/
public Object remove(Object entity) {
if ( entity == null ) {
throw new NullPointerException( "null entities are not supported by " + getClass().getName() );
}
entityToOperatedOnFlagMap.remove( entity );
return entityToCopyMap.remove( entity );
}
/**
* Returns the number of entity-copy mappings in this EventCache
* @return the number of entity-copy mappings in this EventCache
*/
public int size() {
return entityToCopyMap.size();
}
/**
* Returns a collection view of the entity copies contained in this EventCache.
* @return a collection view of the entity copies contained in this EventCache
*/
public Collection values() {
return entityToCopyMap.values();
}
/**
* Returns true if the listener is performing the operation on the specified entity.
* @param entity must be non-null
* @return true if the listener is performing the operation on the specified entity.
* @throws NullPointerException if entity is null
*/
public boolean isOperatedOn(Object entity) {
if ( entity == null ) {
throw new NullPointerException( "null entities are not supported by " + getClass().getName() );
}
return ( ( Boolean ) entityToOperatedOnFlagMap.get( entity ) ).booleanValue();
}
/**
* Set flag to indicate if the listener is performing the operation on the specified entity.
* @param entity must be non-null and this EventCache must contain a mapping for this entity
* @return true if the listener is performing the operation on the specified entity
* @throws NullPointerException if entity is null
* @throws AssertionFailure if this EventCache does not contain a mapping for the specified entity
*/
/* package-private */ void setOperatedOn(Object entity, boolean isOperatedOn) {
if ( entity == null ) {
throw new NullPointerException( "null entities are not supported by " + getClass().getName() );
}
if ( ! entityToOperatedOnFlagMap.containsKey( entity ) ||
! entityToCopyMap.containsKey( entity ) ) {
throw new AssertionFailure( "called EventCache.setOperatedOn() for entity not found in EventCache" );
}
entityToOperatedOnFlagMap.put( entity, Boolean.valueOf( isOperatedOn ) );
}
/**
* Returns the copy-entity mappings
* @return the copy-entity mappings
*/
public Map invertMap() {
Map result = new IdentityHashMap( entityToCopyMap.size() );
for ( Entry entry : (Set<Entry>)entityToCopyMap.entrySet() ) {
result.put( entry.getValue(), entry.getKey() );
}
return result;
}
}