001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import java.util.ArrayList;
005import java.util.Collection;
006import java.util.List;
007import java.util.concurrent.locks.Lock;
008import java.util.function.Predicate;
009
010import org.openstreetmap.josm.data.Data;
011import org.openstreetmap.josm.data.DataSource;
012import org.openstreetmap.josm.data.ProjectionBounds;
013import org.openstreetmap.josm.data.osm.event.SelectionEventManager;
014import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
015import org.openstreetmap.josm.tools.SubclassFilteredCollection;
016
017/**
018 * Abstraction of {@link DataSet}.
019 * This class holds OSM data but does not rely on implementation types,
020 * allowing plugins to define their own representation of OSM data if needed.
021 * @param <O> the base type of OSM primitives
022 * @param <N> type representing OSM nodes
023 * @param <W> type representing OSM ways
024 * @param <R> type representing OSM relations
025 * @since 13764
026 */
027public interface OsmData<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> extends Data, Lockable {
028
029    // --------------
030    //    Metadata
031    // --------------
032
033    /**
034     * Replies the API version this dataset was created from. May be null.
035     * @return the API version this dataset was created from. May be null.
036     */
037    String getVersion();
038
039    /**
040     * Returns the name of this data set (optional).
041     * @return the name of this data set. Can be {@code null}
042     * @since 12718
043     */
044    String getName();
045
046    /**
047     * Sets the name of this data set.
048     * @param name the new name of this data set. Can be {@code null} to reset it
049     * @since 12718
050     */
051    void setName(String name);
052
053    // --------------------
054    //    OSM primitives
055    // --------------------
056
057    /**
058     * Adds a primitive.
059     * @param primitive the primitive
060     */
061    void addPrimitive(O primitive);
062
063    /**
064     * Removes all primitives.
065     */
066    void clear();
067
068    /**
069     * Searches for nodes in the given bounding box.
070     * @param bbox the bounding box
071     * @return List of nodes in the given bbox. Can be empty but not null
072     */
073    List<N> searchNodes(BBox bbox);
074
075    /**
076     * Determines if the given node can be retrieved in the data set through its bounding box. Useful for dataset consistency test.
077     * @param n The node to search
078     * @return {@code true} if {@code n} can be retrieved in this data set, {@code false} otherwise
079     */
080    boolean containsNode(N n);
081
082    /**
083     * Searches for ways in the given bounding box.
084     * @param bbox the bounding box
085     * @return List of ways in the given bbox. Can be empty but not null
086     */
087    List<W> searchWays(BBox bbox);
088
089    /**
090     * Determines if the given way can be retrieved in the data set through its bounding box. Useful for dataset consistency test.
091     * @param w The way to search
092     * @return {@code true} if {@code w} can be retrieved in this data set, {@code false} otherwise
093     */
094    boolean containsWay(W w);
095
096    /**
097     * Searches for relations in the given bounding box.
098     * @param bbox the bounding box
099     * @return List of relations in the given bbox. Can be empty but not null
100     */
101    List<R> searchRelations(BBox bbox);
102
103    /**
104     * Determines if the given relation can be retrieved in the data set through its bounding box. Useful for dataset consistency test.
105     * @param r The relation to search
106     * @return {@code true} if {@code r} can be retrieved in this data set, {@code false} otherwise
107     */
108    boolean containsRelation(R r);
109
110    /**
111     * Returns a primitive with a given id from the data set. null, if no such primitive exists
112     *
113     * @param id uniqueId of the primitive. Might be &lt; 0 for newly created primitives
114     * @param type the type of  the primitive. Must not be null.
115     * @return the primitive
116     * @throws NullPointerException if type is null
117     */
118    default O getPrimitiveById(long id, OsmPrimitiveType type) {
119        return getPrimitiveById(new SimplePrimitiveId(id, type));
120    }
121
122    /**
123     * Returns a primitive with a given id from the data set. null, if no such primitive exists
124     *
125     * @param primitiveId type and uniqueId of the primitive. Might be &lt; 0 for newly created primitives
126     * @return the primitive
127     */
128    O getPrimitiveById(PrimitiveId primitiveId);
129
130    /**
131     * Gets a filtered collection of primitives matching the given predicate.
132     * @param <T> The primitive type.
133     * @param predicate The predicate to match
134     * @return The list of primtives.
135     * @since 10590
136     */
137    <T extends O> Collection<T> getPrimitives(Predicate<? super O> predicate);
138
139    /**
140     * Replies an unmodifiable collection of nodes in this dataset
141     *
142     * @return an unmodifiable collection of nodes in this dataset
143     */
144    Collection<N> getNodes();
145
146    /**
147     * Replies an unmodifiable collection of ways in this dataset
148     *
149     * @return an unmodifiable collection of ways in this dataset
150     */
151    Collection<W> getWays();
152
153    /**
154     * Replies an unmodifiable collection of relations in this dataset
155     *
156     * @return an unmodifiable collection of relations in this dataset
157     */
158    Collection<R> getRelations();
159
160    /**
161     * Returns a collection containing all primitives of the dataset.
162     * @return A collection containing all primitives of the dataset. Data is not ordered
163     */
164    default Collection<O> allPrimitives() {
165        return getPrimitives(o -> true);
166    }
167
168    /**
169     * Returns a collection containing all not-deleted primitives.
170     * @return A collection containing all not-deleted primitives.
171     * @see OsmPrimitive#isDeleted
172     */
173    default Collection<O> allNonDeletedPrimitives() {
174        return getPrimitives(p -> !p.isDeleted());
175    }
176
177    /**
178     * Returns a collection containing all not-deleted complete primitives.
179     * @return A collection containing all not-deleted complete primitives.
180     * @see OsmPrimitive#isDeleted
181     * @see OsmPrimitive#isIncomplete
182     */
183    default Collection<O> allNonDeletedCompletePrimitives() {
184        return getPrimitives(primitive -> !primitive.isDeleted() && !primitive.isIncomplete());
185    }
186
187    /**
188     * Returns a collection containing all not-deleted complete physical primitives.
189     * @return A collection containing all not-deleted complete physical primitives (nodes and ways).
190     * @see OsmPrimitive#isDeleted
191     * @see OsmPrimitive#isIncomplete
192     */
193    default Collection<O> allNonDeletedPhysicalPrimitives() {
194        return getPrimitives(
195                primitive -> !primitive.isDeleted() && !primitive.isIncomplete() && !(primitive instanceof IRelation));
196    }
197
198    /**
199     * Returns a collection containing all modified primitives.
200     * @return A collection containing all modified primitives.
201     * @see OsmPrimitive#isModified
202     */
203    default Collection<O> allModifiedPrimitives() {
204        return getPrimitives(IPrimitive::isModified);
205    }
206
207    /**
208     * Returns a collection containing all primitives preserved from filtering.
209     * @return A collection containing all primitives preserved from filtering.
210     * @see OsmPrimitive#isPreserved
211     * @since 13309
212     */
213    default Collection<O> allPreservedPrimitives() {
214        return getPrimitives(IPrimitive::isPreserved);
215    }
216
217    // --------------
218    //    Policies
219    // --------------
220
221    /**
222     * Get the download policy.
223     * @return the download policy
224     * @see #setDownloadPolicy(DownloadPolicy)
225     * @since 13453
226     */
227    DownloadPolicy getDownloadPolicy();
228
229    /**
230     * Sets the download policy.
231     * @param downloadPolicy the download policy
232     * @see #getUploadPolicy()
233     * @since 13453
234     */
235    void setDownloadPolicy(DownloadPolicy downloadPolicy);
236
237    /**
238     * Get the upload policy.
239     * @return the upload policy
240     * @see #setUploadPolicy(UploadPolicy)
241     */
242    UploadPolicy getUploadPolicy();
243
244    /**
245     * Sets the upload policy.
246     * @param uploadPolicy the upload policy
247     * @see #getUploadPolicy()
248     */
249    void setUploadPolicy(UploadPolicy uploadPolicy);
250
251    // --------------
252    //    Locks
253    // --------------
254
255    /**
256     * Returns the lock used for reading.
257     * @return the lock used for reading
258     */
259    Lock getReadLock();
260
261    // ---------------
262    //    Highlight
263    // ---------------
264
265    /**
266     * Returns an unmodifiable collection of *WaySegments* whose virtual
267     * nodes should be highlighted. WaySegments are used to avoid having
268     * to create a VirtualNode class that wouldn't have much purpose otherwise.
269     *
270     * @return unmodifiable collection of WaySegments
271     */
272    Collection<WaySegment> getHighlightedVirtualNodes();
273
274    /**
275     * Returns an unmodifiable collection of WaySegments that should be highlighted.
276     *
277     * @return unmodifiable collection of WaySegments
278     */
279    Collection<WaySegment> getHighlightedWaySegments();
280
281    /**
282     * clear all highlights of virtual nodes
283     */
284    default void clearHighlightedVirtualNodes() {
285        setHighlightedVirtualNodes(new ArrayList<WaySegment>());
286    }
287
288    /**
289     * clear all highlights of way segments
290     */
291    default void clearHighlightedWaySegments() {
292        setHighlightedWaySegments(new ArrayList<WaySegment>());
293    }
294
295    /**
296     * set what virtual nodes should be highlighted. Requires a Collection of
297     * *WaySegments* to avoid a VirtualNode class that wouldn't have much use otherwise.
298     * @param waySegments Collection of way segments
299     */
300    void setHighlightedVirtualNodes(Collection<WaySegment> waySegments);
301
302    /**
303     * set what virtual ways should be highlighted.
304     * @param waySegments Collection of way segments
305     */
306    void setHighlightedWaySegments(Collection<WaySegment> waySegments);
307
308    /**
309     * Adds a listener that gets notified whenever way segment / virtual nodes highlights change.
310     * @param listener The Listener
311     * @since 12014
312     */
313    void addHighlightUpdateListener(HighlightUpdateListener listener);
314
315    /**
316     * Removes a listener that was added with {@link #addHighlightUpdateListener(HighlightUpdateListener)}
317     * @param listener The Listener
318     * @since 12014
319     */
320    void removeHighlightUpdateListener(HighlightUpdateListener listener);
321
322    // ---------------
323    //    Selection
324    // ---------------
325
326    /**
327     * Replies an unmodifiable collection of primitives currently selected
328     * in this dataset, except deleted ones. May be empty, but not null.
329     *
330     * When iterating through the set it is ordered by the order in which the primitives were added to the selection.
331     *
332     * @return unmodifiable collection of primitives
333     */
334    default Collection<O> getSelected() {
335        return new SubclassFilteredCollection<>(getAllSelected(), p -> !p.isDeleted());
336    }
337
338    /**
339     * Replies an unmodifiable collection of primitives currently selected
340     * in this dataset, including deleted ones. May be empty, but not null.
341     *
342     * When iterating through the set it is ordered by the order in which the primitives were added to the selection.
343     *
344     * @return unmodifiable collection of primitives
345     */
346    Collection<O> getAllSelected();
347
348    /**
349     * Returns selected nodes.
350     * @return selected nodes
351     */
352    default Collection<N> getSelectedNodes() {
353        return new SubclassFilteredCollection<>(getSelected(), Node.class::isInstance);
354    }
355
356    /**
357     * Returns selected ways.
358     * @return selected ways
359     */
360    default Collection<W> getSelectedWays() {
361        return new SubclassFilteredCollection<>(getSelected(), Way.class::isInstance);
362    }
363
364    /**
365     * Returns selected relations.
366     * @return selected relations
367     */
368    default Collection<R> getSelectedRelations() {
369        return new SubclassFilteredCollection<>(getSelected(), Relation.class::isInstance);
370    }
371
372    /**
373     * Determines whether the selection is empty or not
374     * @return whether the selection is empty or not
375     */
376    boolean selectionEmpty();
377
378    /**
379     * Determines whether the given primitive is selected or not
380     * @param osm the primitive
381     * @return whether {@code osm} is selected or not
382     */
383    boolean isSelected(O osm);
384
385    /**
386     * Toggles the selected state of the given collection of primitives.
387     * @param osm The primitives to toggle
388     */
389    void toggleSelected(Collection<? extends PrimitiveId> osm);
390
391    /**
392     * Toggles the selected state of the given collection of primitives.
393     * @param osm The primitives to toggle
394     */
395    void toggleSelected(PrimitiveId... osm);
396
397    /**
398     * Sets the current selection to the primitives in <code>selection</code>
399     * and notifies all {@link DataSelectionListener}.
400     *
401     * @param selection the selection
402     */
403    void setSelected(Collection<? extends PrimitiveId> selection);
404
405    /**
406     * Sets the current selection to the primitives in <code>osm</code>
407     * and notifies all {@link DataSelectionListener}.
408     *
409     * @param osm the primitives to set. <code>null</code> values are ignored for now, but this may be removed in the future.
410     */
411    void setSelected(PrimitiveId... osm);
412
413    /**
414     * Adds the primitives in <code>selection</code> to the current selection
415     * and notifies all {@link DataSelectionListener}.
416     *
417     * @param selection the selection
418     */
419    void addSelected(Collection<? extends PrimitiveId> selection);
420
421    /**
422     * Adds the primitives in <code>osm</code> to the current selection
423     * and notifies all {@link DataSelectionListener}.
424     *
425     * @param osm the primitives to add
426     */
427    void addSelected(PrimitiveId... osm);
428
429    /**
430     * Removes the selection from every value in the collection.
431     * @param osm The collection of ids to remove the selection from.
432     */
433    void clearSelection(PrimitiveId... osm);
434
435    /**
436     * Removes the selection from every value in the collection.
437     * @param list The collection of ids to remove the selection from.
438     */
439    void clearSelection(Collection<? extends PrimitiveId> list);
440
441    /**
442     * Clears the current selection.
443     */
444    void clearSelection();
445
446    /**
447     * Add a listener that listens to selection changes in this specific data set.
448     * @param listener The listener.
449     * @see #removeSelectionListener(DataSelectionListener)
450     * @see SelectionEventManager#addSelectionListener(DataSelectionListener)
451     *      To add a global listener.
452     */
453    void addSelectionListener(DataSelectionListener listener);
454
455    /**
456     * Remove a listener that listens to selection changes in this specific data set.
457     * @param listener The listener.
458     * @see #addSelectionListener(DataSelectionListener)
459     */
460    void removeSelectionListener(DataSelectionListener listener);
461
462    // -------------------
463    //    Miscellaneous
464    // -------------------
465
466    /**
467     * Returns the data sources bounding box.
468     * @return the data sources bounding box
469     */
470    default ProjectionBounds getDataSourceBoundingBox() {
471        BoundingXYVisitor bbox = new BoundingXYVisitor();
472        for (DataSource source : getDataSources()) {
473            bbox.visit(source.bounds);
474        }
475        if (bbox.hasExtend()) {
476            return bbox.getBounds();
477        }
478        return null;
479    }
480
481    /**
482     * Clear the mappaint cache for this DataSet.
483     * @since 13420
484     */
485    void clearMappaintCache();
486
487    /**
488     * Replies true if there is at least one primitive in this dataset with
489     * {@link IPrimitive#isModified()} == <code>true</code>.
490     *
491     * @return true if there is at least one primitive in this dataset with
492     * {@link IPrimitive#isModified()} == <code>true</code>.
493     */
494    default boolean isModified() {
495        return false;
496    }
497}