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 
17 package android.health.connect.datatypes;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.health.connect.internal.datatypes.PlannedExerciseBlockInternal;
23 
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Objects;
27 import java.util.stream.Collectors;
28 
29 /**
30  * Represents a series of {@link PlannedExerciseStep}. Part of a {@link
31  * PlannedExerciseSessionRecord}.
32  */
33 @FlaggedApi("com.android.healthconnect.flags.training_plans")
34 public final class PlannedExerciseBlock {
35     private final int mRepetitions;
36     @Nullable private final CharSequence mDescription;
37     private final List<PlannedExerciseStep> mSteps;
38 
PlannedExerciseBlock( int repetitions, @Nullable CharSequence description, @NonNull List<PlannedExerciseStep> steps)39     private PlannedExerciseBlock(
40             int repetitions,
41             @Nullable CharSequence description,
42             @NonNull List<PlannedExerciseStep> steps) {
43         this.mRepetitions = repetitions;
44         this.mDescription = description;
45         this.mSteps = steps;
46     }
47 
48     /** A description for this block, e.g. "Main set". */
49     @Nullable
getDescription()50     public CharSequence getDescription() {
51         return mDescription;
52     }
53 
54     /**
55      * The steps associated with this block.
56      *
57      * @return An unmodifiable list of {@link PlannedExerciseStep}.
58      */
59     @NonNull
getSteps()60     public List<PlannedExerciseStep> getSteps() {
61         return mSteps;
62     }
63 
64     /** The number of times this block should be repeated by the user. */
getRepetitions()65     public int getRepetitions() {
66         return mRepetitions;
67     }
68 
69     @Override
equals(@ullable Object o)70     public boolean equals(@Nullable Object o) {
71         if (this == o) return true;
72         if (!(o instanceof PlannedExerciseBlock)) return false;
73         PlannedExerciseBlock that = (PlannedExerciseBlock) o;
74         return RecordUtils.isEqualNullableCharSequences(getDescription(), that.getDescription())
75                 && this.getRepetitions() == that.getRepetitions()
76                 && Objects.equals(this.getSteps(), that.getSteps());
77     }
78 
79     @Override
hashCode()80     public int hashCode() {
81         return Objects.hash(getDescription(), getRepetitions(), getSteps());
82     }
83 
84     /** Builder of {@link PlannedExerciseBlock}. */
85     public static final class Builder {
86         private int mRepetitions;
87         private List<PlannedExerciseStep> mSteps = new ArrayList<>();
88         @Nullable private CharSequence mDescription;
89 
90         /**
91          * @param repetitions The number of times this block should be repeated by the user.
92          */
Builder(int repetitions)93         public Builder(int repetitions) {
94             this.mRepetitions = repetitions;
95         }
96 
97         /** Sets the number of repetitions. */
98         @NonNull
setRepetitions(int repetitions)99         public Builder setRepetitions(int repetitions) {
100             this.mRepetitions = repetitions;
101             return this;
102         }
103 
104         /** Sets the description. */
105         @NonNull
setDescription(@ullable CharSequence description)106         public Builder setDescription(@Nullable CharSequence description) {
107             this.mDescription = description;
108             return this;
109         }
110 
111         /** Adds a {@link PlannedExerciseStep}. */
112         @NonNull
addStep(@onNull PlannedExerciseStep step)113         public Builder addStep(@NonNull PlannedExerciseStep step) {
114             Objects.requireNonNull(step);
115             mSteps.add(step);
116             return this;
117         }
118 
119         /** Sets the {@link PlannedExerciseStep} entries. */
120         @NonNull
setSteps(@onNull List<PlannedExerciseStep> steps)121         public Builder setSteps(@NonNull List<PlannedExerciseStep> steps) {
122             Objects.requireNonNull(steps);
123             mSteps.clear();
124             mSteps.addAll(steps);
125             return this;
126         }
127 
128         /** Clears the {@link PlannedExerciseStep} entries. */
129         @NonNull
clearSteps()130         public Builder clearSteps() {
131             mSteps.clear();
132             return this;
133         }
134 
135         /**
136          * @return Object of {@link PlannedExerciseBlock}.
137          */
138         @NonNull
build()139         public PlannedExerciseBlock build() {
140             return new PlannedExerciseBlock(mRepetitions, mDescription, List.copyOf(mSteps));
141         }
142     }
143 
144     /** @hide */
toInternalObject()145     public PlannedExerciseBlockInternal toInternalObject() {
146         PlannedExerciseBlockInternal result = new PlannedExerciseBlockInternal(getRepetitions());
147         if (mDescription != null) {
148             result.setDescription(mDescription.toString());
149         }
150         result.setExerciseSteps(
151                 getSteps().stream().map(it -> it.toInternalObject()).collect(Collectors.toList()));
152         return result;
153     }
154 }
155