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
013public class ImmutableGpxTrack extends WithAttributes implements GpxTrack {
014
015    private final Collection<GpxTrackSegment> segments;
016    private final double length;
017    private final Bounds bounds;
018
019    public ImmutableGpxTrack(Collection<Collection<WayPoint>> trackSegs, Map<String, Object> attributes) {
020        List<GpxTrackSegment> newSegments = new ArrayList<>();
021        for (Collection<WayPoint> trackSeg: trackSegs) {
022            if (trackSeg != null && !trackSeg.isEmpty()) {
023                newSegments.add(new ImmutableGpxTrackSegment(trackSeg));
024            }
025        }
026        this.attr = Collections.unmodifiableMap(new HashMap<>(attributes));
027        this.segments = Collections.unmodifiableCollection(newSegments);
028        this.length = calculateLength();
029        this.bounds = calculateBounds();
030    }
031
032    private double calculateLength(){
033        double result = 0.0; // in meters
034
035        for (GpxTrackSegment trkseg : segments) {
036            result += trkseg.length();
037        }
038        return result;
039    }
040
041    private Bounds calculateBounds() {
042        Bounds result = null;
043        for (GpxTrackSegment segment: segments) {
044            Bounds segBounds = segment.getBounds();
045            if (segBounds != null) {
046                if (result == null) {
047                    result = new Bounds(segBounds);
048                } else {
049                    result.extend(segBounds);
050                }
051            }
052        }
053        return result;
054    }
055
056    @Override
057    public Map<String, Object> getAttributes() {
058        return attr;
059    }
060
061    @Override
062    public Bounds getBounds() {
063        if (bounds == null)
064            return null;
065        else
066            return new Bounds(bounds);
067    }
068
069    @Override
070    public double length() {
071        return length;
072    }
073
074    @Override
075    public Collection<GpxTrackSegment> getSegments() {
076        return segments;
077    }
078
079    @Override
080    public int getUpdateCount() {
081        return 0;
082    }
083}