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

pl.touk.nussknacker.engine.definition.clazz.ClassDefinitionSet.scala Maven / Gradle / Ivy

The newest version!
package pl.touk.nussknacker.engine.definition.clazz

import com.github.ghik.silencer.silent

object ClassDefinitionSet {

  def apply(classDefinitions: Set[ClassDefinition]): ClassDefinitionSet = {
    new ClassDefinitionSet(classDefinitions.toList.map(classDef => classDef.getClazz -> classDef).toMap)
  }

}

case class ClassDefinitionSet(classDefinitionsMap: Map[Class[_], ClassDefinition]) {
  lazy val unknown: Option[ClassDefinition] = get(classOf[java.lang.Object])

  private lazy val parameterlessMethodsByDeclaringTypes: Map[DeclaringClassWithMethodName, ParameterlessMethodInfo] = {
    def getParameterlessMethods(staticMethods: Boolean) = {
      for {
        (clazz, classDefinition) <- classDefinitionsMap
        (methodName, methods)    <- if (staticMethods) classDefinition.staticMethods else classDefinition.methods
        method                   <- methods
        if method.signatures.exists(_.parametersToList.isEmpty)
      } yield DeclaringClassWithMethodName(clazz, methodName) -> ParameterlessMethodInfo(isStatic = staticMethods)
    }
    getParameterlessMethods(staticMethods = true) ++ getParameterlessMethods(staticMethods = false)
  }

  def all: Set[ClassDefinition] = classDefinitionsMap.values.toSet

  def get(clazz: Class[_]): Option[ClassDefinition] = classDefinitionsMap.get(clazz)

  def isParameterlessMethodAllowed(targetClass: Class[_], methodName: String, staticMethodsOnly: Boolean): Boolean = {
    extractAllTypesInHierarchy(targetClass).exists(typeToCheck =>
      parameterlessMethodsByDeclaringTypes
        .get(DeclaringClassWithMethodName(typeToCheck, methodName))
        .exists(methodInfo => !staticMethodsOnly || methodInfo.isStatic)
    )
  }

  // We do runtime "types-walking" during expression invocation because in ClassDefinitionSet
  // we have some definitions for interface (e.g. List, Map.Entry) but we don't know exact used
  // implementation (like ArrayList or Collections.UnmodifiableMap.UnmodifiableEntrySet.UnmodifiableEntry) so we can't precompute it easily
  @silent("deprecated")
  private def extractAllTypesInHierarchy(clazz: Class[_]): Stream[Class[_]] = {
    lazy val superClass          = Option(clazz.getSuperclass).map(_ #:: Stream.empty).getOrElse(Stream.empty)
    lazy val extractedSuperTypes = (superClass #::: clazz.getInterfaces.toStream).flatMap(extractAllTypesInHierarchy)
    clazz #:: extractedSuperTypes
  }

}

private final case class ParameterlessMethodInfo(isStatic: Boolean)

private final case class DeclaringClassWithMethodName(clazz: Class[_], methodName: String)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy