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