Changeset 4099 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2011-05-29T20:26:54+02:00 (14 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.