• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.datatypes;
17 
18 import static android.health.connect.datatypes.validation.ValidationUtils.validateIntDefValue;
19 
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.health.connect.internal.datatypes.MenstruationFlowRecordInternal;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 import java.time.Instant;
27 import java.time.ZoneOffset;
28 import java.util.Objects;
29 import java.util.Set;
30 
31 /**
32  * Captures a description of how heavy a user's menstrual flow was (spotting, light, medium, or
33  * heavy). Each record represents a description of how heavy the user's menstrual bleeding was.
34  */
35 @Identifier(recordIdentifier = RecordTypeIdentifier.RECORD_TYPE_MENSTRUATION_FLOW)
36 public final class MenstruationFlowRecord extends InstantRecord {
37 
38     private final int mFlow;
39 
40     /**
41      * @param metadata Metadata to be associated with the record. See {@link Metadata}.
42      * @param time Start time of this activity
43      * @param zoneOffset Zone offset of the user when the activity started
44      * @param flow Flow of this activity
45      * @param skipValidation Boolean flag to skip validation of record values.
46      */
MenstruationFlowRecord( @onNull Metadata metadata, @NonNull Instant time, @NonNull ZoneOffset zoneOffset, @MenstruationFlowType.MenstruationFlowTypes int flow, boolean skipValidation)47     private MenstruationFlowRecord(
48             @NonNull Metadata metadata,
49             @NonNull Instant time,
50             @NonNull ZoneOffset zoneOffset,
51             @MenstruationFlowType.MenstruationFlowTypes int flow,
52             boolean skipValidation) {
53         super(metadata, time, zoneOffset, skipValidation);
54         Objects.requireNonNull(metadata);
55         Objects.requireNonNull(time);
56         Objects.requireNonNull(zoneOffset);
57         validateIntDefValue(
58                 flow, MenstruationFlowType.VALID_TYPES, MenstruationFlowType.class.getSimpleName());
59         mFlow = flow;
60     }
61 
62     /**
63      * @return menstruation flow
64      */
getFlow()65     public int getFlow() {
66         return mFlow;
67     }
68 
69     /** Identifier for Menstruation Flow */
70     public static final class MenstruationFlowType {
71         public static final int FLOW_UNKNOWN = 0;
72         public static final int FLOW_LIGHT = 1;
73         public static final int FLOW_MEDIUM = 2;
74         public static final int FLOW_HEAVY = 3;
75 
76         /**
77          * Valid set of values for this IntDef. Update this set when add new type or deprecate
78          * existing type.
79          *
80          * @hide
81          */
82         public static final Set<Integer> VALID_TYPES =
83                 Set.of(FLOW_UNKNOWN, FLOW_LIGHT, FLOW_MEDIUM, FLOW_HEAVY);
84 
MenstruationFlowType()85         MenstruationFlowType() {}
86 
87         /** @hide */
88         @IntDef({FLOW_UNKNOWN, FLOW_LIGHT, FLOW_MEDIUM, FLOW_HEAVY})
89         @Retention(RetentionPolicy.SOURCE)
90         public @interface MenstruationFlowTypes {}
91     }
92 
93     /**
94      * Indicates whether some other object is "equal to" this one.
95      *
96      * @param o the reference object with which to compare.
97      * @return {@code true} if this object is the same as the obj
98      */
99     @Override
equals(Object o)100     public boolean equals(Object o) {
101         if (this == o) return true;
102         if (!super.equals(o)) return false;
103         MenstruationFlowRecord that = (MenstruationFlowRecord) o;
104         return getFlow() == that.getFlow();
105     }
106 
107     /** Returns a hash code value for the object. */
108     @Override
hashCode()109     public int hashCode() {
110         return Objects.hash(super.hashCode(), getFlow());
111     }
112 
113     /** Builder class for {@link MenstruationFlowRecord} */
114     public static final class Builder {
115         private final Metadata mMetadata;
116         private final Instant mTime;
117         private ZoneOffset mZoneOffset;
118         private final int mFlow;
119 
120         /**
121          * @param metadata Metadata to be associated with the record. See {@link Metadata}.
122          * @param time Start time of this activity
123          * @param flow How heavy the user's menstrual flow was. Optional field. Allowed values:
124          *     {@link MenstruationFlowType}.
125          */
Builder( @onNull Metadata metadata, @NonNull Instant time, @MenstruationFlowType.MenstruationFlowTypes int flow)126         public Builder(
127                 @NonNull Metadata metadata,
128                 @NonNull Instant time,
129                 @MenstruationFlowType.MenstruationFlowTypes int flow) {
130             Objects.requireNonNull(metadata);
131             Objects.requireNonNull(time);
132             mMetadata = metadata;
133             mTime = time;
134             mFlow = flow;
135             mZoneOffset = ZoneOffset.systemDefault().getRules().getOffset(time);
136         }
137 
138         /** Sets the zone offset of the user when the activity happened */
139         @NonNull
setZoneOffset(@onNull ZoneOffset zoneOffset)140         public Builder setZoneOffset(@NonNull ZoneOffset zoneOffset) {
141             Objects.requireNonNull(zoneOffset);
142             mZoneOffset = zoneOffset;
143             return this;
144         }
145 
146         /** Sets the zone offset of this record to system default. */
147         @NonNull
clearZoneOffset()148         public Builder clearZoneOffset() {
149             mZoneOffset = RecordUtils.getDefaultZoneOffset();
150             return this;
151         }
152 
153         /**
154          * @return Object of {@link MenstruationFlowRecord} without validating the values.
155          * @hide
156          */
157         @NonNull
buildWithoutValidation()158         public MenstruationFlowRecord buildWithoutValidation() {
159             return new MenstruationFlowRecord(mMetadata, mTime, mZoneOffset, mFlow, true);
160         }
161 
162         /**
163          * @return Object of {@link MenstruationFlowRecord}
164          */
165         @NonNull
build()166         public MenstruationFlowRecord build() {
167             return new MenstruationFlowRecord(mMetadata, mTime, mZoneOffset, mFlow, false);
168         }
169     }
170 
171     /** @hide */
172     @Override
toRecordInternal()173     public MenstruationFlowRecordInternal toRecordInternal() {
174         MenstruationFlowRecordInternal recordInternal =
175                 (MenstruationFlowRecordInternal)
176                         new MenstruationFlowRecordInternal()
177                                 .setUuid(getMetadata().getId())
178                                 .setPackageName(getMetadata().getDataOrigin().getPackageName())
179                                 .setLastModifiedTime(
180                                         getMetadata().getLastModifiedTime().toEpochMilli())
181                                 .setClientRecordId(getMetadata().getClientRecordId())
182                                 .setClientRecordVersion(getMetadata().getClientRecordVersion())
183                                 .setManufacturer(getMetadata().getDevice().getManufacturer())
184                                 .setModel(getMetadata().getDevice().getModel())
185                                 .setDeviceType(getMetadata().getDevice().getType())
186                                 .setRecordingMethod(getMetadata().getRecordingMethod());
187         recordInternal.setTime(getTime().toEpochMilli());
188         recordInternal.setZoneOffset(getZoneOffset().getTotalSeconds());
189         recordInternal.setFlow(mFlow);
190         return recordInternal;
191     }
192 }
193