001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.io;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.util.ArrayList;
007    import java.util.Collections;
008    import java.util.HashMap;
009    import java.util.List;
010    
011    /**
012     * Represents the server capabilities
013     *
014     * Example capabilites document:
015     * 
016     * <osm version="0.6" generator="OpenStreetMap server">
017     *   <api>
018     *     <version minimum="0.6" maximum="0.6"/>
019     *     <area maximum="0.25"/>
020     *     <tracepoints per_page="5000"/>
021     *     <waynodes maximum="2000"/>
022     *     <changesets maximum_elements="50000"/>
023     *     <timeout seconds="300"/>
024     *   </api>
025     *   <policy>
026     *     <imagery>
027     *       <blacklist regex=".*\.google\.com/.*"/>
028     *       <blacklist regex=".*209\.85\.2\d\d.*"/>
029     *       <blacklist regex=".*209\.85\.1[3-9]\d.*"/>
030     *       <blacklist regex=".*209\.85\.12[89].*"/>
031     *     </imagery>
032     *   </policy>
033     * </osm>
034     * 
035     * This class is used in conjunction with a very primitive parser
036     * and simply stuffs the each tag and its attributes into a hash
037     * of hashes, with the exception of the "blacklist" tag which gets
038     * a list of its own. The DOM hierarchy is disregarded.
039     */
040    public class Capabilities {
041    
042        private HashMap<String, HashMap<String,String>> capabilities;
043        private ArrayList<String> imageryBlacklist;
044    
045        public Capabilities() {
046            clear();
047        }
048    
049        public boolean isDefined(String element, String attribute) {
050            if (! capabilities.containsKey(element)) return false;
051            HashMap<String, String> e = capabilities.get(element);
052            if (e == null) return false;
053            return (e.get(attribute) != null);
054        }
055    
056        public String get(String element, String attribute ) {
057            if (! capabilities.containsKey(element)) return null;
058            HashMap<String, String> e = capabilities.get(element);
059            if (e == null) return null;
060            return e.get(attribute);
061        }
062    
063        /**
064         * returns the value of configuration item in the capabilities as
065         * double value
066         *
067         * @param element  the name of the element
068         * @param attribute the name of the attribute
069         * @return the value; null, if the respective configuration item doesn't exist
070         * @throws NumberFormatException  if the value is not a valid double
071         */
072        public Double getDouble(String element, String attribute) throws NumberFormatException {
073            String s = get(element, attribute);
074            if (s == null) return null;
075            return Double.parseDouble(s);
076        }
077    
078        public Long getLong(String element, String attribute) {
079            String s = get(element, attribute);
080            if (s == null) return null;
081            return Long.parseLong(s);
082        }
083    
084        public void put(String element, String attribute, String value) {
085            if (element.equals("blacklist")) {
086                if (attribute.equals("regex")) {
087                    imageryBlacklist.add(value);
088                }
089            } else {
090                if (! capabilities.containsKey(element))  {
091                    HashMap<String,String> h = new HashMap<String, String>();
092                    capabilities.put(element, h);
093                }
094                HashMap<String, String> e = capabilities.get(element);
095                e.put(attribute, value);
096            }
097        }
098    
099        public void clear() {
100            capabilities = new HashMap<String, HashMap<String,String>>();
101            imageryBlacklist = new ArrayList<String>();
102        }
103    
104        public boolean supportsVersion(String version) {
105            return get("version", "minimum").compareTo(version) <= 0
106            && get("version", "maximum").compareTo(version) >= 0;
107        }
108    
109        /**
110         * Returns the max number of objects in a changeset. -1 if either the capabilities
111         * don't include this parameter or if the parameter value is illegal (not a number,
112         * a negative number)
113         *
114         * @return the max number of objects in a changeset
115         */
116        public int getMaxChangesetSize() {
117            String v = get("changesets", "maximum_elements");
118            if (v == null) return -1;
119            try {
120                int n = Integer.parseInt(v);
121                if (n <= 0) {
122                    System.err.println(tr("Warning: illegal value of attribute ''{0}'' of element ''{1}'' in server capabilities. Got ''{2}''", "changesets", "maximum_elements", n ));
123                    return -1;
124                }
125                return n;
126            } catch(NumberFormatException e) {
127                System.err.println(tr("Warning: illegal value of attribute ''{0}'' of element ''{1}'' in server capabilities. Got ''{2}''", "changesets", "maximum_elements", v ));
128                return -1;
129            }
130        }
131    
132        /**
133         * checks if the given URL is blacklisted by one of the of the
134         * regular expressions.
135         */
136    
137        public boolean isOnImageryBlacklist(String url)
138        {
139            if (url != null && imageryBlacklist != null) {
140                for (String blacklistRegex : imageryBlacklist) {
141                    if (url.matches(blacklistRegex))
142                        return true;
143                }
144            }
145            return false;
146        }
147    
148        /**
149         * returns the full list of blacklist regular expressions.
150         */
151        public List<String> getImageryBlacklist()
152        {
153            return Collections.unmodifiableList(imageryBlacklist);
154        }
155    }