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