Changeset 2482 in josm


Ignore:
Timestamp:
2009-11-19T16:36:39+01:00 (10 years ago)
Author:
Gubaer
Message:

Had to clean up key handling methods in OsmPrimtive. Semantics of equals() on keys was broken. Also, fixed some FIXMEs related to efficient implementation. See also unit tests.

Location:
trunk
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r2481 r2482  
    1010import java.util.Date;
    1111import java.util.HashMap;
     12import java.util.HashSet;
    1213import java.util.LinkedHashSet;
    1314import java.util.LinkedList;
     
    1516import java.util.Locale;
    1617import java.util.Map;
     18import java.util.Set;
    1719import java.util.Map.Entry;
    1820import java.util.concurrent.atomic.AtomicLong;
     
    595597     *
    596598     */
    597     private Object keys;
    598     private static final String DEFAULT_KEY = "created_by";
     599    private String[] keys;
    599600
    600601    /**
    601602     * Replies the map of key/value pairs. Never replies null. The map can be empty, though.
    602603     *
    603      * @return Keys of this primitive. Changes made in returned map are not mapped
     604     * @return tags of this primitive. Changes made in returned map are not mapped
    604605     * back to the primitive, use setKeys() to modify the keys
    605606     * @since 1924
     
    608609        Map<String, String> result = new HashMap<String, String>();
    609610        if (keys != null) {
    610             if (keys instanceof String) {
    611                 result.put(DEFAULT_KEY, (String)keys);
    612             } else {
    613                 String[] map = (String[])keys;
    614                 if (map[0] != null) {
    615                     result.put(DEFAULT_KEY, map[0]);
    616                 }
    617                 for (int i=0; i<map.length / 2; i++) {
    618                     result.put(map[i * 2 + 1], map[i * 2 + 2]);
    619                 }
     611            for (int i=0; i<keys.length ; i+=2) {
     612                result.put(keys[i], keys[i + 1]);
    620613            }
    621614        }
     
    633626        if (keys == null) {
    634627            this.keys = null;
    635         } else {
    636             String[] newKeys = new String[keys.size() * 2 + (keys.containsKey(DEFAULT_KEY)?-1:1)];
    637             int index = 1;
    638             for (Entry<String, String> entry:keys.entrySet()) {
    639                 if (DEFAULT_KEY.equals(entry.getKey())) {
    640                     newKeys[0] = entry.getValue();
    641                 } else {
    642                     newKeys[index++] = entry.getKey();
    643                     newKeys[index++] = entry.getValue();
    644                 }
    645             }
    646             this.keys = newKeys;
    647         }
     628            return;
     629        }
     630        String[] newKeys = new String[keys.size() * 2];
     631        int index = 0;
     632        for (Entry<String, String> entry:keys.entrySet()) {
     633            newKeys[index++] = entry.getKey();
     634            newKeys[index++] = entry.getValue();
     635        }
     636        this.keys = newKeys;
    648637        keysChangedImpl();
    649638    }
     
    663652        else if (value == null) {
    664653            remove(key);
     654        } else if (keys == null || keys.length == 0){
     655            keys = new String[] {key, value};
    665656        } else {
    666             // TODO More effective implementation
    667             Map<String, String> keys = getKeys();
    668             if (!value.equals(keys.put(key, value))) {
    669                 setKeys(keys);
    670             }
     657            for (int i=0; i<keys.length;i+=2) {
     658                if (keys[i].equals(key)) {
     659                    keys[i+1] = value;
     660                    return;
     661                }
     662            }
     663            String[] newKeys = new String[keys.length + 2];
     664            for (int i=0; i< keys.length;i+=2) {
     665                newKeys[i] = keys[i];
     666                newKeys[i+1] = keys[i+1];
     667            }
     668            newKeys[keys.length] = key;
     669            newKeys[keys.length + 1] = value;
     670            keys = newKeys;
    671671        }
    672672    }
     
    677677     */
    678678    public final void remove(String key) {
    679         Map<String, String> keys = getKeys();
    680         if (keys.remove(key) != null) {
    681             // TODO More effective implemenation
    682             setKeys(keys);
    683         }
     679        if (key == null || keys == null || keys.length == 0 ) return;
     680        if (!hasKey(key))
     681            return;
     682        if (keys.length == 2) {
     683            keys = null;
     684            return;
     685        }
     686        String[] newKeys = new String[keys.length - 2];
     687        int j=0;
     688        for (int i=0; i < keys.length; i+=2) {
     689            if (!keys[i].equals(key)) {
     690                newKeys[j++] = keys[i];
     691                newKeys[j++] = keys[i+1];
     692            }
     693        }
     694        keys = newKeys;
    684695    }
    685696
     
    704715        if (key == null)
    705716            return null;
    706 
    707         if (keys == null)
     717        if (keys == null || keys.length == 0)
    708718            return null;
    709 
    710         if (keys instanceof String)
    711             return DEFAULT_KEY.equals(key)?(String)keys:null;
    712 
    713             String[] map = (String[])keys;
    714             if (DEFAULT_KEY.equals(key))
    715                 return map[0];
    716             else {
    717                 for (int i=0; i<map.length/2; i++) {
    718                     if (key.equals(map[i * 2 + 1]))
    719                         return map[i * 2 + 2];
    720                 }
    721             }
    722             return null;
    723     }
    724 
     719        for (int i=0; i<keys.length;i+=2) {
     720            if (keys[i].equals(key)) return keys[i+1];
     721        }
     722        return null;
     723    }
     724
     725    // FIXME: why replying a collection of entries? Should be replaced by
     726    // a method Map<String,String> getTags()
     727    //
    725728    public final Collection<Entry<String, String>> entrySet() {
    726         if (keys == null)
     729        if (keys == null || keys.length ==0)
    727730            return Collections.emptySet();
    728         else if (keys instanceof String)
    729             return Collections.<Entry<String, String>>singleton(new KeysEntry(DEFAULT_KEY, (String)keys));
    730         else {
    731             String[] map = (String[])keys;
    732             List<Entry<String, String>> result = new ArrayList<Entry<String,String>>();
    733             if (map[0] != null) {
    734                 result.add(new KeysEntry(DEFAULT_KEY, map[0]));
    735             }
    736             for (int i=0; i<map.length / 2; i++) {
    737                 result.add(new KeysEntry(map[i * 2 + 1], map[i * 2 + 2]));
    738             }
    739             return result;
    740         }
     731        Set<Entry<String, String>> result = new HashSet<Entry<String,String>>();
     732        for (int i=0; i<keys.length; i+=2) {
     733            result.add(new KeysEntry(keys[i], keys[i+1]));
     734        }
     735        return result;
    741736    }
    742737
    743738    public final Collection<String> keySet() {
    744         if (keys == null)
     739        if (keys == null || keys.length == 0)
    745740            return Collections.emptySet();
    746         else if (keys instanceof String)
    747             return Collections.singleton(DEFAULT_KEY);
    748         else {
    749             String[] map = (String[])keys;
    750             List<String> result = new ArrayList<String>(map.length / 2 + 1);
    751             if (map[0] != null) {
    752                 result.add(DEFAULT_KEY);
    753             }
    754             for (int i=0; i<map.length / 2; i++) {
    755                 result.add(map[i * 2 + 1]);
    756             }
    757             return result;
    758         }
     741        Set<String> result = new HashSet<String>(keys.length / 2);
     742        for (int i=0; i<keys.length; i+=2) {
     743            result.add(keys[i]);
     744        }
     745        return result;
    759746    }
    760747
     
    766753     */
    767754    public final boolean hasKeys() {
    768         return keys != null;
     755        return keys != null && keys.length != 0;
    769756    }
    770757
     
    778765    }
    779766
     767    /**
     768     * Replies true if this primitive has a tag with key <code>key</code>
     769     *
     770     * @param key the key
     771     * @return true, if his primitive has a tag with key <code>key</code>
     772     */
     773    public boolean hasKey(String key) {
     774        if (key == null) return false;
     775        if (keys == null) return false;
     776        for (int i=0; i< keys.length;i+=2) {
     777            if (keys[i].equals(key)) return true;
     778        }
     779        return false;
     780    }
     781
     782    /**
     783     * Replies true if other isn't null and has the same tags (key/value-pairs) as this.
     784     *
     785     * @param other the other object primitive
     786     * @return true if other isn't null and has the same tags (key/value-pairs) as this.
     787     */
     788    public boolean hasSameTags(OsmPrimitive other) {
     789        return entrySet().equals(other.entrySet());
     790    }
    780791
    781792    /*------------
     
    939950        if (incomplete && ! other.incomplete || !incomplete  && other.incomplete)
    940951            return false;
    941         return keySet().equals(other.keySet());
     952        // can't do an equals check on the internal keys array because it is not ordered
     953        //
     954        return hasSameTags(other);
    942955    }
    943956
Note: See TracChangeset for help on using the changeset viewer.