/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.flink.api.common.typeinfo; import java.util.Map; import org.apache.flink.annotation.PublicEvolving; import org.apache.flink.annotation.Public; import org.apache.flink.api.common.ExecutionConfig; import org.apache.flink.api.common.typeutils.TypeSerializer; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.api.java.typeutils.TypeExtractor; import java.io.Serializable; import java.util.Collections; /** * TypeInformation is the core class of Flink's type system. Flink requires a type information * for all types that are used as input or return type of a user function. This type information * class acts as the tool to generate serializers and comparators, and to perform semantic checks * such as whether the fields that are uses as join/grouping keys actually exist. * <p> * The type information also bridges between the programming languages object model and a * logical flat schema. It maps fields from the types to to columns (fields) in a flat schema. * Not all fields from a type are mapped to a separate fields in the flat schema and * often, entire types are mapped to one field. It is important to notice that the schema must * hold for all instances of a type. For that reason, elements in lists and arrays are not * assigned to individual fields, but the lists and arrays are considered to be one field in total, * to account for different lengths in the arrays. * <ul> * <li>Basic types are indivisible and are considered a single field.</li> * <li>Arrays and collections are one field</li> * <li>Tuples and case classes represent as many fields as the class has fields</li> * </ul> * <p> * To represent this properly, each type has an <i>arity</i> (the number of fields it contains * directly), and a <i>total number of fields</i> (number of fields in the entire schema of this * type, including nested types). * <p> * Consider the example below: * <pre>{@code * public class InnerType { * public int id; * public String text; * } * * public class OuterType { * public long timestamp; * public InnerType nestedType; * } * }</pre> * * The types "id", "text", and "timestamp" are basic types that take up one field. The "InnerType" * has an arity of two, and also two fields totally. The "OuterType" has an arity of two fields, * and a total number of three fields ( it contains "id", "text", and "timestamp" through recursive flattening). * * @param <T> The type represented by this type information. */ @Public public abstract class TypeInformation<T> implements Serializable { private static final long serialVersionUID = -7742311969684489493L; /** * Checks if this type information represents a basic type. * Basic types are defined in {@link BasicTypeInfo} and are primitives, their boxing types, * Strings, Date, Void, ... * * @return True, if this type information describes a basic type, false otherwise. */ @PublicEvolving public abstract boolean isBasicType(); /** * Checks if this type information represents a Tuple type. * Tuple types are subclasses of the Java API tuples. * * @return True, if this type information describes a tuple type, false otherwise. */ @PublicEvolving public abstract boolean isTupleType(); /** * Gets the arity of this type - the number of fields without nesting. * * @return Gets the number of fields in this type without nesting. */ @PublicEvolving public abstract int getArity(); /** * Gets the number of logical fields in this type. This includes its nested and transitively nested * fields, in the case of composite types. In the example below, the OuterType type has three * fields in total. * * * @return The number of fields in this type, including its sub-fields (for composite types) */ @PublicEvolving public abstract int getTotalFields(); /** * Gets the class of the type represented by this type information. * * @return The class of the type represented by this type information. */ @PublicEvolving public abstract Class<T> getTypeClass(); /** * Optional method for giving Flink's type extraction system information about the mapping * of a generic type parameter to the type information of a subtype. This information is necessary * in cases where type information should be deduced from an input type. * * For instance, a method for a {@link Tuple2} would look like this: * <code> * Map m = new HashMap(); * m.put("T0", this.getTypeAt(0)); * m.put("T1", this.getTypeAt(1)); * return m; * </code> * * @return map of inferred subtypes; it does not have to contain all generic parameters as key; * values may be null if type could not be inferred */ @PublicEvolving public Map<String, TypeInformation<?>> getGenericParameters() { // return an empty map as the default implementation return Collections.emptyMap(); } /** * Checks whether this type can be used as a key. As a bare minimum, types have * to be hashable and comparable to be keys. * * @return True, if the type can be used as a key, false otherwise. */ @PublicEvolving public abstract boolean isKeyType(); /** * Checks whether this type can be used as a key for sorting. * The order produced by sorting this type must be meaningful. */ @PublicEvolving public boolean isSortKeyType() { return isKeyType(); } /** * Creates a serializer for the type. The serializer may use the ExecutionConfig * for parameterization. * * @param config The config used to parameterize the serializer. * @return A serializer for this type. */ @PublicEvolving public abstract TypeSerializer<T> createSerializer(ExecutionConfig config); @Override public abstract String toString(); @Override public abstract boolean equals(Object obj); @Override public abstract int hashCode(); /** * Returns true if the given object can be equaled with this object. If not, it returns false. * * @param obj Object which wants to take part in the equality relation * @return true if obj can be equaled with this, otherwise false */ public abstract boolean canEqual(Object obj); // ------------------------------------------------------------------------ /** * Creates a TypeInformation for the type described by the given class. * * <p>This method only works for non-generic types. For generic types, use the * {@link #of(TypeHint)} method. * * @param typeClass The class of the type. * @param <T> The generic type. * * @return The TypeInformation object for the type described by the hint. */ public static <T> TypeInformation<T> of(Class<T> typeClass) { return TypeExtractor.createTypeInfo(typeClass); } /** * Creates a TypeInformation for a generic type via a utility "type hint". * This method can be used as follows: * <pre> * {@code * TypeInformation<Tuple2<String, Long>> info = TypeInformation.of(new TypeHint<Tuple2<String, Long>>(){}); * } * </pre> * * @param typeHint The hint for the generic type. * @param <T> The generic type. * * @return The TypeInformation object for the type described by the hint. */ public static <T> TypeInformation<T> of(TypeHint<T> typeHint) { return typeHint.getTypeInfo(); } }