001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.gpx; 003 004import java.util.ArrayList; 005import java.util.Collection; 006import java.util.Collections; 007import java.util.HashMap; 008import java.util.List; 009import java.util.Map; 010 011import org.openstreetmap.josm.data.Bounds; 012 013/** 014 * Immutable GPX track. 015 * @since 2907 016 */ 017public class ImmutableGpxTrack extends WithAttributes implements GpxTrack { 018 019 private final Collection<GpxTrackSegment> segments; 020 private final double length; 021 private final Bounds bounds; 022 023 /** 024 * Constructs a new {@code ImmutableGpxTrack}. 025 * @param trackSegs track segments 026 * @param attributes track attributes 027 */ 028 public ImmutableGpxTrack(Collection<Collection<WayPoint>> trackSegs, Map<String, Object> attributes) { 029 List<GpxTrackSegment> newSegments = new ArrayList<>(); 030 for (Collection<WayPoint> trackSeg: trackSegs) { 031 if (trackSeg != null && !trackSeg.isEmpty()) { 032 newSegments.add(new ImmutableGpxTrackSegment(trackSeg)); 033 } 034 } 035 this.attr = Collections.unmodifiableMap(new HashMap<>(attributes)); 036 this.segments = Collections.unmodifiableCollection(newSegments); 037 this.length = calculateLength(); 038 this.bounds = calculateBounds(); 039 } 040 041 private double calculateLength() { 042 double result = 0.0; // in meters 043 044 for (GpxTrackSegment trkseg : segments) { 045 result += trkseg.length(); 046 } 047 return result; 048 } 049 050 private Bounds calculateBounds() { 051 Bounds result = null; 052 for (GpxTrackSegment segment: segments) { 053 Bounds segBounds = segment.getBounds(); 054 if (segBounds != null) { 055 if (result == null) { 056 result = new Bounds(segBounds); 057 } else { 058 result.extend(segBounds); 059 } 060 } 061 } 062 return result; 063 } 064 065 @Override 066 public Map<String, Object> getAttributes() { 067 return attr; 068 } 069 070 @Override 071 public Bounds getBounds() { 072 if (bounds == null) 073 return null; 074 else 075 return new Bounds(bounds); 076 } 077 078 @Override 079 public double length() { 080 return length; 081 } 082 083 @Override 084 public Collection<GpxTrackSegment> getSegments() { 085 return segments; 086 } 087 088 @Override 089 public int getUpdateCount() { 090 return 0; 091 } 092}