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