001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.imagery; 003 004import java.io.IOException; 005import java.util.ArrayList; 006import java.util.Arrays; 007import java.util.Collection; 008import java.util.Collections; 009import java.util.List; 010 011import org.openstreetmap.josm.Main; 012import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryPreferenceEntry; 013import org.openstreetmap.josm.io.MirroredInputStream; 014import org.openstreetmap.josm.io.imagery.ImageryReader; 015import org.openstreetmap.josm.tools.Utils; 016import org.xml.sax.SAXException; 017 018/** 019 * Manages the list of imagery entries that are shown in the imagery menu. 020 */ 021public class ImageryLayerInfo { 022 023 public static final ImageryLayerInfo instance = new ImageryLayerInfo(); 024 List<ImageryInfo> layers = new ArrayList<ImageryInfo>(); 025 static List<ImageryInfo> defaultLayers = new ArrayList<ImageryInfo>(); 026 027 private final static String[] DEFAULT_LAYER_SITES = { 028 Main.JOSM_WEBSITE+"/maps" 029 }; 030 031 private ImageryLayerInfo() { 032 } 033 034 public ImageryLayerInfo(ImageryLayerInfo info) { 035 layers.addAll(info.layers); 036 } 037 038 public void clear() { 039 layers.clear(); 040 } 041 042 public void load() { 043 boolean addedDefault = !layers.isEmpty(); 044 List<ImageryPreferenceEntry> entries = Main.pref.getListOfStructs("imagery.entries", null, ImageryPreferenceEntry.class); 045 if (entries != null) { 046 for (ImageryPreferenceEntry prefEntry : entries) { 047 try { 048 ImageryInfo i = new ImageryInfo(prefEntry); 049 add(i); 050 } catch (IllegalArgumentException e) { 051 Main.warn("Unable to load imagery preference entry:"+e); 052 } 053 } 054 Collections.sort(layers); 055 } 056 if (addedDefault) { 057 save(); 058 } 059 } 060 061 /** 062 * Loads the available imagery entries. 063 * 064 * The data is downloaded from the JOSM website (or loaded from cache). 065 * Entries marked as "default" are added to the user selection, if not 066 * already present. 067 * 068 * @param clearCache if true, clear the cache and start a fresh download. 069 */ 070 public void loadDefaults(boolean clearCache) { 071 defaultLayers.clear(); 072 for (String source : Main.pref.getCollection("imagery.layers.sites", Arrays.asList(DEFAULT_LAYER_SITES))) { 073 if (clearCache) { 074 MirroredInputStream.cleanup(source); 075 } 076 MirroredInputStream stream = null; 077 try { 078 ImageryReader reader = new ImageryReader(source); 079 Collection<ImageryInfo> result = reader.parse(); 080 defaultLayers.addAll(result); 081 } catch (IOException ex) { 082 Utils.close(stream); 083 ex.printStackTrace(); 084 continue; 085 } catch (SAXException sex) { 086 Utils.close(stream); 087 sex.printStackTrace(); 088 continue; 089 } 090 } 091 while (defaultLayers.remove(null)); 092 093 Collection<String> defaults = Main.pref.getCollection("imagery.layers.default"); 094 List<String> defaultsSave = new ArrayList<String>(); 095 for (ImageryInfo def : defaultLayers) { 096 if (def.isDefaultEntry()) { 097 defaultsSave.add(def.getUrl()); 098 099 boolean isKnownDefault = false; 100 for (String url : defaults) { 101 if (isSimilar(url, def.getUrl())) { 102 isKnownDefault = true; 103 break; 104 } 105 } 106 boolean isInUserList = false; 107 if (!isKnownDefault) { 108 for (ImageryInfo i : layers) { 109 if (isSimilar(def.getUrl(), i.getUrl())) { 110 isInUserList = true; 111 break; 112 } 113 } 114 } 115 if (!isKnownDefault && !isInUserList) { 116 add(new ImageryInfo(def)); 117 } 118 } 119 } 120 121 Collections.sort(defaultLayers); 122 Main.pref.putCollection("imagery.layers.default", defaultsSave.isEmpty() ? defaults : defaultsSave); 123 } 124 125 // some additional checks to respect extended URLs in preferences (legacy workaround) 126 private boolean isSimilar(String a, String b) { 127 return Utils.equal(a, b) || (a != null && b != null && !a.isEmpty() && !b.isEmpty() && (a.contains(b) || b.contains(a))); 128 } 129 130 public void add(ImageryInfo info) { 131 layers.add(info); 132 } 133 134 public void remove(ImageryInfo info) { 135 layers.remove(info); 136 } 137 138 public void save() { 139 List<ImageryPreferenceEntry> entries = new ArrayList<ImageryPreferenceEntry>(); 140 for (ImageryInfo info : layers) { 141 entries.add(new ImageryPreferenceEntry(info)); 142 } 143 Main.pref.putListOfStructs("imagery.entries", entries, ImageryPreferenceEntry.class); 144 } 145 146 public List<ImageryInfo> getLayers() { 147 return Collections.unmodifiableList(layers); 148 } 149 150 public List<ImageryInfo> getDefaultLayers() { 151 return Collections.unmodifiableList(defaultLayers); 152 } 153 154 public static void addLayer(ImageryInfo info) { 155 instance.add(info); 156 instance.save(); 157 } 158 159 public static void addLayers(Collection<ImageryInfo> infos) { 160 for (ImageryInfo i : infos) { 161 instance.add(i); 162 } 163 instance.save(); 164 Collections.sort(instance.layers); 165 } 166}