1 /**
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * ```
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * ```
10  *
11  * Unless required by applicable law or agreed to in writing, software distributed under the License
12  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13  * or implied. See the License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package com.android.healthconnect.testapps.toolbox.utils
17 
18 import android.content.Context
19 import android.health.connect.datatypes.ActiveCaloriesBurnedRecord
20 import android.health.connect.datatypes.BasalBodyTemperatureRecord
21 import android.health.connect.datatypes.BasalMetabolicRateRecord
22 import android.health.connect.datatypes.BloodGlucoseRecord
23 import android.health.connect.datatypes.BloodPressureRecord
24 import android.health.connect.datatypes.BodyFatRecord
25 import android.health.connect.datatypes.BodyTemperatureRecord
26 import android.health.connect.datatypes.BodyWaterMassRecord
27 import android.health.connect.datatypes.BoneMassRecord
28 import android.health.connect.datatypes.CervicalMucusRecord
29 import android.health.connect.datatypes.CyclingPedalingCadenceRecord
30 import android.health.connect.datatypes.CyclingPedalingCadenceRecord.CyclingPedalingCadenceRecordSample
31 import android.health.connect.datatypes.DistanceRecord
32 import android.health.connect.datatypes.ElevationGainedRecord
33 import android.health.connect.datatypes.ExerciseLap
34 import android.health.connect.datatypes.ExerciseSegment
35 import android.health.connect.datatypes.ExerciseSessionRecord
36 import android.health.connect.datatypes.FloorsClimbedRecord
37 import android.health.connect.datatypes.HeartRateRecord
38 import android.health.connect.datatypes.HeartRateRecord.HeartRateSample
39 import android.health.connect.datatypes.HeartRateVariabilityRmssdRecord
40 import android.health.connect.datatypes.HeightRecord
41 import android.health.connect.datatypes.HydrationRecord
42 import android.health.connect.datatypes.IntermenstrualBleedingRecord
43 import android.health.connect.datatypes.LeanBodyMassRecord
44 import android.health.connect.datatypes.MenstruationFlowRecord
45 import android.health.connect.datatypes.MenstruationPeriodRecord
46 import android.health.connect.datatypes.Metadata
47 import android.health.connect.datatypes.NutritionRecord
48 import android.health.connect.datatypes.OvulationTestRecord
49 import android.health.connect.datatypes.OxygenSaturationRecord
50 import android.health.connect.datatypes.PlannedExerciseBlock
51 import android.health.connect.datatypes.PlannedExerciseSessionRecord
52 import android.health.connect.datatypes.PowerRecord
53 import android.health.connect.datatypes.PowerRecord.PowerRecordSample
54 import android.health.connect.datatypes.Record
55 import android.health.connect.datatypes.RespiratoryRateRecord
56 import android.health.connect.datatypes.RestingHeartRateRecord
57 import android.health.connect.datatypes.SexualActivityRecord
58 import android.health.connect.datatypes.SkinTemperatureRecord
59 import android.health.connect.datatypes.SleepSessionRecord
60 import android.health.connect.datatypes.SpeedRecord
61 import android.health.connect.datatypes.SpeedRecord.SpeedRecordSample
62 import android.health.connect.datatypes.StepsCadenceRecord
63 import android.health.connect.datatypes.StepsCadenceRecord.StepsCadenceRecordSample
64 import android.health.connect.datatypes.StepsRecord
65 import android.health.connect.datatypes.TotalCaloriesBurnedRecord
66 import android.health.connect.datatypes.Vo2MaxRecord
67 import android.health.connect.datatypes.WeightRecord
68 import android.health.connect.datatypes.WheelchairPushesRecord
69 import android.health.connect.datatypes.units.BloodGlucose
70 import android.health.connect.datatypes.units.Energy
71 import android.health.connect.datatypes.units.Length
72 import android.health.connect.datatypes.units.Mass
73 import android.health.connect.datatypes.units.Percentage
74 import android.health.connect.datatypes.units.Power
75 import android.health.connect.datatypes.units.Pressure
76 import android.health.connect.datatypes.units.Temperature
77 import android.health.connect.datatypes.units.Volume
78 import com.android.healthconnect.testapps.toolbox.data.ExerciseRoutesTestData
79 import com.android.healthconnect.testapps.toolbox.data.ExerciseRoutesTestData.Companion.generateExerciseRouteFromLocations
80 import com.android.healthconnect.testapps.toolbox.fieldviews.InputFieldView
81 import com.android.healthconnect.testapps.toolbox.utils.GeneralUtils.Companion.getMetaData
82 import java.time.Instant
83 import kotlin.reflect.KClass
84 
85 class InsertOrUpdateRecords {
86 
87     companion object {
88 
getStringValuenull89         private fun getStringValue(
90             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
91             fieldName: String,
92         ): String {
93             return mFieldNameToFieldInput[fieldName]?.getFieldValue().toString()
94         }
95 
getIntegerValuenull96         private fun getIntegerValue(
97             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
98             fieldName: String,
99         ): Int {
100             return getStringValue(mFieldNameToFieldInput, fieldName).toInt()
101         }
102 
getLongValuenull103         private fun getLongValue(
104             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
105             fieldName: String,
106         ): Long {
107             return getStringValue(mFieldNameToFieldInput, fieldName).toLong()
108         }
109 
getDoubleValuenull110         private fun getDoubleValue(
111             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
112             fieldName: String,
113         ): Double {
114             return getStringValue(mFieldNameToFieldInput, fieldName).toDouble()
115         }
116 
getStartTimenull117         private fun getStartTime(
118             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
119         ): Instant {
120             return mFieldNameToFieldInput["startTime"]?.getFieldValue() as Instant
121         }
122 
getEndTimenull123         private fun getEndTime(
124             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
125         ): Instant {
126             return mFieldNameToFieldInput["endTime"]?.getFieldValue() as Instant
127         }
128 
getTimenull129         private fun getTime(
130             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
131         ): Instant {
132             return mFieldNameToFieldInput["time"]?.getFieldValue() as Instant
133         }
134 
getMassnull135         private fun getMass(
136             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
137             fieldName: String,
138         ): Mass {
139             return Mass.fromGrams(getDoubleValue(mFieldNameToFieldInput, fieldName))
140         }
141 
getTemperaturenull142         private fun getTemperature(
143             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
144             fieldName: String
145         ): Temperature {
146             return Temperature.fromCelsius(getDoubleValue(mFieldNameToFieldInput, fieldName))
147         }
148 
createRecordObjectnull149         fun createRecordObject(
150             recordClass: KClass<out Record>,
151             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
152             context: Context,
153             recordUuid: String,
154         ): Record {
155             return createRecordObjectHelper(
156                 recordClass, mFieldNameToFieldInput, getMetaData(context, recordUuid))
157         }
158 
createRecordObjectnull159         fun createRecordObject(
160             recordClass: KClass<out Record>,
161             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
162             context: Context,
163         ): Record {
164             return createRecordObjectHelper(
165                 recordClass, mFieldNameToFieldInput, getMetaData(context))
166         }
167 
createRecordObjectHelpernull168         private fun createRecordObjectHelper(
169             recordClass: KClass<out Record>,
170             mFieldNameToFieldInput: HashMap<String, InputFieldView>,
171             metaData: Metadata,
172         ): Record {
173             val record: Record
174             when (recordClass) {
175                 StepsRecord::class -> {
176                     record =
177                         StepsRecord.Builder(
178                                 metaData,
179                                 getStartTime(mFieldNameToFieldInput),
180                                 getEndTime(mFieldNameToFieldInput),
181                                 getLongValue(mFieldNameToFieldInput, "mCount"))
182                             .build()
183                 }
184                 DistanceRecord::class -> {
185                     record =
186                         DistanceRecord.Builder(
187                                 metaData,
188                                 getStartTime(mFieldNameToFieldInput),
189                                 getEndTime(mFieldNameToFieldInput),
190                                 Length.fromMeters(
191                                     getDoubleValue(mFieldNameToFieldInput, "mDistance")))
192                             .build()
193                 }
194                 ActiveCaloriesBurnedRecord::class -> {
195                     record =
196                         ActiveCaloriesBurnedRecord.Builder(
197                                 metaData,
198                                 getStartTime(mFieldNameToFieldInput),
199                                 getEndTime(mFieldNameToFieldInput),
200                                 Energy.fromCalories(
201                                     getDoubleValue(mFieldNameToFieldInput, "mEnergy")))
202                             .build()
203                 }
204                 ElevationGainedRecord::class -> {
205                     record =
206                         ElevationGainedRecord.Builder(
207                                 metaData,
208                                 getStartTime(mFieldNameToFieldInput),
209                                 getEndTime(mFieldNameToFieldInput),
210                                 Length.fromMeters(
211                                     getDoubleValue(mFieldNameToFieldInput, "mElevation")))
212                             .build()
213                 }
214                 BasalMetabolicRateRecord::class -> {
215                     record =
216                         BasalMetabolicRateRecord.Builder(
217                                 metaData,
218                                 getTime(mFieldNameToFieldInput),
219                                 Power.fromWatts(
220                                     getDoubleValue(mFieldNameToFieldInput, "mBasalMetabolicRate")))
221                             .build()
222                 }
223                 SpeedRecord::class -> {
224                     record =
225                         SpeedRecord.Builder(
226                                 metaData,
227                                 getStartTime(mFieldNameToFieldInput),
228                                 getEndTime(mFieldNameToFieldInput),
229                                 mFieldNameToFieldInput["mSpeedRecordSamples"]?.getFieldValue()
230                                     as List<SpeedRecordSample>)
231                             .build()
232                 }
233                 HeartRateRecord::class -> {
234                     record =
235                         HeartRateRecord.Builder(
236                                 metaData,
237                                 getStartTime(mFieldNameToFieldInput),
238                                 getEndTime(mFieldNameToFieldInput),
239                                 mFieldNameToFieldInput["mHeartRateSamples"]?.getFieldValue()
240                                     as List<HeartRateSample>)
241                             .build()
242                 }
243                 PowerRecord::class -> {
244                     record =
245                         PowerRecord.Builder(
246                                 metaData,
247                                 getStartTime(mFieldNameToFieldInput),
248                                 getEndTime(mFieldNameToFieldInput),
249                                 mFieldNameToFieldInput["mPowerRecordSamples"]?.getFieldValue()
250                                     as List<PowerRecordSample>)
251                             .build()
252                 }
253                 CyclingPedalingCadenceRecord::class -> {
254                     record =
255                         CyclingPedalingCadenceRecord.Builder(
256                                 metaData,
257                                 getStartTime(mFieldNameToFieldInput),
258                                 getEndTime(mFieldNameToFieldInput),
259                                 mFieldNameToFieldInput["mCyclingPedalingCadenceRecordSamples"]
260                                     ?.getFieldValue() as List<CyclingPedalingCadenceRecordSample>)
261                             .build()
262                 }
263                 FloorsClimbedRecord::class -> {
264                     record =
265                         FloorsClimbedRecord.Builder(
266                                 metaData,
267                                 getStartTime(mFieldNameToFieldInput),
268                                 getEndTime(mFieldNameToFieldInput),
269                                 getDoubleValue(mFieldNameToFieldInput, "mFloors"))
270                             .build()
271                 }
272                 TotalCaloriesBurnedRecord::class -> {
273                     record =
274                         TotalCaloriesBurnedRecord.Builder(
275                                 metaData,
276                                 getStartTime(mFieldNameToFieldInput),
277                                 getEndTime(mFieldNameToFieldInput),
278                                 Energy.fromCalories(
279                                     getDoubleValue(mFieldNameToFieldInput, "mEnergy")))
280                             .build()
281                 }
282                 WheelchairPushesRecord::class -> {
283                     record =
284                         WheelchairPushesRecord.Builder(
285                                 metaData,
286                                 getStartTime(mFieldNameToFieldInput),
287                                 getEndTime(mFieldNameToFieldInput),
288                                 getLongValue(mFieldNameToFieldInput, "mCount"))
289                             .build()
290                 }
291                 Vo2MaxRecord::class -> {
292                     record =
293                         Vo2MaxRecord.Builder(
294                                 metaData,
295                                 getTime(mFieldNameToFieldInput),
296                                 getIntegerValue(mFieldNameToFieldInput, "mMeasurementMethod"),
297                                 getDoubleValue(
298                                     mFieldNameToFieldInput, "mVo2MillilitersPerMinuteKilogram"))
299                             .build()
300                 }
301                 BodyFatRecord::class -> {
302                     record =
303                         BodyFatRecord.Builder(
304                                 metaData,
305                                 getTime(mFieldNameToFieldInput),
306                                 Percentage.fromValue(
307                                     getDoubleValue(mFieldNameToFieldInput, "mPercentage")))
308                             .build()
309                 }
310                 BodyWaterMassRecord::class -> {
311                     record =
312                         BodyWaterMassRecord.Builder(
313                                 metaData,
314                                 getTime(mFieldNameToFieldInput),
315                                 getMass(mFieldNameToFieldInput, "mBodyWaterMass"))
316                             .build()
317                 }
318                 BoneMassRecord::class -> {
319                     record =
320                         BoneMassRecord.Builder(
321                                 metaData,
322                                 getTime(mFieldNameToFieldInput),
323                                 getMass(mFieldNameToFieldInput, "mMass"))
324                             .build()
325                 }
326                 HeightRecord::class -> {
327                     record =
328                         HeightRecord.Builder(
329                                 metaData,
330                                 getTime(mFieldNameToFieldInput),
331                                 Length.fromMeters(
332                                     getDoubleValue(mFieldNameToFieldInput, "mHeight")))
333                             .build()
334                 }
335                 LeanBodyMassRecord::class -> {
336                     record =
337                         LeanBodyMassRecord.Builder(
338                                 metaData,
339                                 getTime(mFieldNameToFieldInput),
340                                 getMass(mFieldNameToFieldInput, "mMass"))
341                             .build()
342                 }
343                 WeightRecord::class -> {
344                     record =
345                         WeightRecord.Builder(
346                                 metaData,
347                                 getTime(mFieldNameToFieldInput),
348                                 getMass(mFieldNameToFieldInput, "mWeight"))
349                             .build()
350                 }
351                 CervicalMucusRecord::class -> {
352                     record =
353                         CervicalMucusRecord.Builder(
354                                 metaData,
355                                 getTime(mFieldNameToFieldInput),
356                                 getIntegerValue(mFieldNameToFieldInput, "mSensation"),
357                                 getIntegerValue(mFieldNameToFieldInput, "mAppearance"))
358                             .build()
359                 }
360                 MenstruationFlowRecord::class -> {
361                     record =
362                         MenstruationFlowRecord.Builder(
363                                 metaData,
364                                 getTime(mFieldNameToFieldInput),
365                                 getIntegerValue(mFieldNameToFieldInput, "mFlow"))
366                             .build()
367                 }
368                 OvulationTestRecord::class -> {
369                     record =
370                         OvulationTestRecord.Builder(
371                                 metaData,
372                                 getTime(mFieldNameToFieldInput),
373                                 getIntegerValue(mFieldNameToFieldInput, "mResult"))
374                             .build()
375                 }
376                 SexualActivityRecord::class -> {
377                     record =
378                         SexualActivityRecord.Builder(
379                                 metaData,
380                                 getTime(mFieldNameToFieldInput),
381                                 getIntegerValue(mFieldNameToFieldInput, "mProtectionUsed"))
382                             .build()
383                 }
384                 HydrationRecord::class -> {
385                     record =
386                         HydrationRecord.Builder(
387                                 metaData,
388                                 getStartTime(mFieldNameToFieldInput),
389                                 getEndTime(mFieldNameToFieldInput),
390                                 Volume.fromLiters(
391                                     getDoubleValue(mFieldNameToFieldInput, "mVolume")))
392                             .build()
393                 }
394                 IntermenstrualBleedingRecord::class -> {
395                     record =
396                         IntermenstrualBleedingRecord.Builder(
397                                 metaData, getTime(mFieldNameToFieldInput))
398                             .build()
399                 }
400                 BasalBodyTemperatureRecord::class -> {
401                     record =
402                         BasalBodyTemperatureRecord.Builder(
403                                 metaData,
404                                 getTime(mFieldNameToFieldInput),
405                                 getIntegerValue(
406                                     mFieldNameToFieldInput, "mBodyTemperatureMeasurementLocation"),
407                                 Temperature.fromCelsius(
408                                     getDoubleValue(mFieldNameToFieldInput, "mTemperature")))
409                             .build()
410                 }
411                 BloodGlucoseRecord::class -> {
412                     record =
413                         BloodGlucoseRecord.Builder(
414                                 metaData,
415                                 getTime(mFieldNameToFieldInput),
416                                 getIntegerValue(mFieldNameToFieldInput, "mSpecimenSource"),
417                                 BloodGlucose.fromMillimolesPerLiter(
418                                     getDoubleValue(mFieldNameToFieldInput, "mLevel")),
419                                 getIntegerValue(mFieldNameToFieldInput, "mRelationToMeal"),
420                                 getIntegerValue(mFieldNameToFieldInput, "mMealType"))
421                             .build()
422                 }
423                 BloodPressureRecord::class -> {
424                     record =
425                         BloodPressureRecord.Builder(
426                                 metaData,
427                                 getTime(mFieldNameToFieldInput),
428                                 getIntegerValue(mFieldNameToFieldInput, "mMeasurementLocation"),
429                                 Pressure.fromMillimetersOfMercury(
430                                     getDoubleValue(mFieldNameToFieldInput, "mSystolic")),
431                                 Pressure.fromMillimetersOfMercury(
432                                     getDoubleValue(mFieldNameToFieldInput, "mDiastolic")),
433                                 getIntegerValue(mFieldNameToFieldInput, "mBodyPosition"))
434                             .build()
435                 }
436                 BodyTemperatureRecord::class -> {
437                     record =
438                         BodyTemperatureRecord.Builder(
439                                 metaData,
440                                 getTime(mFieldNameToFieldInput),
441                                 getIntegerValue(mFieldNameToFieldInput, "mMeasurementLocation"),
442                                 Temperature.fromCelsius(
443                                     getDoubleValue(mFieldNameToFieldInput, "mTemperature")))
444                             .build()
445                 }
446                 HeartRateVariabilityRmssdRecord::class -> {
447                     record =
448                         HeartRateVariabilityRmssdRecord.Builder(
449                                 metaData,
450                                 getTime(mFieldNameToFieldInput),
451                                 getDoubleValue(
452                                     mFieldNameToFieldInput, "mHeartRateVariabilityMillis"))
453                             .build()
454                 }
455                 OxygenSaturationRecord::class -> {
456                     record =
457                         OxygenSaturationRecord.Builder(
458                                 metaData,
459                                 getTime(mFieldNameToFieldInput),
460                                 Percentage.fromValue(
461                                     getDoubleValue(mFieldNameToFieldInput, "mPercentage")))
462                             .build()
463                 }
464                 RespiratoryRateRecord::class -> {
465                     record =
466                         RespiratoryRateRecord.Builder(
467                                 metaData,
468                                 getTime(mFieldNameToFieldInput),
469                                 getDoubleValue(mFieldNameToFieldInput, "mRate"))
470                             .build()
471                 }
472                 RestingHeartRateRecord::class -> {
473                     record =
474                         RestingHeartRateRecord.Builder(
475                                 metaData,
476                                 getTime(mFieldNameToFieldInput),
477                                 getLongValue(mFieldNameToFieldInput, "mBeatsPerMinute"))
478                             .build()
479                 }
480                 SkinTemperatureRecord::class -> {
481                     record =
482                         SkinTemperatureRecord.Builder(
483                                 metaData,
484                                 getStartTime(mFieldNameToFieldInput),
485                                 getEndTime(mFieldNameToFieldInput))
486                             .apply {
487                                 if (!mFieldNameToFieldInput["mDeltas"]!!.isEmpty()) {
488                                     setDeltas(
489                                         mFieldNameToFieldInput["mDeltas"]?.getFieldValue()
490                                             as List<SkinTemperatureRecord.Delta>)
491                                 }
492                                 if (!mFieldNameToFieldInput["mBaseline"]!!.isEmpty()) {
493                                     setBaseline(getTemperature(mFieldNameToFieldInput, "mBaseline"))
494                                 }
495                                 if (!mFieldNameToFieldInput["mMeasurementLocation"]!!.isEmpty()) {
496                                     setMeasurementLocation(
497                                         getIntegerValue(
498                                             mFieldNameToFieldInput, "mMeasurementLocation"))
499                                 }
500                             }
501                             .build()
502                 }
503                 SleepSessionRecord::class -> {
504                     record =
505                         SleepSessionRecord.Builder(
506                                 metaData,
507                                 getStartTime(mFieldNameToFieldInput),
508                                 getEndTime(mFieldNameToFieldInput))
509                             .apply {
510                                 if (!mFieldNameToFieldInput["mNotes"]!!.isEmpty()) {
511                                     setNotes(getStringValue(mFieldNameToFieldInput, "mNotes"))
512                                 }
513                                 if (!mFieldNameToFieldInput["mTitle"]!!.isEmpty()) {
514                                     setTitle(getStringValue(mFieldNameToFieldInput, "mTitle"))
515                                 }
516                                 if (!mFieldNameToFieldInput["mStages"]!!.isEmpty()) {
517                                     setStages(
518                                         mFieldNameToFieldInput["mStages"]?.getFieldValue()
519                                             as List<SleepSessionRecord.Stage>)
520                                 }
521                             }
522                             .build()
523                 }
524                 StepsCadenceRecord::class -> {
525                     record =
526                         StepsCadenceRecord.Builder(
527                                 metaData,
528                                 getStartTime(mFieldNameToFieldInput),
529                                 getEndTime(mFieldNameToFieldInput),
530                                 mFieldNameToFieldInput["mStepsCadenceRecordSamples"]
531                                     ?.getFieldValue() as List<StepsCadenceRecordSample>)
532                             .build()
533                 }
534                 MenstruationPeriodRecord::class -> {
535                     record =
536                         MenstruationPeriodRecord.Builder(
537                                 metaData,
538                                 getStartTime(mFieldNameToFieldInput),
539                                 getEndTime(mFieldNameToFieldInput))
540                             .build()
541                 }
542                 ExerciseSessionRecord::class -> {
543                     val startTime = mFieldNameToFieldInput["startTime"]?.getFieldValue() as Instant
544 
545                     record =
546                         ExerciseSessionRecord.Builder(
547                                 metaData,
548                                 startTime,
549                                 mFieldNameToFieldInput["endTime"]?.getFieldValue() as Instant,
550                                 mFieldNameToFieldInput["mExerciseType"]
551                                     ?.getFieldValue()
552                                     .toString()
553                                     .toInt())
554                             .apply {
555                                 if (!mFieldNameToFieldInput["mNotes"]!!.isEmpty()) {
556                                     setNotes(getStringValue(mFieldNameToFieldInput, "mNotes"))
557                                 }
558                                 if (!mFieldNameToFieldInput["mTitle"]!!.isEmpty()) {
559                                     setTitle(getStringValue(mFieldNameToFieldInput, "mTitle"))
560                                 }
561                                 if (!mFieldNameToFieldInput["mExerciseRoute"]!!.isEmpty()) {
562                                     val exerciseRoutes =
563                                         mFieldNameToFieldInput["mExerciseRoute"]?.getFieldValue()
564                                             as
565                                             List<ExerciseRoutesTestData.ExerciseRouteLocationData>
566                                     setRoute(
567                                         generateExerciseRouteFromLocations(
568                                             exerciseRoutes, startTime.toEpochMilli()))
569                                 }
570                                 if (!mFieldNameToFieldInput["mSegments"]!!.isEmpty()) {
571                                     setSegments(
572                                         mFieldNameToFieldInput["mSegments"]?.getFieldValue()
573                                             as List<ExerciseSegment>)
574                                 }
575                                 if (!mFieldNameToFieldInput["mLaps"]!!.isEmpty()) {
576                                     setLaps(
577                                         mFieldNameToFieldInput["mLaps"]?.getFieldValue()
578                                             as List<ExerciseLap>)
579                                 }
580                             }
581                             .build()
582                 }
583                 PlannedExerciseSessionRecord::class -> {
584                     val startTime = mFieldNameToFieldInput["startTime"]?.getFieldValue() as Instant
585                     record =
586                         PlannedExerciseSessionRecord.Builder(
587                                 metaData,
588                                 mFieldNameToFieldInput["mPlannedExerciseType"]
589                                     ?.getFieldValue()
590                                     .toString()
591                                     .toInt(),
592                                 startTime,
593                                 mFieldNameToFieldInput["endTime"]?.getFieldValue() as Instant,
594                             )
595                             .apply {
596                                 if (!mFieldNameToFieldInput["mNotes"]!!.isEmpty()) {
597                                     setNotes(getStringValue(mFieldNameToFieldInput, "mNotes"))
598                                 }
599                                 if (!mFieldNameToFieldInput["mTitle"]!!.isEmpty()) {
600                                     setTitle(getStringValue(mFieldNameToFieldInput, "mTitle"))
601                                 }
602                                 if (!mFieldNameToFieldInput["mBlocks"]!!.isEmpty()) {
603                                     setBlocks(
604                                         mFieldNameToFieldInput["mBlocks"]?.getFieldValue()
605                                             as List<PlannedExerciseBlock>)
606                                 }
607                             }
608                             .build()
609                 }
610                 NutritionRecord::class -> {
611                     record =
612                         NutritionRecord.Builder(
613                                 metaData,
614                                 getStartTime(mFieldNameToFieldInput),
615                                 getEndTime(mFieldNameToFieldInput))
616                             .apply {
617                                 if (!mFieldNameToFieldInput["mBiotin"]!!.isEmpty()) {
618                                     setBiotin(getMass(mFieldNameToFieldInput, "mBiotin"))
619                                 }
620                                 if (!mFieldNameToFieldInput["mCaffeine"]!!.isEmpty()) {
621                                     setCaffeine(getMass(mFieldNameToFieldInput, "mCaffeine"))
622                                 }
623                                 if (!mFieldNameToFieldInput["mCalcium"]!!.isEmpty()) {
624                                     setCalcium(getMass(mFieldNameToFieldInput, "mCalcium"))
625                                 }
626                                 if (!mFieldNameToFieldInput["mChloride"]!!.isEmpty()) {
627                                     setChloride(getMass(mFieldNameToFieldInput, "mChloride"))
628                                 }
629                                 if (!mFieldNameToFieldInput["mCholesterol"]!!.isEmpty()) {
630                                     setCholesterol(getMass(mFieldNameToFieldInput, "mCholesterol"))
631                                 }
632                                 if (!mFieldNameToFieldInput["mChromium"]!!.isEmpty()) {
633                                     setChromium(getMass(mFieldNameToFieldInput, "mChromium"))
634                                 }
635                                 if (!mFieldNameToFieldInput["mDietaryFiber"]!!.isEmpty()) {
636                                     setDietaryFiber(
637                                         getMass(mFieldNameToFieldInput, "mDietaryFiber"))
638                                 }
639                                 if (!mFieldNameToFieldInput["mCopper"]!!.isEmpty()) {
640                                     setCopper(getMass(mFieldNameToFieldInput, "mCopper"))
641                                 }
642                                 if (!mFieldNameToFieldInput["mEnergy"]!!.isEmpty()) {
643                                     setEnergy(
644                                         Energy.fromCalories(
645                                             getDoubleValue(mFieldNameToFieldInput, "mEnergy")))
646                                 }
647                                 if (!mFieldNameToFieldInput["mFolate"]!!.isEmpty()) {
648                                     setFolate(getMass(mFieldNameToFieldInput, "mFolate"))
649                                 }
650                                 if (!mFieldNameToFieldInput["mEnergyFromFat"]!!.isEmpty()) {
651                                     setEnergyFromFat(
652                                         Energy.fromCalories(
653                                             getDoubleValue(
654                                                 mFieldNameToFieldInput, "mEnergyFromFat")))
655                                 }
656                                 if (!mFieldNameToFieldInput["mFolicAcid"]!!.isEmpty()) {
657                                     setFolicAcid(getMass(mFieldNameToFieldInput, "mFolicAcid"))
658                                 }
659                                 if (!mFieldNameToFieldInput["mIodine"]!!.isEmpty()) {
660                                     setIodine(getMass(mFieldNameToFieldInput, "mIodine"))
661                                 }
662                                 if (!mFieldNameToFieldInput["mIron"]!!.isEmpty()) {
663                                     setIron(getMass(mFieldNameToFieldInput, "mIron"))
664                                 }
665                                 if (!mFieldNameToFieldInput["mMagnesium"]!!.isEmpty()) {
666                                     setMagnesium(getMass(mFieldNameToFieldInput, "mMagnesium"))
667                                 }
668                                 if (!mFieldNameToFieldInput["mManganese"]!!.isEmpty()) {
669                                     setManganese(getMass(mFieldNameToFieldInput, "mManganese"))
670                                 }
671                             }
672                             .build()
673                 }
674                 else -> {
675                     throw NotImplementedError("Record type not implemented")
676                 }
677             }
678             return record
679         }
680     }
681 }
682