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


Ignore:
Timestamp:
2020-02-06T01:03:07+01:00 (5 years ago)
Author:
Don-vip
Message:

fix #18654 - Separate unique identifiers per primitive type

This allows to easily update .osm files with negative ids across multiple sessions, such as internal JOSM boundaries file.

Location:
trunk/src/org/openstreetmap/josm
Files:
1 added
11 edited

Legend:

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

    r15419 r15820  
    1818import java.util.Set;
    1919import java.util.concurrent.TimeUnit;
    20 import java.util.concurrent.atomic.AtomicLong;
    2120import java.util.function.BiPredicate;
    2221
     
    3130 */
    3231public abstract class AbstractPrimitive implements IPrimitive {
    33 
    34     private static final AtomicLong idCounter = new AtomicLong(0);
    35 
    36     /**
    37      * Generates a new primitive unique id.
    38      * @return new primitive unique (negative) id
    39      */
    40     static long generateUniqueId() {
    41         return idCounter.decrementAndGet();
    42     }
    43 
    44     /**
    45      * Returns the current primitive unique id.
    46      * @return the current primitive unique (negative) id (last generated)
    47      * @since 12536
    48      */
    49     public static long currentUniqueId() {
    50         return idCounter.get();
    51     }
    52 
    53     /**
    54      * Advances the current primitive unique id to skip a range of values.
    55      * @param newId new unique id
    56      * @throws IllegalArgumentException if newId is greater than current unique id
    57      * @since 12536
    58      */
    59     public static void advanceUniqueId(long newId) {
    60         if (newId > currentUniqueId()) {
    61             throw new IllegalArgumentException("Cannot modify the id counter backwards");
    62         }
    63         idCounter.set(newId);
    64     }
    6532
    6633    /**
     
    284251    public void clearOsmMetadata() {
    285252        // Not part of dataset - no lock necessary
    286         this.id = generateUniqueId();
     253        this.id = getIdGenerator().generateUniqueId();
    287254        this.version = 0;
    288255        this.user = null;
     
    293260        this.setVisible(true);
    294261    }
     262
     263    /**
     264     * Returns the unique identifier generator.
     265     * @return the unique identifier generator
     266     * @since 15820
     267     */
     268    public abstract UniqueIdGenerator getIdGenerator();
    295269
    296270    @Override
  • trunk/src/org/openstreetmap/josm/data/osm/Node.java

    r15449 r15820  
    2626 */
    2727public final class Node extends OsmPrimitive implements INode {
     28
     29    static final UniqueIdGenerator idGenerator = new UniqueIdGenerator();
    2830
    2931    /*
     
    423425        return false;
    424426    }
     427
     428    @Override
     429    public UniqueIdGenerator getIdGenerator() {
     430        return idGenerator;
     431    }
    425432}
  • trunk/src/org/openstreetmap/josm/data/osm/NodeData.java

    r14120 r15820  
    1313
    1414    private static final long serialVersionUID = 5626323599550908773L;
     15    private static final UniqueIdGenerator idGenerator = Node.idGenerator;
    1516    /*
    1617     * we "inline" lat/lon coordinates instead of using a LatLon => reduces memory footprint
     
    2425    public NodeData() {
    2526        // contents can be set later with setters
     27        this(idGenerator.generateUniqueId());
    2628    }
    2729
     
    109111        return false;
    110112    }
     113
     114    @Override
     115    public UniqueIdGenerator getIdGenerator() {
     116        return idGenerator;
     117    }
    111118}
  • trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r15588 r15820  
    112112                throw new IllegalArgumentException(MessageFormat.format("Expected ID >= 0. Got {0}.", id));
    113113            else if (id == 0) {
    114                 this.id = generateUniqueId();
     114                this.id = getIdGenerator().generateUniqueId();
    115115            } else {
    116116                this.id = id;
  • trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitiveType.java

    r13766 r15820  
    1616
    1717    /** Node type */
    18     NODE(marktr(/* ICON(data/) */"node"), Node.class, NodeData.class),
     18    NODE(marktr(/* ICON(data/) */"node"), Node.class, NodeData.class, Node.idGenerator),
    1919    /** Way type */
    20     WAY(marktr(/* ICON(data/) */"way"), Way.class, WayData.class),
     20    WAY(marktr(/* ICON(data/) */"way"), Way.class, WayData.class, Way.idGenerator),
    2121    /** Relation type */
    22     RELATION(marktr(/* ICON(data/) */"relation"), Relation.class, RelationData.class),
     22    RELATION(marktr(/* ICON(data/) */"relation"), Relation.class, RelationData.class, Relation.idGenerator),
    2323
    2424    /** Closed way: only for display, no real type */
    25     CLOSEDWAY(marktr(/* ICON(data/) */"closedway"), null, WayData.class),
     25    CLOSEDWAY(marktr(/* ICON(data/) */"closedway"), null, WayData.class, Way.idGenerator),
    2626    /** Multipolygon: only for display, no real type */
    27     MULTIPOLYGON(marktr(/* ICON(data/) */"multipolygon"), null, RelationData.class);
     27    MULTIPOLYGON(marktr(/* ICON(data/) */"multipolygon"), null, RelationData.class, Relation.idGenerator);
    2828
    2929    private static final Collection<OsmPrimitiveType> DATA_VALUES = Arrays.asList(NODE, WAY, RELATION);
     
    3232    private final Class<? extends OsmPrimitive> osmClass;
    3333    private final Class<? extends PrimitiveData> dataClass;
     34    private final UniqueIdGenerator idGenerator;
    3435
    35     OsmPrimitiveType(String apiTypeName, Class<? extends OsmPrimitive> osmClass, Class<? extends PrimitiveData> dataClass) {
     36    OsmPrimitiveType(String apiTypeName, Class<? extends OsmPrimitive> osmClass, Class<? extends PrimitiveData> dataClass,
     37            UniqueIdGenerator idGenerator) {
    3638        this.apiTypeName = apiTypeName;
    3739        this.osmClass = osmClass;
    3840        this.dataClass = dataClass;
     41        this.idGenerator = idGenerator;
    3942    }
    4043
     
    154157    }
    155158
     159    /**
     160     * Returns the unique identifier generator.
     161     * @return the unique identifier generator
     162     * @since 15820
     163     */
     164    public final UniqueIdGenerator getIdGenerator() {
     165        return idGenerator;
     166    }
     167
    156168    @Override
    157169    public String toString() {
  • trunk/src/org/openstreetmap/josm/data/osm/PrimitiveData.java

    r13808 r15820  
    2626
    2727    private static final long serialVersionUID = -1044837092478109138L;
    28 
    29     /**
    30      * Constructs a new {@code PrimitiveData}.
    31      */
    32     public PrimitiveData() {
    33         this(OsmPrimitive.generateUniqueId());
    34     }
    3528
    3629    /**
  • trunk/src/org/openstreetmap/josm/data/osm/Relation.java

    r15418 r15820  
    2828 */
    2929public final class Relation extends OsmPrimitive implements IRelation<RelationMember> {
     30
     31    static final UniqueIdGenerator idGenerator = new UniqueIdGenerator();
    3032
    3133    private RelationMember[] members = new RelationMember[0];
     
    550552                .map(m -> (OsmPrimitive) m).collect(Collectors.toList());
    551553    }
     554
     555    @Override
     556    public UniqueIdGenerator getIdGenerator() {
     557        return idGenerator;
     558    }
    552559}
  • trunk/src/org/openstreetmap/josm/data/osm/RelationData.java

    r13908 r15820  
    1414
    1515    private static final long serialVersionUID = 1163664954890478565L;
     16    private static final UniqueIdGenerator idGenerator = Relation.idGenerator;
    1617    private List<RelationMemberData> members = new ArrayList<>();
    1718
     
    2122    public RelationData() {
    2223        // contents can be set later with setters
     24        this(idGenerator.generateUniqueId());
    2325    }
    2426
     
    100102        throw new UnsupportedOperationException();
    101103    }
     104
     105    @Override
     106    public UniqueIdGenerator getIdGenerator() {
     107        return idGenerator;
     108    }
    102109}
  • trunk/src/org/openstreetmap/josm/data/osm/Way.java

    r15436 r15820  
    2828 */
    2929public final class Way extends OsmPrimitive implements IWay<Node> {
     30
     31    static final UniqueIdGenerator idGenerator = new UniqueIdGenerator();
    3032
    3133    /**
     
    749751        return angles;
    750752    }
     753
     754    @Override
     755    public UniqueIdGenerator getIdGenerator() {
     756        return idGenerator;
     757    }
    751758}
  • trunk/src/org/openstreetmap/josm/data/osm/WayData.java

    r13922 r15820  
    1414
    1515    private static final long serialVersionUID = 106944939313286415L;
     16    private static final UniqueIdGenerator idGenerator = Way.idGenerator;
    1617    private List<Long> nodes = new ArrayList<>();
    1718
     
    2122    public WayData() {
    2223        // contents can be set later with setters
     24        this(idGenerator.generateUniqueId());
    2325    }
    2426
     
    130132        throw new UnsupportedOperationException();
    131133    }
     134
     135    @Override
     136    public UniqueIdGenerator getIdGenerator() {
     137        return idGenerator;
     138    }
    132139}
  • trunk/src/org/openstreetmap/josm/io/AbstractReader.java

    r15783 r15820  
    326326            throw new IllegalDataException(e);
    327327        } finally {
    328             OptionalLong minId = externalIdMap.values().stream().mapToLong(AbstractPrimitive::getUniqueId).min();
    329             synchronized (AbstractPrimitive.class) {
    330                 if (minId.isPresent() && minId.getAsLong() < AbstractPrimitive.currentUniqueId()) {
    331                     AbstractPrimitive.advanceUniqueId(minId.getAsLong());
     328            for (OsmPrimitiveType dataType : OsmPrimitiveType.dataValues()) {
     329                OptionalLong minId = externalIdMap.entrySet().parallelStream()
     330                        .filter(e -> e.getKey().getType() == dataType)
     331                        .mapToLong(e -> e.getValue().getUniqueId()).min();
     332                synchronized (dataType.getDataClass()) {
     333                    if (minId.isPresent() && minId.getAsLong() < dataType.getIdGenerator().currentUniqueId()) {
     334                        dataType.getIdGenerator().advanceUniqueId(minId.getAsLong());
     335                    }
    332336                }
    333337            }
     
    615619    protected OsmPrimitive buildPrimitive(PrimitiveData pd) {
    616620        OsmPrimitive p;
    617         if (pd.getUniqueId() < AbstractPrimitive.currentUniqueId()) {
     621        if (pd.getUniqueId() < pd.getIdGenerator().currentUniqueId()) {
    618622            p = pd.getType().newInstance(pd.getUniqueId(), true);
    619             AbstractPrimitive.advanceUniqueId(pd.getUniqueId());
     623            pd.getIdGenerator().advanceUniqueId(pd.getUniqueId());
    620624        } else {
    621625            p = pd.getType().newVersionedInstance(pd.getId(), pd.getVersion());
     
    655659    protected final Node parseNode(String lat, String lon, CommonReader commonReader, NodeReader nodeReader)
    656660            throws IllegalDataException {
    657         NodeData nd = new NodeData();
     661        NodeData nd = new NodeData(0);
    658662        LatLon ll = null;
    659663        if (areLatLonDefined(lat, lon)) {
Note: See TracChangeset for help on using the changeset viewer.