2
* Copyright (c) 2005-2010 Substance Kirill Grouchnikov. All Rights Reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* o Redistributions of source code must retain the above copyright notice,
8
* this list of conditions and the following disclaimer.
10
* o Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
14
* o Neither the name of Substance Kirill Grouchnikov nor the names of
15
* its contributors may be used to endorse or promote products derived
16
* from this software without specific prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
package org.pushingpixels.substance.internal.utils;
32
import net.jcip.annotations.GuardedBy;
34
import java.util.LinkedList;
35
import java.util.List;
37
import java.util.TreeMap;
40
* Lazily initialized hash map for caching images. Note that this class is
41
* <b>not</b> thread safe. In Substance, it is used only from EDT.
43
* @author Kirill Grouchnikov
45
* Class for the stored values.
47
public class LazyResettableHashMap<T> {
49
private static final Object staticLock = new Object();
50
private final Object instanceLock = new Object();
53
* List of all existing maps.
55
@GuardedBy("staticLock")
56
private static List<LazyResettableHashMap<?>> all;
61
@GuardedBy("instanceLock")
62
private Map<HashMapKey, T> cache;
65
* Display name of this hash map. Is used for tracking the statistics.
67
private String displayName;
70
* Creates a new hash map.
73
* Display name of the new hash map.
75
public LazyResettableHashMap(String displayName) {
76
this.displayName = displayName;
77
synchronized (staticLock) {
79
all = new LinkedList<LazyResettableHashMap<?>>();
86
* Creates the delegate cache if necessary.
88
private void createIfNecessary() {
89
synchronized (instanceLock) {
90
if (this.cache == null)
91
this.cache = new SoftHashMap<HashMapKey, T>();
96
* Puts a new key-value pair in the map.
103
public void put(HashMapKey key, T entry) {
104
synchronized (instanceLock) {
105
this.createIfNecessary();
106
this.cache.put(key, entry);
111
* Returns the value registered for the specified key.
115
* @return Registered value or <code>null</code> if none.
117
public T get(HashMapKey key) {
118
synchronized (instanceLock) {
119
if (this.cache == null)
121
return this.cache.get(key);
126
* Checks whether there is a value associated with the specified key.
130
* @return <code>true</code> if there is an associated value,
131
* <code>false</code> otherwise.
133
public boolean containsKey(HashMapKey key) {
134
synchronized (instanceLock) {
135
if (this.cache == null)
137
return this.cache.containsKey(key);
142
* Returns the number of key-value pairs of this hash map.
144
* @return The number of key-value pairs of this hash map.
147
synchronized (instanceLock) {
148
if (this.cache == null)
150
return this.cache.size();
155
* Resets all existing hash maps.
157
public static void reset() {
158
synchronized (staticLock) {
160
for (LazyResettableHashMap<?> map : all) {
161
// this is too locked!
162
synchronized(map.instanceLock) {
163
//noinspection FieldAccessNotGuarded
164
if (map.cache != null)
165
//noinspection FieldAccessNotGuarded
174
* Returns statistical information of the existing hash maps.
176
* @return Statistical information of the existing hash maps.
178
public static List<String> getStats() {
179
synchronized (staticLock) {
181
List<String> result = new LinkedList<String>();
183
Map<String, Integer> mapCounter = new TreeMap<String, Integer>();
184
Map<String, Integer> entryCounter = new TreeMap<String, Integer>();
186
for (LazyResettableHashMap<?> map : all) {
187
String key = map.displayName;
188
if (!mapCounter.containsKey(key)) {
189
mapCounter.put(key, 0);
190
entryCounter.put(key, 0);
192
mapCounter.put(key, mapCounter.get(key) + 1);
193
entryCounter.put(key, entryCounter.get(key) + map.size());
196
for (Map.Entry<String, Integer> entry : mapCounter.entrySet()) {
197
String key = entry.getKey();
198
result.add(entry.getValue() + " " + key + " with "
199
+ entryCounter.get(key) + " entries total");