Changeset 4099 in josm


Ignore:
Timestamp:
May 29, 2011 8:26:54 PM (2 years ago)
Author:
bastiK
Message:

Move common code for OsmPrimitive & PrimitiveData to abstract subclass.
PrimitiveData benefits now from prior memory optimizations in OsmPrimitive.

Location:
trunk/src/org/openstreetmap/josm/data/osm
Files:
1 added
3 edited

Legend:

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

    r4098 r4099  
    1212    public NodeData() { 
    1313 
    14     } 
    15  
    16     public NodeData(double lat, double lon, String... keys) { 
    17         setCoor(new LatLon(lat, lon)); 
    18         setKeysAsList(keys); 
    19     } 
    20  
    21     public NodeData(String... keys) { 
    22         setKeysAsList(keys); 
    2314    } 
    2415 
  • trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r4098 r4099  
    1010import java.util.Collections; 
    1111import java.util.Date; 
    12 import java.util.HashMap; 
    1312import java.util.HashSet; 
    1413import java.util.LinkedHashSet; 
     
    1716import java.util.Locale; 
    1817import java.util.Map; 
    19 import java.util.Map.Entry; 
    2018import java.util.Set; 
    21 import java.util.concurrent.atomic.AtomicLong; 
    2219 
    2320import org.openstreetmap.josm.Main; 
     
    4037 * @author imi 
    4138 */ 
    42 abstract public class OsmPrimitive implements Comparable<OsmPrimitive>, IPrimitive { 
    43  
    44     private static final AtomicLong idCounter = new AtomicLong(0); 
    45  
    46     static long generateUniqueId() { 
    47         return idCounter.decrementAndGet(); 
    48     } 
    49  
    50     /** 
    51      * This flag shows, that the properties have been changed by the user 
    52      * and on upload the object will be send to the server 
    53      */ 
    54     private static final int FLAG_MODIFIED = 1 << 0; 
    55  
    56     /** 
    57      * The visible flag indicates, that an object is marked 
    58      * as deleted on the server. 
    59      */ 
    60     private static final int FLAG_VISIBLE  = 1 << 1; 
     39abstract public class OsmPrimitive extends AbstractPrimitive implements Comparable<OsmPrimitive> { 
    6140 
    6241    /** 
     
    6746     * while the filter is active. 
    6847     */ 
    69     private static final int FLAG_DISABLED = 1 << 2; 
    70  
    71     /** 
    72      * An object that was deleted by the user. 
    73      * Deleted objects are usually hidden on the map and a request 
    74      * for deletion will be send to the server on upload. 
    75      * An object usually cannot be deleted if it has non-deleted 
    76      * objects still referring to it. 
    77      */ 
    78     private static final int FLAG_DELETED  = 1 << 3; 
     48    protected static final int FLAG_DISABLED = 1 << 4; 
    7949 
    8050    /** 
     
    8757     * unset as well (for efficient access). 
    8858     */ 
    89     private static final int FLAG_HIDE_IF_DISABLED = 1 << 4; 
     59    protected static final int FLAG_HIDE_IF_DISABLED = 1 << 5; 
    9060 
    9161    /** 
     
    9464     * (e.g. one way street.) 
    9565     */ 
    96     private static final int FLAG_HAS_DIRECTIONS = 1 << 5; 
     66    protected static final int FLAG_HAS_DIRECTIONS = 1 << 6; 
    9767 
    9868    /** 
     
    10070     * Some trivial tags like source=* are ignored here. 
    10171     */ 
    102     private static final int FLAG_TAGGED = 1 << 6; 
     72    protected static final int FLAG_TAGGED = 1 << 7; 
    10373 
    10474    /** 
     
    10777     * (E.g. oneway=-1.) 
    10878     */ 
    109     private static final int FLAG_DIRECTION_REVERSED = 1 << 7; 
     79    protected static final int FLAG_DIRECTION_REVERSED = 1 << 8; 
    11080 
    11181    /** 
     
    11484     * that the primitive is currently highlighted. 
    11585     */ 
    116     private static final int FLAG_HIGHLIGHTED = 1 << 8; 
    117  
    118     /** 
    119      * A primitive is incomplete if we know its id and type, but nothing more. 
    120      * Typically some members of a relation are incomplete until they are 
    121      * fetched from the server. 
    122      */ 
    123     private static final int FLAG_INCOMPLETE = 1 << 9; 
     86    protected static final int FLAG_HIGHLIGHTED = 1 << 9; 
    12487 
    12588    /** 
     
    359322    } 
    360323 
    361  
    362     /*------------------- 
    363      * OTHER PROPERTIES 
    364      *-------------------*/ 
    365  
    366     /** 
    367      * Unique identifier in OSM. This is used to identify objects on the server. 
    368      * An id of 0 means an unknown id. The object has not been uploaded yet to 
    369      * know what id it will get. 
    370      * 
    371      */ 
    372     private long id = 0; 
    373  
    374     /** 
    375      * User that last modified this primitive, as specified by the server. 
    376      * Never changed by JOSM. 
    377      */ 
    378     private User user = null; 
    379  
    380     /** 
    381      * Contains the version number as returned by the API. Needed to 
    382      * ensure update consistency 
    383      */ 
    384     private int version = 0; 
    385  
    386     /** 
    387      * The id of the changeset this primitive was last uploaded to. 
    388      * 0 if it wasn't uploaded to a changeset yet of if the changeset 
    389      * id isn't known. 
    390      */ 
    391     private int changesetId; 
    392  
    393     /** 
    394      * Replies the version number as returned by the API. The version is 0 if the id is 0 or 
    395      * if this primitive is incomplete. 
    396      * 
    397      * @see #setVersion(int) 
    398      */ 
    399     @Override 
    400     public int getVersion() { 
    401         return version; 
    402     } 
    403  
    404     /** 
    405      * Replies the id of this primitive. 
    406      * 
    407      * @return the id of this primitive. 
    408      */ 
    409     @Override 
    410     public long getId() { 
    411         long id = this.id; 
    412         return id >= 0?id:0; 
    413     } 
    414  
    415     /** 
    416      * 
    417      * @return Osm id if primitive already exists on the server. Unique negative value if primitive is new 
    418      */ 
    419     @Override 
    420     public long getUniqueId() { 
    421         return id; 
    422     } 
    423  
    424     /** 
    425      * 
    426      * @return True if primitive is new (not yet uploaded the server, id <= 0) 
    427      */ 
    428     @Override 
    429     public boolean isNew() { 
    430         return id <= 0; 
    431     } 
    432  
    433     /** 
    434      * 
    435      * @return True if primitive is new or undeleted 
    436      * @see #isNew() 
    437      * @see #isUndeleted() 
    438      */ 
    439     public boolean isNewOrUndeleted() { 
    440         return (id <= 0) || ((flags & (FLAG_VISIBLE + FLAG_DELETED)) == 0); 
    441     } 
    442  
    443324    /** 
    444325     * Sets the id and the version of this primitive if it is known to the OSM API. 
     
    468349                datasetCopy.addPrimitive(this); 
    469350            } 
    470             this.id = id; 
    471             this.version = version; 
    472             this.setIncomplete(false); 
     351            super.setOsmId(id, version); 
    473352        } finally { 
    474353            writeUnlock(locked); 
     
    485364     * @throws DataIntegrityProblemException If primitive was already added to the dataset 
    486365     */ 
     366    @Override 
    487367    public void clearOsmId() { 
    488368        if (dataSet != null) 
    489369            throw new DataIntegrityProblemException("Method cannot be called after primitive was added to the dataset"); 
    490  
    491         // Not part of dataset - no lock necessary 
    492         this.id = generateUniqueId(); 
    493         this.version = 0; 
    494         this.changesetId = 0; // reset changeset id on a new object 
    495         this.setIncomplete(false); 
    496     } 
    497  
    498     /** 
    499      * Replies the user who has last touched this object. May be null. 
    500      * 
    501      * @return the user who has last touched this object. May be null. 
    502      */ 
    503     @Override 
    504     public User getUser() { 
    505         return user; 
    506     } 
    507  
    508     /** 
    509      * Sets the user who has last touched this object. 
    510      * 
    511      * @param user the user 
    512      */ 
     370        super.clearOsmId(); 
     371    } 
     372 
    513373    @Override 
    514374    public void setUser(User user) { 
    515375        boolean locked = writeLock(); 
    516376        try { 
    517             this.user = user; 
    518         } finally { 
    519             writeUnlock(locked); 
    520         } 
    521     } 
    522  
    523     /** 
    524      * Replies the id of the changeset this primitive was last uploaded to. 
    525      * 0 if this primitive wasn't uploaded to a changeset yet or if the 
    526      * changeset isn't known. 
    527      * 
    528      * @return the id of the changeset this primitive was last uploaded to. 
    529      */ 
    530     @Override 
    531     public int getChangesetId() { 
    532         return changesetId; 
    533     } 
    534  
    535     /** 
    536      * Sets the changeset id of this primitive. Can't be set on a new 
    537      * primitive. 
    538      * 
    539      * @param changesetId the id. >= 0 required. 
    540      * @throws IllegalStateException thrown if this primitive is new. 
    541      * @throws IllegalArgumentException thrown if id < 0 
    542      */ 
     377            super.setUser(user); 
     378        } finally { 
     379            writeUnlock(locked); 
     380        } 
     381    } 
     382 
    543383    @Override 
    544384    public void setChangesetId(int changesetId) throws IllegalStateException, IllegalArgumentException { 
    545385        boolean locked = writeLock(); 
    546386        try { 
    547             if (this.changesetId == changesetId) 
    548                 return; 
    549             if (changesetId < 0) 
    550                 throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' >= 0 expected, got {1}", "changesetId", changesetId)); 
    551             if (isNew() && changesetId > 0) 
    552                 throw new IllegalStateException(tr("Cannot assign a changesetId > 0 to a new primitive. Value of changesetId is {0}", changesetId)); 
    553  
    554387            int old = this.changesetId; 
    555             this.changesetId = changesetId; 
     388            super.setChangesetId(changesetId); 
    556389            if (dataSet != null) { 
    557390                dataSet.fireChangesetIdChanged(this, old, changesetId); 
     
    562395    } 
    563396 
    564     /** 
    565      * Replies the unique primitive id for this primitive 
    566      * 
    567      * @return the unique primitive id for this primitive 
    568      */ 
    569     public PrimitiveId getPrimitiveId() { 
    570         return new SimplePrimitiveId(getUniqueId(), getType()); 
    571     } 
    572  
    573     public OsmPrimitiveType getDisplayType() { 
    574         return getType(); 
    575     } 
    576  
    577397    @Override 
    578398    public void setTimestamp(Date timestamp) { 
    579399        boolean locked = writeLock(); 
    580400        try { 
    581             this.timestamp = (int)(timestamp.getTime() / 1000); 
    582         } finally { 
    583             writeUnlock(locked); 
    584         } 
    585     } 
    586  
    587     /** 
    588      * Time of last modification to this object. This is not set by JOSM but 
    589      * read from the server and delivered back to the server unmodified. It is 
    590      * used to check against edit conflicts. 
    591      * 
    592      */ 
    593     @Override 
    594     public Date getTimestamp() { 
    595         return new Date(timestamp * 1000l); 
    596     } 
    597  
    598     @Override 
    599     public boolean isTimestampEmpty() { 
    600         return timestamp == 0; 
    601     } 
    602  
    603     private int timestamp; 
     401            super.setTimestamp(timestamp); 
     402        } finally { 
     403            writeUnlock(locked); 
     404        } 
     405    } 
     406 
    604407 
    605408    /* ------- 
     
    607410    /* ------*/ 
    608411 
    609     private volatile short flags = FLAG_VISIBLE;   // visible per default 
    610  
    611     private void updateFlagsNoLock(int flag, boolean value) { 
    612         if (value) { 
    613             flags |= flag; 
    614         } else { 
    615             flags &= ~flag; 
    616         } 
    617     } 
    618  
    619     private void updateFlags(int flag, boolean value) { 
     412    private void updateFlagsNoLock (int flag, boolean value) { 
     413        super.updateFlags(flag, value); 
     414    } 
     415     
     416    @Override 
     417    protected final void updateFlags(int flag, boolean value) { 
    620418        boolean locked = writeLock(); 
    621419        try { 
     
    681479    } 
    682480 
    683     /** 
    684      * Marks this primitive as being modified. 
    685      * 
    686      * @param modified true, if this primitive is to be modified 
    687      */ 
    688     @Override 
    689     public void setModified(boolean modified) { 
    690         updateFlags(FLAG_MODIFIED, modified); 
    691     } 
    692  
    693     /** 
    694      * Replies <code>true</code> if the object has been modified since it was loaded from 
    695      * the server. In this case, on next upload, this object will be updated. 
    696      * 
    697      * Deleted objects are deleted from the server. If the objects are added (id=0), 
    698      * the modified is ignored and the object is added to the server. 
    699      * 
    700      * @return <code>true</code> if the object has been modified since it was loaded from 
    701      * the server 
    702      */ 
    703     @Override 
    704     public boolean isModified() { 
    705         return (flags & FLAG_MODIFIED) != 0; 
    706     } 
    707  
    708     /** 
    709      * Replies <code>true</code>, if the object has been deleted. 
    710      * 
    711      * @return <code>true</code>, if the object has been deleted. 
    712      * @see #setDeleted(boolean) 
    713      */ 
    714     @Override 
    715     public boolean isDeleted() { 
    716         return (flags & FLAG_DELETED) != 0; 
    717     } 
    718  
    719     /** 
    720      * Replies <code>true</code> if the object has been deleted on the server and was undeleted by the user. 
    721      * @return <code>true</code> if the object has been undeleted 
    722      */ 
    723     public boolean isUndeleted() { 
    724         return (flags & (FLAG_VISIBLE + FLAG_DELETED)) == 0; 
    725     } 
    726  
    727     /** 
    728      * Replies <code>true</code>, if the object is usable (i.e. complete 
    729      * and not deleted). 
    730      * 
    731      * @return <code>true</code>, if the object is usable. 
    732      * @see #delete(boolean) 
    733      */ 
    734     public boolean isUsable() { 
    735         return (flags & (FLAG_DELETED + FLAG_INCOMPLETE)) == 0; 
    736     } 
    737481 
    738482    public boolean isSelectable() { 
     
    744488    } 
    745489 
    746     /** 
    747      * Replies true if this primitive is either unknown to the server (i.e. its id 
    748      * is 0) or it is known to the server and it hasn't be deleted on the server. 
    749      * Replies false, if this primitive is known on the server and has been deleted 
    750      * on the server. 
    751      * 
    752      * @see #setVisible(boolean) 
    753      */ 
    754     @Override 
    755     public boolean isVisible() { 
    756         return (flags & FLAG_VISIBLE) != 0; 
    757     } 
    758  
    759     /** 
    760      * Sets whether this primitive is visible, i.e. whether it is known on the server 
    761      * and not deleted on the server. 
    762      * 
    763      * @see #isVisible() 
    764      * @throws IllegalStateException thrown if visible is set to false on an primitive with 
    765      * id==0 
    766      */ 
    767     @Override 
    768     public void setVisible(boolean visible) throws IllegalStateException{ 
    769         boolean locked = writeLock(); 
    770         try { 
    771             if (isNew() && visible == false) 
    772                 throw new IllegalStateException(tr("A primitive with ID = 0 cannot be invisible.")); 
    773             updateFlagsNoLock(FLAG_VISIBLE, visible); 
    774         } finally { 
    775             writeUnlock(locked); 
    776         } 
    777     } 
    778  
    779     /** 
    780      * Sets whether this primitive is deleted or not. 
    781      * 
    782      * Also marks this primitive as modified if deleted is true. 
    783      * 
    784      * @param deleted  true, if this primitive is deleted; false, otherwise 
    785      */ 
     490    @Override 
     491    public void setVisible(boolean visible) throws IllegalStateException { 
     492        boolean locked = writeLock(); 
     493        try { 
     494            super.setVisible(visible); 
     495        } finally { 
     496            writeUnlock(locked); 
     497        } 
     498    } 
     499 
    786500    @Override 
    787501    public void setDeleted(boolean deleted) { 
    788502        boolean locked = writeLock(); 
    789503        try { 
    790             updateFlagsNoLock(FLAG_DELETED, deleted); 
    791             setModified(deleted ^ !isVisible()); 
     504            super.setDeleted(deleted); 
    792505            if (dataSet != null) { 
    793506                if (deleted) { 
     
    802515    } 
    803516 
    804  
    805     /** 
    806      * If set to true, this object is incomplete, which means only the id 
    807      * and type is known (type is the objects instance class) 
    808      */ 
    809     private void setIncomplete(boolean incomplete) { 
     517    @Override 
     518    protected void setIncomplete(boolean incomplete) { 
    810519        boolean locked = writeLock(); 
    811520        try { 
     
    817526                } 
    818527            } 
    819             updateFlagsNoLock(FLAG_INCOMPLETE, incomplete); 
     528            super.setIncomplete(incomplete); 
    820529        }  finally { 
    821530            writeUnlock(locked); 
    822531        } 
    823     } 
    824  
    825     @Override 
    826     public boolean isIncomplete() { 
    827         return (flags & FLAG_INCOMPLETE) != 0; 
    828532    } 
    829533 
     
    997701     * Keys handling 
    998702     ------------*/ 
    999  
    1000     // Note that all methods that read keys first make local copy of keys array reference. This is to ensure thread safety - reading 
    1001     // doesn't have to be locked so it's possible that keys array will be modified. But all write methods make copy of keys array so 
    1002     // the array itself will be never modified - only reference will be changed 
    1003  
    1004     /** 
    1005      * The key/value list for this primitive. 
    1006      * 
    1007      */ 
    1008     private String[] keys; 
    1009  
    1010     /** 
    1011      * Replies the map of key/value pairs. Never replies null. The map can be empty, though. 
    1012      * 
    1013      * @return tags of this primitive. Changes made in returned map are not mapped 
    1014      * back to the primitive, use setKeys() to modify the keys 
    1015      */ 
    1016     @Override 
    1017     public Map<String, String> getKeys() { 
    1018         Map<String, String> result = new HashMap<String, String>(); 
    1019         String[] keys = this.keys; 
    1020         if (keys != null) { 
    1021             for (int i=0; i<keys.length ; i+=2) { 
    1022                 result.put(keys[i], keys[i + 1]); 
    1023             } 
    1024         } 
    1025         return result; 
    1026     } 
    1027  
    1028     /** 
    1029      * Sets the keys of this primitives to the key/value pairs in <code>keys</code>. 
    1030      * If <code>keys</code> is null removes all existing key/value pairs. 
    1031      * 
    1032      * @param keys the key/value pairs to set. If null, removes all existing key/value pairs. 
    1033      */ 
    1034     @Override 
    1035     public void setKeys(Map<String, String> keys) { 
    1036         boolean locked = writeLock(); 
    1037         try { 
    1038             Map<String, String> originalKeys = getKeys(); 
    1039             if (keys == null || keys.isEmpty()) { 
    1040                 this.keys = null; 
    1041                 keysChangedImpl(originalKeys); 
    1042                 return; 
    1043             } 
    1044             String[] newKeys = new String[keys.size() * 2]; 
    1045             int index = 0; 
    1046             for (Entry<String, String> entry:keys.entrySet()) { 
    1047                 newKeys[index++] = entry.getKey(); 
    1048                 newKeys[index++] = entry.getValue(); 
    1049             } 
    1050             this.keys = newKeys; 
    1051             keysChangedImpl(originalKeys); 
    1052         } finally { 
    1053             writeUnlock(locked); 
    1054         } 
    1055     } 
    1056  
    1057     /** 
    1058      * Set the given value to the given key. If key is null, does nothing. If value is null, 
    1059      * removes the key and behaves like {@see #remove(String)}. 
    1060      * 
    1061      * @param key  The key, for which the value is to be set. Can be null, does nothing in this case. 
    1062      * @param value The value for the key. If null, removes the respective key/value pair. 
    1063      * 
    1064      * @see #remove(String) 
    1065      */ 
     703     
     704    @Override 
     705    public final void setKeys(Map<String, String> keys) { 
     706        boolean locked = writeLock(); 
     707        try { 
     708            super.setKeys(keys); 
     709        } finally { 
     710            writeUnlock(locked); 
     711        } 
     712    } 
     713     
    1066714    @Override 
    1067715    public final void put(String key, String value) { 
    1068716        boolean locked = writeLock(); 
    1069717        try { 
    1070             Map<String, String> originalKeys = getKeys(); 
    1071             if (key == null) 
    1072                 return; 
    1073             else if (value == null) { 
    1074                 remove(key); 
    1075             } else if (keys == null){ 
    1076                 keys = new String[] {key, value}; 
    1077                 keysChangedImpl(originalKeys); 
    1078             } else { 
    1079                 for (int i=0; i<keys.length;i+=2) { 
    1080                     if (keys[i].equals(key)) { 
    1081                         keys[i+1] = value;  // This modifies the keys array but it doesn't make it invalidate for any time so its ok (see note no top) 
    1082                         keysChangedImpl(originalKeys); 
    1083                         return; 
    1084                     } 
    1085                 } 
    1086                 String[] newKeys = new String[keys.length + 2]; 
    1087                 for (int i=0; i< keys.length;i+=2) { 
    1088                     newKeys[i] = keys[i]; 
    1089                     newKeys[i+1] = keys[i+1]; 
    1090                 } 
    1091                 newKeys[keys.length] = key; 
    1092                 newKeys[keys.length + 1] = value; 
    1093                 keys = newKeys; 
    1094                 keysChangedImpl(originalKeys); 
    1095             } 
    1096         } finally { 
    1097             writeUnlock(locked); 
    1098         } 
    1099     } 
    1100     /** 
    1101      * Remove the given key from the list 
    1102      * 
    1103      * @param key  the key to be removed. Ignored, if key is null. 
    1104      */ 
     718            super.put(key, value); 
     719        } finally { 
     720            writeUnlock(locked); 
     721        } 
     722    }   
     723     
    1105724    @Override 
    1106725    public final void remove(String key) { 
    1107726        boolean locked = writeLock(); 
    1108727        try { 
    1109             if (key == null || keys == null) return; 
    1110             if (!hasKey(key)) 
    1111                 return; 
    1112             Map<String, String> originalKeys = getKeys(); 
    1113             if (keys.length == 2) { 
    1114                 keys = null; 
    1115                 keysChangedImpl(originalKeys); 
    1116                 return; 
    1117             } 
    1118             String[] newKeys = new String[keys.length - 2]; 
    1119             int j=0; 
    1120             for (int i=0; i < keys.length; i+=2) { 
    1121                 if (!keys[i].equals(key)) { 
    1122                     newKeys[j++] = keys[i]; 
    1123                     newKeys[j++] = keys[i+1]; 
    1124                 } 
    1125             } 
    1126             keys = newKeys; 
    1127             keysChangedImpl(originalKeys); 
    1128         } finally { 
    1129             writeUnlock(locked); 
    1130         } 
    1131     } 
    1132  
    1133     /** 
    1134      * Removes all keys from this primitive. 
    1135      * 
    1136      * @since 1843 
    1137      */ 
     728            super.remove(key); 
     729        } finally { 
     730            writeUnlock(locked); 
     731        } 
     732    } 
     733 
    1138734    @Override 
    1139735    public final void removeAll() { 
    1140736        boolean locked = writeLock(); 
    1141737        try { 
    1142             if (keys != null) { 
    1143                 Map<String, String> originalKeys = getKeys(); 
    1144                 keys = null; 
    1145                 keysChangedImpl(originalKeys); 
    1146             } 
    1147         } finally { 
    1148             writeUnlock(locked); 
    1149         } 
    1150     } 
    1151  
    1152     /** 
    1153      * Replies the value for key <code>key</code>. Replies null, if <code>key</code> is null. 
    1154      * Replies null, if there is no value for the given key. 
    1155      * 
    1156      * @param key the key. Can be null, replies null in this case. 
    1157      * @return the value for key <code>key</code>. 
    1158      */ 
    1159     @Override 
    1160     public final String get(String key) { 
    1161         String[] keys = this.keys; 
    1162         if (key == null) 
    1163             return null; 
    1164         if (keys == null) 
    1165             return null; 
    1166         for (int i=0; i<keys.length;i+=2) { 
    1167             if (keys[i].equals(key)) return keys[i+1]; 
    1168         } 
    1169         return null; 
    1170     } 
    1171  
    1172     @Override 
    1173     public final Collection<String> keySet() { 
    1174         String[] keys = this.keys; 
    1175         if (keys == null) 
    1176             return Collections.emptySet(); 
    1177         Set<String> result = new HashSet<String>(keys.length / 2); 
    1178         for (int i=0; i<keys.length; i+=2) { 
    1179             result.add(keys[i]); 
    1180         } 
    1181         return result; 
    1182     } 
    1183  
    1184     /** 
    1185      * Replies true, if the map of key/value pairs of this primitive is not empty. 
    1186      * 
    1187      * @return true, if the map of key/value pairs of this primitive is not empty; false 
    1188      *   otherwise 
    1189      */ 
    1190     @Override 
    1191     public final boolean hasKeys() { 
    1192         return keys != null; 
    1193     } 
    1194  
    1195     private void keysChangedImpl(Map<String, String> originalKeys) { 
     738            super.removeAll(); 
     739        } finally { 
     740            writeUnlock(locked); 
     741        } 
     742    }   
     743     
     744    @Override 
     745    protected final void keysChangedImpl(Map<String, String> originalKeys) { 
    1196746        clearCachedStyle(); 
    1197747        if (dataSet != null) { 
     
    1205755            dataSet.fireTagsChanged(this, originalKeys); 
    1206756        } 
    1207     } 
    1208  
    1209     /** 
    1210      * Replies true if this primitive has a tag with key <code>key</code> 
    1211      * 
    1212      * @param key the key 
    1213      * @return true, if his primitive has a tag with key <code>key</code> 
    1214      */ 
    1215     public boolean hasKey(String key) { 
    1216         String[] keys = this.keys; 
    1217         if (key == null) return false; 
    1218         if (keys == null) return false; 
    1219         for (int i=0; i< keys.length;i+=2) { 
    1220             if (keys[i].equals(key)) return true; 
    1221         } 
    1222         return false; 
    1223     } 
    1224  
    1225     /** 
    1226      * Replies true if other isn't null and has the same tags (key/value-pairs) as this. 
    1227      * 
    1228      * @param other the other object primitive 
    1229      * @return true if other isn't null and has the same tags (key/value-pairs) as this. 
    1230      */ 
    1231     public boolean hasSameTags(OsmPrimitive other) { 
    1232         return getKeys().equals(other.getKeys()); 
    1233757    } 
    1234758 
     
    1392916    abstract public void visit(Visitor visitor); 
    1393917 
    1394  
    1395918    /** 
    1396919     * Get and write all attributes from the parameter. Does not fire any listener, so 
     
    1401924        if (id != other.id && dataSet != null) 
    1402925            throw new DataIntegrityProblemException("Osm id cannot be changed after primitive was added to the dataset"); 
    1403         setKeys(other.getKeys()); 
    1404         id = other.id; 
    1405         if (id <=0) { 
    1406             // reset version and changeset id 
    1407             version = 0; 
    1408             changesetId = 0; 
    1409         } 
    1410         timestamp = other.timestamp; 
    1411         if (id > 0) { 
    1412             version = other.version; 
    1413         } 
    1414         setIncomplete(other.isIncomplete()); 
    1415         flags = other.flags; 
    1416         user= other.user; 
    1417         if (id > 0 && other.changesetId > 0) { 
    1418             // #4208: sometimes we cloned from other with id < 0 *and* 
    1419             // an assigned changeset id. Don't know why yet. For primitives 
    1420             // with id < 0 we don't propagate the changeset id any more. 
    1421             // 
    1422             setChangesetId(other.changesetId); 
    1423         } 
     926 
     927        super.cloneFrom(other); 
    1424928        clearCachedStyle(); 
    1425929    } 
     
    15871091    } 
    15881092 
    1589  
    15901093    public abstract BBox getBBox(); 
    15911094 
     
    15991102     *---------------*/ 
    16001103 
     1104    @Override 
    16011105    protected String getFlagsAsString() { 
    1602         StringBuilder builder = new StringBuilder(); 
    1603  
    1604         if (isIncomplete()) { 
    1605             builder.append("I"); 
    1606         } 
    1607         if (isModified()) { 
    1608             builder.append("M"); 
    1609         } 
    1610         if (isVisible()) { 
    1611             builder.append("V"); 
    1612         } 
    1613         if (isDeleted()) { 
    1614             builder.append("D"); 
    1615         } 
     1106        StringBuilder builder = new StringBuilder(super.getFlagsAsString()); 
     1107 
    16161108        if (isDisabled()) { 
    16171109            if (isDisabledAndHidden()) { 
  • trunk/src/org/openstreetmap/josm/data/osm/PrimitiveData.java

    r4098 r4099  
    22package org.openstreetmap.josm.data.osm; 
    33 
    4 import static org.openstreetmap.josm.tools.I18n.tr; 
    5  
    64import java.util.ArrayList; 
    75import java.util.Collection; 
    8 import java.util.Date; 
    9 import java.util.HashMap; 
    106import java.util.List; 
    117import java.util.Map; 
     
    1814 * 
    1915 */ 
    20 public abstract class PrimitiveData implements IPrimitive { 
    21  
    22     // Useful? 
    23     //private boolean disabled; 
    24     //private boolean filtered; 
    25     //private boolean selected; 
    26     //private boolean highlighted; 
     16public abstract class PrimitiveData extends AbstractPrimitive { 
    2717 
    2818    public PrimitiveData() { 
     
    3121 
    3222    public PrimitiveData(PrimitiveData data) { 
    33         this.keys.putAll(data.keys); 
    34         this.modified = data.modified; 
    35         this.visible = data.visible; 
    36         this.deleted = data.deleted; 
    37         this.id = data.id; 
    38         this.user = data.user; 
    39         this.version = data.version; 
    40         this.timestamp = data.timestamp; 
    41         this.incomplete = data.incomplete; 
     23        cloneFrom(data); 
    4224    } 
    4325 
    44     private final Map<String, String> keys = new HashMap<String, String>(); 
    45     private boolean modified; 
    46     private boolean visible = true; 
    47     private boolean deleted; 
    48     private boolean incomplete; 
    49     private long id; 
    50     private User user; 
    51     private int version; 
    52     private Date timestamp = new Date(); 
    53     private int changesetId; 
    54  
    55     @Override 
    56     public boolean isModified() { 
    57         return modified; 
    58     } 
    59     @Override 
    60     public void setModified(boolean modified) { 
    61         this.modified = modified; 
    62     } 
    63     @Override 
    64     public boolean isVisible() { 
    65         return visible; 
    66     } 
    67     @Override 
    68     public void setVisible(boolean visible) { 
    69         this.visible = visible; 
    70     } 
    71     @Override 
    72     public boolean isDeleted() { 
    73         return deleted; 
    74     } 
    75     @Override 
    76     public void setDeleted(boolean deleted) { 
    77         this.deleted = deleted; 
    78     } 
    79     @Override 
    80     public long getId() { 
    81         return id > 0 ? id : 0; 
    82     } 
    8326    public void setId(long id) { 
    8427        this.id = id; 
    8528    } 
    86     @Override 
    87     public User getUser() { 
    88         return user; 
    89     } 
    90     @Override 
    91     public void setUser(User user) { 
    92         this.user = user; 
    93     } 
    94     @Override 
    95     public int getVersion() { 
    96         return version; 
    97     } 
     29     
    9830    public void setVersion(int version) { 
    9931        this.version = version; 
    10032    } 
     33     
     34    /** 
     35     * override to make it public 
     36     */ 
    10137    @Override 
    102     public void setOsmId(long id, int version) { 
    103         if (id <= 0) 
    104             throw new IllegalArgumentException(tr("ID > 0 expected. Got {0}.", id)); 
    105         if (version <= 0) 
    106             throw new IllegalArgumentException(tr("Version > 0 expected. Got {0}.", version)); 
    107         this.id = id; 
    108         this.version = version; 
    109         this.setIncomplete(false); 
    110     } 
    111     @Override 
    112     public Date getTimestamp() { 
    113         return timestamp; 
    114     } 
    115     @Override 
    116     public void setTimestamp(Date timestamp) { 
    117         this.timestamp = timestamp; 
    118     } 
    119     @Override 
    120     public boolean isTimestampEmpty() { 
    121         return timestamp == null || timestamp.getTime() == 0; 
    122     } 
    123  
    124     @Override 
    125     public int getChangesetId() { 
    126         return changesetId; 
    127     } 
    128  
    129     @Override 
    130     public void setChangesetId(int changesetId) { 
    131         this.changesetId = changesetId; 
    132     } 
    133  
    134     @Override 
    135     public Map<String, String> getKeys() { 
    136         return keys; 
    137     } 
    138     @Override 
    139     public boolean isIncomplete() { 
    140         return incomplete; 
    141     } 
    14238    public void setIncomplete(boolean incomplete) { 
    143         this.incomplete = incomplete; 
    144     } 
    145  
    146     public void clearOsmId() { 
    147         id = OsmPrimitive.generateUniqueId(); 
     39        super.setIncomplete(incomplete); 
    14840    } 
    14941 
     
    15345    public String toString() { 
    15446        StringBuilder builder = new StringBuilder(); 
    155  
    156         builder.append(id).append(keys); 
    157         if (modified) { 
    158             builder.append("M"); 
    159         } 
    160         if (visible) { 
    161             builder.append("V"); 
    162         } 
    163         if (deleted) { 
    164             builder.append("D"); 
    165         } 
    166         if (incomplete) { 
    167             builder.append("I"); 
    168         } 
    169  
     47        builder.append(id).append(keys).append(getFlagsAsString()); 
    17048        return builder.toString(); 
    17149    } 
    17250 
    173     // Tagged implementation 
    174  
    175     @Override 
    176     public String get(String key) { 
    177         return keys.get(key); 
    178     } 
    179  
    180     @Override 
    181     public boolean hasKeys() { 
    182         return !keys.isEmpty(); 
    183     } 
    184  
    185     @Override 
    186     public Collection<String> keySet() { 
    187         return keys.keySet(); 
    188     } 
    189  
    190     @Override 
    191     public void put(String key, String value) { 
    192         keys.put(key, value); 
    193     } 
    194  
    195     @Override 
    196     public void remove(String key) { 
    197         keys.remove(key); 
    198     } 
    199  
    200     @Override 
    201     public void removeAll() { 
    202         keys.clear(); 
    203     } 
    204  
    205     @Override 
    206     public void setKeys(Map<String, String> keys) { 
    207         this.keys.clear(); 
    208         this.keys.putAll(keys); 
    209     } 
    210  
    21151    @SuppressWarnings("unchecked") 
    212     static public <T extends PrimitiveData>  List<T> getFilteredList(Collection<T> list, OsmPrimitiveType type) { 
     52    static public <T extends PrimitiveData> List<T> getFilteredList(Collection<T> list, OsmPrimitiveType type) { 
    21353        List<T> ret = new ArrayList<T>(); 
    21454        for(PrimitiveData p: list) { 
     
    22060    } 
    22161 
    222     protected void setKeysAsList(String... keys) { 
    223         assert keys.length % 2 == 0; 
    224         for (int i=0; i<keys.length/2; i++) { 
    225             this.keys.put(keys[i * 2], keys[i * 2 + 1]); 
    226         } 
    227     } 
    228  
    229     /** 
    230      * PrimitiveId implementation. Returns the same value as getId() 
    231      */ 
    23262    @Override 
    233     public long getUniqueId() { 
    234         return id; 
    235     } 
    236  
    237     /** 
    238      * Returns a PrimitiveId object for this primitive 
    239      * 
    240      * @return the PrimitiveId for this primitive 
    241      */ 
    242     public PrimitiveId getPrimitiveId() { 
    243         return new SimplePrimitiveId(getUniqueId(), getType()); 
    244     } 
    245  
    246     @Override 
    247     public boolean isNew() { 
    248         return id <= 0; 
     63    protected final void keysChangedImpl(Map<String, String> originalKeys) { 
    24964    } 
    25065 
Note: See TracChangeset for help on using the changeset viewer.