• 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.CervicalMucusRecordInternal;
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 the description of cervical mucus. Each record represents a self-assessed description of
33  * cervical mucus for a user. All fields are optional and can be used to describe the look and feel
34  * of cervical mucus.
35  */
36 @Identifier(recordIdentifier = RecordTypeIdentifier.RECORD_TYPE_CERVICAL_MUCUS)
37 public final class CervicalMucusRecord extends InstantRecord {
38 
39     private final int mSensation;
40     private final int mAppearance;
41 
42     /**
43      * @param metadata Metadata to be associated with the record. See {@link Metadata}.
44      * @param time Start time of this activity
45      * @param zoneOffset Zone offset of the user when the activity started
46      * @param sensation Sensation of this activity
47      * @param appearance Appearance of this activity
48      * @param skipValidation Boolean flag to skip validation of record values.
49      */
CervicalMucusRecord( @onNull Metadata metadata, @NonNull Instant time, @NonNull ZoneOffset zoneOffset, @CervicalMucusSensation.CervicalMucusSensations int sensation, @CervicalMucusAppearance.CervicalMucusAppearances int appearance, boolean skipValidation)50     private CervicalMucusRecord(
51             @NonNull Metadata metadata,
52             @NonNull Instant time,
53             @NonNull ZoneOffset zoneOffset,
54             @CervicalMucusSensation.CervicalMucusSensations int sensation,
55             @CervicalMucusAppearance.CervicalMucusAppearances int appearance,
56             boolean skipValidation) {
57         super(metadata, time, zoneOffset, skipValidation);
58         Objects.requireNonNull(metadata);
59         Objects.requireNonNull(time);
60         Objects.requireNonNull(zoneOffset);
61         validateIntDefValue(
62                 sensation,
63                 CervicalMucusSensation.VALID_TYPES,
64                 CervicalMucusSensation.class.getSimpleName());
65         validateIntDefValue(
66                 appearance,
67                 CervicalMucusAppearance.VALID_TYPES,
68                 CervicalMucusAppearance.class.getSimpleName());
69         mSensation = sensation;
70         mAppearance = appearance;
71     }
72 
73     /**
74      * @return sensation
75      */
76     @CervicalMucusSensation.CervicalMucusSensations
getSensation()77     public int getSensation() {
78         return mSensation;
79     }
80 
81     /**
82      * @return appearance
83      */
84     @CervicalMucusAppearance.CervicalMucusAppearances
getAppearance()85     public int getAppearance() {
86         return mAppearance;
87     }
88 
89     /** Identifier for Cervical Mucus Appearance */
90     public static final class CervicalMucusAppearance {
91         /** A constant describing cervical mucus which appearance is unknown. */
92         public static final int APPEARANCE_UNKNOWN = 0;
93 
94         /** A constant describing a dry cervical mucus. */
95         public static final int APPEARANCE_DRY = 1;
96 
97         /** A constant describing a sticky cervical mucus. */
98         public static final int APPEARANCE_STICKY = 2;
99 
100         /** A constant describing creamy like looking cervical mucus. */
101         public static final int APPEARANCE_CREAMY = 3;
102 
103         /** A constant describing watery like looking cervical mucus. */
104         public static final int APPEARANCE_WATERY = 4;
105 
106         /** A constant describing clear or egg white like looking cervical mucus. */
107         public static final int APPEARANCE_EGG_WHITE = 5;
108 
109         /** A constant describing an unusual (worth attention) kind of cervical mucus. */
110         public static final int APPEARANCE_UNUSUAL = 6;
111 
112         /**
113          * Valid set of values for this IntDef. Update this set when add new type or deprecate
114          * existing type.
115          *
116          * @hide
117          */
118         public static final Set<Integer> VALID_TYPES =
119                 Set.of(
120                         APPEARANCE_UNKNOWN,
121                         APPEARANCE_DRY,
122                         APPEARANCE_STICKY,
123                         APPEARANCE_CREAMY,
124                         APPEARANCE_WATERY,
125                         APPEARANCE_EGG_WHITE,
126                         APPEARANCE_UNUSUAL);
127 
CervicalMucusAppearance()128         CervicalMucusAppearance() {}
129 
130         /** @hide */
131         @IntDef({
132             APPEARANCE_UNKNOWN,
133             APPEARANCE_DRY,
134             APPEARANCE_STICKY,
135             APPEARANCE_CREAMY,
136             APPEARANCE_WATERY,
137             APPEARANCE_EGG_WHITE,
138             APPEARANCE_UNUSUAL
139         })
140         @Retention(RetentionPolicy.SOURCE)
141         public @interface CervicalMucusAppearances {}
142     }
143 
144     /** Identifier for Cervical Mucus Sensation */
145     public static final class CervicalMucusSensation {
146         public static final int SENSATION_UNKNOWN = 0;
147         public static final int SENSATION_LIGHT = 1;
148         public static final int SENSATION_MEDIUM = 2;
149         public static final int SENSATION_HEAVY = 3;
150 
151         /**
152          * Valid set of values for this IntDef. Update this set when add new type or deprecate
153          * existing type.
154          *
155          * @hide
156          */
157         public static final Set<Integer> VALID_TYPES =
158                 Set.of(SENSATION_UNKNOWN, SENSATION_LIGHT, SENSATION_MEDIUM, SENSATION_HEAVY);
159 
CervicalMucusSensation()160         CervicalMucusSensation() {}
161 
162         /** @hide */
163         @IntDef({SENSATION_UNKNOWN, SENSATION_LIGHT, SENSATION_MEDIUM, SENSATION_HEAVY})
164         @Retention(RetentionPolicy.SOURCE)
165         public @interface CervicalMucusSensations {}
166     }
167 
168     /**
169      * Indicates whether some other object is "equal to" this one.
170      *
171      * @param o the reference object with which to compare.
172      * @return {@code true} if this object is the same as the obj
173      */
174     @SuppressWarnings("NullAway") // TODO(b/317029272): fix this suppression
175     @Override
equals(Object o)176     public boolean equals(Object o) {
177         if (this == o) return true;
178         if (!super.equals(o)) return false;
179         CervicalMucusRecord that = (CervicalMucusRecord) o;
180         return getSensation() == that.getSensation() && getAppearance() == that.getAppearance();
181     }
182 
183     /** Returns a hash code value for the object. */
184     @Override
hashCode()185     public int hashCode() {
186         return Objects.hash(super.hashCode(), getSensation(), getAppearance());
187     }
188 
189     /** Builder class for {@link CervicalMucusRecord} */
190     public static final class Builder {
191         private final Metadata mMetadata;
192         private final Instant mTime;
193         private ZoneOffset mZoneOffset;
194         private final int mSensation;
195         private final int mAppearance;
196 
197         /**
198          * @param metadata Metadata to be associated with the record. See {@link Metadata}.
199          * @param time Start time of this activity
200          * @param sensation The feel of the user's cervical mucus. Optional field. Allowed values:
201          *     {@link CervicalMucusSensation}.
202          * @param appearance The consistency of the user's cervical mucus. Optional field. Allowed
203          *     values: {@link CervicalMucusAppearance}.
204          */
Builder( @onNull Metadata metadata, @NonNull Instant time, @CervicalMucusSensation.CervicalMucusSensations int sensation, @CervicalMucusAppearance.CervicalMucusAppearances int appearance)205         public Builder(
206                 @NonNull Metadata metadata,
207                 @NonNull Instant time,
208                 @CervicalMucusSensation.CervicalMucusSensations int sensation,
209                 @CervicalMucusAppearance.CervicalMucusAppearances int appearance) {
210             Objects.requireNonNull(metadata);
211             Objects.requireNonNull(time);
212             mMetadata = metadata;
213             mTime = time;
214             mSensation = sensation;
215             mAppearance = appearance;
216             mZoneOffset = ZoneOffset.systemDefault().getRules().getOffset(time);
217         }
218 
219         /** Sets the zone offset of the user when the activity happened */
220         @NonNull
setZoneOffset(@onNull ZoneOffset zoneOffset)221         public Builder setZoneOffset(@NonNull ZoneOffset zoneOffset) {
222             Objects.requireNonNull(zoneOffset);
223             mZoneOffset = zoneOffset;
224             return this;
225         }
226 
227         /** Sets the zone offset of this record to system default. */
228         @NonNull
clearZoneOffset()229         public Builder clearZoneOffset() {
230             mZoneOffset = RecordUtils.getDefaultZoneOffset();
231             return this;
232         }
233 
234         /**
235          * @return Object of {@link CervicalMucusRecord} without validating the values.
236          * @hide
237          */
238         @NonNull
buildWithoutValidation()239         public CervicalMucusRecord buildWithoutValidation() {
240             return new CervicalMucusRecord(
241                     mMetadata, mTime, mZoneOffset, mSensation, mAppearance, true);
242         }
243 
244         /**
245          * @return Object of {@link CervicalMucusRecord}
246          */
247         @NonNull
build()248         public CervicalMucusRecord build() {
249             return new CervicalMucusRecord(
250                     mMetadata, mTime, mZoneOffset, mSensation, mAppearance, false);
251         }
252     }
253 
254     /** @hide */
255     @Override
toRecordInternal()256     public CervicalMucusRecordInternal toRecordInternal() {
257         CervicalMucusRecordInternal recordInternal =
258                 (CervicalMucusRecordInternal)
259                         new CervicalMucusRecordInternal()
260                                 .setUuid(getMetadata().getId())
261                                 .setPackageName(getMetadata().getDataOrigin().getPackageName())
262                                 .setLastModifiedTime(
263                                         getMetadata().getLastModifiedTime().toEpochMilli())
264                                 .setClientRecordId(getMetadata().getClientRecordId())
265                                 .setClientRecordVersion(getMetadata().getClientRecordVersion())
266                                 .setManufacturer(getMetadata().getDevice().getManufacturer())
267                                 .setModel(getMetadata().getDevice().getModel())
268                                 .setDeviceType(getMetadata().getDevice().getType())
269                                 .setRecordingMethod(getMetadata().getRecordingMethod());
270         recordInternal.setTime(getTime().toEpochMilli());
271         recordInternal.setZoneOffset(getZoneOffset().getTotalSeconds());
272         recordInternal.setSensation(mSensation);
273         recordInternal.setAppearance(mAppearance);
274         return recordInternal;
275     }
276 }
277