Changeset 7186 in josm for trunk/src


Ignore:
Timestamp:
2014-05-29T08:49:43+02:00 (6 years ago)
Author:
bastiK
Message:

see #9914 - automatic update for imagery entries using id

Location:
trunk/src/org/openstreetmap/josm
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java

    r7005 r7186  
    1010import java.util.Collections;
    1111import java.util.List;
     12import java.util.Objects;
    1213import java.util.regex.Matcher;
    1314import java.util.regex.Pattern;
     
    146147        }
    147148    }
    148 
     149   
    149150    /** name of the imagery entry (gets translated by josm usually) */
    150151    private String name;
    151152    /** original name of the imagery entry in case of translation call */
    152153    private String origName;
     154    /** id for this imagery entry, optional at the moment */
     155    private String id;
    153156    private String url = null;
    154157    private boolean defaultEntry = false;
     
    176179    public static class ImageryPreferenceEntry {
    177180        @pref String name;
     181        @pref String id;
    178182        @pref String type;
    179183        @pref String url;
     
    207211        public ImageryPreferenceEntry(ImageryInfo i) {
    208212            name = i.name;
     213            id = i.id;
    209214            type = i.imageryType.getTypeString();
    210215            url = i.url;
     
    249254        @Override
    250255        public String toString() {
    251             return "ImageryPreferenceEntry [name=" + name + "]";
     256            String s = "ImageryPreferenceEntry [name=" + name;
     257            if (id != null) {
     258                s += " id=" + id;
     259            }
     260            s += "]";
     261            return s;
    252262        }
    253263    }
     
    308318        CheckParameterUtil.ensureParameterNotNull(e.url, "url");
    309319        name = e.name;
     320        id = e.id;
    310321        url = e.url;
    311322        cookies = e.cookies;
     
    347358    public ImageryInfo(ImageryInfo i) {
    348359        this.name = i.name;
     360        this.id = i.id;
    349361        this.url = i.url;
    350362        this.defaultEntry = i.defaultEntry;
     
    380392        return true;
    381393    }
    382 
     394   
     395    /**
     396     * Check if this object equals another ImageryInfo with respect to the properties
     397     * that get written to the preference file.
     398     *
     399     * The field {@link #pixelPerDegree} is ignored.
     400     *
     401     * @param other the ImageryInfo object to compare to
     402     * @return true if they are equal
     403     */
     404    public boolean equalsPref(ImageryInfo other) {
     405        if (other == null) {
     406            return false;
     407        }
     408        if (!Objects.equals(this.name, other.name)) {
     409            return false;
     410        }
     411        if (!Objects.equals(this.id, other.id)) {
     412            return false;
     413        }
     414        if (!Objects.equals(this.url, other.url)) {
     415            return false;
     416        }
     417        if (!Objects.equals(this.cookies, other.cookies)) {
     418            return false;
     419        }
     420        if (!Objects.equals(this.eulaAcceptanceRequired, other.eulaAcceptanceRequired)) {
     421            return false;
     422        }
     423        if (this.imageryType != other.imageryType) {
     424            return false;
     425        }
     426        if (this.defaultMaxZoom != other.defaultMaxZoom) {
     427            return false;
     428        }
     429        if (this.defaultMinZoom != other.defaultMinZoom) {
     430            return false;
     431        }
     432        if (!Objects.equals(this.bounds, other.bounds)) {
     433            return false;
     434        }
     435        if (!Objects.equals(this.serverProjections, other.serverProjections)) {
     436            return false;
     437        }
     438        if (!Objects.equals(this.attributionText, other.attributionText)) {
     439            return false;
     440        }
     441        if (!Objects.equals(this.attributionLinkURL, other.attributionLinkURL)) {
     442            return false;
     443        }
     444        if (!Objects.equals(this.attributionImage, other.attributionImage)) {
     445            return false;
     446        }
     447        if (!Objects.equals(this.attributionImageURL, other.attributionImageURL)) {
     448            return false;
     449        }
     450        if (!Objects.equals(this.termsOfUseText, other.termsOfUseText)) {
     451            return false;
     452        }
     453        if (!Objects.equals(this.termsOfUseURL, other.termsOfUseURL)) {
     454            return false;
     455        }
     456        if (!Objects.equals(this.countryCode, other.countryCode)) {
     457            return false;
     458        }
     459        if (!Objects.equals(this.icon, other.icon)) {
     460            return false;
     461        }
     462        return true;
     463    }
     464
     465   
    383466    @Override
    384467    public int hashCode() {
     
    594677
    595678    /**
     679     * Gets the entry id.
     680     *
     681     * Id can be null. This gets the configured id as is. Due to a user error,
     682     * this may not be unique. Use {@link ImageryLayerInfo#getUniqueId} to ensure
     683     * a unique value.
     684     * @return the id
     685     */
     686    public String getId() {
     687        return this.id;
     688    }
     689
     690    /**
     691     * Sets the entry id.
     692     * @param id the entry id
     693     */
     694    public void setId(String id) {
     695        this.id = id;
     696    }
     697
     698    /**
    596699     * Returns the entry URL.
    597700     * @return The entry URL
  • trunk/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java

    r7083 r7186  
    77import java.util.Collection;
    88import java.util.Collections;
     9import java.util.HashMap;
     10import java.util.HashSet;
    911import java.util.List;
     12import java.util.Map;
    1013import java.util.Objects;
    11 
     14import java.util.Set;
     15import java.util.TreeSet;
    1216import org.openstreetmap.josm.Main;
    1317import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryPreferenceEntry;
     
    2226
    2327    public static final ImageryLayerInfo instance = new ImageryLayerInfo();
    24     List<ImageryInfo> layers = new ArrayList<>();
    25     static List<ImageryInfo> defaultLayers = new ArrayList<>();
     28    private final List<ImageryInfo> layers = new ArrayList<>();
     29    private final Map<String, ImageryInfo> layerIds = new HashMap<>();
     30    private final static List<ImageryInfo> defaultLayers = new ArrayList<>();
     31    private final static Map<String, ImageryInfo> defaultLayerIds = new HashMap<>();
    2632
    2733    private static final String[] DEFAULT_LAYER_SITES = {
     
    3844    public void clear() {
    3945        layers.clear();
     46        layerIds.clear();
    4047    }
    4148
    4249    public void load() {
    43         boolean addedDefault = !layers.isEmpty();
     50        clear();
    4451        List<ImageryPreferenceEntry> entries = Main.pref.getListOfStructs("imagery.entries", null, ImageryPreferenceEntry.class);
    4552        if (entries != null) {
     
    5461            Collections.sort(layers);
    5562        }
    56         if (addedDefault) {
    57             save();
    58         }
     63        loadDefaults(false);
    5964    }
    6065
     
    7075    public void loadDefaults(boolean clearCache) {
    7176        defaultLayers.clear();
     77        defaultLayerIds.clear();
    7278        for (String source : Main.pref.getCollection("imagery.layers.sites", Arrays.asList(DEFAULT_LAYER_SITES))) {
    7379            if (clearCache) {
     
    8086            } catch (IOException ex) {
    8187                Main.error(ex, false);
    82                 continue;
    8388            } catch (SAXException ex) {
    8489                Main.error(ex);
    85                 continue;
    8690            }
    8791        }
    8892        while (defaultLayers.remove(null));
    89 
    90         Collection<String> defaults = Main.pref.getCollection("imagery.layers.default");
    91         List<String> defaultsSave = new ArrayList<>();
     93        Collections.sort(defaultLayers);
     94        buildIdMap(defaultLayers, defaultLayerIds);
     95        updateEntriesFromDefaults();
     96        buildIdMap(layers, layerIds);
     97    }
     98   
     99    /**
     100     * Build the mapping of unique ids to {@link ImageryInfo}s.
     101     * @param lst input list
     102     * @param idMap output map
     103     */
     104    private static void buildIdMap(List<ImageryInfo> lst, Map<String, ImageryInfo> idMap) {
     105        idMap.clear();
     106        Set<String> notUnique = new HashSet<>();
     107        for (ImageryInfo i : lst) {
     108            if (i.getId() != null) {
     109                if (idMap.containsKey(i.getId())) {
     110                    notUnique.add(i.getId());
     111                    Main.error("Id ''{0}'' is not unique - used by ''{1}'' and ''{2}''!",
     112                            i.getId(), i.getName(), idMap.get(i.getId()).getName());
     113                    continue;
     114                }
     115                idMap.put(i.getId(), i);
     116            }
     117        }
     118        for (String i : notUnique) {
     119            idMap.remove(i);
     120        }
     121    }
     122   
     123    /**
     124     * Update user entries according to the list of default entries.
     125     */
     126    public void updateEntriesFromDefaults() {
     127        // add new default entries to the user selection
     128        boolean changed = false;
     129        Collection<String> knownDefaults = Main.pref.getCollection("imagery.layers.default");
     130        Collection<String> newKnownDefaults = new TreeSet<>(knownDefaults);
    92131        for (ImageryInfo def : defaultLayers) {
    93132            if (def.isDefaultEntry()) {
    94                 defaultsSave.add(def.getUrl());
    95 
    96133                boolean isKnownDefault = false;
    97                 for (String url : defaults) {
     134                for (String url : knownDefaults) {
    98135                    if (isSimilar(url, def.getUrl())) {
    99136                        isKnownDefault = true;
     
    103140                boolean isInUserList = false;
    104141                if (!isKnownDefault) {
     142                    newKnownDefaults.add(def.getUrl());
    105143                    for (ImageryInfo i : layers) {
    106                         if (isSimilar(def.getUrl(), i.getUrl())) {
     144                        if (isSimilar(def, i)) {
    107145                            isInUserList = true;
    108146                            break;
     
    112150                if (!isKnownDefault && !isInUserList) {
    113151                    add(new ImageryInfo(def));
    114                 }
    115             }
    116         }
    117 
    118         Collections.sort(defaultLayers);
    119         Main.pref.putCollection("imagery.layers.default", defaultsSave.isEmpty() ? defaults : defaultsSave);
    120     }
    121 
     152                    changed = true;
     153                }
     154            }
     155        }
     156        Main.pref.putCollection("imagery.layers.default", newKnownDefaults);
     157
     158        // Add ids to user entries without id.
     159        // Only do this the first time for each id, so the user can have
     160        // custom entries that don't get updated automatically
     161        Collection<String> addedIds = Main.pref.getCollection("imagery.layers.addedIds");
     162        Collection<String> newAddedIds = new TreeSet<>(addedIds);
     163        for (ImageryInfo info : layers) {
     164            for (ImageryInfo def : defaultLayers) {
     165                if (isSimilar(def, info)) {
     166                    if (def.getId() != null && !addedIds.contains(def.getId())) {
     167                        if (!defaultLayerIds.containsKey(def.getId())) {
     168                            // ignore ids used more than once (have been purged from the map)
     169                            continue;
     170                        }
     171                        newAddedIds.add(def.getId());
     172                        if (info.getId() == null) {
     173                            info.setId(def.getId());
     174                            changed = true;
     175                        }
     176                    }
     177                }
     178            }
     179        }
     180        Main.pref.putCollection("imagery.layers.migration.addedIds", newAddedIds);
     181       
     182        // automatically update user entries with same id as a default entry
     183        for (int i=0; i<layers.size(); i++) {
     184            ImageryInfo info = layers.get(i);
     185            if (info.getId() == null) {
     186                continue;
     187            }
     188            ImageryInfo matchingDefault = defaultLayerIds.get(info.getId());
     189            if (matchingDefault != null && !matchingDefault.equalsPref(info)) {
     190                layers.set(i, matchingDefault);
     191                changed = true;
     192            }
     193        }
     194       
     195        if (changed) {
     196            save();
     197        }
     198    }
     199
     200    private boolean isSimilar(ImageryInfo iiA, ImageryInfo iiB) {
     201        if (iiA.getId() != null && iiB.getId() != null) return iiA.getId().equals(iiB.getId());
     202        return isSimilar(iiA.getUrl(), iiB.getUrl());
     203    }
     204   
    122205    // some additional checks to respect extended URLs in preferences (legacy workaround)
    123206    private boolean isSimilar(String a, String b) {
    124207        return Objects.equals(a, b) || (a != null && b != null && !a.isEmpty() && !b.isEmpty() && (a.contains(b) || b.contains(a)));
    125208    }
    126 
     209   
    127210    public void add(ImageryInfo info) {
    128211        layers.add(info);
     
    161244        Collections.sort(instance.layers);
    162245    }
     246   
     247    /**
     248     * Get unique id for ImageryInfo.
     249     *
     250     * This takes care, that no id is used twice (due to a user error)
     251     * @param info the ImageryInfo to look up
     252     * @return null, if there is no id or the id is used twice,
     253     * the corresponding id otherwise
     254     */
     255    public String getUniqueId(ImageryInfo info) {
     256        if (info.getId() != null && layerIds.get(info.getId()) == info) {
     257            return info.getId();
     258        }
     259        return null;
     260    }
    163261}
  • trunk/src/org/openstreetmap/josm/data/imagery/Shape.java

    r7005 r7186  
    77import java.util.ArrayList;
    88import java.util.List;
     9import java.util.Objects;
    910
    1011import org.openstreetmap.gui.jmapviewer.Coordinate;
     
    8485        coords.add(new Coordinate(LatLon.roundToOsmPrecision(lat), LatLon.roundToOsmPrecision(lon)));
    8586    }
     87
     88    @Override
     89    public int hashCode() {
     90        int hash = 5;
     91        hash = 47 * hash + Objects.hashCode(this.coords);
     92        return hash;
     93    }
     94
     95    @Override
     96    public boolean equals(Object obj) {
     97        if (obj == null) {
     98            return false;
     99        }
     100        if (getClass() != obj.getClass()) {
     101            return false;
     102        }
     103        final Shape other = (Shape) obj;
     104        if (!Objects.equals(this.coords, other.coords)) {
     105            return false;
     106        }
     107        return true;
     108    }
     109   
     110   
    86111}
  • trunk/src/org/openstreetmap/josm/gui/ImageryMenu.java

    r7176 r7186  
    8080    };
    8181
    82     private JMenuItem singleOffset = new JMenuItem(offsetAction);
     82    private final JMenuItem singleOffset = new JMenuItem(offsetAction);
    8383    private JMenuItem offsetMenuItem = singleOffset;
    84     private MapRectifierWMSmenuAction rectaction = new MapRectifierWMSmenuAction();
     84    private final MapRectifierWMSmenuAction rectaction = new MapRectifierWMSmenuAction();
    8585
    8686    public ImageryMenu(JMenu subMenu) {
  • trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java

    r7005 r7186  
    880880     */
    881881    public static void initialize() {
    882         ImageryLayerInfo.instance.clear();
    883         ImageryLayerInfo.instance.loadDefaults(false);
    884882        ImageryLayerInfo.instance.load();
    885883        OffsetBookmark.loadBookmarks();
  • trunk/src/org/openstreetmap/josm/io/imagery/ImageryReader.java

    r7083 r7186  
    112112                if (Arrays.asList(new String[] {
    113113                        "name",
     114                        "id",
    114115                        "type",
    115116                        "default",
     
    204205                    entry.setTranslatedName(accumulator.toString());
    205206                    break;
     207                case "id":
     208                    entry.setId(accumulator.toString());
     209                    break;
    206210                case "type":
    207211                    boolean found = false;
Note: See TracChangeset for help on using the changeset viewer.