All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.autonomousapps.internal.utils.collections.kt Maven / Gradle / Ivy

There is a newer version: 2.0.2
Show newest version
package com.autonomousapps.internal.utils

import org.gradle.api.artifacts.ArtifactCollection
import org.gradle.api.artifacts.result.ResolvedArtifactResult
import org.gradle.api.file.FileCollection
import org.gradle.internal.component.local.model.OpaqueComponentIdentifier
import org.w3c.dom.*
import java.util.Collections
import java.util.TreeSet
import java.util.zip.ZipEntry
import java.util.zip.ZipFile

/**
 * Takes an [ArtifactCollection] and filters out all [OpaqueComponentIdentifier]s, which seem to be jars from the Gradle
 * distribution, e.g. "Gradle API", "Gradle TestKit", and "Gradle Kotlin DSL". They are often not very useful for
 * analysis.
 */
internal fun ArtifactCollection.filterNonGradle(): List = filterNot {
  // e.g. "Gradle API", "Gradle TestKit", "Gradle Kotlin DSL"
  it.id.componentIdentifier is OpaqueComponentIdentifier
}

internal fun Sequence.filterNonGradle() = filterNot {
  // e.g. "Gradle API", "Gradle TestKit", "Gradle Kotlin DSL"
  it.id.componentIdentifier is OpaqueComponentIdentifier
}

/**
 * Transforms a [ZipFile] into a collection of [ZipEntry]s, which contains only class files (and not
 * the module-info.class file).
 */
internal fun ZipFile.asClassFiles(): Set {
  return entries().toList().filterToSetOfClassFiles()
}

internal fun ZipFile.asSequenceOfClassFiles(): Sequence {
  return entries().asSequence().filter {
    it.name.endsWith(".class") && it.name != "module-info.class"
  }
}

/** Filters a collection of [ZipEntry]s to contain only class files (and not the module-info.class file). */
internal fun Iterable.filterToSetOfClassFiles(): Set {
  return filterToSet {
    it.name.endsWith(".class") && it.name != "module-info.class"
  }
}

/** Filters a collection of [ZipEntry]s to contain only class files (and not the module-info.class file). */
internal fun Iterable.asSequenceOfClassFiles(): Sequence {
  return asSequence().filter {
    it.name.endsWith(".class") && it.name != "module-info.class"
  }
}

/**
 * Filters a [FileCollection] to contain only class files.
 */
internal fun FileCollection.filterToClassFiles(): FileCollection {
  return filter {
    it.isFile && it.name.endsWith(".class")
  }
}

internal inline fun  Iterable.filterToSet(predicate: (T) -> Boolean): Set {
  return filterTo(HashSet(), predicate)
}

internal inline fun  Iterable.filterNotToSet(predicate: (T) -> Boolean): Set {
  return filterNotTo(HashSet(), predicate)
}

internal inline fun  Iterable.filterToOrderedSet(predicate: (T) -> Boolean): Set {
  return filterTo(TreeSet(), predicate)
}

internal inline fun  Iterable.filterNotToOrderedSet(predicate: (T) -> Boolean): Set {
  return filterNotTo(TreeSet(), predicate)
}

internal inline fun  Iterable.filterToOrderedSet(
  comparator: Comparator, predicate: (T) -> Boolean
): Set {
  return filterTo(TreeSet(comparator), predicate)
}

internal fun  T.intoSet(): Set = Collections.singleton(this)
internal fun  T.intoMutableSet(): MutableSet = HashSet().apply { add(this@intoMutableSet) }

fun  T?.toSetOrEmpty(): Set =
  if (this == null) emptySet() else setOf(this)

internal inline fun  Iterable.mapToSet(transform: (T) -> R): Set {
  return mapTo(LinkedHashSet(collectionSizeOrDefault(10)), transform)
}

internal inline fun  Iterable.mapToOrderedSet(transform: (T) -> R): Set {
  return mapTo(TreeSet(), transform)
}

internal inline fun  Iterable.flatMapToSet(transform: (T) -> Iterable): Set {
  return flatMapToMutableSet(transform)
}

internal inline fun  Iterable.flatMapToMutableSet(transform: (T) -> Iterable): MutableSet {
  return flatMapTo(HashSet(collectionSizeOrDefault(10)), transform)
}

internal inline fun  Iterable.flatMapToOrderedSet(transform: (T) -> Iterable): Set {
  return flatMapTo(TreeSet(), transform)
}

internal fun  Iterable.collectionSizeOrDefault(default: Int): Int =
  if (this is Collection<*>) this.size
  else default

internal inline fun  Iterable.mapNotNullToSet(transform: (T) -> R?): Set {
  return mapNotNullTo(HashSet(), transform)
}

internal inline fun  Iterable.mapNotNullToOrderedSet(transform: (T) -> R?): Set {
  return mapNotNullTo(TreeSet(), transform)
}

internal inline fun  NodeList.mapNotNull(transform: (Node) -> R?): List {
  val destination = ArrayList(length)
  for (i in 0 until length) {
    transform(item(i))?.let { destination.add(it) }
  }
  return destination
}

internal inline fun  NodeList.map(transform: (Node) -> R): List {
  val destination = ArrayList(length)
  for (i in 0 until length) {
    destination.add(transform(item(i)))
  }
  return destination
}

internal inline fun  NodeList.mapToSet(transform: (Node) -> R): Set {
  val destination = HashSet(length)
  for (i in 0 until length) {
    destination.add(transform(item(i)))
  }
  return destination
}

internal inline fun NodeList.filter(predicate: (Node) -> Boolean): List {
  val destination = ArrayList(length)
  for (i in 0 until length) {
    if (predicate(item(i))) destination.add(item(i))
  }
  return destination
}

internal fun  NamedNodeMap.map(transform: (Node) -> R): List {
  val destination = ArrayList()
  for (i in 0 until length) {
    destination.add(transform(item(i)))
  }
  return destination
}

internal fun  Iterable.flatMap(transform: (Node) -> R): List {
  val destination = ArrayList()

  for (it in this) {
    for (i in 0 until it.length) {
      destination.add(transform(it.item(i)))
    }
  }

  return destination
}

internal fun Document.attrs(): List> {
  return getElementsByTagName("*")
    .map { it.attributes }
    // this flatMap looks redundant but isn't!
    .flatMap { it }
    .filterIsInstance()
    .map { it.name to it.value }
}

internal fun Document.contentReferences(): Map {
  return getElementsByTagName("*")
    .map { it.textContent }
    .filter { it.startsWith('@') }
    // placeholder value; meaningless.
    .associateBy { "DIRECT-REFERENCE" }
}

internal inline fun  Iterable.mutPartitionOf(
  predicate1: (T) -> Boolean,
  predicate2: (T) -> Boolean
): Pair, MutableSet> {
  val first = LinkedHashSet()
  val second = LinkedHashSet()
  for (element in this) {
    if (predicate1(element)) {
      first.add(element)
    } else if (predicate2(element)) {
      second.add(element)
    }
  }
  return Pair(first, second)
}

internal inline fun  Iterable.mutPartitionOf(
  predicate1: (T) -> Boolean,
  predicate2: (T) -> Boolean,
  predicate3: (T) -> Boolean,
): Triple, MutableSet, MutableSet> {
  val first = LinkedHashSet()
  val second = LinkedHashSet()
  val third = LinkedHashSet()
  for (element in this) {
    if (predicate1(element)) {
      first.add(element)
    } else if (predicate2(element)) {
      second.add(element)
    } else if (predicate3(element)) {
      third.add(element)
    }
  }
  return Triple(first, second, third)
}

internal inline fun  Iterable.mutPartitionOf(
  predicate1: (T) -> Boolean,
  predicate2: (T) -> Boolean,
  predicate3: (T) -> Boolean,
  predicate4: (T) -> Boolean,
): Quadruple, MutableSet, MutableSet, MutableSet> {
  val first = LinkedHashSet()
  val second = LinkedHashSet()
  val third = LinkedHashSet()
  val fourth = LinkedHashSet()
  for (element in this) {
    if (predicate1(element)) {
      first.add(element)
    } else if (predicate2(element)) {
      second.add(element)
    } else if (predicate3(element)) {
      third.add(element)
    } else if (predicate4(element)) {
      fourth.add(element)
    }
  }
  return Quadruple(first, second, third, fourth)
}

data class Quadruple(
  val first: A,
  val second: B,
  val third: C,
  val fourth: D,
) {
  override fun toString(): String = "($first, $second, $third, $fourth)"
}

// standard `all` function returns true if collection is empty!
internal inline fun  Collection.reallyAll(predicate: (T) -> Boolean): Boolean {
  if (isEmpty()) return false
  for (element in this) if (!predicate(element)) return false
  return true
}

internal fun  Set.efficient(): Set = when {
  isEmpty() -> emptySet()
  size == 1 -> Collections.singleton(first())
  else -> this
}

/**
 * Given a list of pairs, where the pairs are key -> (value as Set) pairs, merge into a map (not
 * losing any values).
 */
internal fun  List>>.mergedMapSets(): Map> {
  return foldRight(linkedMapOf>()) { (key, values), map ->
    map.apply {
      merge(key, values) { old, new -> old.apply { addAll(new) } }
    }
  }
}

internal inline fun  C.ifNotEmpty(block: (C) -> Unit) where C : Collection<*> {
  if (isNotEmpty()) {
    block(this)
  }
}

internal inline fun  Map.ifNotEmpty(block: (Map) -> Unit) {
  if (isNotEmpty()) {
    block(this)
  }
}

internal fun  Map.reversed() = entries.associateBy({ it.value }) { it.key }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy