001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data; 003 004import java.awt.geom.Area; 005import java.awt.geom.Path2D; 006import java.util.Collection; 007import java.util.List; 008import java.util.Objects; 009import java.util.stream.Collectors; 010 011import org.openstreetmap.josm.tools.CheckParameterUtil; 012import org.openstreetmap.josm.tools.Utils; 013 014/** 015 * A data source, defined by bounds and textual description for the origin. 016 * @since 247 (creation) 017 * @since 7575 (moved package) 018 */ 019public class DataSource { 020 021 /** 022 * The bounds of this data source 023 */ 024 public final Bounds bounds; 025 026 /** 027 * The textual description of the origin (example: "OpenStreetMap Server") 028 */ 029 public final String origin; 030 031 /** 032 * Constructs a new {@code DataSource}. 033 * @param bounds The bounds of this data source 034 * @param origin The textual description of the origin (example: "OpenStreetMap Server") 035 * @throws IllegalArgumentException if bounds is {@code null} 036 */ 037 public DataSource(Bounds bounds, String origin) { 038 CheckParameterUtil.ensureParameterNotNull(bounds, "bounds"); 039 this.bounds = bounds; 040 this.origin = origin; 041 } 042 043 /** 044 * Constructs a new {@link DataSource} 045 * @param source The source to copy the data from. 046 * @since 10346 047 */ 048 public DataSource(DataSource source) { 049 this(source.bounds, source.origin); 050 } 051 052 @Override 053 public int hashCode() { 054 return Objects.hash(bounds, origin); 055 } 056 057 @Override 058 public boolean equals(Object obj) { 059 if (this == obj) return true; 060 if (obj == null || getClass() != obj.getClass()) return false; 061 DataSource that = (DataSource) obj; 062 return Objects.equals(bounds, that.bounds) && 063 Objects.equals(origin, that.origin); 064 } 065 066 @Override 067 public String toString() { 068 return "DataSource [bounds=" + bounds + ", origin=" + origin + ']'; 069 } 070 071 /** 072 * Returns the total area of downloaded data (the "yellow rectangles"). 073 * @param dataSources list of data sources 074 * @return Area object encompassing downloaded data. 075 * @see Data#getDataSourceArea() 076 */ 077 public static Area getDataSourceArea(Collection<DataSource> dataSources) { 078 if (Utils.isEmpty(dataSources)) { 079 return null; 080 } 081 Path2D.Double p = new Path2D.Double(); 082 for (DataSource source : dataSources) { 083 // create area from data bounds 084 p.append(source.bounds.asRect(), false); 085 } 086 return new Area(p); 087 } 088 089 /** 090 * <p>Replies the list of data source bounds.</p> 091 * 092 * <p>Dataset maintains a list of data sources which have been merged into the 093 * data set. Each of these sources can optionally declare a bounding box of the 094 * data it supplied to the dataset.</p> 095 * 096 * <p>This method replies the list of defined (non {@code null}) bounding boxes.</p> 097 * @param dataSources list of data sources 098 * 099 * @return the list of data source bounds. An empty list, if no non-null data source 100 * bounds are defined. 101 * @see Data#getDataSourceBounds() 102 */ 103 public static List<Bounds> getDataSourceBounds(Collection<DataSource> dataSources) { 104 if (dataSources == null) { 105 return null; 106 } 107 return dataSources.stream() 108 .filter(ds -> ds.bounds != null).map(ds -> ds.bounds) 109 .collect(Collectors.toList()); 110 } 111}