Skip to content

Commit 72dded7

Browse files
authored
Merge pull request #215 from Jeremya/main
#213 Implemented DSE Type Codecs
2 parents f60a811 + 30bee04 commit 72dded7

File tree

10 files changed

+525
-2
lines changed

10 files changed

+525
-2
lines changed

PERF/cdm-v4.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ spark.cdm.perfops.writeRateLimit 5000
216216
# as Epoch milliseconds
217217
# TIMESTAMP_STRING_FORMAT : timestamp stored in a String,
218218
# with a custom format
219+
# POLYGON_TYPE : PolygonType geospatial DSE type
220+
# POINT_TYPE : PointType geospatial DSE type
221+
# LINE_STRING : LineStringType geospatial DSE type
222+
# DATE_RANGE : DateRange DSE type
219223
#
220224
# *** NOTE where there are multiple type pair options, such as with
221225
# *** TIMESTAMP_STRING, only one can be configured at a time.

pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@
143143
<artifactId>log4j-to-slf4j</artifactId>
144144
<version>${log4j.version}</version>
145145
</dependency>
146+
<dependency>
147+
<scope>runtime</scope>
148+
<groupId>com.esri.geometry</groupId>
149+
<artifactId>esri-geometry-api</artifactId>
150+
<version>2.2.0</version>
151+
</dependency>
146152

147153
<!-- Test Dependencies -->
148154
<dependency>
@@ -326,7 +332,7 @@
326332
<counter>LINE</counter>
327333
<value>MISSEDCOUNT</value>
328334
<!-- <maximum>1544</maximum>-->
329-
<maximum>3073</maximum>
335+
<maximum>3085</maximum>
330336
</limit>
331337
</limits>
332338
</rule>

src/main/java/com/datastax/cdm/cql/codec/CodecFactory.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package com.datastax.cdm.cql.codec;
22

33
import com.datastax.cdm.properties.PropertyHelper;
4+
import com.datastax.dse.driver.internal.core.type.codec.geometry.LineStringCodec;
5+
import com.datastax.dse.driver.internal.core.type.codec.geometry.PointCodec;
6+
import com.datastax.dse.driver.internal.core.type.codec.geometry.PolygonCodec;
7+
import com.datastax.dse.driver.internal.core.type.codec.time.DateRangeCodec;
48
import com.datastax.oss.driver.api.core.type.codec.TypeCodec;
59

610
import java.util.Arrays;
@@ -15,6 +19,11 @@ public static List<TypeCodec<?>> getCodecPair(PropertyHelper propertyHelper, Cod
1519
case DECIMAL_STRING: return Arrays.asList(new DECIMAL_StringCodec(propertyHelper), new TEXT_BigDecimalCodec(propertyHelper));
1620
case TIMESTAMP_STRING_MILLIS: return Arrays.asList(new TIMESTAMP_StringMillisCodec(propertyHelper), new TEXTMillis_InstantCodec(propertyHelper));
1721
case TIMESTAMP_STRING_FORMAT: return Arrays.asList(new TIMESTAMP_StringFormatCodec(propertyHelper), new TEXTFormat_InstantCodec(propertyHelper));
22+
case POLYGON_TYPE: return Arrays.asList(new PolygonCodec());
23+
case POINT_TYPE: return Arrays.asList(new PointCodec());
24+
case DATE_RANGE: return Arrays.asList(new DateRangeCodec());
25+
case LINE_STRING: return Arrays.asList(new LineStringCodec());
26+
1827
default:
1928
throw new IllegalArgumentException("Unknown codec: " + codec);
2029
}

src/main/java/com/datastax/cdm/cql/codec/Codecset.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,9 @@ public enum Codecset {
66
BIGINT_STRING,
77
DECIMAL_STRING,
88
TIMESTAMP_STRING_MILLIS,
9-
TIMESTAMP_STRING_FORMAT
9+
TIMESTAMP_STRING_FORMAT,
10+
POINT_TYPE,
11+
POLYGON_TYPE,
12+
DATE_RANGE,
13+
LINE_STRING
1014
}

src/main/java/com/datastax/cdm/data/CqlData.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.datastax.cdm.data;
22

3+
import com.datastax.dse.driver.api.core.type.DseDataTypes;
34
import com.datastax.oss.driver.api.core.data.UdtValue;
45
import com.datastax.oss.driver.api.core.type.*;
56

@@ -39,6 +40,10 @@ public enum Type {
3940
primitiveDataTypeToJavaClassMap.put(DataTypes.TIMEUUID, java.util.UUID.class);
4041
primitiveDataTypeToJavaClassMap.put(DataTypes.COUNTER, Long.class);
4142
primitiveDataTypeToJavaClassMap.put(DataTypes.DURATION, com.datastax.oss.driver.api.core.data.CqlDuration.class);
43+
primitiveDataTypeToJavaClassMap.put(DseDataTypes.POLYGON, com.datastax.dse.driver.api.core.data.geometry.Polygon.class);
44+
primitiveDataTypeToJavaClassMap.put(DseDataTypes.POINT, com.datastax.dse.driver.api.core.data.geometry.Point.class);
45+
primitiveDataTypeToJavaClassMap.put(DseDataTypes.LINE_STRING, com.datastax.dse.driver.api.core.data.geometry.LineString.class);
46+
primitiveDataTypeToJavaClassMap.put(DseDataTypes.DATE_RANGE, com.datastax.dse.driver.api.core.data.time.DateRange.class);
4247
}
4348

4449
public static Type toType(DataType dataType) {
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package com.datastax.cdm.cql.codec;
2+
3+
import com.datastax.cdm.data.MockitoExtension;
4+
import com.datastax.cdm.properties.PropertyHelper;
5+
import com.datastax.dse.driver.internal.core.type.codec.geometry.LineStringCodec;
6+
import com.datastax.dse.driver.internal.core.type.codec.geometry.PointCodec;
7+
import com.datastax.dse.driver.internal.core.type.codec.geometry.PolygonCodec;
8+
import com.datastax.dse.driver.internal.core.type.codec.time.DateRangeCodec;
9+
import com.datastax.oss.driver.api.core.type.codec.TypeCodec;
10+
import org.junit.jupiter.api.BeforeEach;
11+
import org.junit.jupiter.api.Test;
12+
import org.junit.jupiter.api.extension.ExtendWith;
13+
import org.mockito.Mock;
14+
import org.mockito.Mockito;
15+
16+
import java.util.List;
17+
18+
import static org.junit.jupiter.api.Assertions.*;
19+
20+
@ExtendWith(MockitoExtension.class)
21+
class CodecFactoryTest {
22+
@Mock
23+
private PropertyHelper propertyHelper;
24+
25+
@BeforeEach
26+
void setUp() {
27+
//Mockito.when(propertyHelper.getString("timestamp.format")).thenReturn("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
28+
}
29+
30+
@Test
31+
void getCodecPair_ShouldReturnCorrectCodecsForPolygonType() {
32+
List<TypeCodec<?>> codecs = CodecFactory.getCodecPair(propertyHelper, Codecset.POLYGON_TYPE);
33+
assertFalse(codecs.isEmpty());
34+
assertTrue(codecs.get(0) instanceof PolygonCodec);
35+
}
36+
37+
@Test
38+
void getCodecPair_ShouldReturnCorrectCodecsForIntString() {
39+
List<TypeCodec<?>> codecs = CodecFactory.getCodecPair(propertyHelper, Codecset.INT_STRING);
40+
assertFalse(codecs.isEmpty());
41+
assertTrue(codecs.get(0) instanceof INT_StringCodec);
42+
assertTrue(codecs.get(1) instanceof TEXT_IntegerCodec);
43+
}
44+
45+
@Test
46+
void getCodecPair_ShouldReturnCorrectCodecsForDoubleString() {
47+
List<TypeCodec<?>> codecs = CodecFactory.getCodecPair(propertyHelper, Codecset.DOUBLE_STRING);
48+
assertFalse(codecs.isEmpty());
49+
assertTrue(codecs.get(0) instanceof DOUBLE_StringCodec);
50+
assertTrue(codecs.get(1) instanceof TEXT_DoubleCodec);
51+
}
52+
53+
@Test
54+
void getCodecPair_ShouldReturnCorrectCodecsForBigintString() {
55+
List<TypeCodec<?>> codecs = CodecFactory.getCodecPair(propertyHelper, Codecset.BIGINT_STRING);
56+
assertFalse(codecs.isEmpty());
57+
assertTrue(codecs.get(0) instanceof BIGINT_StringCodec);
58+
assertTrue(codecs.get(1) instanceof TEXT_LongCodec);
59+
}
60+
61+
@Test
62+
void getCodecPair_ShouldReturnCorrectCodecsForDecimalString() {
63+
List<TypeCodec<?>> codecs = CodecFactory.getCodecPair(propertyHelper, Codecset.DECIMAL_STRING);
64+
assertFalse(codecs.isEmpty());
65+
assertTrue(codecs.get(0) instanceof DECIMAL_StringCodec);
66+
assertTrue(codecs.get(1) instanceof TEXT_BigDecimalCodec);
67+
}
68+
69+
@Test
70+
void getCodecPair_ShouldReturnCorrectCodecsForTimestampStringMillis() {
71+
List<TypeCodec<?>> codecs = CodecFactory.getCodecPair(propertyHelper, Codecset.TIMESTAMP_STRING_MILLIS);
72+
assertFalse(codecs.isEmpty());
73+
assertTrue(codecs.get(0) instanceof TIMESTAMP_StringMillisCodec);
74+
assertTrue(codecs.get(1) instanceof TEXTMillis_InstantCodec);
75+
}
76+
77+
// @Test
78+
// void getCodecPair_ShouldReturnCorrectCodecsForTimestampStringFormat() {
79+
// Mockito.when(propertyHelper.getString("timestamp.format")).thenReturn("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
80+
// List<TypeCodec<?>> codecs = CodecFactory.getCodecPair(propertyHelper, Codecset.TIMESTAMP_STRING_FORMAT);
81+
// assertFalse(codecs.isEmpty());
82+
// assertTrue(codecs.get(0) instanceof TIMESTAMP_StringFormatCodec);
83+
// assertTrue(codecs.get(1) instanceof TEXTFormat_InstantCodec);
84+
// }
85+
86+
@Test
87+
void getCodecPair_ShouldReturnCorrectCodecsForPointType() {
88+
List<TypeCodec<?>> codecs = CodecFactory.getCodecPair(propertyHelper, Codecset.POINT_TYPE);
89+
assertFalse(codecs.isEmpty());
90+
assertTrue(codecs.get(0) instanceof PointCodec);
91+
}
92+
93+
@Test
94+
void getCodecPair_ShouldReturnCorrectCodecsForDateRange() {
95+
List<TypeCodec<?>> codecs = CodecFactory.getCodecPair(propertyHelper, Codecset.DATE_RANGE);
96+
assertFalse(codecs.isEmpty());
97+
assertTrue(codecs.get(0) instanceof DateRangeCodec);
98+
}
99+
100+
@Test
101+
void getCodecPair_ShouldReturnCorrectCodecsForLineString() {
102+
List<TypeCodec<?>> codecs = CodecFactory.getCodecPair(propertyHelper, Codecset.LINE_STRING);
103+
assertFalse(codecs.isEmpty());
104+
assertTrue(codecs.get(0) instanceof LineStringCodec);
105+
}
106+
107+
@Test
108+
void getCodecPair_ShouldThrowExceptionForUnknownCodec() {
109+
assertThrows(NullPointerException.class, () -> {
110+
CodecFactory.getCodecPair(propertyHelper, null);
111+
});
112+
}
113+
114+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package com.datastax.cdm.cql.codec;
2+
3+
import com.datastax.dse.driver.api.core.data.time.DateRange;
4+
import com.datastax.dse.driver.internal.core.type.codec.time.DateRangeCodec;
5+
import com.datastax.oss.driver.api.core.ProtocolVersion;
6+
import org.junit.jupiter.api.BeforeEach;
7+
import org.junit.jupiter.api.Test;
8+
import java.nio.ByteBuffer;
9+
import java.text.ParseException;
10+
import java.time.Instant;
11+
import java.time.ZoneOffset;
12+
import java.time.ZonedDateTime;
13+
import java.time.format.DateTimeFormatter;
14+
import java.time.temporal.ChronoUnit;
15+
16+
import static org.junit.jupiter.api.Assertions.*;
17+
18+
class DATERANGETYPE_CodecTest {
19+
20+
private DateRangeCodec codec;
21+
private final ProtocolVersion protocolVersion = ProtocolVersion.DEFAULT;
22+
23+
@BeforeEach
24+
void setUp() {
25+
codec = new DateRangeCodec();
26+
}
27+
28+
@Test
29+
void encode_ShouldEncodeDateRangeToByteBuffer() throws ParseException {
30+
String dateRangeString = "2001-01-01";
31+
DateRange dateRange;
32+
try {
33+
dateRange = DateRange.parse(dateRangeString);
34+
} catch (ParseException e) {
35+
fail("Failed to parse the date range: " + e.getMessage());
36+
return;
37+
}
38+
39+
// Encode the DateRange object
40+
ByteBuffer encoded = codec.encode(dateRange, protocolVersion);
41+
42+
// Assertions
43+
assertNotNull(encoded);
44+
assertTrue(encoded.remaining() > 0);
45+
46+
// Decode the ByteBuffer back to a DateRange and compare
47+
DateRange decoded = codec.decode(encoded, protocolVersion);
48+
assertEquals(dateRange, decoded);
49+
}
50+
51+
@Test
52+
void decode_ShouldDecodeByteBufferToDateRange() throws ParseException {
53+
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.DAYS);
54+
String expectedFormattedDate = DateTimeFormatter.ISO_LOCAL_DATE.format(zonedDateTime);
55+
56+
// Create a DateRange object using a string in the expected format
57+
DateRange dateRange = DateRange.parse(expectedFormattedDate);
58+
String formatted = codec.format(dateRange);
59+
60+
// The formatted string should be surrounded by single quotes, remove them for the comparison
61+
String unquotedFormatted = formatted.replace("'", "");
62+
assertEquals(expectedFormattedDate, unquotedFormatted);
63+
}
64+
65+
@Test
66+
void format_ShouldFormatDateRangeToString() throws ParseException {
67+
String dateRangeString = "2001-01-01"; // Adjust this string to the correct format
68+
DateRange dateRange;
69+
try {
70+
dateRange = DateRange.parse(dateRangeString);
71+
} catch (ParseException e) {
72+
fail("Failed to parse the date range for setup: " + e.getMessage());
73+
return;
74+
}
75+
76+
// Format the date range using the codec
77+
String formatted = codec.format(dateRange);
78+
assertNotNull(formatted);
79+
80+
// Remove single quotes for parsing
81+
String unquotedFormatted = formatted.replace("'", "");
82+
DateRange parsedDateRange;
83+
try {
84+
parsedDateRange = DateRange.parse(unquotedFormatted);
85+
} catch (ParseException e) {
86+
fail("Failed to parse the formatted date range: " + e.getMessage());
87+
return;
88+
}
89+
90+
// The parsed DateRange should equal the original DateRange
91+
assertEquals(dateRange, parsedDateRange);
92+
}
93+
94+
@Test
95+
void parse_ShouldParseStringToDateRange() throws ParseException {
96+
String formattedDateTime = ZonedDateTime.now()
97+
.withZoneSameInstant(ZoneOffset.UTC)
98+
.truncatedTo(ChronoUnit.MILLIS)
99+
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
100+
101+
// Enclose in single quotes as per the error message
102+
String dateRangeLiteral = "'" + formattedDateTime + "'";
103+
104+
// Attempt to parse it using the codec
105+
DateRange parsedDateRange;
106+
try {
107+
parsedDateRange = codec.parse(dateRangeLiteral);
108+
} catch (Exception e) {
109+
fail("Parsing failed with exception: " + e.getMessage());
110+
return;
111+
}
112+
113+
assertNotNull(parsedDateRange);
114+
}
115+
116+
@Test
117+
void encode_ShouldHandleNullValues() {
118+
ByteBuffer result = codec.encode(null, protocolVersion);
119+
assertNull(result);
120+
}
121+
122+
@Test
123+
void decode_ShouldHandleNullByteBuffer() {
124+
DateRange result = codec.decode(null, protocolVersion);
125+
assertNull(result);
126+
}
127+
}

0 commit comments

Comments
 (0)