source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/imagery/CacheContentsPanel.java@ 9682

Last change on this file since 9682 was 9078, checked in by Don-vip, 9 years ago

sonar - Immutable Field

  • Property svn:eol-style set to native
File size: 9.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.imagery;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Color;
7import java.awt.Component;
8import java.awt.GridBagLayout;
9import java.awt.event.ActionEvent;
10import java.awt.event.ActionListener;
11import java.util.ArrayList;
12import java.util.Collections;
13import java.util.Comparator;
14import java.util.List;
15import java.util.Map;
16import java.util.Map.Entry;
17import java.util.Set;
18import java.util.concurrent.ConcurrentHashMap;
19import java.util.concurrent.ExecutorService;
20import java.util.concurrent.Executors;
21
22import javax.swing.AbstractAction;
23import javax.swing.AbstractCellEditor;
24import javax.swing.Action;
25import javax.swing.Icon;
26import javax.swing.JButton;
27import javax.swing.JLabel;
28import javax.swing.JPanel;
29import javax.swing.JScrollPane;
30import javax.swing.JTable;
31import javax.swing.UIManager;
32import javax.swing.border.LineBorder;
33import javax.swing.table.DefaultTableModel;
34import javax.swing.table.TableCellEditor;
35import javax.swing.table.TableCellRenderer;
36import javax.swing.table.TableColumn;
37import javax.swing.table.TableModel;
38
39import org.apache.commons.jcs.access.CacheAccess;
40import org.apache.commons.jcs.engine.stats.behavior.ICacheStats;
41import org.apache.commons.jcs.engine.stats.behavior.IStatElement;
42import org.apache.commons.jcs.engine.stats.behavior.IStats;
43import org.openstreetmap.josm.Main;
44import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
45import org.openstreetmap.josm.gui.layer.TMSLayer;
46import org.openstreetmap.josm.gui.layer.WMSLayer;
47import org.openstreetmap.josm.gui.layer.WMTSLayer;
48import org.openstreetmap.josm.gui.util.GuiHelper;
49import org.openstreetmap.josm.tools.GBC;
50import org.openstreetmap.josm.tools.Pair;
51import org.openstreetmap.josm.tools.Utils;
52
53/**
54 * Panel for cache content management.
55 *
56 * @author Wiktor Niesiobędzki
57 *
58 */
59public class CacheContentsPanel extends JPanel {
60
61 /**
62 *
63 * Class based on: http://www.camick.com/java/source/ButtonColumn.java
64 * https://tips4java.wordpress.com/2009/07/12/table-button-column/
65 *
66 */
67 private static final class ButtonColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener {
68 private final Action action;
69 private final JButton renderButton;
70 private final JButton editButton;
71 private Object editorValue;
72
73 private ButtonColumn(Action action) {
74 this.action = action;
75 renderButton = new JButton();
76 editButton = new JButton();
77 editButton.setFocusPainted(false);
78 editButton.addActionListener(this);
79 editButton.setBorder(new LineBorder(Color.BLUE));
80 }
81
82 @Override
83 public Object getCellEditorValue() {
84 return editorValue;
85 }
86
87 @Override
88 public void actionPerformed(ActionEvent e) {
89 this.action.actionPerformed(e);
90 }
91
92 @Override
93 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
94 this.editorValue = value;
95 if (value == null) {
96 editButton.setText("");
97 editButton.setIcon(null);
98 } else if (value instanceof Icon) {
99 editButton.setText("");
100 editButton.setIcon((Icon) value);
101 } else {
102 editButton.setText(value.toString());
103 editButton.setIcon(null);
104 }
105 this.editorValue = value;
106 return editButton;
107 }
108
109 @Override
110 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
111 boolean hasFocus, int row, int column) {
112 if (isSelected) {
113 renderButton.setForeground(table.getSelectionForeground());
114 renderButton.setBackground(table.getSelectionBackground());
115 } else {
116 renderButton.setForeground(table.getForeground());
117 renderButton.setBackground(UIManager.getColor("Button.background"));
118 }
119
120 renderButton.setFocusPainted(hasFocus);
121
122 if (value == null) {
123 renderButton.setText("");
124 renderButton.setIcon(null);
125 } else if (value instanceof Icon) {
126 renderButton.setText("");
127 renderButton.setIcon((Icon) value);
128 } else {
129 renderButton.setText(value.toString());
130 renderButton.setIcon(null);
131 }
132 return renderButton;
133 }
134
135 }
136
137 private final transient ExecutorService executor =
138 Executors.newSingleThreadExecutor(Utils.newThreadFactory(getClass() + "-%d", Thread.NORM_PRIORITY));
139
140 /**
141 * Creates cache content panel
142 */
143 public CacheContentsPanel() {
144 super(new GridBagLayout());
145 executor.submit(new Runnable() {
146 @Override
147 public void run() {
148 addToPanel(TMSLayer.getCache(), "TMS");
149 addToPanel(WMSLayer.getCache(), "WMS");
150 addToPanel(WMTSLayer.getCache(), "WMTS");
151 }
152 });
153 executor.shutdown();
154 }
155
156 private void addToPanel(final CacheAccess<String, BufferedImageCacheEntry> cache, final String name) {
157 final Long cacheSize = getCacheSize(cache);
158 final TableModel tableModel = getTableModel(cache);
159
160 GuiHelper.runInEDT(new Runnable() {
161 @Override
162 public void run() {
163 add(
164 new JLabel(tr("{0} cache, total cache size: {1} bytes", name, cacheSize)),
165 GBC.eol().insets(5, 5, 0, 0));
166
167 add(
168 new JScrollPane(getTableForCache(cache, tableModel)),
169 GBC.eol().fill(GBC.BOTH));
170 }
171 });
172 }
173
174 private static Long getCacheSize(CacheAccess<String, BufferedImageCacheEntry> cache) {
175 ICacheStats stats = cache.getStatistics();
176 for (IStats cacheStats: stats.getAuxiliaryCacheStats()) {
177 for (IStatElement<?> statElement: cacheStats.getStatElements()) {
178 if ("Data File Length".equals(statElement.getName())) {
179 Object val = statElement.getData();
180 if (val instanceof Long) {
181 return (Long) val;
182 }
183
184 }
185 }
186 }
187 return Long.valueOf(-1);
188 }
189
190 private static String[][] getCacheStats(CacheAccess<String, BufferedImageCacheEntry> cache) {
191 Set<String> keySet = cache.getCacheControl().getKeySet();
192 Map<String, int[]> temp = new ConcurrentHashMap<>(); // use int[] as a Object reference to int, gives better performance
193 for (String key: keySet) {
194 String[] keyParts = key.split(":", 2);
195 if (keyParts.length == 2) {
196 int[] counter = temp.get(keyParts[0]);
197 if (counter == null) {
198 temp.put(keyParts[0], new int[]{1});
199 } else {
200 counter[0]++;
201 }
202 } else {
203 Main.warn("Could not parse the key: {0}. No colon found", key);
204 }
205 }
206
207 List<Pair<String, Integer>> sortedStats = new ArrayList<>();
208 for (Entry<String, int[]> e: temp.entrySet()) {
209 sortedStats.add(new Pair<>(e.getKey(), e.getValue()[0]));
210 }
211 Collections.sort(sortedStats, new Comparator<Pair<String, Integer>>() {
212 @Override
213 public int compare(Pair<String, Integer> o1, Pair<String, Integer> o2) {
214 return -1 * o1.b.compareTo(o2.b);
215 }
216 });
217 String[][] ret = new String[sortedStats.size()][3];
218 int index = 0;
219 for (Pair<String, Integer> e: sortedStats) {
220 ret[index] = new String[]{e.a, e.b.toString(), tr("Clear")};
221 index++;
222 }
223 return ret;
224 }
225
226 private JTable getTableForCache(final CacheAccess<String, BufferedImageCacheEntry> cache, final TableModel tableModel) {
227 final JTable ret = new JTable(tableModel);
228
229 ButtonColumn buttonColumn = new ButtonColumn(
230 new AbstractAction() {
231 @Override
232 public void actionPerformed(ActionEvent e) {
233 int row = ret.convertRowIndexToModel(ret.getEditingRow());
234 tableModel.setValueAt("0", row, 1);
235 cache.remove(ret.getValueAt(row, 0) + ":");
236 }
237 });
238 TableColumn tableColumn = ret.getColumnModel().getColumn(2);
239 tableColumn.setCellRenderer(buttonColumn);
240 tableColumn.setCellEditor(buttonColumn);
241 return ret;
242 }
243
244 private static DefaultTableModel getTableModel(final CacheAccess<String, BufferedImageCacheEntry> cache) {
245 final DefaultTableModel tableModel = new DefaultTableModel(
246 getCacheStats(cache),
247 new String[]{tr("Cache name"), tr("Object Count"), tr("Clear")}) {
248 @Override
249 public boolean isCellEditable(int row, int column) {
250 return column == 2;
251 }
252 };
253 return tableModel;
254 }
255}
Note: See TracBrowser for help on using the repository browser.