1/*
2 * Copyright (C) 2017 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
17package android.arch.persistence.room.solver.binderprovider
18
19import android.arch.persistence.room.ext.RoomRxJava2TypeNames
20import android.arch.persistence.room.ext.typeName
21import android.arch.persistence.room.parser.ParsedQuery
22import android.arch.persistence.room.processor.Context
23import android.arch.persistence.room.processor.ProcessorErrors
24import android.arch.persistence.room.solver.QueryResultBinderProvider
25import android.arch.persistence.room.solver.query.result.InstantQueryResultBinder
26import android.arch.persistence.room.solver.query.result.QueryResultBinder
27import android.arch.persistence.room.solver.query.result.RxCallableQueryResultBinder
28import javax.lang.model.type.DeclaredType
29
30sealed class RxCallableQueryResultBinderProvider(val context: Context,
31                                                 val rxType: RxCallableQueryResultBinder.RxType)
32    : QueryResultBinderProvider {
33    private val hasRxJava2Artifact by lazy {
34        context.processingEnv.elementUtils
35                .getTypeElement(RoomRxJava2TypeNames.RX_ROOM.toString()) != null
36    }
37
38    override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
39        val typeArg = declared.typeArguments.first()
40        val adapter = context.typeAdapterStore.findQueryResultAdapter(typeArg, query)
41        return RxCallableQueryResultBinder(rxType,
42                typeArg, InstantQueryResultBinder(adapter), adapter)
43    }
44
45    override fun matches(declared: DeclaredType): Boolean =
46            declared.typeArguments.size == 1 && matchesRxType(declared)
47
48    private fun matchesRxType(declared: DeclaredType): Boolean {
49        val erasure = context.processingEnv.typeUtils.erasure(declared)
50        val match = erasure.typeName() == rxType.className
51        if (match && !hasRxJava2Artifact) {
52            context.logger.e(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
53        }
54        return match
55    }
56}
57
58class RxSingleQueryResultBinderProvider(context: Context)
59    : RxCallableQueryResultBinderProvider(context, RxCallableQueryResultBinder.RxType.SINGLE)
60
61class RxMaybeQueryResultBinderProvider(context: Context)
62    : RxCallableQueryResultBinderProvider(context, RxCallableQueryResultBinder.RxType.MAYBE)
63