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