/*
 * Copyright DataStax, Inc.
 *
 * Licensed 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.data;

import com.datastax.oss.driver.api.core.metadata.token.Token;
import com.datastax.oss.driver.api.core.type.DataType;
import com.datastax.oss.driver.api.core.type.codec.CodecNotFoundException;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveBooleanCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveByteCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveDoubleCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveFloatCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveIntCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveLongCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveShortCodec;
import com.datastax.oss.driver.api.core.type.codec.TypeCodec;
import com.datastax.oss.driver.api.core.type.reflect.GenericType;
import com.datastax.oss.driver.internal.core.metadata.token.ByteOrderedToken;
import com.datastax.oss.driver.internal.core.metadata.token.Murmur3Token;
import com.datastax.oss.driver.internal.core.metadata.token.RandomToken;
import edu.umd.cs.findbugs.annotations.CheckReturnValue;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
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.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

A data structure that provides methods to set its values via an integer index.
/** A data structure that provides methods to set its values via an integer index. */
public interface SettableByIndex<SelfT extends SettableByIndex<SelfT>> extends AccessibleByIndex {
Sets the raw binary representation of the ith value.

This is primarily for internal use; you'll likely want to use one of the typed setters instead, to pass a higher-level Java representation.

Params:
  • v – the raw value, or null to set the CQL value NULL. For performance reasons, this is the actual instance used internally. If pass in a buffer that you're going to modify elsewhere in your application, make sure to duplicate it beforehand. If you change the buffer's index or its contents in any way, further usage of this data will have unpredictable results.
Throws:
/** * Sets the raw binary representation of the {@code i}th value. * * <p>This is primarily for internal use; you'll likely want to use one of the typed setters * instead, to pass a higher-level Java representation. * * @param v the raw value, or {@code null} to set the CQL value {@code NULL}. For performance * reasons, this is the actual instance used internally. If pass in a buffer that you're going * to modify elsewhere in your application, make sure to {@link ByteBuffer#duplicate() * duplicate} it beforehand. If you change the buffer's index or its contents in any way, * further usage of this data will have unpredictable results. * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue SelfT setBytesUnsafe(int i, @Nullable ByteBuffer v);
Sets the ith value to CQL NULL.
Throws:
/** * Sets the {@code i}th value to CQL {@code NULL}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setToNull(int i) { return setBytesUnsafe(i, null); }
Sets the ith value, using the given codec for the conversion.

This method completely bypasses the Data.codecRegistry(), and forces the driver to use the given codec instead. This can be useful if the codec would collide with a previously registered one, or if you want to use the codec just once without registering it.

It is the caller's responsibility to ensure that the given codec is appropriate for the conversion. Failing to do so will result in errors at runtime.

Throws:
/** * Sets the {@code i}th value, using the given codec for the conversion. * * <p>This method completely bypasses the {@link #codecRegistry()}, and forces the driver to use * the given codec instead. This can be useful if the codec would collide with a previously * registered one, or if you want to use the codec just once without registering it. * * <p>It is the caller's responsibility to ensure that the given codec is appropriate for the * conversion. Failing to do so will result in errors at runtime. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default <ValueT> SelfT set(int i, @Nullable ValueT v, @NonNull TypeCodec<ValueT> codec) { return setBytesUnsafe(i, codec.encode(v, protocolVersion())); }
Sets the ith value, converting it to the given Java type.

The Data.codecRegistry() will be used to look up a codec to handle the conversion.

This variant is for generic Java types. If the target type is not generic, use set(int, Object, Class) instead, which may perform slightly better.

Throws:
/** * Sets the {@code i}th value, converting it to the given Java type. * * <p>The {@link #codecRegistry()} will be used to look up a codec to handle the conversion. * * <p>This variant is for generic Java types. If the target type is not generic, use {@link * #set(int, Object, Class)} instead, which may perform slightly better. * * @throws IndexOutOfBoundsException if the index is invalid. * @throws CodecNotFoundException if no codec can perform the conversion. */
@NonNull @CheckReturnValue default <ValueT> SelfT set(int i, @Nullable ValueT v, @NonNull GenericType<ValueT> targetType) { DataType cqlType = getType(i); TypeCodec<ValueT> codec = codecRegistry().codecFor(cqlType, targetType); return set(i, v, codec); }
Returns the ith value, converting it to the given Java type.

The Data.codecRegistry() will be used to look up a codec to handle the conversion.

If the target type is generic, use set(int, Object, GenericType) instead.

Throws:
/** * Returns the {@code i}th value, converting it to the given Java type. * * <p>The {@link #codecRegistry()} will be used to look up a codec to handle the conversion. * * <p>If the target type is generic, use {@link #set(int, Object, GenericType)} instead. * * @throws IndexOutOfBoundsException if the index is invalid. * @throws CodecNotFoundException if no codec can perform the conversion. */
@NonNull @CheckReturnValue default <ValueT> SelfT set(int i, @Nullable ValueT v, @NonNull Class<ValueT> targetClass) { // This is duplicated from the GenericType variant, because we want to give the codec registry // a chance to process the unwrapped class directly, if it can do so in a more efficient way. DataType cqlType = getType(i); TypeCodec<ValueT> codec = codecRegistry().codecFor(cqlType, targetClass); return set(i, v, codec); }
Sets the ith value to the provided Java primitive boolean.

By default, this works with CQL type boolean.

To set the value to CQL NULL, use setToNull(int), or set(i, v, Boolean.class).

Throws:
/** * Sets the {@code i}th value to the provided Java primitive boolean. * * <p>By default, this works with CQL type {@code boolean}. * * <p>To set the value to CQL {@code NULL}, use {@link #setToNull(int)}, or {@code set(i, v, * Boolean.class)}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setBoolean(int i, boolean v) { DataType cqlType = getType(i); TypeCodec<Boolean> codec = codecRegistry().codecFor(cqlType, Boolean.class); return (codec instanceof PrimitiveBooleanCodec) ? setBytesUnsafe(i, ((PrimitiveBooleanCodec) codec).encodePrimitive(v, protocolVersion())) : set(i, v, codec); }
Sets the ith value to the provided Java primitive byte.

By default, this works with CQL type tinyint.

To set the value to CQL NULL, use setToNull(int), or set(i, v, Boolean.class).

Throws:
/** * Sets the {@code i}th value to the provided Java primitive byte. * * <p>By default, this works with CQL type {@code tinyint}. * * <p>To set the value to CQL {@code NULL}, use {@link #setToNull(int)}, or {@code set(i, v, * Boolean.class)}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setByte(int i, byte v) { DataType cqlType = getType(i); TypeCodec<Byte> codec = codecRegistry().codecFor(cqlType, Byte.class); return (codec instanceof PrimitiveByteCodec) ? setBytesUnsafe(i, ((PrimitiveByteCodec) codec).encodePrimitive(v, protocolVersion())) : set(i, v, codec); }
Sets the ith value to the provided Java primitive double.

By default, this works with CQL type double.

To set the value to CQL NULL, use setToNull(int), or set(i, v, Double.class).

Throws:
/** * Sets the {@code i}th value to the provided Java primitive double. * * <p>By default, this works with CQL type {@code double}. * * <p>To set the value to CQL {@code NULL}, use {@link #setToNull(int)}, or {@code set(i, v, * Double.class)}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setDouble(int i, double v) { DataType cqlType = getType(i); TypeCodec<Double> codec = codecRegistry().codecFor(cqlType, Double.class); return (codec instanceof PrimitiveDoubleCodec) ? setBytesUnsafe(i, ((PrimitiveDoubleCodec) codec).encodePrimitive(v, protocolVersion())) : set(i, v, codec); }
Sets the ith value to the provided Java primitive float.

By default, this works with CQL type float.

To set the value to CQL NULL, use setToNull(int), or set(i, v, Float.class).

Throws:
/** * Sets the {@code i}th value to the provided Java primitive float. * * <p>By default, this works with CQL type {@code float}. * * <p>To set the value to CQL {@code NULL}, use {@link #setToNull(int)}, or {@code set(i, v, * Float.class)}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setFloat(int i, float v) { DataType cqlType = getType(i); TypeCodec<Float> codec = codecRegistry().codecFor(cqlType, Float.class); return (codec instanceof PrimitiveFloatCodec) ? setBytesUnsafe(i, ((PrimitiveFloatCodec) codec).encodePrimitive(v, protocolVersion())) : set(i, v, codec); }
Sets the ith value to the provided Java primitive integer.

By default, this works with CQL type int.

To set the value to CQL NULL, use setToNull(int), or set(i, v, Integer.class).

Throws:
/** * Sets the {@code i}th value to the provided Java primitive integer. * * <p>By default, this works with CQL type {@code int}. * * <p>To set the value to CQL {@code NULL}, use {@link #setToNull(int)}, or {@code set(i, v, * Integer.class)}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setInt(int i, int v) { DataType cqlType = getType(i); TypeCodec<Integer> codec = codecRegistry().codecFor(cqlType, Integer.class); return (codec instanceof PrimitiveIntCodec) ? setBytesUnsafe(i, ((PrimitiveIntCodec) codec).encodePrimitive(v, protocolVersion())) : set(i, v, codec); }
Sets the ith value to the provided Java primitive long.

By default, this works with CQL types bigint and counter.

To set the value to CQL NULL, use setToNull(int), or set(i, v, Long.class).

Throws:
/** * Sets the {@code i}th value to the provided Java primitive long. * * <p>By default, this works with CQL types {@code bigint} and {@code counter}. * * <p>To set the value to CQL {@code NULL}, use {@link #setToNull(int)}, or {@code set(i, v, * Long.class)}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setLong(int i, long v) { DataType cqlType = getType(i); TypeCodec<Long> codec = codecRegistry().codecFor(cqlType, Long.class); return (codec instanceof PrimitiveLongCodec) ? setBytesUnsafe(i, ((PrimitiveLongCodec) codec).encodePrimitive(v, protocolVersion())) : set(i, v, codec); }
Sets the ith value to the provided Java primitive short.

By default, this works with CQL type smallint.

To set the value to CQL NULL, use setToNull(int), or set(i, v, Short.class).

Throws:
/** * Sets the {@code i}th value to the provided Java primitive short. * * <p>By default, this works with CQL type {@code smallint}. * * <p>To set the value to CQL {@code NULL}, use {@link #setToNull(int)}, or {@code set(i, v, * Short.class)}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setShort(int i, short v) { DataType cqlType = getType(i); TypeCodec<Short> codec = codecRegistry().codecFor(cqlType, Short.class); return (codec instanceof PrimitiveShortCodec) ? setBytesUnsafe(i, ((PrimitiveShortCodec) codec).encodePrimitive(v, protocolVersion())) : set(i, v, codec); }
Sets the ith value to the provided Java instant.

By default, this works with CQL type timestamp.

Throws:
/** * Sets the {@code i}th value to the provided Java instant. * * <p>By default, this works with CQL type {@code timestamp}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setInstant(int i, @Nullable Instant v) { return set(i, v, Instant.class); }
Sets the ith value to the provided Java local date.

By default, this works with CQL type date.

Throws:
/** * Sets the {@code i}th value to the provided Java local date. * * <p>By default, this works with CQL type {@code date}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setLocalDate(int i, @Nullable LocalDate v) { return set(i, v, LocalDate.class); }
Sets the ith value to the provided Java local time.

By default, this works with CQL type time.

Throws:
/** * Sets the {@code i}th value to the provided Java local time. * * <p>By default, this works with CQL type {@code time}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setLocalTime(int i, @Nullable LocalTime v) { return set(i, v, LocalTime.class); }
Sets the ith value to the provided Java byte buffer.

By default, this works with CQL type blob.

Throws:
/** * Sets the {@code i}th value to the provided Java byte buffer. * * <p>By default, this works with CQL type {@code blob}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setByteBuffer(int i, @Nullable ByteBuffer v) { return set(i, v, ByteBuffer.class); }
Sets the ith value to the provided Java string.

By default, this works with CQL types text, varchar and ascii.

Throws:
/** * Sets the {@code i}th value to the provided Java string. * * <p>By default, this works with CQL types {@code text}, {@code varchar} and {@code ascii}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setString(int i, @Nullable String v) { return set(i, v, String.class); }
Sets the ith value to the provided Java big integer.

By default, this works with CQL type varint.

Throws:
/** * Sets the {@code i}th value to the provided Java big integer. * * <p>By default, this works with CQL type {@code varint}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setBigInteger(int i, @Nullable BigInteger v) { return set(i, v, BigInteger.class); }
Sets the ith value to the provided Java big decimal.

By default, this works with CQL type decimal.

Throws:
/** * Sets the {@code i}th value to the provided Java big decimal. * * <p>By default, this works with CQL type {@code decimal}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setBigDecimal(int i, @Nullable BigDecimal v) { return set(i, v, BigDecimal.class); }
Sets the ith value to the provided Java UUID.

By default, this works with CQL types uuid and timeuuid.

Throws:
/** * Sets the {@code i}th value to the provided Java UUID. * * <p>By default, this works with CQL types {@code uuid} and {@code timeuuid}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setUuid(int i, @Nullable UUID v) { return set(i, v, UUID.class); }
Sets the ith value to the provided Java IP address.

By default, this works with CQL type inet.

Throws:
/** * Sets the {@code i}th value to the provided Java IP address. * * <p>By default, this works with CQL type {@code inet}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setInetAddress(int i, @Nullable InetAddress v) { return set(i, v, InetAddress.class); }
Sets the ith value to the provided duration.

By default, this works with CQL type duration.

Throws:
/** * Sets the {@code i}th value to the provided duration. * * <p>By default, this works with CQL type {@code duration}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setCqlDuration(int i, @Nullable CqlDuration v) { return set(i, v, CqlDuration.class); }
Sets the ith value to the provided token.

This works with the CQL type matching the partitioner in use for this cluster: bigint for Murmur3Partitioner, blob for ByteOrderedPartitioner, and varint for RandomPartitioner.

Throws:
/** * Sets the {@code i}th value to the provided token. * * <p>This works with the CQL type matching the partitioner in use for this cluster: {@code * bigint} for {@code Murmur3Partitioner}, {@code blob} for {@code ByteOrderedPartitioner}, and * {@code varint} for {@code RandomPartitioner}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setToken(int i, @NonNull Token v) { // Simply enumerate all known implementations. This goes against the concept of TokenFactory, // but injecting the factory here is too much of a hassle. // The only issue is if someone uses a custom partitioner, but this is highly unlikely, and even // then they can set the value manually as a workaround. if (v instanceof Murmur3Token) { return setLong(i, ((Murmur3Token) v).getValue()); } else if (v instanceof ByteOrderedToken) { return setByteBuffer(i, ((ByteOrderedToken) v).getValue()); } else if (v instanceof RandomToken) { return setBigInteger(i, ((RandomToken) v).getValue()); } else { throw new IllegalArgumentException("Unsupported token type " + v.getClass()); } }
Sets the ith value to the provided Java list.

By default, this works with CQL type list.

This method is provided for convenience when the element type is a non-generic type. For more complex list types, use set(int, Object, GenericType).

Throws:
/** * Sets the {@code i}th value to the provided Java list. * * <p>By default, this works with CQL type {@code list}. * * <p>This method is provided for convenience when the element type is a non-generic type. For * more complex list types, use {@link #set(int, Object, GenericType)}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default <ElementT> SelfT setList( int i, @Nullable List<ElementT> v, @NonNull Class<ElementT> elementsClass) { return set(i, v, GenericType.listOf(elementsClass)); }
Sets the ith value to the provided Java set.

By default, this works with CQL type set.

This method is provided for convenience when the element type is a non-generic type. For more complex set types, use set(int, Object, GenericType).

Throws:
/** * Sets the {@code i}th value to the provided Java set. * * <p>By default, this works with CQL type {@code set}. * * <p>This method is provided for convenience when the element type is a non-generic type. For * more complex set types, use {@link #set(int, Object, GenericType)}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default <ElementT> SelfT setSet( int i, @Nullable Set<ElementT> v, @NonNull Class<ElementT> elementsClass) { return set(i, v, GenericType.setOf(elementsClass)); }
Sets the ith value to the provided Java map.

By default, this works with CQL type map.

This method is provided for convenience when the element type is a non-generic type. For more complex map types, use set(int, Object, GenericType).

Throws:
/** * Sets the {@code i}th value to the provided Java map. * * <p>By default, this works with CQL type {@code map}. * * <p>This method is provided for convenience when the element type is a non-generic type. For * more complex map types, use {@link #set(int, Object, GenericType)}. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default <KeyT, ValueT> SelfT setMap( int i, @Nullable Map<KeyT, ValueT> v, @NonNull Class<KeyT> keyClass, @NonNull Class<ValueT> valueClass) { return set(i, v, GenericType.mapOf(keyClass, valueClass)); }
Sets the ith value to the provided user defined type value.

By default, this works with CQL user-defined types.

Throws:
/** * Sets the {@code i}th value to the provided user defined type value. * * <p>By default, this works with CQL user-defined types. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setUdtValue(int i, @Nullable UdtValue v) { return set(i, v, UdtValue.class); }
Sets the ith value to the provided tuple value.

By default, this works with CQL tuples.

Throws:
/** * Sets the {@code i}th value to the provided tuple value. * * <p>By default, this works with CQL tuples. * * @throws IndexOutOfBoundsException if the index is invalid. */
@NonNull @CheckReturnValue default SelfT setTupleValue(int i, @Nullable TupleValue v) { return set(i, v, TupleValue.class); } }