001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005import static org.openstreetmap.josm.tools.I18n.trn; 006 007import java.io.IOException; 008import java.io.InputStream; 009import java.text.MessageFormat; 010import java.util.ArrayList; 011import java.util.Collection; 012import java.util.Collections; 013import java.util.List; 014 015import org.openstreetmap.josm.Main; 016import org.openstreetmap.josm.data.osm.Changeset; 017import org.openstreetmap.josm.data.osm.ChangesetDataSet; 018import org.openstreetmap.josm.data.osm.DataSet; 019import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 020import org.openstreetmap.josm.gui.progress.ProgressMonitor; 021import org.openstreetmap.josm.tools.CheckParameterUtil; 022import org.openstreetmap.josm.tools.XmlParsingException; 023 024/** 025 * Reads the history of an {@link org.openstreetmap.josm.data.osm.OsmPrimitive} from the OSM API server. 026 * 027 */ 028public class OsmServerChangesetReader extends OsmServerReader { 029 030 /** 031 * Constructs a new {@code OsmServerChangesetReader}. 032 */ 033 public OsmServerChangesetReader() { 034 setDoAuthenticate(false); 035 } 036 037 /** 038 * don't use - not implemented! 039 */ 040 @Override 041 public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException { 042 return null; 043 } 044 045 protected final InputStream getChangesetInputStream(long id, boolean includeDiscussion, ProgressMonitor monitor) 046 throws OsmTransferException { 047 StringBuilder sb = new StringBuilder(48).append("changeset/").append(id); 048 if (includeDiscussion) { 049 sb.append("?include_discussion=true"); 050 } 051 return getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true)); 052 } 053 054 /** 055 * Queries a list 056 * @param query the query specification. Must not be null. 057 * @param monitor a progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null 058 * @return the list of changesets read from the server 059 * @throws IllegalArgumentException if query is null 060 * @throws OsmTransferException if something goes wrong w 061 */ 062 public List<Changeset> queryChangesets(ChangesetQuery query, ProgressMonitor monitor) throws OsmTransferException { 063 CheckParameterUtil.ensureParameterNotNull(query, "query"); 064 List<Changeset> result = null; 065 if (monitor == null) { 066 monitor = NullProgressMonitor.INSTANCE; 067 } 068 try { 069 monitor.beginTask(tr("Reading changesets...")); 070 StringBuilder sb = new StringBuilder(); 071 sb.append("changesets?").append(query.getQueryString()); 072 try (InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true))) { 073 if (in == null) 074 return Collections.emptyList(); 075 monitor.indeterminateSubTask(tr("Downloading changesets ...")); 076 result = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true)); 077 } catch (IOException e) { 078 Main.warn(e); 079 } 080 } catch (OsmTransferException e) { 081 throw e; 082 } catch (IllegalDataException e) { 083 throw new OsmTransferException(e); 084 } finally { 085 monitor.finishTask(); 086 } 087 return result; 088 } 089 090 /** 091 * Reads the changeset with id <code>id</code> from the server. 092 * 093 * @param id the changeset id. id > 0 required. 094 * @param includeDiscussion determines if discussion comments must be downloaded or not 095 * @param monitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null 096 * @return the changeset read 097 * @throws OsmTransferException if something goes wrong 098 * @throws IllegalArgumentException if id <= 0 099 * @since 7704 100 */ 101 public Changeset readChangeset(long id, boolean includeDiscussion, ProgressMonitor monitor) throws OsmTransferException { 102 if (id <= 0) 103 throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' > 0 expected. Got ''{1}''.", "id", id)); 104 if (monitor == null) { 105 monitor = NullProgressMonitor.INSTANCE; 106 } 107 Changeset result = null; 108 try { 109 monitor.beginTask(tr("Reading changeset {0} ...", id)); 110 try (InputStream in = getChangesetInputStream(id, includeDiscussion, monitor)) { 111 if (in == null) 112 return null; 113 monitor.indeterminateSubTask(tr("Downloading changeset {0} ...", id)); 114 List<Changeset> changesets = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true)); 115 if (changesets == null || changesets.isEmpty()) 116 return null; 117 result = changesets.get(0); 118 } catch (IOException e) { 119 Main.warn(e); 120 } 121 } catch (OsmTransferException e) { 122 throw e; 123 } catch (IllegalDataException e) { 124 throw new OsmTransferException(e); 125 } finally { 126 monitor.finishTask(); 127 } 128 return result; 129 } 130 131 /** 132 * Reads the changesets with id <code>ids</code> from the server. 133 * 134 * @param ids the list of ids. Ignored if null. Only load changesets for ids > 0. 135 * @param includeDiscussion determines if discussion comments must be downloaded or not 136 * @param monitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null 137 * @return the changeset read 138 * @throws OsmTransferException if something goes wrong 139 * @throws IllegalArgumentException if id <= 0 140 * @since 7704 141 */ 142 public List<Changeset> readChangesets(Collection<Integer> ids, boolean includeDiscussion, ProgressMonitor monitor) 143 throws OsmTransferException { 144 if (ids == null) 145 return Collections.emptyList(); 146 if (monitor == null) { 147 monitor = NullProgressMonitor.INSTANCE; 148 } 149 try { 150 monitor.beginTask(trn("Downloading {0} changeset ...", "Downloading {0} changesets ...", ids.size(), ids.size())); 151 monitor.setTicksCount(ids.size()); 152 List<Changeset> ret = new ArrayList<>(); 153 int i = 0; 154 for (int id : ids) { 155 if (id <= 0) { 156 continue; 157 } 158 i++; 159 try (InputStream in = getChangesetInputStream(id, includeDiscussion, monitor)) { 160 if (in == null) 161 return null; 162 monitor.indeterminateSubTask(tr("({0}/{1}) Downloading changeset {2} ...", i, ids.size(), id)); 163 List<Changeset> changesets = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true)); 164 if (changesets == null || changesets.isEmpty()) { 165 continue; 166 } 167 ret.addAll(changesets); 168 } catch (IOException e) { 169 Main.warn(e); 170 } 171 monitor.worked(1); 172 } 173 return ret; 174 } catch (OsmTransferException e) { 175 throw e; 176 } catch (IllegalDataException e) { 177 throw new OsmTransferException(e); 178 } finally { 179 monitor.finishTask(); 180 } 181 } 182 183 /** 184 * Downloads the content of a changeset 185 * 186 * @param id the changeset id. > 0 required. 187 * @param monitor the progress monitor. {@link NullProgressMonitor#INSTANCE} assumed if null. 188 * @return the changeset content 189 * @throws IllegalArgumentException if id <= 0 190 * @throws OsmTransferException if something went wrong 191 */ 192 public ChangesetDataSet downloadChangeset(int id, ProgressMonitor monitor) throws OsmTransferException { 193 if (id <= 0) 194 throw new IllegalArgumentException( 195 MessageFormat.format("Expected value of type integer > 0 for parameter ''{0}'', got {1}", "id", id)); 196 if (monitor == null) { 197 monitor = NullProgressMonitor.INSTANCE; 198 } 199 ChangesetDataSet result = null; 200 try { 201 monitor.beginTask(tr("Downloading changeset content")); 202 StringBuilder sb = new StringBuilder(32).append("changeset/").append(id).append("/download"); 203 try (InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true))) { 204 if (in == null) 205 return null; 206 monitor.setCustomText(tr("Downloading content for changeset {0} ...", id)); 207 OsmChangesetContentParser parser = new OsmChangesetContentParser(in); 208 result = parser.parse(monitor.createSubTaskMonitor(1, true)); 209 } catch (IOException e) { 210 Main.warn(e); 211 } 212 } catch (XmlParsingException e) { 213 throw new OsmTransferException(e); 214 } finally { 215 monitor.finishTask(); 216 } 217 return result; 218 } 219}