com.jetbrains.plugin.structure.classes.resolvers.CompositeResolver.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of structure-classes Show documentation
Show all versions of structure-classes Show documentation
Base library for resolving class files and resources. Used by other JetBrains Plugins Structure Classes libraries.
/*
* Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package com.jetbrains.plugin.structure.classes.resolvers
import com.jetbrains.plugin.structure.base.utils.closeAll
import org.objectweb.asm.tree.ClassNode
import java.util.*
/**
* [Resolver] that combines several [resolvers] with the Java classpath search strategy.
*/
class CompositeResolver private constructor(
private val resolvers: List,
override val readMode: ReadMode
) : Resolver() {
private val packageToResolvers: MutableMap> = hashMapOf()
private val fullBundleNames = hashMapOf>()
private val baseBundleNameToResolvers: MutableMap> = hashMapOf()
init {
buildIndex()
}
private fun buildIndex() {
for (resolver in resolvers) {
for (packageName in resolver.allPackages) {
packageToResolvers.getOrPut(packageName) { arrayListOf() } += resolver
}
val bundleNameSet = resolver.allBundleNameSet
for (baseBundleName in bundleNameSet.baseBundleNames) {
baseBundleNameToResolvers.getOrPut(baseBundleName) { arrayListOf() } += resolver
val resolverAllNames = bundleNameSet[baseBundleName]
if (resolverAllNames.isNotEmpty()) {
fullBundleNames.getOrPut(baseBundleName) { hashSetOf() } += resolverAllNames
}
}
}
}
override val allClasses
get() = resolvers.flatMapTo(hashSetOf()) { it.allClasses }
override val allBundleNameSet: ResourceBundleNameSet
get() = ResourceBundleNameSet(fullBundleNames)
override val allPackages
get() = packageToResolvers.keys
override fun processAllClasses(processor: (ResolutionResult) -> Boolean) =
resolvers.all { it.processAllClasses(processor) }
private fun getPackageName(className: String) = className.substringBeforeLast('/', "")
override fun containsClass(className: String): Boolean {
val packageName = getPackageName(className)
val resolvers = packageToResolvers[packageName] ?: emptyList()
return resolvers.any { it.containsClass(className) }
}
override fun containsPackage(packageName: String) = packageName in packageToResolvers
override fun resolveClass(className: String): ResolutionResult {
val packageName = getPackageName(className)
val resolvers = packageToResolvers[packageName] ?: emptyList()
for (resolver in resolvers) {
val resolutionResult = resolver.resolveClass(className)
if (resolutionResult !is ResolutionResult.NotFound) {
return resolutionResult
}
}
return ResolutionResult.NotFound
}
override fun resolveExactPropertyResourceBundle(baseName: String, locale: Locale): ResolutionResult {
val resolvers = baseBundleNameToResolvers[baseName] ?: emptyList()
for (resolver in resolvers) {
val resolutionResult = resolver.resolveExactPropertyResourceBundle(baseName, locale)
if (resolutionResult !is ResolutionResult.NotFound) {
return resolutionResult
}
}
return ResolutionResult.NotFound
}
override fun close() {
resolvers.closeAll()
}
override fun toString() = "Union of ${resolvers.size} resolver" + (if (resolvers.size != 1) "s" else "")
companion object {
@JvmStatic
fun create(vararg resolvers: Resolver): Resolver = create(resolvers.asIterable())
@JvmStatic
fun create(resolvers: Iterable): Resolver {
val list = resolvers.toList()
return when(list.size) {
0 -> EmptyResolver
1 -> list.first()
else -> {
val readMode = if (list.all { it.readMode == ReadMode.FULL }) {
ReadMode.FULL
} else {
ReadMode.SIGNATURES
}
CompositeResolver(list, readMode)
}
}
}
}
}