source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreferencesModel.java@ 8017

Last change on this file since 8017 was 8017, checked in by bastiK, 9 years ago

see #11090 - basic support for plugin loading at runtime.

This is still in testing stage. It will be announced on
the mailing list when plugin authors can start to adapt
their code.

  • Property svn:eol-style set to native
File size: 11.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.plugin;
3
4import java.io.File;
5import java.util.ArrayList;
6import java.util.Collection;
7import java.util.Collections;
8import java.util.Comparator;
9import java.util.HashMap;
10import java.util.HashSet;
11import java.util.LinkedList;
12import java.util.List;
13import java.util.Map;
14import java.util.Map.Entry;
15import java.util.Observable;
16import java.util.Set;
17
18import org.openstreetmap.josm.Main;
19import org.openstreetmap.josm.plugins.PluginException;
20import org.openstreetmap.josm.plugins.PluginHandler;
21import org.openstreetmap.josm.plugins.PluginInformation;
22
23/**
24 * The plugin model behind a {@code PluginListPanel}.
25 */
26public class PluginPreferencesModel extends Observable {
27 // remember the initial list of active plugins
28 private final Set<String> currentActivePlugins;
29 private final List<PluginInformation> availablePlugins = new ArrayList<>();
30 private String filterExpression;
31 private final List<PluginInformation> displayedPlugins = new ArrayList<>();
32 private final Map<PluginInformation, Boolean> selectedPluginsMap = new HashMap<>();
33 // plugins that still require an update/download
34 private Set<String> pendingDownloads = new HashSet<>();
35
36 /**
37 * Constructs a new {@code PluginPreferencesModel}.
38 */
39 public PluginPreferencesModel() {
40 currentActivePlugins = new HashSet<>();
41 currentActivePlugins.addAll(Main.pref.getCollection("plugins", currentActivePlugins));
42 }
43
44 /**
45 * Filters the list of displayed plugins.
46 * @param filter The filter used against plugin name, description or version
47 */
48 public void filterDisplayedPlugins(String filter) {
49 if (filter == null) {
50 displayedPlugins.clear();
51 displayedPlugins.addAll(availablePlugins);
52 this.filterExpression = null;
53 return;
54 }
55 displayedPlugins.clear();
56 for (PluginInformation pi: availablePlugins) {
57 if (pi.matches(filter)) {
58 displayedPlugins.add(pi);
59 }
60 }
61 filterExpression = filter;
62 clearChanged();
63 notifyObservers();
64 }
65
66 /**
67 * Sets the list of available plugins.
68 * @param available The available plugins
69 */
70 public void setAvailablePlugins(Collection<PluginInformation> available) {
71 availablePlugins.clear();
72 if (available != null) {
73 availablePlugins.addAll(available);
74 }
75 availablePluginsModified();
76 }
77
78 protected final void availablePluginsModified() {
79 sort();
80 filterDisplayedPlugins(filterExpression);
81 Set<String> activePlugins = new HashSet<>();
82 activePlugins.addAll(Main.pref.getCollection("plugins", activePlugins));
83 for (PluginInformation pi: availablePlugins) {
84 if (selectedPluginsMap.get(pi) == null) {
85 if (activePlugins.contains(pi.name)) {
86 selectedPluginsMap.put(pi, true);
87 }
88 }
89 }
90 clearChanged();
91 notifyObservers();
92 }
93
94 protected void updateAvailablePlugin(PluginInformation other) {
95 if (other == null) return;
96 PluginInformation pi = getPluginInformation(other.name);
97 if (pi == null) {
98 availablePlugins.add(other);
99 return;
100 }
101 pi.updateFromPluginSite(other);
102 }
103
104 /**
105 * Updates the list of plugin information objects with new information from
106 * plugin update sites.
107 *
108 * @param fromPluginSite plugin information read from plugin update sites
109 */
110 public void updateAvailablePlugins(Collection<PluginInformation> fromPluginSite) {
111 for (PluginInformation other: fromPluginSite) {
112 updateAvailablePlugin(other);
113 }
114 availablePluginsModified();
115 }
116
117 /**
118 * Replies the list of selected plugin information objects
119 *
120 * @return the list of selected plugin information objects
121 */
122 public List<PluginInformation> getSelectedPlugins() {
123 List<PluginInformation> ret = new LinkedList<>();
124 for (PluginInformation pi: availablePlugins) {
125 if (selectedPluginsMap.get(pi) == null) {
126 continue;
127 }
128 if (selectedPluginsMap.get(pi)) {
129 ret.add(pi);
130 }
131 }
132 return ret;
133 }
134
135 /**
136 * Replies the list of selected plugin information objects
137 *
138 * @return the list of selected plugin information objects
139 */
140 public Set<String> getSelectedPluginNames() {
141 Set<String> ret = new HashSet<>();
142 for (PluginInformation pi: getSelectedPlugins()) {
143 ret.add(pi.name);
144 }
145 return ret;
146 }
147
148 /**
149 * Sorts the list of available plugins
150 */
151 protected void sort() {
152 Collections.sort(
153 availablePlugins,
154 new Comparator<PluginInformation>() {
155 @Override
156 public int compare(PluginInformation o1, PluginInformation o2) {
157 String n1 = o1.getName() == null ? "" : o1.getName().toLowerCase();
158 String n2 = o2.getName() == null ? "" : o2.getName().toLowerCase();
159 return n1.compareTo(n2);
160 }
161 }
162 );
163 }
164
165 /**
166 * Replies the list of plugin informations to display
167 *
168 * @return the list of plugin informations to display
169 */
170 public List<PluginInformation> getDisplayedPlugins() {
171 return displayedPlugins;
172 }
173
174
175 /**
176 * Replies the list of plugins waiting for update or download
177 *
178 * @return the list of plugins waiting for update or download
179 */
180 public List<PluginInformation> getPluginsScheduledForUpdateOrDownload() {
181 List<PluginInformation> ret = new ArrayList<>();
182 for (String plugin: pendingDownloads) {
183 PluginInformation pi = getPluginInformation(plugin);
184 if (pi == null) {
185 continue;
186 }
187 ret.add(pi);
188 }
189 return ret;
190 }
191
192 /**
193 * Sets whether the plugin is selected or not.
194 *
195 * @param name the name of the plugin
196 * @param selected true, if selected; false, otherwise
197 */
198 public void setPluginSelected(String name, boolean selected) {
199 PluginInformation pi = getPluginInformation(name);
200 if (pi != null) {
201 selectedPluginsMap.put(pi, selected);
202 if (pi.isUpdateRequired()) {
203 pendingDownloads.add(pi.name);
204 }
205 }
206 if (!selected) {
207 pendingDownloads.remove(name);
208 }
209 }
210
211 /**
212 * Removes all the plugin in {@code plugins} from the list of plugins
213 * with a pending download
214 *
215 * @param plugins the list of plugins to clear for a pending download
216 */
217 public void clearPendingPlugins(Collection<PluginInformation> plugins) {
218 if (plugins == null || plugins.isEmpty()) return;
219 for (PluginInformation pi: plugins) {
220 pendingDownloads.remove(pi.name);
221 }
222 }
223
224 /**
225 * Replies the plugin info with the name <code>name</code>. null, if no
226 * such plugin info exists.
227 *
228 * @param name the name. If null, replies null.
229 * @return the plugin info.
230 */
231 public PluginInformation getPluginInformation(String name) {
232 for (PluginInformation pi: availablePlugins) {
233 if (pi.getName() != null && pi.getName().equals(name))
234 return pi;
235 }
236 return null;
237 }
238
239 /**
240 * Initializes the model from preferences
241 */
242 public void initFromPreferences() {
243 Collection<String> enabledPlugins = Main.pref.getCollection("plugins", null);
244 if (enabledPlugins == null) {
245 this.selectedPluginsMap.clear();
246 return;
247 }
248 for (String name: enabledPlugins) {
249 PluginInformation pi = getPluginInformation(name);
250 if (pi == null) {
251 continue;
252 }
253 setPluginSelected(name, true);
254 }
255 }
256
257 /**
258 * Replies true if the plugin with name <code>name</code> is currently
259 * selected in the plugin model
260 *
261 * @param name the plugin name
262 * @return true if the plugin is selected; false, otherwise
263 */
264 public boolean isSelectedPlugin(String name) {
265 PluginInformation pi = getPluginInformation(name);
266 if (pi == null) return false;
267 if (selectedPluginsMap.get(pi) == null) return false;
268 return selectedPluginsMap.get(pi);
269 }
270
271 /**
272 * Replies the set of plugins which have been added by the user to
273 * the set of activated plugins.
274 *
275 * @return the set of newly deactivated plugins
276 */
277 public List<PluginInformation> getNewlyActivatedPlugins() {
278 List<PluginInformation> ret = new LinkedList<>();
279 for (Entry<PluginInformation, Boolean> entry: selectedPluginsMap.entrySet()) {
280 PluginInformation pi = entry.getKey();
281 boolean selected = entry.getValue();
282 if (selected && ! currentActivePlugins.contains(pi.name)) {
283 ret.add(pi);
284 }
285 }
286 return ret;
287 }
288
289 /**
290 * Replies the set of plugins which have been removed by the user from
291 * the set of activated plugins.
292 *
293 * @return the set of newly deactivated plugins
294 */
295 public List<PluginInformation> getNewlyDeactivatedPlugins() {
296 List<PluginInformation> ret = new LinkedList<>();
297 for (PluginInformation pi: availablePlugins) {
298 if (!currentActivePlugins.contains(pi.name)) {
299 continue;
300 }
301 if (selectedPluginsMap.get(pi) == null || ! selectedPluginsMap.get(pi)) {
302 ret.add(pi);
303 }
304 }
305 return ret;
306 }
307
308 /**
309 * Replies the set of all available plugins.
310 *
311 * @return the set of all available plugins
312 */
313 public List<PluginInformation> getAvailablePlugins() {
314 return new LinkedList<>(availablePlugins);
315 }
316
317 /**
318 * Replies the set of plugin names which have been added by the user to
319 * the set of activated plugins.
320 *
321 * @return the set of newly activated plugin names
322 */
323 public Set<String> getNewlyActivatedPluginNames() {
324 Set<String> ret = new HashSet<>();
325 List<PluginInformation> plugins = getNewlyActivatedPlugins();
326 for (PluginInformation pi: plugins) {
327 ret.add(pi.name);
328 }
329 return ret;
330 }
331
332 /**
333 * Replies true if the set of active plugins has been changed by the user
334 * in this preference model. He has either added plugins or removed plugins
335 * being active before.
336 *
337 * @return true if the collection of active plugins has changed
338 */
339 public boolean isActivePluginsChanged() {
340 Set<String> newActivePlugins = getSelectedPluginNames();
341 return ! newActivePlugins.equals(currentActivePlugins);
342 }
343
344 /**
345 * Refreshes the local version field on the plugins in <code>plugins</code> with
346 * the version in the manifest of the downloaded "jar.new"-file for this plugin.
347 *
348 * @param plugins the collections of plugins to refresh
349 */
350 public void refreshLocalPluginVersion(Collection<PluginInformation> plugins) {
351 if (plugins == null) return;
352 for (PluginInformation pi : plugins) {
353 File downloadedPluginFile = PluginHandler.findUpdatedJar(pi.name);
354 if (downloadedPluginFile == null) {
355 continue;
356 }
357 try {
358 PluginInformation newinfo = new PluginInformation(downloadedPluginFile, pi.name);
359 PluginInformation oldinfo = getPluginInformation(pi.name);
360 if (oldinfo == null) {
361 // should not happen
362 continue;
363 }
364 oldinfo.updateLocalInfo(newinfo);
365 } catch(PluginException e) {
366 Main.error(e);
367 }
368 }
369 }
370}
Note: See TracBrowser for help on using the repository browser.