Specialized TypeInformation implementations for Scala-specific types providing efficient serialization and type handling for case classes, Option, Either, Try, and collections.
Abstract class providing TypeInformation for Scala case classes with comprehensive field access and type introspection.
abstract class CaseClassTypeInfo[T](
clazz: Class[T],
typeParamTypeInfos: Array[TypeInformation[_]],
fieldTypes: Seq[TypeInformation[_]],
fieldNames: Seq[String]
) extends CompositeType[T] {
// Field information
def getFieldNames: Array[String]
def getFieldIndex(fieldName: String): Int
def getFieldIndices(fields: Array[String]): Array[Int]
def getFieldTypes: Array[TypeInformation[_]]
// Type introspection
def getTypeAt[X](fieldExpression: String): TypeInformation[X]
def getFlatFields(fieldExpression: String): List[FlatFieldDescriptor]
def getGenericParameters: java.util.Map[String, TypeInformation[_]]
// Comparator creation
def createTypeComparatorBuilder(): TypeComparatorBuilder[T]
// Standard TypeInformation methods
def getTypeClass: Class[T]
def isBasicType: Boolean = false
def isTupleType: Boolean = true
def getArity: Int = fieldTypes.length
def getTotalFields: Int
def isKeyType: Boolean
def createSerializer(config: SerializerConfig): TypeSerializer[T]
}Usage examples:
case class Product(id: Int, name: String, price: Double, category: String)
val productTypeInfo = Types.CASE_CLASS[Product]
// Field access
val fieldNames = productTypeInfo.getFieldNames // Array("id", "name", "price", "category")
val nameIndex = productTypeInfo.getFieldIndex("name") // 1
val priceType = productTypeInfo.getTypeAt[Double]("price") // TypeInformation[Double]
// Multiple field indices
val indices = productTypeInfo.getFieldIndices(Array("id", "price")) // Array(0, 2)
// Nested field access (for nested case classes)
case class Order(id: Int, product: Product, quantity: Int)
val orderTypeInfo = Types.CASE_CLASS[Order]
val productNameType = orderTypeInfo.getTypeAt[String]("product.name")For accessing nested fields in complex case class hierarchies:
case class FlatFieldDescriptor(position: Int, typeInfo: TypeInformation[_])
// Usage
val flatFields = orderTypeInfo.getFlatFields("product.*")
// Returns descriptors for all fields in the nested productTypeInformation for Scala Option types with null-safe serialization.
class OptionTypeInfo[A, T <: Option[A]](elemTypeInfo: TypeInformation[A])
extends TypeInformation[T] {
def getElementTypeInfo: TypeInformation[A]
def getTypeClass: Class[T]
def isBasicType: Boolean = false
def isTupleType: Boolean = false
def getArity: Int = 1
def getTotalFields: Int = 1
def isKeyType: Boolean // Based on element type
def createSerializer(config: SerializerConfig): TypeSerializer[T]
}Usage examples:
case class User(id: Int, name: String, email: Option[String])
val userTypeInfo = Types.CASE_CLASS[User]
val emailFieldType = userTypeInfo.getTypeAt[Option[String]]("email")
// Option type info properties
val optStringTypeInfo = Types.OPTION(Types.STRING)
val elementType = optStringTypeInfo.getElementTypeInfo // TypeInformation[String]
val isKey = optStringTypeInfo.isKeyType // Based on String being a key type
// Direct Option handling
val optionalValue: Option[String] = Some("test")
val optionalTypeInfo = Types.of[Option[String]]TypeInformation for Scala Either types supporting both Left and Right type information.
class EitherTypeInfo[A, B, T <: Either[A, B]](
clazz: Class[T],
leftTypeInfo: TypeInformation[A],
rightTypeInfo: TypeInformation[B]
) extends TypeInformation[T] {
def getLeftTypeInfo: TypeInformation[A]
def getRightTypeInfo: TypeInformation[B]
def getTypeClass: Class[T]
def isBasicType: Boolean = false
def isTupleType: Boolean = false
def getArity: Int = 2
def getTotalFields: Int = 2
def isKeyType: Boolean = false // Either is not a key type
def createSerializer(config: SerializerConfig): TypeSerializer[T]
}Usage examples:
// Either type for error handling
type ProcessingResult = Either[String, Int] // Error message or success code
val eitherTypeInfo = Types.EITHER(Types.STRING, Types.INT)
val leftType = eitherTypeInfo.getLeftTypeInfo // TypeInformation[String]
val rightType = eitherTypeInfo.getRightTypeInfo // TypeInformation[Int]
// Case class with Either field
case class TaskResult(id: Int, result: Either[String, Double])
val taskTypeInfo = Types.CASE_CLASS[TaskResult]
val resultFieldType = taskTypeInfo.getTypeAt[Either[String, Double]]("result")
// Usage in expressions
val processedResult = ifThenElse(
$"success" === lit(true),
lit(Right(42.0)),
lit(Left("Processing failed"))
)TypeInformation for Scala Try types handling success and failure cases.
class TryTypeInfo[A, T <: Try[A]](valueType: TypeInformation[A])
extends TypeInformation[T] {
def getValueTypeInfo: TypeInformation[A]
def getTypeClass: Class[T]
def isBasicType: Boolean = false
def isTupleType: Boolean = false
def getArity: Int = 1
def getTotalFields: Int = 1
def isKeyType: Boolean = false // Try is not a key type
def createSerializer(config: SerializerConfig): TypeSerializer[T]
}Usage examples:
import scala.util.{Try, Success, Failure}
// Try type for operations that might fail
val tryIntTypeInfo = Types.TRY(Types.INT)
val valueType = tryIntTypeInfo.getValueTypeInfo // TypeInformation[Int]
// Case class with Try field
case class SafeOperation(id: Int, result: Try[Double])
val opTypeInfo = Types.CASE_CLASS[SafeOperation]
// Working with Try in table operations
val safeResult = table.select(
$"id",
ifThenElse(
$"error".isNull,
// Success case - create Success[Double]
call("SUCCESS", $"value"),
// Failure case - create Failure[Double]
call("FAILURE", $"error")
) as "result"
)Abstract base class for Scala collection types implementing TraversableOnce.
abstract class TraversableTypeInfo[T <: TraversableOnce[E], E](
clazz: Class[T],
elementTypeInfo: TypeInformation[E]
) extends TypeInformation[T] {
def getElementTypeInfo: TypeInformation[E]
def getTypeClass: Class[T]
def isBasicType: Boolean = false
def isTupleType: Boolean = false
def getArity: Int = 1
def getTotalFields: Int = 1
def isKeyType: Boolean = false // Collections are not key types
// Abstract method - must be implemented by concrete collection types
def createSerializer(config: SerializerConfig): TypeSerializer[T]
}Usage examples:
// List type
val listTypeInfo = Types.TRAVERSABLE[List[String]]
val elementType = listTypeInfo.getElementTypeInfo // TypeInformation[String]
// Set type
val setTypeInfo = Types.TRAVERSABLE[Set[Int]]
// Case class with collection fields
case class ShoppingCart(userId: Int, items: List[String], quantities: Array[Int])
val cartTypeInfo = Types.CASE_CLASS[ShoppingCart]
val itemsType = cartTypeInfo.getTypeAt[List[String]]("items")
val quantitiesType = cartTypeInfo.getTypeAt[Array[Int]]("quantities")
// Working with collections in tables
val processedCart = table.select(
$"userId",
size($"items") as "itemCount",
array_contains($"items", lit("laptop")) as "hasLaptop"
)TypeInformation for Scala Enumeration values with comparison and hashing support.
class EnumValueTypeInfo[E <: Enumeration](enum: E, clazz: Class[E#Value])
extends TypeInformation[E#Value] with AtomicType[E#Value] {
def getEnumeration: E
def getTypeClass: Class[E#Value]
def isBasicType: Boolean = true
def isTupleType: Boolean = false
def getArity: Int = 1
def getTotalFields: Int = 1
def isKeyType: Boolean = true // Enumerations support comparison
def createSerializer(config: SerializerConfig): TypeSerializer[E#Value]
def createComparator(
sortOrderAscending: Boolean,
executionConfig: ExecutionConfig
): TypeComparator[E#Value]
}Usage examples:
// Define enumeration
object Priority extends Enumeration {
type Priority = Value
val LOW, MEDIUM, HIGH, CRITICAL = Value
}
// Create type information
val priorityTypeInfo = Types.ENUMERATION(Priority, classOf[Priority.Priority])
val enumeration = priorityTypeInfo.getEnumeration // Priority object
// Usage in case class
case class Task(id: Int, name: String, priority: Priority.Priority)
val taskTypeInfo = Types.CASE_CLASS[Task]
// Enumeration in table operations
val highPriorityTasks = table.filter($"priority" === lit(Priority.HIGH))
val sortedTasks = table.orderBy($"priority".desc) // Enumeration supports orderingTypeInformation for Scala Unit type.
class UnitTypeInfo extends TypeInformation[Unit] with AtomicType[Unit] {
def getTypeClass: Class[Unit] = classOf[Unit]
def isBasicType: Boolean = true
def isTupleType: Boolean = false
def getArity: Int = 0
def getTotalFields: Int = 0
def isKeyType: Boolean = true
def createSerializer(config: SerializerConfig): TypeSerializer[Unit]
def createComparator(
sortOrderAscending: Boolean,
executionConfig: ExecutionConfig
): TypeComparator[Unit]
}TypeInformation for Scala Nothing type (bottom type).
class ScalaNothingTypeInfo extends TypeInformation[Nothing] {
def getTypeClass: Class[Nothing] = classOf[Nothing]
def isBasicType: Boolean = true
def isTupleType: Boolean = false
def getArity: Int = 0
def getTotalFields: Int = 0
def isKeyType: Boolean = false // Nothing cannot be instantiated
def createSerializer(config: SerializerConfig): TypeSerializer[Nothing]
}case class Address(street: String, city: String, zip: String)
case class Person(name: String, age: Int, address: Address)
val personTypeInfo = Types.CASE_CLASS[Person]
// Access nested fields
val streetType = personTypeInfo.getTypeAt[String]("address.street")
val cityType = personTypeInfo.getTypeAt[String]("address.city")
// Flat field access for all address fields
val addressFields = personTypeInfo.getFlatFields("address.*")case class Container[T](id: Int, content: T)
// Explicit type parameter specification
val stringContainerType = Types.CASE_CLASS[Container[String]]
val intContainerType = Types.CASE_CLASS[Container[Int]]
// Generic parameter information
val genericParams = stringContainerType.getGenericParameters
// Map("T" -> TypeInformation[String])case class Order(id: Int, amount: Double)
val orderListType = Types.TRAVERSABLE[List[Order]]
val orderElementType = orderListType.getElementTypeInfo // CaseClassTypeInfo[Order]
// Nested access in collections
val ordersTable = table.select(
$"customerId",
$"orders",
size($"orders") as "orderCount",
$"orders"[0].get("amount") as "firstOrderAmount"
)// Cache frequently used type information
val userTypeInfo = Types.CASE_CLASS[User]
val userListTypeInfo = Types.TRAVERSABLE[List[User]]
// Reuse in multiple contexts
val usersTable = tEnv.fromDataStream(userStream)(userTypeInfo)
val processedUsers = table.select($"*")(userTypeInfo)// Use type-safe field access
val nestedFieldType = complexTypeInfo.getTypeAt[String]("path.to.field")
// Prefer flat field access for performance
val flatFields = typeInfo.getFlatFields("*")// Explicit type specification for generics
val optionalUserType = Types.OPTION(Types.CASE_CLASS[User])
val eitherResultType = Types.EITHER(Types.STRING, Types.CASE_CLASS[Result])
// Type-safe generic operations
def createOptionalType[T: TypeInformation]: TypeInformation[Option[T]] = {
Types.OPTION(Types.of[T])
}