Track is now a record.

This commit is contained in:
Dennis Guse
2025-11-27 19:35:05 +01:00
parent 6a262426a5
commit 990c91f978
51 changed files with 772 additions and 523 deletions
@@ -50,6 +50,7 @@ import de.dennisguse.opentracks.data.models.Power;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.data.tables.MarkerColumns;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
@@ -93,11 +94,6 @@ public class ContentProviderUtils {
this.contentResolver = contentResolver;
}
/**
* Creates a {@link Track} from a cursor.
*
* @param cursor the cursor pointing to the track
*/
public static Track createTrack(Cursor cursor) {
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
int uuidIndex = cursor.getColumnIndexOrThrow(TracksColumns.UUID);
@@ -133,7 +129,7 @@ public class ContentProviderUtils {
null
);
Track track = new Track(ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex)), trackStatistics);
TrackBuilder track = new TrackBuilder(ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex)), trackStatistics);
track.setId(new Track.Id(cursor.getLong(idIndex)));
track.setUuid(UUIDUtils.fromBytes(cursor.getBlob(uuidIndex)));
if (!cursor.isNull(nameIndex)) {
@@ -149,7 +145,7 @@ public class ContentProviderUtils {
track.setActivityTypeLocalized(cursor.getString(activityTypeLocalizedIndex));
}
return track;
return track.getTrack();
}
@VisibleForTesting
@@ -273,23 +269,23 @@ public class ContentProviderUtils {
* @param track the track
*/
public void updateTrack(Track track) {
contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), TracksColumns._ID + "=?", new String[]{Long.toString(track.getId().id())});
contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), TracksColumns._ID + "=?", new String[]{Long.toString(track.id().id())});
}
private ContentValues createContentValues(Track track) {
ContentValues values = new ContentValues();
if (track.getId() != null) {
values.put(TracksColumns._ID, track.getId().id());
if (track.id() != null) {
values.put(TracksColumns._ID, track.id().id());
}
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid()));
values.put(TracksColumns.NAME, track.getName());
values.put(TracksColumns.DESCRIPTION, track.getDescription());
values.put(TracksColumns.ACTIVITY_TYPE, track.getActivityType() != null ? track.getActivityType().getId() : null);
values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.getActivityTypeLocalized());
values.put(TracksColumns.STARTTIME_OFFSET, track.getZoneOffset().getTotalSeconds());
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.uuid()));
values.put(TracksColumns.NAME, track.name());
values.put(TracksColumns.DESCRIPTION, track.description());
values.put(TracksColumns.ACTIVITY_TYPE, track.activityType() != null ? track.activityType().getId() : null);
values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.activityTypeLocalized());
values.put(TracksColumns.STARTTIME_OFFSET, track.zoneOffset().getTotalSeconds());
values.putAll(createContentValues(track.getStatistics()));
values.putAll(createContentValues(track.statistics()));
return values;
}
@@ -9,7 +9,6 @@ import java.util.NoSuchElementException;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.util.AutoCloseableIterator;
class MarkerIterator extends AutoCloseableIterator<Marker> {
@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.tables.TracksColumns;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
@@ -19,7 +19,6 @@ package de.dennisguse.opentracks.data;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
@@ -34,6 +33,7 @@ import java.util.Set;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.data.tables.MarkerColumns;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
@@ -1,164 +1,46 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.data.models;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.UUID;
import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
public record Track(
// May be null if the track was not loaded from the database.
@NonNull
Id id,
// May be null if the track was not loaded from the database.
@NonNull
UUID uuid,
@NonNull
String name,
@NonNull
String description,
/**
* A track.
*
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
//TODO Do not default initialize attributes; might be confusing for debugging
public class Track {
@NonNull
String activityTypeLocalized,
@NonNull
ActivityType activityType,
@NonNull
ZoneOffset zoneOffset,
@NonNull
Statistics statistics
) {
private Track.Id id;
private UUID uuid = UUID.randomUUID();
private String name = "";
private String description = "";
private String activityTypeLocalized = "";
private ActivityType activityType;
@NonNull
private ZoneOffset zoneOffset;
@NonNull
private Statistics trackStatistics;
@VisibleForTesting
public Track(Statistics statistics) {
this(ZoneOffset.UTC, statistics);
}
public Track(@NonNull ZoneOffset zoneOffset, @NonNull Statistics trackStatistics) {
this.zoneOffset = zoneOffset;
this.trackStatistics = trackStatistics;
}
/**
* May be null if the track was not loaded from the database.
*/
@Nullable
public Id getId() {
return id;
}
public void setId(Id id) {
this.id = id;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getActivityTypeLocalized() {
return activityTypeLocalized;
}
public void setActivityTypeLocalized(String activityTypeLocalized) {
this.activityTypeLocalized = activityTypeLocalized;
}
public ActivityType getActivityType() {
return activityType;
}
public void setActivityType(ActivityType activityType) {
this.activityType = activityType;
}
public void setActivityTypeLocalizedAndUpdateActivityType(Context context, String activityTypeLocalized) {
setActivityTypeLocalized(activityTypeLocalized);
setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
}
public ZoneOffset getZoneOffset() {
return zoneOffset;
}
public void setZoneOffset(@NonNull ZoneOffset zoneOffset) {
this.zoneOffset = zoneOffset;
}
public OffsetDateTime getStartTime() {
return trackStatistics
public OffsetDateTime startTime() {
return statistics
.startTime().atOffset(zoneOffset);
}
public OffsetDateTime getStopTime() {
return trackStatistics
public OffsetDateTime stopTime() {
return statistics
.stopTime().atOffset(zoneOffset);
}
public Statistics getStatistics() {
return trackStatistics;
}
public void setStatistics(Statistics trackStatistics) {
this.trackStatistics = trackStatistics;
}
@NonNull
@Override
public String toString() {
return "Track{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", activityTypeLocalized='" + activityTypeLocalized + '\'' +
", activityType=" + activityType +
'}';
}
public record Id(long id) implements Parcelable {
@Override
@@ -0,0 +1,193 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.data.models;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.UUID;
/**
* A track.
*
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
//TODO Do not default initialize attributes; might be confusing for debugging
public class TrackBuilder {
private Track.Id id;
private UUID uuid = UUID.randomUUID();
private String name = "";
private String description = "";
private String activityTypeLocalized = "";
private ActivityType activityType;
@NonNull
private ZoneOffset zoneOffset;
@NonNull
private Statistics trackStatistics;
@Deprecated
@VisibleForTesting
public TrackBuilder(Statistics statistics) {
this(ZoneOffset.UTC, statistics);
}
@Deprecated
public TrackBuilder(@NonNull ZoneOffset zoneOffset, @NonNull Statistics trackStatistics) {
this.zoneOffset = zoneOffset;
this.trackStatistics = trackStatistics;
}
public TrackBuilder(Track track) {
this.id = track.id();
this.uuid = track.uuid();
this.name = track.name();
this.description = track.description();
this.activityTypeLocalized = track.activityTypeLocalized();
this.activityType = track.activityType();
this.zoneOffset = track.zoneOffset();
this.trackStatistics = track.statistics();
}
/**
* May be null if the track was not loaded from the database.
*/
@Nullable
@Deprecated
public Track.Id getId() {
return id;
}
public void setId(Track.Id id) {
this.id = id;
}
@Deprecated
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
@Deprecated
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Deprecated
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Deprecated
public String getActivityTypeLocalized() {
return activityTypeLocalized;
}
public void setActivityTypeLocalized(String activityTypeLocalized) {
this.activityTypeLocalized = activityTypeLocalized;
}
@Deprecated
public ActivityType getActivityType() {
return activityType;
}
public void setActivityType(ActivityType activityType) {
this.activityType = activityType;
}
public void setActivityTypeLocalizedAndUpdateActivityType(Context context, String activityTypeLocalized) {
setActivityTypeLocalized(activityTypeLocalized);
setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
}
@Deprecated
public ZoneOffset getZoneOffset() {
return zoneOffset;
}
public void setZoneOffset(@NonNull ZoneOffset zoneOffset) {
this.zoneOffset = zoneOffset;
}
@Deprecated
public OffsetDateTime getStartTime() {
return trackStatistics
.startTime().atOffset(zoneOffset);
}
@Deprecated
public OffsetDateTime getStopTime() {
return trackStatistics
.stopTime().atOffset(zoneOffset);
}
@Deprecated
public Statistics getStatistics() {
return trackStatistics;
}
public void setStatistics(Statistics trackStatistics) {
this.trackStatistics = trackStatistics;
}
public Track getTrack() {
return new Track(
id,
uuid,
name,
description,
activityTypeLocalized,
activityType,
zoneOffset,
trackStatistics
);
}
@NonNull
@Override
public String toString() {
return "Track{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", activityTypeLocalized='" + activityTypeLocalized + '\'' +
", activityType=" + activityType +
'}';
}
}