content: /*
   * 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 com.datastax.oss.driver.api.core.type.codec;
  
  import com.datastax.oss.driver.api.core.data.CqlDuration;
  import com.datastax.oss.driver.api.core.data.CqlVector;
  import com.datastax.oss.driver.api.core.data.TupleValue;
  import com.datastax.oss.driver.api.core.data.UdtValue;
  import com.datastax.oss.driver.api.core.type.CustomType;
  import com.datastax.oss.driver.api.core.type.DataType;
  import com.datastax.oss.driver.api.core.type.DataTypes;
  import com.datastax.oss.driver.api.core.type.TupleType;
  import com.datastax.oss.driver.api.core.type.UserDefinedType;
  import com.datastax.oss.driver.api.core.type.VectorType;
  import com.datastax.oss.driver.internal.core.type.codec.BigIntCodec;
  import com.datastax.oss.driver.internal.core.type.codec.BlobCodec;
  import com.datastax.oss.driver.internal.core.type.codec.BooleanCodec;
  import com.datastax.oss.driver.internal.core.type.codec.CounterCodec;
  import com.datastax.oss.driver.internal.core.type.codec.CqlDurationCodec;
  import com.datastax.oss.driver.internal.core.type.codec.CustomCodec;
  import com.datastax.oss.driver.internal.core.type.codec.DateCodec;
  import com.datastax.oss.driver.internal.core.type.codec.DecimalCodec;
  import com.datastax.oss.driver.internal.core.type.codec.DoubleCodec;
  import com.datastax.oss.driver.internal.core.type.codec.FloatCodec;
  import com.datastax.oss.driver.internal.core.type.codec.InetCodec;
  import com.datastax.oss.driver.internal.core.type.codec.IntCodec;
  import com.datastax.oss.driver.internal.core.type.codec.ListCodec;
  import com.datastax.oss.driver.internal.core.type.codec.MapCodec;
  import com.datastax.oss.driver.internal.core.type.codec.SetCodec;
  import com.datastax.oss.driver.internal.core.type.codec.SmallIntCodec;
  import com.datastax.oss.driver.internal.core.type.codec.StringCodec;
  import com.datastax.oss.driver.internal.core.type.codec.TimeCodec;
  import com.datastax.oss.driver.internal.core.type.codec.TimeUuidCodec;
  import com.datastax.oss.driver.internal.core.type.codec.TimestampCodec;
  import com.datastax.oss.driver.internal.core.type.codec.TinyIntCodec;
  import com.datastax.oss.driver.internal.core.type.codec.TupleCodec;
  import com.datastax.oss.driver.internal.core.type.codec.UdtCodec;
  import com.datastax.oss.driver.internal.core.type.codec.UuidCodec;
  import com.datastax.oss.driver.internal.core.type.codec.VarIntCodec;
  import com.datastax.oss.driver.internal.core.type.codec.VectorCodec;
  import com.datastax.oss.driver.shaded.guava.common.base.Charsets;
  import com.datastax.oss.driver.shaded.guava.common.base.Preconditions;
  import edu.umd.cs.findbugs.annotations.NonNull;
  import java.math.BigDecimal;
  import java.math.BigInteger;
  import java.net.InetAddress;
  import java.nio.ByteBuffer;
  import java.time.Instant;
  import java.time.LocalDate;
  import java.time.LocalTime;
  import java.time.ZoneId;
  import java.time.ZonedDateTime;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.UUID;
  
  /**
   * Constants and factory methods to obtain instances of the driver's default type codecs.
   *
   * <p>See also {@link ExtraTypeCodecs} for additional codecs that you can register with your session
   * to handle different type mappings.
   */
  public class TypeCodecs {
  
    /** The default codec that maps CQL type {@code boolean} to Java's {@code boolean}. */
    public static final PrimitiveBooleanCodec BOOLEAN = new BooleanCodec();
  
    /** The default codec that maps CQL type {@code tinyint} to Java's {@code byte}. */
    public static final PrimitiveByteCodec TINYINT = new TinyIntCodec();
  
    /** The default codec that maps CQL type {@code double} to Java's {@code double}. */
    public static final PrimitiveDoubleCodec DOUBLE = new DoubleCodec();
  
    /** The default codec that maps CQL type {@code counter} to Java's {@code long}. */
    public static final PrimitiveLongCodec COUNTER = new CounterCodec();
  
    /** The default codec that maps CQL type {@code float} to Java's {@code float}. */
    public static final PrimitiveFloatCodec FLOAT = new FloatCodec();
  
    /** The default codec that maps CQL type {@code int} to Java's {@code int}. */
    public static final PrimitiveIntCodec INT = new IntCodec();
  
    /** The default codec that maps CQL type {@code bigint} to Java's {@code long}. */
    public static final PrimitiveLongCodec BIGINT = new BigIntCodec();
  
    /** The default codec that maps CQL type {@code smallint} to Java's {@code short}. */
    public static final PrimitiveShortCodec SMALLINT = new SmallIntCodec();
  
    /**
     * The default codec that maps CQL type {@code timestamp} to Java's {@link Instant}, using the
     * system's default time zone to parse and format CQL literals.
     *
     * <p>This codec uses the system's {@linkplain ZoneId#systemDefault() default time zone} as its
     * source of time zone information when formatting values as CQL literals, or parsing CQL literals
     * that do not have any time zone indication. Note that this only applies to the {@link
     * TypeCodec#format(Object)} and {@link TypeCodec#parse(String)} methods; regular encoding and
     * decoding, like setting a value on a bound statement or reading a column from a row, are not
     * affected by the time zone.
     *
     * <p>If you need a different time zone, consider other codecs in {@link ExtraTypeCodecs}, or call
     * {@link ExtraTypeCodecs#timestampAt(ZoneId)} instead.
     *
     * @see ExtraTypeCodecs#TIMESTAMP_UTC
     * @see ExtraTypeCodecs#timestampAt(ZoneId)
     */
    public static final TypeCodec<Instant> TIMESTAMP = new TimestampCodec();
  
    /** The default codec that maps CQL type {@code date} to Java's {@link LocalDate}. */
    public static final TypeCodec<LocalDate> DATE = new DateCodec();
  
    /** The default codec that maps CQL type {@code time} to Java's {@link LocalTime}. */
    public static final TypeCodec<LocalTime> TIME = new TimeCodec();
  
    /**
     * The default codec that maps CQL type {@code blob} to Java's {@link ByteBuffer}.
     *
     * <p>If you are looking for a codec mapping CQL type {@code blob} to the Java type {@code
     * byte[]}, you should use {@link ExtraTypeCodecs#BLOB_TO_ARRAY} instead.
     *
     * <p>If you are looking for a codec mapping CQL type {@code list<tinyint>} to the Java type
     * {@code byte[]}, you should use {@link ExtraTypeCodecs#BYTE_LIST_TO_ARRAY} instead.
     *
     * @see ExtraTypeCodecs#BLOB_TO_ARRAY
     * @see ExtraTypeCodecs#BYTE_LIST_TO_ARRAY
     */
    public static final TypeCodec<ByteBuffer> BLOB = new BlobCodec();
  
    /** The default codec that maps CQL type {@code text} to Java's {@link String}. */
    public static final TypeCodec<String> TEXT = new StringCodec(DataTypes.TEXT, Charsets.UTF_8);
    /** The default codec that maps CQL type {@code ascii} to Java's {@link String}. */
    public static final TypeCodec<String> ASCII = new StringCodec(DataTypes.ASCII, Charsets.US_ASCII);
    /** The default codec that maps CQL type {@code varint} to Java's {@link BigInteger}. */
    public static final TypeCodec<BigInteger> VARINT = new VarIntCodec();
    /** The default codec that maps CQL type {@code decimal} to Java's {@link BigDecimal}. */
    public static final TypeCodec<BigDecimal> DECIMAL = new DecimalCodec();
    /** The default codec that maps CQL type {@code uuid} to Java's {@link UUID}. */
    public static final TypeCodec<UUID> UUID = new UuidCodec();
    /** The default codec that maps CQL type {@code timeuuid} to Java's {@link UUID}. */
    public static final TypeCodec<UUID> TIMEUUID = new TimeUuidCodec();
    /** The default codec that maps CQL type {@code inet} to Java's {@link InetAddress}. */
    public static final TypeCodec<InetAddress> INET = new InetCodec();
    /** The default codec that maps CQL type {@code duration} to the driver's {@link CqlDuration}. */
    public static final TypeCodec<CqlDuration> DURATION = new CqlDurationCodec();
  
    /**
     * Builds a new codec that maps a CQL custom type to Java's {@link ByteBuffer}.
     *
     * @param cqlType the fully-qualified name of the custom type.
     */
    @NonNull
    public static TypeCodec<ByteBuffer> custom(@NonNull DataType cqlType) {
      Preconditions.checkArgument(cqlType instanceof CustomType, "cqlType must be a custom type");
      return new CustomCodec((CustomType) cqlType);
    }
  
    /**
     * Builds a new codec that maps a CQL list to a Java list, using the given codec to map each
     * element.
     */
    @NonNull
    public static <T> TypeCodec<List<T>> listOf(@NonNull TypeCodec<T> elementCodec) {
      return new ListCodec<>(DataTypes.listOf(elementCodec.getCqlType()), elementCodec);
    }
  
    /**
     * Builds a new codec that maps a CQL set to a Java set, using the given codec to map each
     * element.
     */
    @NonNull
    public static <T> TypeCodec<Set<T>> setOf(@NonNull TypeCodec<T> elementCodec) {
      return new SetCodec<>(DataTypes.setOf(elementCodec.getCqlType()), elementCodec);
    }
  
    /**
     * Builds a new codec that maps a CQL map to a Java map, using the given codecs to map each key
     * and value.
     */
    @NonNull
    public static <K, V> TypeCodec<Map<K, V>> mapOf(
        @NonNull TypeCodec<K> keyCodec, @NonNull TypeCodec<V> valueCodec) {
      return new MapCodec<>(
          DataTypes.mapOf(keyCodec.getCqlType(), valueCodec.getCqlType()), keyCodec, valueCodec);
    }
  
    /**
     * Builds a new codec that maps a CQL tuple to the driver's {@link TupleValue}, for the given type
     * definition.
     *
     * <p>Note that the components of a {@link TupleValue} are stored in their encoded form. They are
     * encoded/decoded on the fly when you set or get them, using the codec registry.
     */
    @NonNull
    public static TypeCodec<TupleValue> tupleOf(@NonNull TupleType cqlType) {
      return new TupleCodec(cqlType);
    }
  
    public static <SubtypeT> TypeCodec<CqlVector<SubtypeT>> vectorOf(
        @NonNull VectorType type, @NonNull TypeCodec<SubtypeT> subtypeCodec) {
      return new VectorCodec(
          DataTypes.vectorOf(subtypeCodec.getCqlType(), type.getDimensions()), subtypeCodec);
    }
  
    public static <SubtypeT> TypeCodec<CqlVector<SubtypeT>> vectorOf(
        int dimensions, @NonNull TypeCodec<SubtypeT> subtypeCodec) {
      return new VectorCodec(DataTypes.vectorOf(subtypeCodec.getCqlType(), dimensions), subtypeCodec);
    }
  
    /**
     * Builds a new codec that maps a CQL user defined type to the driver's {@link UdtValue}, for the
     * given type definition.
     *
     * <p>Note that the fields of a {@link UdtValue} are stored in their encoded form. They are
     * encoded/decoded on the fly when you set or get them, using the codec registry.
     */
    @NonNull
    public static TypeCodec<UdtValue> udtOf(@NonNull UserDefinedType cqlType) {
      return new UdtCodec(cqlType);
    }
  
    /**
     * An alias for {@link ExtraTypeCodecs#ZONED_TIMESTAMP_SYSTEM}.
     *
     * <p>This exists for historical reasons: the constant was originally defined in this class, but
     * technically it belongs to {@link ExtraTypeCodecs} because this is not a built-in mapping.
     */
    public static final TypeCodec<ZonedDateTime> ZONED_TIMESTAMP_SYSTEM =
        ExtraTypeCodecs.ZONED_TIMESTAMP_SYSTEM;
  
    /**
     * An alias for {@link ExtraTypeCodecs#ZONED_TIMESTAMP_UTC}.
     *
     * <p>This exists for historical reasons: the constant was originally defined in this class, but
     * technically it belongs to {@link ExtraTypeCodecs} because this is not a built-in mapping.
     */
    public static final TypeCodec<ZonedDateTime> ZONED_TIMESTAMP_UTC =
        ExtraTypeCodecs.ZONED_TIMESTAMP_UTC;
  
    /**
     * An alias for {@link ExtraTypeCodecs#zonedTimestampAt(ZoneId)}.
     *
     * <p>This exists for historical reasons: the method was originally defined in this class, but
     * technically it belongs to {@link ExtraTypeCodecs} because this is not a built-in mapping.
     */
    @NonNull
    public static TypeCodec<ZonedDateTime> zonedTimestampAt(@NonNull ZoneId timeZone) {
      return ExtraTypeCodecs.zonedTimestampAt(timeZone);
    }
  }
  