1 /*
<lambda>null2  * 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 
17 package com.android.libraries.pcc.chronicle.analysis
18 
19 import com.android.libraries.pcc.chronicle.api.Connection
20 import com.android.libraries.pcc.chronicle.api.ConnectionProvider
21 import com.android.libraries.pcc.chronicle.api.DataTypeDescriptor
22 import com.android.libraries.pcc.chronicle.api.DataTypeDescriptorSet
23 import com.android.libraries.pcc.chronicle.api.ManagementStrategy
24 import com.android.libraries.pcc.chronicle.api.ProcessorNode
25 import com.android.libraries.pcc.chronicle.api.error.ConnectionTypeAmbiguity
26 import com.android.libraries.pcc.chronicle.util.TypedMap
27 
28 /**
29  * Default implementation of [ChronicleContext] configured and intended to represent the data-flow
30  * characteristics and requirements of Chronicle in the process.
31  */
32 class DefaultChronicleContext(
33   override val connectionProviders: Set<ConnectionProvider>,
34   override val processorNodes: Set<ProcessorNode>,
35   override val policySet: PolicySet,
36   override val dataTypeDescriptorSet: DataTypeDescriptorSet,
37   override val connectionContext: TypedMap = TypedMap()
38 ) : ChronicleContext {
39   private val connectionProviderByType: Map<Class<out Connection>, ConnectionProvider>
40   private val dtdByType: Map<Class<out Connection>, DataTypeDescriptor>
41   private val mgmtStrategyByType: Map<Class<out Connection>, ManagementStrategy>
42 
43   // Note: It would be nice to not have to do this much work each time we create a new
44   // ChronicleContextImpl when adding a node.
45   init {
46     val tempConnectionProviders = mutableMapOf<Class<out Connection>, ConnectionProvider>()
47     val tempDtds = mutableMapOf<Class<out Connection>, DataTypeDescriptor>()
48     val tempMgmtProperties = mutableMapOf<Class<out Connection>, ManagementStrategy>()
49 
50     connectionProviders.forEach { connectionProvider ->
51       val dataType = connectionProvider.dataType
52       dataType.connectionTypes.forEach { connectionType ->
53         // Make sure we do not have connection ambiguity.
54         val existingConnectionProvider = tempConnectionProviders[connectionType]
55         if (existingConnectionProvider != null) {
56           throw ConnectionTypeAmbiguity(
57             connectionType,
58             setOf(existingConnectionProvider, connectionProvider)
59           )
60         }
61         tempConnectionProviders[connectionType] = connectionProvider
62         tempDtds[connectionType] = dataType.descriptor
63         tempMgmtProperties[connectionType] = dataType.managementStrategy
64       }
65     }
66 
67     connectionProviderByType = tempConnectionProviders
68     dtdByType = tempDtds
69     mgmtStrategyByType = tempMgmtProperties
70   }
71 
72   override fun <T : Connection> findConnectionProvider(
73     connectionType: Class<T>
74   ): ConnectionProvider? {
75     return connectionProviderByType[connectionType]
76   }
77 
78   override fun <T : Connection> findDataType(connectionType: Class<T>): DataTypeDescriptor? {
79     return dtdByType[connectionType]
80   }
81 
82   override fun withNode(node: ProcessorNode): ChronicleContext {
83     return DefaultChronicleContext(
84       connectionProviders = connectionProviders,
85       processorNodes = processorNodes + node,
86       policySet = policySet,
87       dataTypeDescriptorSet = dataTypeDescriptorSet,
88       connectionContext = connectionContext
89     )
90   }
91 
92   /**
93    * Returns a copy of the current [ChronicleContext] containing the provided [connectionContext].
94    */
95   override fun withConnectionContext(connectionContext: TypedMap): ChronicleContext {
96     return DefaultChronicleContext(
97       connectionProviders = connectionProviders,
98       processorNodes = processorNodes,
99       policySet = policySet,
100       dataTypeDescriptorSet = dataTypeDescriptorSet,
101       connectionContext = connectionContext
102     )
103   }
104 
105   override fun equals(other: Any?): Boolean {
106     if (this === other) return true
107     if (javaClass != other?.javaClass) return false
108 
109     other as DefaultChronicleContext
110 
111     if (connectionProviders != other.connectionProviders) return false
112     if (processorNodes != other.processorNodes) return false
113     if (policySet != other.policySet) return false
114     if (connectionContext != other.connectionContext) return false
115 
116     return true
117   }
118 
119   override fun hashCode(): Int {
120     var result = connectionProviders.hashCode()
121     result = 31 * result + processorNodes.hashCode()
122     result = 31 * result + policySet.hashCode()
123     result = 31 * result + connectionContext.hashCode()
124     return result
125   }
126 }
127