Skip to content

Commit b75a146

Browse files
committed
feat: Introduce Mapping To Type Support
<TODO>
1 parent 61cd40b commit b75a146

Some content is hidden

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

53 files changed

+1429
-39
lines changed

driver/clirr-ignored-differences.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,4 +633,10 @@
633633
<method>org.neo4j.driver.net.ServerAddress of(java.lang.String)</method>
634634
</difference>
635635

636+
<difference>
637+
<className>org/neo4j/driver/Value</className>
638+
<differenceType>7012</differenceType>
639+
<method>java.lang.Object as(java.lang.Class)</method>
640+
</difference>
641+
636642
</differences>

driver/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
exports org.neo4j.driver.util;
3030
exports org.neo4j.driver.exceptions;
3131
exports org.neo4j.driver.exceptions.value;
32+
exports org.neo4j.driver.mapping;
3233

3334
requires org.neo4j.bolt.connection;
3435
requires org.neo4j.bolt.connection.netty;

driver/src/main/java/org/neo4j/driver/Value.java

Lines changed: 250 additions & 38 deletions
Large diffs are not rendered by default.

driver/src/main/java/org/neo4j/driver/exceptions/value/ValueException.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,22 @@ public class ValueException extends ClientException {
3333
* @param message the message
3434
*/
3535
public ValueException(String message) {
36+
this(message, null);
37+
}
38+
39+
/**
40+
* Creates a new instance.
41+
* @param message the message
42+
* @param cause todo
43+
* @since 5.28.4
44+
*/
45+
public ValueException(String message, Throwable cause) {
3646
super(
3747
GqlStatusError.UNKNOWN.getStatus(),
3848
GqlStatusError.UNKNOWN.getStatusDescription(message),
3949
"N/A",
4050
message,
4151
GqlStatusError.DIAGNOSTIC_RECORD,
42-
null);
52+
cause);
4353
}
4454
}

driver/src/main/java/org/neo4j/driver/internal/value/BooleanValue.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717
package org.neo4j.driver.internal.value;
1818

19+
import org.neo4j.driver.exceptions.value.Uncoercible;
1920
import org.neo4j.driver.internal.types.InternalTypeSystem;
2021
import org.neo4j.driver.types.Type;
2122

@@ -57,6 +58,17 @@ public boolean asBoolean() {
5758
return true;
5859
}
5960

61+
@SuppressWarnings("unchecked")
62+
@Override
63+
public <T> T as(Class<T> targetClass) {
64+
if (targetClass.isAssignableFrom(Boolean.class)) {
65+
return targetClass.cast(Boolean.TRUE);
66+
} else if (targetClass.isAssignableFrom(boolean.class)) {
67+
return (T) Boolean.TRUE;
68+
}
69+
throw new Uncoercible(type().name(), targetClass.getCanonicalName());
70+
}
71+
6072
@Override
6173
public boolean isTrue() {
6274
return true;
@@ -90,6 +102,17 @@ public boolean asBoolean() {
90102
return false;
91103
}
92104

105+
@SuppressWarnings("unchecked")
106+
@Override
107+
public <T> T as(Class<T> targetClass) {
108+
if (targetClass.isAssignableFrom(Boolean.class)) {
109+
return targetClass.cast(Boolean.FALSE);
110+
} else if (targetClass.isAssignableFrom(boolean.class)) {
111+
return (T) Boolean.FALSE;
112+
}
113+
throw new Uncoercible(type().name(), targetClass.getCanonicalName());
114+
}
115+
93116
@Override
94117
public boolean isFalse() {
95118
return true;

driver/src/main/java/org/neo4j/driver/internal/value/BytesValue.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.neo4j.driver.internal.value;
1818

1919
import java.util.Arrays;
20+
import org.neo4j.driver.exceptions.value.Uncoercible;
2021
import org.neo4j.driver.internal.types.InternalTypeSystem;
2122
import org.neo4j.driver.types.Type;
2223

@@ -50,6 +51,14 @@ public byte[] asByteArray() {
5051
return val;
5152
}
5253

54+
@Override
55+
public <T> T as(Class<T> targetClass) {
56+
if (targetClass.isAssignableFrom(byte[].class)) {
57+
return targetClass.cast(asByteArray());
58+
}
59+
throw new Uncoercible(type().name(), targetClass.getCanonicalName());
60+
}
61+
5362
@Override
5463
public Type type() {
5564
return InternalTypeSystem.TYPE_SYSTEM.BYTES();

driver/src/main/java/org/neo4j/driver/internal/value/DateTimeValue.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.time.OffsetDateTime;
2020
import java.time.ZonedDateTime;
21+
import org.neo4j.driver.exceptions.value.Uncoercible;
2122
import org.neo4j.driver.internal.types.InternalTypeSystem;
2223
import org.neo4j.driver.types.Type;
2324

@@ -45,4 +46,14 @@ public Type type() {
4546
public BoltValue asBoltValue() {
4647
return new BoltValue(this, org.neo4j.bolt.connection.values.Type.DATE_TIME);
4748
}
49+
50+
@Override
51+
public <T> T as(Class<T> targetClass) {
52+
if (targetClass.isAssignableFrom(ZonedDateTime.class)) {
53+
return targetClass.cast(asZonedDateTime());
54+
} else if (targetClass.isAssignableFrom(OffsetDateTime.class)) {
55+
return targetClass.cast(asOffsetDateTime());
56+
}
57+
throw new Uncoercible(type().name(), targetClass.getCanonicalName());
58+
}
4859
}

driver/src/main/java/org/neo4j/driver/internal/value/DateValue.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.neo4j.driver.internal.value;
1818

1919
import java.time.LocalDate;
20+
import org.neo4j.driver.exceptions.value.Uncoercible;
2021
import org.neo4j.driver.internal.types.InternalTypeSystem;
2122
import org.neo4j.driver.types.Type;
2223

@@ -39,4 +40,12 @@ public Type type() {
3940
public BoltValue asBoltValue() {
4041
return new BoltValue(this, org.neo4j.bolt.connection.values.Type.DATE);
4142
}
43+
44+
@Override
45+
public <T> T as(Class<T> targetClass) {
46+
if (targetClass.isAssignableFrom(LocalDate.class)) {
47+
return targetClass.cast(asLocalDate());
48+
}
49+
throw new Uncoercible(type().name(), targetClass.getCanonicalName());
50+
}
4251
}

driver/src/main/java/org/neo4j/driver/internal/value/DurationValue.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,12 @@ public Type type() {
3939
public BoltValue asBoltValue() {
4040
return new BoltValue(this, org.neo4j.bolt.connection.values.Type.DURATION);
4141
}
42+
43+
@Override
44+
public <T> T as(Class<T> targetClass) {
45+
if (targetClass.isAssignableFrom(IsoDuration.class)) {
46+
return targetClass.cast(asIsoDuration());
47+
}
48+
return asMapped(targetClass);
49+
}
4250
}

driver/src/main/java/org/neo4j/driver/internal/value/FloatValue.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.neo4j.driver.internal.value;
1818

1919
import org.neo4j.driver.exceptions.value.LossyCoercion;
20+
import org.neo4j.driver.exceptions.value.Uncoercible;
2021
import org.neo4j.driver.internal.types.InternalTypeSystem;
2122
import org.neo4j.driver.types.Type;
2223

@@ -72,6 +73,29 @@ public float asFloat() {
7273
return floatVal;
7374
}
7475

76+
@SuppressWarnings("unchecked")
77+
@Override
78+
public <T> T as(Class<T> targetClass) {
79+
if (targetClass.equals(double.class)) {
80+
return (T) Double.valueOf(asDouble());
81+
} else if (targetClass.isAssignableFrom(Double.class)) {
82+
return targetClass.cast(asDouble());
83+
} else if (targetClass.equals(long.class)) {
84+
return (T) Long.valueOf(asLong());
85+
} else if (targetClass.equals(Long.class)) {
86+
return targetClass.cast(asLong());
87+
} else if (targetClass.equals(int.class)) {
88+
return (T) Integer.valueOf(asInt());
89+
} else if (targetClass.equals(Integer.class)) {
90+
return targetClass.cast(asInt());
91+
} else if (targetClass.equals(float.class)) {
92+
return (T) Float.valueOf(asFloat());
93+
} else if (targetClass.equals(Float.class)) {
94+
return targetClass.cast(asFloat());
95+
}
96+
throw new Uncoercible(type().name(), targetClass.getCanonicalName());
97+
}
98+
7599
@Override
76100
public boolean equals(Object o) {
77101
if (this == o) {

driver/src/main/java/org/neo4j/driver/internal/value/IntegerValue.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.neo4j.driver.internal.value;
1818

1919
import org.neo4j.driver.exceptions.value.LossyCoercion;
20+
import org.neo4j.driver.exceptions.value.Uncoercible;
2021
import org.neo4j.driver.internal.types.InternalTypeSystem;
2122
import org.neo4j.driver.types.Type;
2223

@@ -65,6 +66,29 @@ public float asFloat() {
6566
return (float) val;
6667
}
6768

69+
@SuppressWarnings("unchecked")
70+
@Override
71+
public <T> T as(Class<T> targetClass) {
72+
if (targetClass.equals(long.class)) {
73+
return (T) Long.valueOf(asLong());
74+
} else if (targetClass.isAssignableFrom(Long.class)) {
75+
return targetClass.cast(asLong());
76+
} else if (targetClass.equals(int.class)) {
77+
return (T) Integer.valueOf(asInt());
78+
} else if (targetClass.equals(Integer.class)) {
79+
return targetClass.cast(asInt());
80+
} else if (targetClass.equals(double.class)) {
81+
return (T) Double.valueOf(asDouble());
82+
} else if (targetClass.equals(Double.class)) {
83+
return targetClass.cast(asDouble());
84+
} else if (targetClass.equals(float.class)) {
85+
return (T) Float.valueOf(asFloat());
86+
} else if (targetClass.equals(Float.class)) {
87+
return targetClass.cast(asFloat());
88+
}
89+
throw new Uncoercible(type().name(), targetClass.getCanonicalName());
90+
}
91+
6892
@Override
6993
public String toString() {
7094
return Long.toString(val);

driver/src/main/java/org/neo4j/driver/internal/value/InternalValue.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,29 @@
1616
*/
1717
package org.neo4j.driver.internal.value;
1818

19+
import java.lang.reflect.ParameterizedType;
20+
import java.lang.reflect.Type;
1921
import org.neo4j.driver.Value;
22+
import org.neo4j.driver.exceptions.value.Uncoercible;
2023
import org.neo4j.driver.internal.AsValue;
2124
import org.neo4j.driver.internal.types.TypeConstructor;
2225

2326
public interface InternalValue extends Value, AsValue {
2427
TypeConstructor typeConstructor();
2528

2629
BoltValue asBoltValue();
30+
31+
default Object as(Type type) {
32+
if (type instanceof ParameterizedType parameterizedType) {
33+
return as(parameterizedType);
34+
} else if (type instanceof Class<?> classType) {
35+
return as(classType);
36+
} else {
37+
throw new Uncoercible(type().name(), type.toString());
38+
}
39+
}
40+
41+
default Object as(ParameterizedType type) {
42+
throw new Uncoercible(type().name(), type.toString());
43+
}
2744
}

driver/src/main/java/org/neo4j/driver/internal/value/ListValue.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818

1919
import static org.neo4j.driver.Values.ofObject;
2020

21+
import java.lang.reflect.ParameterizedType;
2122
import java.util.Arrays;
2223
import java.util.Iterator;
2324
import java.util.List;
2425
import java.util.function.Function;
2526
import org.neo4j.driver.Value;
2627
import org.neo4j.driver.Values;
28+
import org.neo4j.driver.exceptions.value.Uncoercible;
2729
import org.neo4j.driver.internal.types.InternalTypeSystem;
2830
import org.neo4j.driver.internal.util.Extract;
2931
import org.neo4j.driver.types.Type;
@@ -58,6 +60,29 @@ public <T> List<T> asList(Function<Value, T> mapFunction) {
5860
return Extract.list(values, mapFunction);
5961
}
6062

63+
@Override
64+
public <T> T as(Class<T> targetClass) {
65+
if (targetClass.isAssignableFrom(List.class)) {
66+
return targetClass.cast(asList());
67+
}
68+
throw new Uncoercible(type().name(), targetClass.getCanonicalName());
69+
}
70+
71+
@Override
72+
public Object as(ParameterizedType type) {
73+
var rawType = type.getRawType();
74+
if (rawType instanceof Class<?> cls) {
75+
if (cls.isAssignableFrom(List.class)) {
76+
return asList(v -> {
77+
var value = (InternalValue) v;
78+
var typeArgument = type.getActualTypeArguments()[0];
79+
return value.as(typeArgument);
80+
});
81+
}
82+
}
83+
throw new Uncoercible(type().name(), type.toString());
84+
}
85+
6186
@Override
6287
public int size() {
6388
return values.length;

driver/src/main/java/org/neo4j/driver/internal/value/LocalDateTimeValue.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.neo4j.driver.internal.value;
1818

1919
import java.time.LocalDateTime;
20+
import org.neo4j.driver.exceptions.value.Uncoercible;
2021
import org.neo4j.driver.internal.types.InternalTypeSystem;
2122
import org.neo4j.driver.types.Type;
2223

@@ -39,4 +40,12 @@ public Type type() {
3940
public BoltValue asBoltValue() {
4041
return new BoltValue(this, org.neo4j.bolt.connection.values.Type.LOCAL_DATE_TIME);
4142
}
43+
44+
@Override
45+
public <T> T as(Class<T> targetClass) {
46+
if (targetClass.isAssignableFrom(LocalDateTime.class)) {
47+
return targetClass.cast(asLocalDateTime());
48+
}
49+
throw new Uncoercible(type().name(), targetClass.getCanonicalName());
50+
}
4251
}

driver/src/main/java/org/neo4j/driver/internal/value/LocalTimeValue.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.neo4j.driver.internal.value;
1818

1919
import java.time.LocalTime;
20+
import org.neo4j.driver.exceptions.value.Uncoercible;
2021
import org.neo4j.driver.internal.types.InternalTypeSystem;
2122
import org.neo4j.driver.types.Type;
2223

@@ -39,4 +40,12 @@ public Type type() {
3940
public BoltValue asBoltValue() {
4041
return new BoltValue(this, org.neo4j.bolt.connection.values.Type.LOCAL_TIME);
4142
}
43+
44+
@Override
45+
public <T> T as(Class<T> targetClass) {
46+
if (targetClass.isAssignableFrom(LocalTime.class)) {
47+
return targetClass.cast(asLocalTime());
48+
}
49+
throw new Uncoercible(type().name(), targetClass.getCanonicalName());
50+
}
4251
}

0 commit comments

Comments
 (0)