001//License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.io.InputStream;
007import java.text.MessageFormat;
008
009import org.openstreetmap.josm.data.osm.DataSet;
010import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
011import org.openstreetmap.josm.data.osm.PrimitiveId;
012import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
013import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
014import org.openstreetmap.josm.gui.progress.ProgressMonitor;
015import org.openstreetmap.josm.tools.CheckParameterUtil;
016import org.openstreetmap.josm.tools.Utils;
017
018/**
019 * OsmServerObjectReader reads an individual object from the OSM server.
020 *
021 * It can either download the object including or not including its immediate children.
022 * The former case is called a "full download".
023 *
024 * It can also download a specific version of the object (however, "full" download is not possible
025 * in that case).
026 *
027 */
028public class OsmServerObjectReader extends OsmServerReader {
029    /** the id of the object to download */
030    private PrimitiveId id;
031    /** true if a full download is required, i.e. a download including the immediate children */
032    private boolean full;
033    /** the specific version number, if required (incompatible with full), or -1 else */
034    private int version;
035
036    /**
037     * Creates a new server object reader for a given id and a primitive type.
038     *
039     * @param id the object id. > 0 required.
040     * @param type the type. Must not be null.
041     * @param full true, if a full download is requested (i.e. a download including
042     * immediate children); false, otherwise
043     * @throws IllegalArgumentException thrown if id <= 0
044     * @throws IllegalArgumentException thrown if type is null
045     */
046    public OsmServerObjectReader(long id, OsmPrimitiveType type, boolean full) throws IllegalArgumentException {
047        this(id, type, full, -1);
048    }
049
050    /**
051     * Creates a new server object reader for a given id and a primitive type.
052     *
053     * @param id the object id. > 0 required.
054     * @param type the type. Must not be null.
055     * @param version the specific version number, if required; -1, otherwise
056     * @throws IllegalArgumentException thrown if id <= 0
057     * @throws IllegalArgumentException thrown if type is null
058     */
059    public OsmServerObjectReader(long id, OsmPrimitiveType type, int version) throws IllegalArgumentException {
060        this(id, type, false, version);
061    }
062
063    protected OsmServerObjectReader(long id, OsmPrimitiveType type, boolean full, int version) throws IllegalArgumentException {
064        if (id <= 0)
065            throw new IllegalArgumentException(MessageFormat.format("Expected value > 0 for parameter ''{0}'', got {1}", "id", id));
066        CheckParameterUtil.ensureParameterNotNull(type, "type");
067        this.id = new SimplePrimitiveId(id, type);
068        this.full = full;
069        this.version = version;
070    }
071
072    /**
073     * Creates a new server object reader for an object with the given <code>id</code>
074     *
075     * @param id the object id. Must not be null. Unique id > 0 required.
076     * @param full true, if a full download is requested (i.e. a download including
077     * immediate children); false, otherwise
078     * @throws IllegalArgumentException thrown if id is null
079     * @throws IllegalArgumentException thrown if id.getUniqueId() <= 0
080     */
081    public OsmServerObjectReader(PrimitiveId id, boolean full) {
082        this(id, full, -1);
083    }
084
085    /**
086     * Creates a new server object reader for an object with the given <code>id</code>
087     *
088     * @param id the object id. Must not be null. Unique id > 0 required.
089     * @param version the specific version number, if required; -1, otherwise
090     * @throws IllegalArgumentException thrown if id is null
091     * @throws IllegalArgumentException thrown if id.getUniqueId() <= 0
092     */
093    public OsmServerObjectReader(PrimitiveId id, int version) {
094        this(id, false, version);
095    }
096
097    protected OsmServerObjectReader(PrimitiveId id, boolean full, int version) {
098        CheckParameterUtil.ensureValidPrimitiveId(id, "id");
099        this.id = id;
100        this.full = full;
101        this.version = version;
102    }
103
104    /**
105     * Downloads and parses the data.
106     *
107     * @param progressMonitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if
108     * null
109     * @return the downloaded data
110     * @throws OsmTransferException
111     */
112    @Override
113    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
114        if (progressMonitor == null) {
115            progressMonitor = NullProgressMonitor.INSTANCE;
116        }
117        progressMonitor.beginTask("", 1);
118        InputStream in = null;
119        try {
120            progressMonitor.indeterminateSubTask(tr("Downloading OSM data..."));
121            StringBuffer sb = new StringBuffer();
122            sb.append(id.getType().getAPIName());
123            sb.append("/");
124            sb.append(id.getUniqueId());
125            if (full && ! id.getType().equals(OsmPrimitiveType.NODE)) {
126                sb.append("/full");
127            } else if (version > 0) {
128                sb.append("/").append(version);
129            }
130
131            in = getInputStream(sb.toString(), progressMonitor.createSubTaskMonitor(1, true));
132            if (in == null)
133                return null;
134            final DataSet data = OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
135            return data;
136        } catch(OsmTransferException e) {
137            if (cancel) return null;
138            throw e;
139        } catch (Exception e) {
140            if (cancel) return null;
141            throw new OsmTransferException(e);
142        } finally {
143            progressMonitor.finishTask();
144            Utils.close(in);
145            activeConnection = null;
146        }
147    }
148}