1 /*
2  * Copyright (C) 2022 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 com.android.quicksearchbox
17 
18 import android.app.SearchManager
19 import android.database.AbstractCursor
20 import android.database.CursorIndexOutOfBoundsException
21 import kotlin.collections.ArrayList
22 
23 class SuggestionCursorBackedCursor(private val mCursor: SuggestionCursor?) : AbstractCursor() {
24   private var mExtraColumns: ArrayList<String>? = null
25 
26   @Override
closenull27   override fun close() {
28     super.close()
29     mCursor?.close()
30   }
31 
32   @Override
getColumnNamesnull33   override fun getColumnNames(): Array<String> {
34     val extraColumns: Collection<String>? = mCursor?.extraColumns
35     return if (extraColumns != null) {
36       val allColumns: ArrayList<String> = ArrayList<String>(COLUMNS.size + extraColumns.size)
37       mExtraColumns = ArrayList<String>(extraColumns)
38       allColumns.addAll(COLUMNS.asList())
39       mExtraColumns?.let { allColumns.addAll(it) }
40       allColumns.toArray(arrayOfNulls<String>(allColumns.size))
41     } else {
42       COLUMNS
43     }
44   }
45 
46   @Override
getCountnull47   override fun getCount(): Int {
48     return mCursor!!.count
49   }
50 
getnull51   private fun get(): SuggestionCursor? {
52     mCursor?.moveTo(position)
53     return mCursor
54   }
55 
getExtranull56   private fun getExtra(columnIdx: Int): String? {
57     val extraColumn = columnIdx - COLUMNS.size
58     val extras: SuggestionExtras? = get()?.extras
59     return extras?.getExtra(mExtraColumns!!.get(extraColumn))
60   }
61 
62   @Override
getIntnull63   override fun getInt(column: Int): Int {
64     return if (column == COLUMN_INDEX_ID) {
65       position
66     } else {
67       try {
68         getString(column)!!.toInt()
69       } catch (e: NumberFormatException) {
70         0
71       }
72     }
73   }
74 
75   @Override
getStringnull76   override fun getString(column: Int): String? {
77     return if (column < COLUMNS.size) {
78       when (column) {
79         COLUMN_INDEX_ID -> position.toString()
80         COLUMN_INDEX_TEXT1 -> get()?.suggestionText1
81         COLUMN_INDEX_TEXT2 -> get()?.suggestionText2
82         COLUMN_INDEX_TEXT2_URL -> get()?.suggestionText2Url
83         COLUMN_INDEX_ICON1 -> get()?.suggestionIcon1
84         COLUMN_INDEX_ICON2 -> get()?.suggestionIcon2
85         COLUMN_INDEX_INTENT_ACTION -> get()?.suggestionIntentAction
86         COLUMN_INDEX_INTENT_DATA -> get()?.suggestionIntentDataString
87         COLUMN_INDEX_INTENT_EXTRA_DATA -> get()?.suggestionIntentExtraData
88         COLUMN_INDEX_QUERY -> get()?.suggestionQuery
89         COLUMN_INDEX_FORMAT -> get()?.suggestionFormat
90         COLUMN_INDEX_SHORTCUT_ID -> get()?.shortcutId
91         COLUMN_INDEX_SPINNER_WHILE_REFRESHING -> get()?.isSpinnerWhileRefreshing.toString()
92         else ->
93           throw CursorIndexOutOfBoundsException(
94             "Requested column " + column + " of " + COLUMNS.size
95           )
96       }
97     } else {
98       getExtra(column)
99     }
100   }
101 
102   @Override
getLongnull103   override fun getLong(column: Int): Long {
104     return try {
105       getString(column)!!.toLong()
106     } catch (e: NumberFormatException) {
107       0
108     }
109   }
110 
111   @Override
isNullnull112   override fun isNull(column: Int): Boolean {
113     return getString(column) == null
114   }
115 
116   @Override
getShortnull117   override fun getShort(column: Int): Short {
118     return try {
119       getString(column)!!.toShort()
120     } catch (e: NumberFormatException) {
121       0
122     }
123   }
124 
125   @Override
getDoublenull126   override fun getDouble(column: Int): Double {
127     return try {
128       getString(column)!!.toDouble()
129     } catch (e: NumberFormatException) {
130       0.0
131     }
132   }
133 
134   @Override
getFloatnull135   override fun getFloat(column: Int): Float {
136     return try {
137       getString(column)!!.toFloat()
138     } catch (e: NumberFormatException) {
139       0.0F
140     }
141   }
142 
143   companion object {
144     // This array also used in CursorBackedSuggestionExtras to avoid duplication.
145     val COLUMNS =
146       arrayOf(
147         "_id", // 0, This will contain the row number. CursorAdapter, used by SuggestionsAdapter,
148         // used by SearchDialog, expects an _id column.
149         SearchManager.SUGGEST_COLUMN_TEXT_1, // 1
150         SearchManager.SUGGEST_COLUMN_TEXT_2, // 2
151         SearchManager.SUGGEST_COLUMN_TEXT_2_URL, // 3
152         SearchManager.SUGGEST_COLUMN_ICON_1, // 4
153         SearchManager.SUGGEST_COLUMN_ICON_2, // 5
154         SearchManager.SUGGEST_COLUMN_INTENT_ACTION, // 6
155         SearchManager.SUGGEST_COLUMN_INTENT_DATA, // 7
156         SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA, // 8
157         SearchManager.SUGGEST_COLUMN_QUERY, // 9
158         SearchManager.SUGGEST_COLUMN_FORMAT, // 10
159         SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, // 11
160         SearchManager.SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING
161       )
162     private const val COLUMN_INDEX_ID = 0
163     private const val COLUMN_INDEX_TEXT1 = 1
164     private const val COLUMN_INDEX_TEXT2 = 2
165     private const val COLUMN_INDEX_TEXT2_URL = 3
166     private const val COLUMN_INDEX_ICON1 = 4
167     private const val COLUMN_INDEX_ICON2 = 5
168     private const val COLUMN_INDEX_INTENT_ACTION = 6
169     private const val COLUMN_INDEX_INTENT_DATA = 7
170     private const val COLUMN_INDEX_INTENT_EXTRA_DATA = 8
171     private const val COLUMN_INDEX_QUERY = 9
172     private const val COLUMN_INDEX_FORMAT = 10
173     private const val COLUMN_INDEX_SHORTCUT_ID = 11
174     private const val COLUMN_INDEX_SPINNER_WHILE_REFRESHING = 12
175   }
176 }
177