source: josm/trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java@ 10657

Last change on this file since 10657 was 10657, checked in by Don-vip, 8 years ago

see #11390, see #12890 - use Java 8 Predicates

  • Property svn:eol-style set to native
File size: 7.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm;
3
4import java.util.ArrayList;
5import java.util.Collection;
6import java.util.HashMap;
7import java.util.HashSet;
8import java.util.List;
9import java.util.Map;
10import java.util.Set;
11import java.util.concurrent.CopyOnWriteArrayList;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
15import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
16import org.openstreetmap.josm.gui.JosmUserIdentityManager;
17import org.openstreetmap.josm.gui.util.GuiHelper;
18import org.openstreetmap.josm.tools.SubclassFilteredCollection;
19
20/**
21 * ChangesetCache is global in-memory cache for changesets downloaded from
22 * an OSM API server. The unique instance is available as singleton, see
23 * {@link #getInstance()}.
24 *
25 * Clients interested in cache updates can register for {@link ChangesetCacheEvent}s
26 * using {@link #addChangesetCacheListener(ChangesetCacheListener)}. They can use
27 * {@link #removeChangesetCacheListener(ChangesetCacheListener)} to unregister as
28 * cache event listener.
29 *
30 * The cache itself listens to {@link java.util.prefs.PreferenceChangeEvent}s. It
31 * clears itself if the OSM API URL is changed in the preferences.
32 *
33 * {@link ChangesetCacheEvent}s are delivered on the EDT.
34 *
35 */
36public final class ChangesetCache implements PreferenceChangedListener {
37 /** the unique instance */
38 private static final ChangesetCache instance = new ChangesetCache();
39
40 /**
41 * Replies the unique instance of the cache
42 *
43 * @return the unique instance of the cache
44 */
45 public static ChangesetCache getInstance() {
46 return instance;
47 }
48
49 /** the cached changesets */
50 private final Map<Integer, Changeset> cache = new HashMap<>();
51
52 private final CopyOnWriteArrayList<ChangesetCacheListener> listeners = new CopyOnWriteArrayList<>();
53
54 private ChangesetCache() {
55 Main.pref.addPreferenceChangeListener(this);
56 }
57
58 public void addChangesetCacheListener(ChangesetCacheListener listener) {
59 if (listener != null) {
60 listeners.addIfAbsent(listener);
61 }
62 }
63
64 public void removeChangesetCacheListener(ChangesetCacheListener listener) {
65 if (listener != null) {
66 listeners.remove(listener);
67 }
68 }
69
70 protected void fireChangesetCacheEvent(final ChangesetCacheEvent e) {
71 GuiHelper.runInEDT(() -> {
72 for (ChangesetCacheListener l: listeners) {
73 l.changesetCacheUpdated(e);
74 }
75 });
76 }
77
78 protected void update(Changeset cs, DefaultChangesetCacheEvent e) {
79 if (cs == null) return;
80 if (cs.isNew()) return;
81 Changeset inCache = cache.get(cs.getId());
82 if (inCache != null) {
83 inCache.mergeFrom(cs);
84 e.rememberUpdatedChangeset(inCache);
85 } else {
86 e.rememberAddedChangeset(cs);
87 cache.put(cs.getId(), cs);
88 }
89 }
90
91 public void update(Changeset cs) {
92 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
93 update(cs, e);
94 fireChangesetCacheEvent(e);
95 }
96
97 public void update(Collection<Changeset> changesets) {
98 if (changesets == null || changesets.isEmpty()) return;
99 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
100 for (Changeset cs: changesets) {
101 update(cs, e);
102 }
103 fireChangesetCacheEvent(e);
104 }
105
106 public boolean contains(int id) {
107 if (id <= 0) return false;
108 return cache.get(id) != null;
109 }
110
111 public boolean contains(Changeset cs) {
112 if (cs == null) return false;
113 if (cs.isNew()) return false;
114 return contains(cs.getId());
115 }
116
117 public Changeset get(int id) {
118 return cache.get(id);
119 }
120
121 public Set<Changeset> getChangesets() {
122 return new HashSet<>(cache.values());
123 }
124
125 protected void remove(int id, DefaultChangesetCacheEvent e) {
126 if (id <= 0) return;
127 Changeset cs = cache.get(id);
128 if (cs == null) return;
129 cache.remove(id);
130 e.rememberRemovedChangeset(cs);
131 }
132
133 public void remove(int id) {
134 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
135 remove(id, e);
136 if (!e.isEmpty()) {
137 fireChangesetCacheEvent(e);
138 }
139 }
140
141 public void remove(Changeset cs) {
142 if (cs == null) return;
143 if (cs.isNew()) return;
144 remove(cs.getId());
145 }
146
147 /**
148 * Removes the changesets in <code>changesets</code> from the cache. A
149 * {@link ChangesetCacheEvent} is fired.
150 *
151 * @param changesets the changesets to remove. Ignored if null.
152 */
153 public void remove(Collection<Changeset> changesets) {
154 if (changesets == null) return;
155 DefaultChangesetCacheEvent evt = new DefaultChangesetCacheEvent(this);
156 for (Changeset cs : changesets) {
157 if (cs == null || cs.isNew()) {
158 continue;
159 }
160 remove(cs.getId(), evt);
161 }
162 if (!evt.isEmpty()) {
163 fireChangesetCacheEvent(evt);
164 }
165 }
166
167 public int size() {
168 return cache.size();
169 }
170
171 public void clear() {
172 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
173 for (Changeset cs: cache.values()) {
174 e.rememberRemovedChangeset(cs);
175 }
176 cache.clear();
177 fireChangesetCacheEvent(e);
178 }
179
180 /**
181 * Replies the list of open changesets.
182 * @return The list of open changesets
183 */
184 public List<Changeset> getOpenChangesets() {
185 List<Changeset> ret = new ArrayList<>();
186 for (Changeset cs: cache.values()) {
187 if (cs.isOpen()) {
188 ret.add(cs);
189 }
190 }
191 return ret;
192 }
193
194 /**
195 * If the current user {@link JosmUserIdentityManager#isAnonymous() is known}, the {@link #getOpenChangesets() open changesets}
196 * for the {@link JosmUserIdentityManager#isCurrentUser(User) current user} are returned. Otherwise,
197 * the unfiltered {@link #getOpenChangesets() open changesets} are returned.
198 *
199 * @return a list of changesets
200 */
201 public List<Changeset> getOpenChangesetsForCurrentUser() {
202 if (JosmUserIdentityManager.getInstance().isAnonymous()) {
203 return getOpenChangesets();
204 } else {
205 return new ArrayList<>(SubclassFilteredCollection.filter(getOpenChangesets(),
206 object -> JosmUserIdentityManager.getInstance().isCurrentUser(object.getUser())));
207 }
208 }
209
210 /* ------------------------------------------------------------------------- */
211 /* interface PreferenceChangedListener */
212 /* ------------------------------------------------------------------------- */
213 @Override
214 public void preferenceChanged(PreferenceChangeEvent e) {
215 if (e.getKey() == null || !"osm-server.url".equals(e.getKey()))
216 return;
217
218 // clear the cache when the API url changes
219 if (e.getOldValue() == null || e.getNewValue() == null || !e.getOldValue().equals(e.getNewValue())) {
220 clear();
221 }
222 }
223}
Note: See TracBrowser for help on using the repository browser.