19fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik/*
29fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * Copyright (C) 2017 The Android Open Source Project
39fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik *
49fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * Licensed under the Apache License, Version 2.0 (the "License");
59fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * you may not use this file except in compliance with the License.
69fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * You may obtain a copy of the License at
79fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik *
89fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik *      http://www.apache.org/licenses/LICENSE-2.0
99fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik *
109fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * Unless required by applicable law or agreed to in writing, software
119fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * distributed under the License is distributed on an "AS IS" BASIS,
129fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * See the License for the specific language governing permissions and
149fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * limitations under the License.
159fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik */
169fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
17bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverettepackage androidx.room.solver.binderprovider
189fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
19bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.ext.PagingTypeNames
20bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.parser.ParsedQuery
21bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.processor.Context
22bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.processor.ProcessorErrors
23bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.solver.QueryResultBinderProvider
24bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.solver.query.result.DataSourceFactoryQueryResultBinder
25bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.solver.query.result.ListQueryResultAdapter
26bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.solver.query.result.PositionalDataSourceQueryResultBinder
27bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.solver.query.result.QueryResultBinder
289fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport javax.lang.model.type.DeclaredType
299fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport javax.lang.model.type.TypeMirror
309fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
31dc60cacc66972b47f27acdf727332878ce5958aeChris Craikclass DataSourceFactoryQueryResultBinderProvider(val context: Context) : QueryResultBinderProvider {
32dc60cacc66972b47f27acdf727332878ce5958aeChris Craik    private val dataSourceFactoryTypeMirror: TypeMirror? by lazy {
339fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        context.processingEnv.elementUtils
34dc60cacc66972b47f27acdf727332878ce5958aeChris Craik                .getTypeElement(PagingTypeNames.DATA_SOURCE_FACTORY.toString())?.asType()
359fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    }
369fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
379fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
38cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar        if (query.tables.isEmpty()) {
39cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar            context.logger.e(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
40cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar        }
412e9d5136685b07ef5bfabcd3936b1eedb5d24e91Chris Craik        val typeArg = declared.typeArguments[1]
421b805d37217a328107a7ad021c877d3c224e5869Chris Craik        val adapter = context.typeAdapterStore.findRowAdapter(typeArg, query)?.let {
439fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            ListQueryResultAdapter(it)
449fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        }
451b805d37217a328107a7ad021c877d3c224e5869Chris Craik
461b805d37217a328107a7ad021c877d3c224e5869Chris Craik        val tableNames = ((adapter?.accessedTableNames() ?: emptyList())
471b805d37217a328107a7ad021c877d3c224e5869Chris Craik                + query.tables.map { it.name }).toSet()
481b805d37217a328107a7ad021c877d3c224e5869Chris Craik        val countedBinder = PositionalDataSourceQueryResultBinder(adapter, tableNames)
491b805d37217a328107a7ad021c877d3c224e5869Chris Craik        return DataSourceFactoryQueryResultBinder(countedBinder)
509fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    }
519fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
529fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    override fun matches(declared: DeclaredType): Boolean =
532e9d5136685b07ef5bfabcd3936b1eedb5d24e91Chris Craik            declared.typeArguments.size == 2 && isLivePagedList(declared)
549fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
559fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    private fun isLivePagedList(declared: DeclaredType): Boolean {
56dc60cacc66972b47f27acdf727332878ce5958aeChris Craik        if (dataSourceFactoryTypeMirror == null) {
579fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            return false
589fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        }
599fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        val erasure = context.processingEnv.typeUtils.erasure(declared)
609fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        // we don't want to return paged list unless explicitly requested
61dc60cacc66972b47f27acdf727332878ce5958aeChris Craik        return context.processingEnv.typeUtils.isAssignable(dataSourceFactoryTypeMirror, erasure)
629fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    }
63dc60cacc66972b47f27acdf727332878ce5958aeChris Craik}
64