1 /**
2  * Copyright (C) 2023 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  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package com.android.healthconnect.controller.dataentries.formatters.shared
15 
16 import android.content.Context
17 import android.health.connect.datatypes.InstantRecord
18 import android.health.connect.datatypes.IntervalRecord
19 import android.health.connect.datatypes.Record
20 import com.android.healthconnect.controller.R
21 import com.android.healthconnect.controller.data.entries.FormattedEntry
22 import com.android.healthconnect.controller.dataentries.units.UnitPreferences
23 import com.android.healthconnect.controller.shared.DataType
24 import com.android.healthconnect.controller.utils.LocalDateTimeFormatter
25 import java.time.Instant
26 
27 /** Abstract formatter for Record types. This formatter handles header for FormattedEntries. */
28 abstract class BaseFormatter<T : Record>(private val context: Context) : Formatter<T> {
29 
30     private val timeFormatter = LocalDateTimeFormatter(context)
31     protected val unitPreferences = UnitPreferences(context)
32 
formatnull33     override suspend fun format(record: T, appName: String): FormattedEntry {
34         return formatRecord(
35             record = record,
36             header = getHeader(record, appName),
37             headerA11y = getHeaderA11y(record, appName),
38             unitPreferences = unitPreferences)
39     }
40 
formatRecordnull41     abstract suspend fun formatRecord(
42         record: T,
43         header: String,
44         headerA11y: String,
45         unitPreferences: UnitPreferences
46     ): FormattedEntry
47 
48     protected fun getDataType(record: T): DataType {
49         return DataType.values().first { it.recordClass == record::class.java }
50     }
51 
getStartTimenull52     protected fun getStartTime(record: T): Instant {
53         return when (record) {
54             is IntervalRecord -> record.startTime
55             is InstantRecord -> record.time
56             else -> throw IllegalArgumentException("${record::class.java} Not supported!")
57         }
58     }
59 
getHeadernull60     private fun getHeader(record: T, appName: String): String {
61         if (appName == "")
62             return context.getString(
63                 R.string.data_entry_header_without_source_app, getFormattedTime(record))
64         return context.getString(
65             R.string.data_entry_header_with_source_app, getFormattedTime(record), appName)
66     }
67 
getHeaderA11ynull68     private fun getHeaderA11y(record: T, appName: String): String {
69         if (appName == "")
70             return context.getString(
71                 R.string.data_entry_header_without_source_app, getFormattedA11yTime(record))
72         return context.getString(
73             R.string.data_entry_header_with_source_app, getFormattedA11yTime(record), appName)
74     }
75 
getFormattedTimenull76     private fun getFormattedTime(record: T): String {
77         return when (record) {
78             is IntervalRecord -> timeFormatter.formatTimeRange(record.startTime, record.endTime)
79             is InstantRecord -> timeFormatter.formatTime(record.time)
80             else -> throw IllegalArgumentException("${record::class.java} Not supported!")
81         }
82     }
83 
getFormattedA11yTimenull84     private fun getFormattedA11yTime(record: T): String {
85         return when (record) {
86             is IntervalRecord -> timeFormatter.formatTimeRangeA11y(record.startTime, record.endTime)
87             is InstantRecord -> timeFormatter.formatTime(record.time)
88             else -> throw IllegalArgumentException("${record::class.java} Not supported!")
89         }
90     }
91 }
92