Changeset 10006 in josm


Ignore:
Timestamp:
2016-03-18T00:41:42+01:00 (3 years ago)
Author:
Don-vip
Message:

fix #12639 - NPE in History Window for primitives with more than 100 versions

Location:
trunk
Files:
3 added
4 edited

Legend:

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

    r9371 r10006  
    180180    }
    181181
     182    /**
     183     * Returns the changeset for this history primitive.
     184     * @return the changeset for this history primitive
     185     */
    182186    public Changeset getChangeset() {
    183187        return changeset;
    184188    }
    185189
     190    /**
     191     * Sets the changeset for this history primitive.
     192     * @param changeset the changeset for this history primitive
     193     */
    186194    public void setChangeset(Changeset changeset) {
    187195        this.changeset = changeset;
  • trunk/src/org/openstreetmap/josm/gui/history/HistoryLoadTask.java

    r9078 r10006  
    77import java.awt.Component;
    88import java.io.IOException;
    9 import java.text.MessageFormat;
     9import java.util.ArrayList;
    1010import java.util.Collection;
    1111import java.util.HashSet;
     12import java.util.List;
    1213import java.util.Set;
    1314
    1415import org.openstreetmap.josm.data.osm.Changeset;
    1516import org.openstreetmap.josm.data.osm.OsmPrimitive;
    16 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    1717import org.openstreetmap.josm.data.osm.PrimitiveId;
    18 import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
    1918import org.openstreetmap.josm.data.osm.history.History;
    2019import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
     
    2221import org.openstreetmap.josm.gui.ExceptionDialogUtil;
    2322import org.openstreetmap.josm.gui.PleaseWaitRunnable;
     23import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    2424import org.openstreetmap.josm.io.ChangesetQuery;
    2525import org.openstreetmap.josm.io.OsmServerChangesetReader;
     
    3030
    3131/**
    32  * Loads the object history of an collection of objects from the
    33  * server.
     32 * Loads the object history of a collection of objects from the server.
    3433 *
    3534 * It provides a fluent API for configuration.
     
    3837 *
    3938 * <pre>
    40  *   HistoryLoadTask task  = new HistoryLoadTask()
    41  *      .add(1, OsmPrimitiveType.NODE)
    42  *      .add(1233, OsmPrimitiveType.WAY)
    43  *      .add(37234, OsmPrimitveType.RELATION)
     39 *   HistoryLoadTask task = new HistoryLoadTask()
     40 *      .add(node)
     41 *      .add(way)
     42 *      .add(relation)
    4443 *      .add(aHistoryItem);
    4544 *
    4645 *   Main.worker.execute(task);
    47  *
    4846 * </pre>
    4947 */
     
    5250    private boolean canceled;
    5351    private Exception lastException;
    54     private final Set<PrimitiveId> toLoad;
     52    private final Set<PrimitiveId> toLoad = new HashSet<>();
    5553    private HistoryDataSet loadedData;
    5654    private OsmServerHistoryReader reader;
     
    6159    public HistoryLoadTask() {
    6260        super(tr("Load history"), true);
    63         toLoad = new HashSet<>();
    6461    }
    6562
     
    7572        super(parent, tr("Load history"), true);
    7673        CheckParameterUtil.ensureParameterNotNull(parent, "parent");
    77         toLoad = new HashSet<>();
    78     }
    79 
    80     /**
    81      * Adds an object whose history is to be loaded.
    82      *
    83      * @param id the object id
    84      * @param type the object type
    85      * @return this task
    86      */
    87     public HistoryLoadTask add(long id, OsmPrimitiveType type) {
    88         if (id <= 0)
    89             throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' > 0 expected. Got {1}.", "id", id));
    90         CheckParameterUtil.ensureParameterNotNull(type, "type");
    91         SimplePrimitiveId pid = new SimplePrimitiveId(id, type);
    92         toLoad.add(pid);
    93         return this;
    9474    }
    9575
     
    11595    public HistoryLoadTask add(HistoryOsmPrimitive primitive) {
    11696        CheckParameterUtil.ensureParameterNotNull(primitive, "primitive");
    117         toLoad.add(primitive.getPrimitiveId());
    118         return this;
     97        return add(primitive.getPrimitiveId());
    11998    }
    12099
     
    128107    public HistoryLoadTask add(History history) {
    129108        CheckParameterUtil.ensureParameterNotNull(history, "history");
    130         toLoad.add(history.getPrimitiveId());
    131         return this;
     109        return add(history.getPrimitiveId());
    132110    }
    133111
     
    142120    public HistoryLoadTask add(OsmPrimitive primitive) {
    143121        CheckParameterUtil.ensureValidPrimitiveId(primitive, "primitive");
    144         toLoad.add(primitive.getPrimitiveId());
    145         return this;
     122        return add(primitive.getPrimitiveId());
    146123    }
    147124
     
    194171                    break;
    195172                }
    196                 String msg = "";
    197                 switch(pid.getType()) {
    198                 case NODE: msg = marktr("Loading history for node {0}"); break;
    199                 case WAY: msg = marktr("Loading history for way {0}"); break;
    200                 case RELATION: msg = marktr("Loading history for relation {0}"); break;
    201                 }
    202                 progressMonitor.indeterminateSubTask(tr(msg,
    203                         Long.toString(pid.getUniqueId())));
     173                String msg = getLoadingMessage(pid);
     174                progressMonitor.indeterminateSubTask(tr(msg, Long.toString(pid.getUniqueId())));
    204175                reader = null;
    205                 HistoryDataSet ds = null;
     176                HistoryDataSet ds;
    206177                try {
    207178                    reader = new OsmServerHistoryReader(pid.getType(), pid.getUniqueId());
    208                     ds = reader.parseHistory(progressMonitor.createSubTaskMonitor(1, false));
    209                     // load corresponding changesets (mostly for changeset comment)
    210                     for (final Changeset i : new OsmServerChangesetReader().queryChangesets(
    211                             new ChangesetQuery().forChangesetIds(ds.getChangesetIds()), progressMonitor.createSubTaskMonitor(1, false))) {
    212                         ds.putChangeset(i);
    213                     }
     179                    ds = loadHistory(reader, progressMonitor);
    214180                } catch (OsmTransferException e) {
    215181                    if (canceled)
     
    225191    }
    226192
     193    protected static HistoryDataSet loadHistory(OsmServerHistoryReader reader, ProgressMonitor progressMonitor) throws OsmTransferException {
     194        HistoryDataSet ds = reader.parseHistory(progressMonitor.createSubTaskMonitor(1, false));
     195        // load corresponding changesets (mostly for changeset comment)
     196        OsmServerChangesetReader changesetReader = new OsmServerChangesetReader();
     197        List<Long> changesetIds = new ArrayList<>(ds.getChangesetIds());
     198
     199        // query changesets 100 by 100 (OSM API limit)
     200        int n = ChangesetQuery.MAX_CHANGESETS_NUMBER;
     201        for (int i = 0; i < changesetIds.size(); i += n) {
     202            for (Changeset c : changesetReader.queryChangesets(
     203                    new ChangesetQuery().forChangesetIds(changesetIds.subList(i, Math.min(i + n, changesetIds.size()))),
     204                    progressMonitor.createSubTaskMonitor(1, false))) {
     205                ds.putChangeset(c);
     206            }
     207        }
     208
     209        return ds;
     210    }
     211
     212    protected static String getLoadingMessage(PrimitiveId pid) {
     213        switch (pid.getType()) {
     214        case NODE:
     215            return marktr("Loading history for node {0}");
     216        case WAY:
     217            return marktr("Loading history for way {0}");
     218        case RELATION:
     219            return marktr("Loading history for relation {0}");
     220        default:
     221            return "";
     222        }
     223    }
     224
     225    /**
     226     * Determines if this task has ben canceled.
     227     * @return {@code true} if this task has ben canceled
     228     */
    227229    public boolean isCanceled() {
    228230        return canceled;
    229231    }
    230232
     233    /**
     234     * Returns the last exception that occured during loading, if any.
     235     * @return the last exception that occured during loading, or {@code null}
     236     */
    231237    public Exception getLastException() {
    232238        return lastException;
  • trunk/src/org/openstreetmap/josm/io/ChangesetQuery.java

    r8840 r10006  
    1616import java.util.Map.Entry;
    1717
     18import org.openstreetmap.josm.Main;
    1819import org.openstreetmap.josm.data.Bounds;
    1920import org.openstreetmap.josm.data.coor.LatLon;
     
    2324
    2425public class ChangesetQuery {
     26
     27    /**
     28     * Maximum number of changesets returned by the OSM API call "/changesets?"
     29     */
     30    public static int MAX_CHANGESETS_NUMBER = 100;
    2531
    2632    /**
     
    234240    public ChangesetQuery forChangesetIds(Collection<Long> changesetIds) {
    235241        CheckParameterUtil.ensureParameterNotNull(changesetIds, "changesetIds");
     242        if (changesetIds.size() > MAX_CHANGESETS_NUMBER) {
     243            Main.warn("Changeset query built with more than " + MAX_CHANGESETS_NUMBER + " changeset ids (" + changesetIds.size() + ")");
     244        }
    236245        this.changesetIds = changesetIds;
    237246        return this;
  • trunk/src/org/openstreetmap/josm/io/OsmServerChangesetReader.java

    r8540 r10006  
    7373            try (InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true))) {
    7474                if (in == null)
    75                     return null;
     75                    return Collections.emptyList();
    7676                monitor.indeterminateSubTask(tr("Downloading changesets ..."));
    7777                result = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true));
Note: See TracChangeset for help on using the changeset viewer.