1 /*
2  * Copyright (C) 2023 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 
17 package com.android.tools.metalava.model.source
18 
19 import com.android.tools.metalava.model.ModelOptions
20 import com.android.tools.metalava.model.provider.FilterableCodebaseCreator
21 import java.util.ServiceLoader
22 
23 /** Service provider interface for a model implementation that consumes source code. */
24 interface SourceModelProvider : FilterableCodebaseCreator {
25 
26     /**
27      * Create an [EnvironmentManager] that will manage any resources needed while creating
28      * [SourceCodebase]s from source files.
29      *
30      * @param disableStderrDumping if false then the manager will output useful information to
31      *   stderr, otherwise it will suppress the errors.
32      * @param forTesting if true then the manager is being used in tests and should behave
33      *   appropriately.
34      */
createEnvironmentManagernull35     fun createEnvironmentManager(
36         disableStderrDumping: Boolean = false,
37         forTesting: Boolean = false,
38     ): EnvironmentManager
39 
40     /**
41      * A list of sets of [ModelOptions] that must be tested.
42      *
43      * Default to a list of [ModelOptions.empty].
44      */
45     val modelOptionsList: List<ModelOptions>
46         get() = listOf(ModelOptions.empty)
47 
48     companion object {
49         /**
50          * Implementations of this interface that were found by the [ServiceLoader] in the
51          * [ClassLoader] from which this class was loaded.
52          */
53         val implementations by lazy { ServiceLoader.load(SourceModelProvider::class.java).toList() }
54 
55         /**
56          * Get an implementation of this interface that matches the [filter].
57          *
58          * @param filter the filter that selects the required provider.
59          * @throws IllegalStateException if there is not exactly one provider that matches.
60          */
61         fun getImplementation(
62             filter: (SourceModelProvider) -> Boolean,
63             filterDescription: String
64         ): SourceModelProvider {
65             val sourceModelProviders = implementations.filter(filter).toList()
66             return sourceModelProviders.singleOrNull()
67                 ?: throw IllegalStateException(
68                     "Expected exactly one SourceModelProvider $filterDescription but found $implementations of which $sourceModelProviders matched"
69                 )
70         }
71 
72         /**
73          * Get an implementation of this interface that matches the [requiredProvider].
74          *
75          * @param requiredProvider the [SourceModelProvider.providerName] of the required provider.
76          * @throws IllegalStateException if there is not exactly one provider that matches.
77          */
78         fun getImplementation(requiredProvider: String): SourceModelProvider {
79             return getImplementation(
80                 { it.providerName == requiredProvider },
81                 "called $requiredProvider"
82             )
83         }
84     }
85 }
86