1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.health.connect.internal.datatypes;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.health.connect.datatypes.ExerciseSessionType;
21 import android.health.connect.datatypes.Identifier;
22 import android.health.connect.datatypes.PlannedExerciseSessionRecord;
23 import android.health.connect.datatypes.RecordTypeIdentifier;
24 import android.os.Parcel;
25 
26 import java.time.Duration;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.UUID;
30 
31 /**
32  * Represents a planned workout that should be completed by the user.
33  *
34  * @hide
35  * @see PlannedExerciseSessionRecord
36  */
37 @Identifier(recordIdentifier = RecordTypeIdentifier.RECORD_TYPE_PLANNED_EXERCISE_SESSION)
38 public final class PlannedExerciseSessionRecordInternal
39         extends IntervalRecordInternal<PlannedExerciseSessionRecord> {
40     @Nullable private String mNotes;
41 
42     private int mExerciseType;
43 
44     @Nullable private String mTitle;
45 
46     private boolean mHasExplicitTime;
47 
48     private List<PlannedExerciseBlockInternal> mExerciseBlocks = Collections.emptyList();
49 
50     @Nullable private UUID mCompletedExerciseSessionId;
51 
52     @Nullable
getNotes()53     public String getNotes() {
54         return mNotes;
55     }
56 
57     /** returns this object with the specified notes. */
58     @NonNull
setNotes(String notes)59     public PlannedExerciseSessionRecordInternal setNotes(String notes) {
60         this.mNotes = notes;
61         return this;
62     }
63 
64     /** returns the title of this planned workout. */
65     @Nullable
getTitle()66     public String getTitle() {
67         return mTitle;
68     }
69 
70     /** returns this object with the specified title. */
71     @NonNull
setTitle(String title)72     public PlannedExerciseSessionRecordInternal setTitle(String title) {
73         this.mTitle = title;
74         return this;
75     }
76 
77     /** returns this object with the specified notes. */
78     @NonNull
setHasExplicitTime(boolean hasExplicitTime)79     public PlannedExerciseSessionRecordInternal setHasExplicitTime(boolean hasExplicitTime) {
80         this.mHasExplicitTime = hasExplicitTime;
81         return this;
82     }
83 
84     /** returns this object with the specified {@link PlannedExerciseBlockInternal} entries. */
85     @NonNull
setExerciseBlocks( List<PlannedExerciseBlockInternal> blocks)86     public PlannedExerciseSessionRecordInternal setExerciseBlocks(
87             List<PlannedExerciseBlockInternal> blocks) {
88         this.mExerciseBlocks = blocks;
89         return this;
90     }
91 
92     /** returns this object with the specified completed exercise session id. */
93     @NonNull
setCompletedExerciseSessionId(UUID id)94     public PlannedExerciseSessionRecordInternal setCompletedExerciseSessionId(UUID id) {
95         this.mCompletedExerciseSessionId = id;
96         return this;
97     }
98 
99     /** returns the {@link PlannedExerciseBlockInternal} entries associated with this object. */
100     @NonNull
getExerciseBlocks()101     public List<PlannedExerciseBlockInternal> getExerciseBlocks() {
102         return mExerciseBlocks;
103     }
104 
105     /** returns the UUID of the exercise session which completed this plan, if it exists. */
106     @Nullable
getCompletedExerciseSessionId()107     public UUID getCompletedExerciseSessionId() {
108         return mCompletedExerciseSessionId;
109     }
110 
111     /** returns whether this object has an explicit time set. */
getHasExplicitTime()112     public boolean getHasExplicitTime() {
113         return mHasExplicitTime;
114     }
115 
116     /** returns the exercise type of this planned workout. */
117     @ExerciseSessionType.ExerciseSessionTypes
getExerciseType()118     public int getExerciseType() {
119         return mExerciseType;
120     }
121 
122     /** returns this object with the specified exercise type. */
123     @NonNull
setExerciseType(int exerciseType)124     public PlannedExerciseSessionRecordInternal setExerciseType(int exerciseType) {
125         this.mExerciseType = exerciseType;
126         return this;
127     }
128 
129     @Override
populateIntervalRecordFrom(Parcel parcel)130     void populateIntervalRecordFrom(Parcel parcel) {
131         mNotes = parcel.readString();
132         mExerciseType = parcel.readInt();
133         mTitle = parcel.readString();
134         mHasExplicitTime = parcel.readBoolean();
135         mExerciseBlocks = PlannedExerciseBlockInternal.readFromParcel(parcel);
136         String uuid = parcel.readString();
137         mCompletedExerciseSessionId = uuid == null ? null : UUID.fromString(uuid);
138     }
139 
140     @Override
populateIntervalRecordTo(Parcel parcel)141     void populateIntervalRecordTo(Parcel parcel) {
142         parcel.writeString(mNotes);
143         parcel.writeInt(mExerciseType);
144         parcel.writeString(mTitle);
145         parcel.writeBoolean(mHasExplicitTime);
146         PlannedExerciseBlockInternal.writeToParcel(mExerciseBlocks, parcel);
147         parcel.writeString(
148                 mCompletedExerciseSessionId == null
149                         ? null
150                         : mCompletedExerciseSessionId.toString());
151     }
152 
153     /** Convert this object to an external representation. */
154     @Override
toExternalRecord()155     public PlannedExerciseSessionRecord toExternalRecord() {
156         PlannedExerciseSessionRecord.Builder builder =
157                 mHasExplicitTime
158                         ? new PlannedExerciseSessionRecord.Builder(
159                                 buildMetaData(), getExerciseType(), getStartTime(), getEndTime())
160                         : new PlannedExerciseSessionRecord.Builder(
161                                 buildMetaData(),
162                                 getExerciseType(),
163                                 getStartTime().atOffset(getStartZoneOffset()).toLocalDate(),
164                                 Duration.between(getStartTime(), getEndTime()));
165 
166         if (getStartZoneOffset() != null) {
167             builder.setStartZoneOffset(getStartZoneOffset());
168         }
169         if (getEndZoneOffset() != null) {
170             builder.setEndZoneOffset(getEndZoneOffset());
171         }
172         if (getNotes() != null) {
173             builder.setNotes(getNotes());
174         }
175         if (getTitle() != null) {
176             builder.setTitle(getTitle());
177         }
178         for (PlannedExerciseBlockInternal block : mExerciseBlocks) {
179             builder.addBlock(block.toExternalObject());
180         }
181         if (mCompletedExerciseSessionId != null) {
182             builder.setCompletedExerciseSessionId(mCompletedExerciseSessionId.toString());
183         }
184         return builder.buildWithoutValidation();
185     }
186 }
187