// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.io; import static org.openstreetmap.josm.tools.I18n.tr; import java.text.DateFormat; import java.text.MessageFormat; import java.text.ParseException; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.stream.Collectors; import java.util.stream.Stream; import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.UserIdentityManager; import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.tools.CheckParameterUtil; import org.openstreetmap.josm.tools.Logging; import org.openstreetmap.josm.tools.Utils; import org.openstreetmap.josm.tools.date.DateUtils; /** * Data class to collect restrictions (parameters) for downloading changesets from the * OSM API. *
* @see OSM API 0.6 call "/changesets?"
*/
public class ChangesetQuery {
/**
* Maximum number of changesets returned by the OSM API call "/changesets?"
*/
public static final int MAX_CHANGESETS_NUMBER = 100;
/** the user id this query is restricted to. null, if no restriction to a user id applies */
private Integer uid;
/** the user name this query is restricted to. null, if no restriction to a user name applies */
private String userName;
/** the bounding box this query is restricted to. null, if no restriction to a bounding box applies */
private Bounds bounds;
private Date closedAfter;
private Date createdBefore;
/** indicates whether only open changesets are queried. null, if no restrictions regarding open changesets apply */
private Boolean open;
/** indicates whether only closed changesets are queried. null, if no restrictions regarding open changesets apply */
private Boolean closed;
/** a collection of changeset ids to query for */
private Collectionuid
.
*
* @param uid the uid of the user. > 0 expected.
* @return the query object with the applied restriction
* @throws IllegalArgumentException if uid <= 0
* @see #forUser(String)
*/
public ChangesetQuery forUser(int uid) {
if (uid <= 0)
throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' > 0 expected. Got ''{1}''.", "uid", uid));
this.uid = uid;
this.userName = null;
return this;
}
/**
* Restricts the query to changesets owned by the user with user name username
.
*
* Caveat: for historical reasons the username might not be unique! It is recommended to use
* {@link #forUser(int)} to restrict the query to a specific user.
*
* @param username the username. Must not be null.
* @return the query object with the applied restriction
* @throws IllegalArgumentException if username is null.
* @see #forUser(int)
*/
public ChangesetQuery forUser(String username) {
CheckParameterUtil.ensureParameterNotNull(username, "username");
this.userName = username;
this.uid = null;
return this;
}
/**
* Replies true if this query is restricted to user whom we only know the user name for.
*
* @return true if this query is restricted to user whom we only know the user name for
*/
public boolean isRestrictedToPartiallyIdentifiedUser() {
return userName != null;
}
/**
* Replies the user name which this query is restricted to. null, if this query isn't
* restricted to a user name, i.e. if {@link #isRestrictedToPartiallyIdentifiedUser()} is false.
*
* @return the user name which this query is restricted to
*/
public String getUserName() {
return userName;
}
/**
* Replies true if this query is restricted to user whom know the user id for.
*
* @return true if this query is restricted to user whom know the user id for
*/
public boolean isRestrictedToFullyIdentifiedUser() {
return uid > 0;
}
/**
* Replies a query which is restricted to a bounding box.
*
* @param minLon min longitude of the bounding box. Valid longitude value expected.
* @param minLat min latitude of the bounding box. Valid latitude value expected.
* @param maxLon max longitude of the bounding box. Valid longitude value expected.
* @param maxLat max latitude of the bounding box. Valid latitude value expected.
*
* @return the restricted changeset query
* @throws IllegalArgumentException if either of the parameters isn't a valid longitude or
* latitude value
*/
public ChangesetQuery inBbox(double minLon, double minLat, double maxLon, double maxLat) {
if (!LatLon.isValidLon(minLon))
throw new IllegalArgumentException(tr("Illegal longitude value for parameter ''{0}'', got {1}", "minLon", minLon));
if (!LatLon.isValidLon(maxLon))
throw new IllegalArgumentException(tr("Illegal longitude value for parameter ''{0}'', got {1}", "maxLon", maxLon));
if (!LatLon.isValidLat(minLat))
throw new IllegalArgumentException(tr("Illegal latitude value for parameter ''{0}'', got {1}", "minLat", minLat));
if (!LatLon.isValidLat(maxLat))
throw new IllegalArgumentException(tr("Illegal longitude value for parameter ''{0}'', got {1}", "maxLat", maxLat));
return inBbox(new LatLon(minLon, minLat), new LatLon(maxLon, maxLat));
}
/**
* Replies a query which is restricted to a bounding box.
*
* @param min the min lat/lon coordinates of the bounding box. Must not be null.
* @param max the max lat/lon coordiantes of the bounding box. Must not be null.
*
* @return the restricted changeset query
* @throws IllegalArgumentException if min is null
* @throws IllegalArgumentException if max is null
*/
public ChangesetQuery inBbox(LatLon min, LatLon max) {
CheckParameterUtil.ensureParameterNotNull(min, "min");
CheckParameterUtil.ensureParameterNotNull(max, "max");
this.bounds = new Bounds(min, max);
return this;
}
/**
* Replies a query which is restricted to a bounding box given by bbox
.
*
* @param bbox the bounding box. Must not be null.
* @return the changeset query
* @throws IllegalArgumentException if bbox is null.
*/
public ChangesetQuery inBbox(Bounds bbox) {
CheckParameterUtil.ensureParameterNotNull(bbox, "bbox");
this.bounds = bbox;
return this;
}
/**
* Restricts the result to changesets which have been closed after the date given by d
.
* d
d is a date relative to the current time zone.
*
* @param d the date . Must not be null.
* @return the restricted changeset query
* @throws IllegalArgumentException if d is null
*/
public ChangesetQuery closedAfter(Date d) {
CheckParameterUtil.ensureParameterNotNull(d, "d");
this.closedAfter = DateUtils.cloneDate(d);
return this;
}
/**
* Restricts the result to changesets which have been closed after closedAfter
and which
* habe been created before createdBefore
. Both dates are expressed relative to the current
* time zone.
*
* @param closedAfter only reply changesets closed after this date. Must not be null.
* @param createdBefore only reply changesets created before this date. Must not be null.
* @return the restricted changeset query
* @throws IllegalArgumentException if closedAfter is null
* @throws IllegalArgumentException if createdBefore is null
*/
public ChangesetQuery closedAfterAndCreatedBefore(Date closedAfter, Date createdBefore) {
CheckParameterUtil.ensureParameterNotNull(closedAfter, "closedAfter");
CheckParameterUtil.ensureParameterNotNull(createdBefore, "createdBefore");
this.closedAfter = DateUtils.cloneDate(closedAfter);
this.createdBefore = DateUtils.cloneDate(createdBefore);
return this;
}
/**
* Restricts the result to changesets which are or aren't open, depending on the value of
* isOpen
*
* @param isOpen whether changesets should or should not be open
* @return the restricted changeset query
*/
public ChangesetQuery beingOpen(boolean isOpen) {
this.open = isOpen;
return this;
}
/**
* Restricts the result to changesets which are or aren't closed, depending on the value of
* isClosed
*
* @param isClosed whether changesets should or should not be open
* @return the restricted changeset query
*/
public ChangesetQuery beingClosed(boolean isClosed) {
this.closed = isClosed;
return this;
}
/**
* Restricts the query to the given changeset ids (which are added to previously added ones).
*
* @param changesetIds the changeset ids
* @return the query object with the applied restriction
* @throws IllegalArgumentException if changesetIds is null.
*/
public ChangesetQuery forChangesetIds(Collectionquery
is the query part of a API url for querying changesets,
* see OSM API.
*
* Example for an query string:
*
* uid=1234&open=true
*
*
* @param query the query string. If null, an empty query (identical to a query for all changesets) is assumed
* @return the changeset query
* @throws ChangesetQueryUrlException if the query string doesn't represent a legal query for changesets
*/
public ChangesetQuery parse(String query) throws ChangesetQueryUrlException {
if (query == null)
return new ChangesetQuery();
String apiQuery = query.trim();
if (apiQuery.isEmpty())
return new ChangesetQuery();
return createFromMap(createMapFromQueryString(apiQuery));
}
}
}