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 }