1 | // License: GPL. Copyright 2007 by Immanuel Scholz and others
|
---|
2 | package org.openstreetmap.josm.data.osm;
|
---|
3 |
|
---|
4 | import java.awt.geom.Area;
|
---|
5 | import java.util.Arrays;
|
---|
6 | import java.util.Collection;
|
---|
7 | import java.util.Comparator;
|
---|
8 | import java.util.HashSet;
|
---|
9 | import java.util.HashMap;
|
---|
10 | import java.util.LinkedList;
|
---|
11 | import java.util.List;
|
---|
12 |
|
---|
13 | import org.openstreetmap.josm.data.SelectionChangedListener;
|
---|
14 |
|
---|
15 | /**
|
---|
16 | * DataSet is the data behind the application. It can consists of only a few points up to the whole
|
---|
17 | * osm database. DataSet's can be merged together, saved, (up/down/disk)loaded etc.
|
---|
18 | *
|
---|
19 | * Note that DataSet is not an osm-primitive and so has no key association but a few members to
|
---|
20 | * store some information.
|
---|
21 | *
|
---|
22 | * @author imi
|
---|
23 | */
|
---|
24 | public class DataSet implements Cloneable {
|
---|
25 |
|
---|
26 | /**
|
---|
27 | * The API version that created this data set, if any.
|
---|
28 | */
|
---|
29 | public String version;
|
---|
30 |
|
---|
31 | /**
|
---|
32 | * All nodes goes here, even when included in other data (ways etc). This enables the instant
|
---|
33 | * conversion of the whole DataSet by iterating over this data structure.
|
---|
34 | */
|
---|
35 | public Collection<Node> nodes = new LinkedList<Node>();
|
---|
36 |
|
---|
37 | /**
|
---|
38 | * All ways (Streets etc.) in the DataSet.
|
---|
39 | *
|
---|
40 | * The way nodes are stored only in the way list.
|
---|
41 | */
|
---|
42 | public Collection<Way> ways = new LinkedList<Way>();
|
---|
43 |
|
---|
44 | /**
|
---|
45 | * All relations/relationships
|
---|
46 | */
|
---|
47 | public Collection<Relation> relations = new LinkedList<Relation>();
|
---|
48 |
|
---|
49 | /**
|
---|
50 | * All data sources of this DataSet.
|
---|
51 | */
|
---|
52 | public Collection<DataSource> dataSources = new LinkedList<DataSource>();
|
---|
53 |
|
---|
54 | /**
|
---|
55 | * A list of listeners to selection changed events. The list is static, as listeners register
|
---|
56 | * themselves for any dataset selection changes that occur, regardless of the current active
|
---|
57 | * dataset. (However, the selection does only change in the active layer)
|
---|
58 | */
|
---|
59 | public static Collection<SelectionChangedListener> selListeners = new LinkedList<SelectionChangedListener>();
|
---|
60 |
|
---|
61 | /**
|
---|
62 | * @return A collection containing all primitives of the dataset. The data is ordered after:
|
---|
63 | * first come nodes, then ways, then relations. Ordering in between the categories is not
|
---|
64 | * guaranteed.
|
---|
65 | */
|
---|
66 | public List<OsmPrimitive> allPrimitives() {
|
---|
67 | List<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
|
---|
68 | o.addAll(nodes);
|
---|
69 | o.addAll(ways);
|
---|
70 | o.addAll(relations);
|
---|
71 | return o;
|
---|
72 | }
|
---|
73 |
|
---|
74 | /**
|
---|
75 | * @return A collection containing all not-deleted primitives (except keys).
|
---|
76 | */
|
---|
77 | public Collection<OsmPrimitive> allNonDeletedPrimitives() {
|
---|
78 | Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
|
---|
79 | for (OsmPrimitive osm : allPrimitives())
|
---|
80 | if (!osm.deleted)
|
---|
81 | o.add(osm);
|
---|
82 | return o;
|
---|
83 | }
|
---|
84 |
|
---|
85 | public Collection<OsmPrimitive> allNonDeletedCompletePrimitives() {
|
---|
86 | Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
|
---|
87 | for (OsmPrimitive osm : allPrimitives())
|
---|
88 | if (!osm.deleted && !osm.incomplete)
|
---|
89 | o.add(osm);
|
---|
90 | return o;
|
---|
91 | }
|
---|
92 |
|
---|
93 | public Collection<OsmPrimitive> allNonDeletedPhysicalPrimitives() {
|
---|
94 | Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
|
---|
95 | for (OsmPrimitive osm : allPrimitives())
|
---|
96 | if (!osm.deleted && !osm.incomplete && !(osm instanceof Relation))
|
---|
97 | o.add(osm);
|
---|
98 | return o;
|
---|
99 | }
|
---|
100 |
|
---|
101 | public void addPrimitive(OsmPrimitive osm) {
|
---|
102 | if (osm instanceof Node) {
|
---|
103 | nodes.add((Node) osm);
|
---|
104 | } else if (osm instanceof Way) {
|
---|
105 | ways.add((Way) osm);
|
---|
106 | } else if (osm instanceof Relation) {
|
---|
107 | relations.add((Relation) osm);
|
---|
108 | }
|
---|
109 | }
|
---|
110 |
|
---|
111 | public Collection<OsmPrimitive> getSelectedNodesAndWays() {
|
---|
112 | Collection<OsmPrimitive> sel = getSelected(nodes);
|
---|
113 | sel.addAll(getSelected(ways));
|
---|
114 | return sel;
|
---|
115 | }
|
---|
116 | /**
|
---|
117 | * Return a list of all selected objects. Even keys are returned.
|
---|
118 | * @return List of all selected objects.
|
---|
119 | */
|
---|
120 | public Collection<OsmPrimitive> getSelected() {
|
---|
121 | Collection<OsmPrimitive> sel = getSelected(nodes);
|
---|
122 | sel.addAll(getSelected(ways));
|
---|
123 | sel.addAll(getSelected(relations));
|
---|
124 | return sel;
|
---|
125 | }
|
---|
126 |
|
---|
127 | /**
|
---|
128 | * Return selected nodes.
|
---|
129 | */
|
---|
130 | public Collection<OsmPrimitive> getSelectedNodes() {
|
---|
131 | return getSelected(nodes);
|
---|
132 | }
|
---|
133 |
|
---|
134 | /**
|
---|
135 | * Return selected ways.
|
---|
136 | */
|
---|
137 | public Collection<OsmPrimitive> getSelectedWays() {
|
---|
138 | return getSelected(ways);
|
---|
139 | }
|
---|
140 |
|
---|
141 | /**
|
---|
142 | * Return selected relations.
|
---|
143 | */
|
---|
144 | public Collection<OsmPrimitive> getSelectedRelations() {
|
---|
145 | return getSelected(relations);
|
---|
146 | }
|
---|
147 |
|
---|
148 | public void setSelected(Collection<? extends OsmPrimitive> selection) {
|
---|
149 | clearSelection(nodes);
|
---|
150 | clearSelection(ways);
|
---|
151 | clearSelection(relations);
|
---|
152 | for (OsmPrimitive osm : selection)
|
---|
153 | osm.selected = true;
|
---|
154 | fireSelectionChanged(selection);
|
---|
155 | }
|
---|
156 |
|
---|
157 | public void setSelected(OsmPrimitive... osm) {
|
---|
158 | if (osm.length == 1 && osm[0] == null) {
|
---|
159 | setSelected();
|
---|
160 | return;
|
---|
161 | }
|
---|
162 | clearSelection(nodes);
|
---|
163 | clearSelection(ways);
|
---|
164 | clearSelection(relations);
|
---|
165 | for (OsmPrimitive o : osm)
|
---|
166 | if (o != null)
|
---|
167 | o.selected = true;
|
---|
168 | fireSelectionChanged(Arrays.asList(osm));
|
---|
169 | }
|
---|
170 |
|
---|
171 | /**
|
---|
172 | * Remove the selection from every value in the collection.
|
---|
173 | * @param list The collection to remove the selection from.
|
---|
174 | */
|
---|
175 | private void clearSelection(Collection<? extends OsmPrimitive> list) {
|
---|
176 | if (list == null)
|
---|
177 | return;
|
---|
178 | for (OsmPrimitive osm : list)
|
---|
179 | osm.selected = false;
|
---|
180 | }
|
---|
181 |
|
---|
182 | /**
|
---|
183 | * Return all selected items in the collection.
|
---|
184 | * @param list The collection from which the selected items are returned.
|
---|
185 | */
|
---|
186 | private Collection<OsmPrimitive> getSelected(Collection<? extends OsmPrimitive> list) {
|
---|
187 | Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
|
---|
188 | if (list == null)
|
---|
189 | return sel;
|
---|
190 | for (OsmPrimitive osm : list)
|
---|
191 | if (osm.selected && !osm.deleted)
|
---|
192 | sel.add(osm);
|
---|
193 | return sel;
|
---|
194 | }
|
---|
195 |
|
---|
196 | /**
|
---|
197 | * Remember to fire an selection changed event. A call to this will not fire the event
|
---|
198 | * immediately. For more,
|
---|
199 | * @see SelectionChangedListener
|
---|
200 | */
|
---|
201 | public static void fireSelectionChanged(Collection<? extends OsmPrimitive> sel) {
|
---|
202 | for (SelectionChangedListener l : selListeners)
|
---|
203 | l.selectionChanged(sel);
|
---|
204 | }
|
---|
205 |
|
---|
206 | @Override public DataSet clone() {
|
---|
207 | DataSet ds = new DataSet();
|
---|
208 | for (Node n : nodes)
|
---|
209 | ds.nodes.add(new Node(n));
|
---|
210 | for (Way w : ways)
|
---|
211 | ds.ways.add(new Way(w));
|
---|
212 | for (Relation e : relations)
|
---|
213 | ds.relations.add(new Relation(e));
|
---|
214 | for (DataSource source : dataSources)
|
---|
215 | ds.dataSources.add(new DataSource(source.bounds, source.origin));
|
---|
216 | ds.version = version;
|
---|
217 | return ds;
|
---|
218 | }
|
---|
219 |
|
---|
220 | /**
|
---|
221 | * Returns the total area of downloaded data (the "yellow rectangles").
|
---|
222 | * @return Area object encompassing downloaded data.
|
---|
223 | */
|
---|
224 | public Area getDataSourceArea() {
|
---|
225 | if (dataSources.isEmpty()) return null;
|
---|
226 | Area a = new Area();
|
---|
227 | for (DataSource source : dataSources) {
|
---|
228 | // create area from data bounds
|
---|
229 | a.add(new Area(source.bounds.asRect()));
|
---|
230 | }
|
---|
231 | return a;
|
---|
232 | }
|
---|
233 |
|
---|
234 | // Provide well-defined sorting for collections of OsmPrimitives.
|
---|
235 | // FIXME: probably not a good place to put this code.
|
---|
236 | public static OsmPrimitive[] sort(Collection<? extends OsmPrimitive> list) {
|
---|
237 | OsmPrimitive[] selArr = new OsmPrimitive[list.size()];
|
---|
238 | final HashMap<Object, String> h = new HashMap<Object, String>();
|
---|
239 | selArr = list.toArray(selArr);
|
---|
240 | Arrays.sort(selArr, new Comparator<OsmPrimitive>() {
|
---|
241 | public int compare(OsmPrimitive a, OsmPrimitive b) {
|
---|
242 | if (a.getClass() == b.getClass()) {
|
---|
243 | String as = h.get(a);
|
---|
244 | if (as == null) {
|
---|
245 | as = a.getName();
|
---|
246 | h.put(a, as);
|
---|
247 | }
|
---|
248 | String bs = h.get(b);
|
---|
249 | if (bs == null) {
|
---|
250 | bs = b.getName();
|
---|
251 | h.put(b, bs);
|
---|
252 | }
|
---|
253 | int res = as.compareTo(bs);
|
---|
254 | if (res != 0)
|
---|
255 | return res;
|
---|
256 | }
|
---|
257 | return a.compareTo(b);
|
---|
258 | }
|
---|
259 | });
|
---|
260 | return selArr;
|
---|
261 | }
|
---|
262 | }
|
---|