Skip to content

Commit 842415b

Browse files
adutraolim7t
authored andcommitted
JAVA-2691: Provide driver 4 support for extra codecs
1 parent dd48ad7 commit 842415b

55 files changed

Lines changed: 5296 additions & 362 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

changelog/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### 4.8.0 (in progress)
66

7+
- [new feature] JAVA-2691: Provide driver 4 support for extra codecs
78
- [improvement] Allow injection of CodecRegistry on session builder
89
- [improvement] JAVA-2828: Add safe paging state wrapper
910
- [bug] JAVA-2835: Correctly handle unresolved addresses in DefaultEndPoint.equals

core/revapi.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5005,6 +5005,31 @@
50055005
"new": "parameter int com.datastax.oss.driver.api.core.type.UserDefinedType::firstIndexOf(===java.lang.String===)",
50065006
"annotation": "@edu.umd.cs.findbugs.annotations.NonNull",
50075007
"justification": "Add missing `@NonNull` annotation to UserDefinedType.firstIndexOf"
5008+
},
5009+
{
5010+
"code": "java.class.nonPublicPartOfAPI",
5011+
"new": "class com.fasterxml.jackson.databind.introspect.AnnotatedConstructor.Serialization",
5012+
"justification": "Caused by the exposure of ObjectMapper as a parameter in ExtraTypeCodecs.json()"
5013+
},
5014+
{
5015+
"code": "java.class.nonPublicPartOfAPI",
5016+
"new": "class com.fasterxml.jackson.databind.introspect.AnnotatedField.Serialization",
5017+
"justification": "Caused by the exposure of ObjectMapper as a parameter in ExtraTypeCodecs.json()"
5018+
},
5019+
{
5020+
"code": "java.class.nonPublicPartOfAPI",
5021+
"new": "class com.fasterxml.jackson.databind.introspect.AnnotatedMethod.Serialization",
5022+
"justification": "Caused by the exposure of ObjectMapper as a parameter in ExtraTypeCodecs.json()"
5023+
},
5024+
{
5025+
"code": "java.class.nonPublicPartOfAPI",
5026+
"new": "class com.fasterxml.jackson.databind.type.TypeParser.MyTokenizer",
5027+
"justification": "Caused by the exposure of ObjectMapper as a parameter in ExtraTypeCodecs.json()"
5028+
},
5029+
{
5030+
"code": "java.class.nonPublicPartOfAPI",
5031+
"new": "class com.fasterxml.jackson.databind.util.PrimitiveArrayBuilder.Node<T extends java.lang.Object>",
5032+
"justification": "Caused by the exposure of ObjectMapper as a parameter in ExtraTypeCodecs.json()"
50085033
}
50095034
]
50105035
}

core/src/main/java/com/datastax/oss/driver/api/core/type/codec/ExtraTypeCodecs.java

Lines changed: 482 additions & 0 deletions
Large diffs are not rendered by default.

core/src/main/java/com/datastax/oss/driver/api/core/type/codec/TypeCodecs.java

Lines changed: 110 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
import com.datastax.oss.driver.internal.core.type.codec.UdtCodec;
4949
import com.datastax.oss.driver.internal.core.type.codec.UuidCodec;
5050
import com.datastax.oss.driver.internal.core.type.codec.VarIntCodec;
51-
import com.datastax.oss.driver.internal.core.type.codec.ZonedTimestampCodec;
5251
import com.datastax.oss.driver.shaded.guava.common.base.Charsets;
5352
import com.datastax.oss.driver.shaded.guava.common.base.Preconditions;
5453
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -60,112 +59,190 @@
6059
import java.time.LocalDate;
6160
import java.time.LocalTime;
6261
import java.time.ZoneId;
63-
import java.time.ZoneOffset;
6462
import java.time.ZonedDateTime;
6563
import java.util.List;
6664
import java.util.Map;
6765
import java.util.Set;
6866
import java.util.UUID;
6967

70-
/** Constants and factory methods to obtain type codec instances. */
68+
/**
69+
* Constants and factory methods to obtain instances of the driver's default type codecs.
70+
*
71+
* <p>See also {@link ExtraTypeCodecs} for additional codecs that you can register with your session
72+
* to handle different type mappings.
73+
*/
7174
public class TypeCodecs {
7275

76+
/** The default codec that maps CQL type {@code boolean} to Java's {@code boolean}. */
7377
public static final PrimitiveBooleanCodec BOOLEAN = new BooleanCodec();
78+
79+
/** The default codec that maps CQL type {@code tinyint} to Java's {@code byte}. */
7480
public static final PrimitiveByteCodec TINYINT = new TinyIntCodec();
81+
82+
/** The default codec that maps CQL type {@code double} to Java's {@code double}. */
7583
public static final PrimitiveDoubleCodec DOUBLE = new DoubleCodec();
84+
85+
/** The default codec that maps CQL type {@code counter} to Java's {@code long}. */
7686
public static final PrimitiveLongCodec COUNTER = new CounterCodec();
87+
88+
/** The default codec that maps CQL type {@code float} to Java's {@code float}. */
7789
public static final PrimitiveFloatCodec FLOAT = new FloatCodec();
90+
91+
/** The default codec that maps CQL type {@code int} to Java's {@code int}. */
7892
public static final PrimitiveIntCodec INT = new IntCodec();
93+
94+
/** The default codec that maps CQL type {@code bigint} to Java's {@code long}. */
7995
public static final PrimitiveLongCodec BIGINT = new BigIntCodec();
96+
97+
/** The default codec that maps CQL type {@code smallint} to Java's {@code short}. */
8098
public static final PrimitiveShortCodec SMALLINT = new SmallIntCodec();
81-
public static final TypeCodec<Instant> TIMESTAMP = new TimestampCodec();
8299

83100
/**
84-
* A codec that handles Apache Cassandra(R)'s timestamp type and maps it to Java's {@link
85-
* ZonedDateTime}, using the system's {@linkplain ZoneId#systemDefault() default time zone} as its
86-
* source of time zone information.
101+
* The default codec that maps CQL type {@code timestamp} to Java's {@link Instant}, using the
102+
* system's default time zone to parse and format CQL literals.
103+
*
104+
* <p>This codec uses the system's {@linkplain ZoneId#systemDefault() default time zone} as its
105+
* source of time zone information when formatting values as CQL literals, or parsing CQL literals
106+
* that do not have any time zone indication. Note that this only applies to the {@link
107+
* TypeCodec#format(Object)} and {@link TypeCodec#parse(String)} methods; regular encoding and
108+
* decoding, like setting a value on a bound statement or reading a column from a row, are not
109+
* affected by the time zone.
87110
*
88-
* <p>Note that Apache Cassandra(R)'s timestamp type does not store any time zone; this codec is
89-
* provided merely as a convenience for users that need to deal with zoned timestamps in their
90-
* applications.
111+
* <p>If you need a different time zone, consider other codecs in {@link ExtraTypeCodecs}, or call
112+
* {@link ExtraTypeCodecs#timestampAt(ZoneId)} instead.
91113
*
92-
* @see #ZONED_TIMESTAMP_UTC
93-
* @see #zonedTimestampAt(ZoneId)
114+
* @see ExtraTypeCodecs#TIMESTAMP_UTC
115+
* @see ExtraTypeCodecs#timestampAt(ZoneId)
94116
*/
95-
public static final TypeCodec<ZonedDateTime> ZONED_TIMESTAMP_SYSTEM = new ZonedTimestampCodec();
117+
public static final TypeCodec<Instant> TIMESTAMP = new TimestampCodec();
118+
119+
/** The default codec that maps CQL type {@code date} to Java's {@link LocalDate}. */
120+
public static final TypeCodec<LocalDate> DATE = new DateCodec();
121+
122+
/** The default codec that maps CQL type {@code time} to Java's {@link LocalTime}. */
123+
public static final TypeCodec<LocalTime> TIME = new TimeCodec();
96124

97125
/**
98-
* A codec that handles Apache Cassandra(R)'s timestamp type and maps it to Java's {@link
99-
* ZonedDateTime}, using {@link ZoneOffset#UTC} as its source of time zone information.
126+
* The default codec that maps CQL type {@code blob} to Java's {@link ByteBuffer}.
127+
*
128+
* <p>If you are looking for a codec mapping CQL type {@code blob} to the Java type {@code
129+
* byte[]}, you should use {@link ExtraTypeCodecs#BLOB_TO_ARRAY} instead.
100130
*
101-
* <p>Note that Apache Cassandra(R)'s timestamp type does not store any time zone; this codec is
102-
* provided merely as a convenience for users that need to deal with zoned timestamps in their
103-
* applications.
131+
* <p>If you are looking for a codec mapping CQL type {@code list<tinyint>} to the Java type
132+
* {@code byte[]}, you should use {@link ExtraTypeCodecs#BYTE_LIST_TO_ARRAY} instead.
104133
*
105-
* @see #ZONED_TIMESTAMP_SYSTEM
106-
* @see #zonedTimestampAt(ZoneId)
134+
* @see ExtraTypeCodecs#BLOB_TO_ARRAY
135+
* @see ExtraTypeCodecs#BYTE_LIST_TO_ARRAY
107136
*/
108-
public static final TypeCodec<ZonedDateTime> ZONED_TIMESTAMP_UTC =
109-
new ZonedTimestampCodec(ZoneOffset.UTC);
110-
111-
public static final TypeCodec<LocalDate> DATE = new DateCodec();
112-
public static final TypeCodec<LocalTime> TIME = new TimeCodec();
113137
public static final TypeCodec<ByteBuffer> BLOB = new BlobCodec();
138+
139+
/** The default codec that maps CQL type {@code text} to Java's {@link String}. */
114140
public static final TypeCodec<String> TEXT = new StringCodec(DataTypes.TEXT, Charsets.UTF_8);
141+
/** The default codec that maps CQL type {@code ascii} to Java's {@link String}. */
115142
public static final TypeCodec<String> ASCII = new StringCodec(DataTypes.ASCII, Charsets.US_ASCII);
143+
/** The default codec that maps CQL type {@code varint} to Java's {@link BigInteger}. */
116144
public static final TypeCodec<BigInteger> VARINT = new VarIntCodec();
145+
/** The default codec that maps CQL type {@code decimal} to Java's {@link BigDecimal}. */
117146
public static final TypeCodec<BigDecimal> DECIMAL = new DecimalCodec();
147+
/** The default codec that maps CQL type {@code uuid} to Java's {@link UUID}. */
118148
public static final TypeCodec<UUID> UUID = new UuidCodec();
149+
/** The default codec that maps CQL type {@code timeuuid} to Java's {@link UUID}. */
119150
public static final TypeCodec<UUID> TIMEUUID = new TimeUuidCodec();
151+
/** The default codec that maps CQL type {@code inet} to Java's {@link InetAddress}. */
120152
public static final TypeCodec<InetAddress> INET = new InetCodec();
153+
/** The default codec that maps CQL type {@code duration} to the driver's {@link CqlDuration}. */
121154
public static final TypeCodec<CqlDuration> DURATION = new CqlDurationCodec();
122155

156+
/**
157+
* Builds a new codec that maps a CQL custom type to Java's {@link ByteBuffer}.
158+
*
159+
* @param cqlType the fully-qualified name of the custom type.
160+
*/
123161
@NonNull
124162
public static TypeCodec<ByteBuffer> custom(@NonNull DataType cqlType) {
125163
Preconditions.checkArgument(cqlType instanceof CustomType, "cqlType must be a custom type");
126164
return new CustomCodec((CustomType) cqlType);
127165
}
128166

167+
/**
168+
* Builds a new codec that maps a CQL list to a Java list, using the given codec to map each
169+
* element.
170+
*/
129171
@NonNull
130172
public static <T> TypeCodec<List<T>> listOf(@NonNull TypeCodec<T> elementCodec) {
131173
return new ListCodec<>(DataTypes.listOf(elementCodec.getCqlType()), elementCodec);
132174
}
133175

176+
/**
177+
* Builds a new codec that maps a CQL set to a Java set, using the given codec to map each
178+
* element.
179+
*/
134180
@NonNull
135181
public static <T> TypeCodec<Set<T>> setOf(@NonNull TypeCodec<T> elementCodec) {
136182
return new SetCodec<>(DataTypes.setOf(elementCodec.getCqlType()), elementCodec);
137183
}
138184

185+
/**
186+
* Builds a new codec that maps a CQL map to a Java map, using the given codecs to map each key
187+
* and value.
188+
*/
139189
@NonNull
140190
public static <K, V> TypeCodec<Map<K, V>> mapOf(
141191
@NonNull TypeCodec<K> keyCodec, @NonNull TypeCodec<V> valueCodec) {
142192
return new MapCodec<>(
143193
DataTypes.mapOf(keyCodec.getCqlType(), valueCodec.getCqlType()), keyCodec, valueCodec);
144194
}
145195

196+
/**
197+
* Builds a new codec that maps a CQL tuple to the driver's {@link TupleValue}, for the given type
198+
* definition.
199+
*
200+
* <p>Note that the components of a {@link TupleValue} are stored in their encoded form. They are
201+
* encoded/decoded on the fly when you set or get them, using the codec registry.
202+
*/
146203
@NonNull
147204
public static TypeCodec<TupleValue> tupleOf(@NonNull TupleType cqlType) {
148205
return new TupleCodec(cqlType);
149206
}
150207

208+
/**
209+
* Builds a new codec that maps a CQL user defined type to the driver's {@link UdtValue}, for the
210+
* given type definition.
211+
*
212+
* <p>Note that the fields of a {@link UdtValue} are stored in their encoded form. They are
213+
* encoded/decoded on the fly when you set or get them, using the codec registry.
214+
*/
151215
@NonNull
152216
public static TypeCodec<UdtValue> udtOf(@NonNull UserDefinedType cqlType) {
153217
return new UdtCodec(cqlType);
154218
}
155219

156220
/**
157-
* Returns a codec that handles Apache Cassandra(R)'s timestamp type and maps it to Java's {@link
158-
* ZonedDateTime}, using the supplied {@link ZoneId} as its source of time zone information.
221+
* An alias for {@link ExtraTypeCodecs#ZONED_TIMESTAMP_SYSTEM}.
159222
*
160-
* <p>Note that Apache Cassandra(R)'s timestamp type does not store any time zone; the codecs
161-
* created by this method are provided merely as a convenience for users that need to deal with
162-
* zoned timestamps in their applications.
223+
* <p>This exists for historical reasons: the constant was originally defined in this class, but
224+
* technically it belongs to {@link ExtraTypeCodecs} because this is not a built-in mapping.
225+
*/
226+
public static final TypeCodec<ZonedDateTime> ZONED_TIMESTAMP_SYSTEM =
227+
ExtraTypeCodecs.ZONED_TIMESTAMP_SYSTEM;
228+
229+
/**
230+
* An alias for {@link ExtraTypeCodecs#ZONED_TIMESTAMP_UTC}.
231+
*
232+
* <p>This exists for historical reasons: the constant was originally defined in this class, but
233+
* technically it belongs to {@link ExtraTypeCodecs} because this is not a built-in mapping.
234+
*/
235+
public static final TypeCodec<ZonedDateTime> ZONED_TIMESTAMP_UTC =
236+
ExtraTypeCodecs.ZONED_TIMESTAMP_UTC;
237+
238+
/**
239+
* An alias for {@link ExtraTypeCodecs#zonedTimestampAt(ZoneId)}.
163240
*
164-
* @see #ZONED_TIMESTAMP_SYSTEM
165-
* @see #ZONED_TIMESTAMP_UTC
241+
* <p>This exists for historical reasons: the method was originally defined in this class, but
242+
* technically it belongs to {@link ExtraTypeCodecs} because this is not a built-in mapping.
166243
*/
167244
@NonNull
168245
public static TypeCodec<ZonedDateTime> zonedTimestampAt(@NonNull ZoneId timeZone) {
169-
return new ZonedTimestampCodec(timeZone);
246+
return ExtraTypeCodecs.zonedTimestampAt(timeZone);
170247
}
171248
}

core/src/main/java/com/datastax/oss/driver/api/core/type/reflect/GenericType.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@
3434
import java.time.Duration;
3535
import java.time.Instant;
3636
import java.time.LocalDate;
37+
import java.time.LocalDateTime;
3738
import java.time.LocalTime;
3839
import java.time.ZonedDateTime;
3940
import java.util.List;
4041
import java.util.Map;
42+
import java.util.Optional;
4143
import java.util.Set;
4244
import java.util.UUID;
4345
import net.jcip.annotations.Immutable;
@@ -95,6 +97,7 @@ public class GenericType<T> {
9597
public static final GenericType<ZonedDateTime> ZONED_DATE_TIME = of(ZonedDateTime.class);
9698
public static final GenericType<LocalDate> LOCAL_DATE = of(LocalDate.class);
9799
public static final GenericType<LocalTime> LOCAL_TIME = of(LocalTime.class);
100+
public static final GenericType<LocalDateTime> LOCAL_DATE_TIME = of(LocalDateTime.class);
98101
public static final GenericType<ByteBuffer> BYTE_BUFFER = of(ByteBuffer.class);
99102
public static final GenericType<String> STRING = of(String.class);
100103
public static final GenericType<BigInteger> BIG_INTEGER = of(BigInteger.class);
@@ -162,6 +165,35 @@ public static <K, V> GenericType<Map<K, V>> mapOf(
162165
return new GenericType<>(token);
163166
}
164167

168+
@NonNull
169+
public static <T> GenericType<T[]> arrayOf(@NonNull Class<T> componentType) {
170+
TypeToken<T[]> token =
171+
new TypeToken<T[]>() {}.where(new TypeParameter<T>() {}, TypeToken.of(componentType));
172+
return new GenericType<>(token);
173+
}
174+
175+
@NonNull
176+
public static <T> GenericType<T[]> arrayOf(@NonNull GenericType<T> componentType) {
177+
TypeToken<T[]> token =
178+
new TypeToken<T[]>() {}.where(new TypeParameter<T>() {}, componentType.token);
179+
return new GenericType<>(token);
180+
}
181+
182+
@NonNull
183+
public static <T> GenericType<Optional<T>> optionalOf(@NonNull Class<T> componentType) {
184+
TypeToken<Optional<T>> token =
185+
new TypeToken<Optional<T>>() {}.where(
186+
new TypeParameter<T>() {}, TypeToken.of(componentType));
187+
return new GenericType<>(token);
188+
}
189+
190+
@NonNull
191+
public static <T> GenericType<Optional<T>> optionalOf(@NonNull GenericType<T> componentType) {
192+
TypeToken<Optional<T>> token =
193+
new TypeToken<Optional<T>>() {}.where(new TypeParameter<T>() {}, componentType.token);
194+
return new GenericType<>(token);
195+
}
196+
165197
private final TypeToken<T> token;
166198

167199
private GenericType(TypeToken<T> token) {

core/src/main/java/com/datastax/oss/driver/internal/core/type/codec/BlobCodec.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
import java.nio.ByteBuffer;
2727
import net.jcip.annotations.ThreadSafe;
2828

29+
/**
30+
* A codec that maps the CQL type {@code blob} to the Java type {@link ByteBuffer}.
31+
*
32+
* <p>If you are looking for a codec mapping the CQL type {@code blob} to the Java type {@code
33+
* byte[]}, you should use {@link SimpleBlobCodec} instead.
34+
*/
2935
@ThreadSafe
3036
public class BlobCodec implements TypeCodec<ByteBuffer> {
3137
@NonNull

0 commit comments

Comments
 (0)