Skip to content

Commit 4ed1ce7

Browse files
committed
Remove custom array-handling code
HIBERNATE-58
1 parent 221ec3d commit 4ed1ce7

File tree

5 files changed

+26
-196
lines changed

5 files changed

+26
-196
lines changed

src/integrationTest/java/com/mongodb/hibernate/ArrayAndCollectionIntegrationTests.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@
6363
})
6464
@ServiceRegistry(settings = {@Setting(name = WRAPPER_ARRAY_HANDLING, value = "allow")})
6565
@ExtendWith(MongoExtension.class)
66-
// TODO-HIBERNATE-48 verify that we support `null`s in arrays/collections
6766
class ArrayAndCollectionIntegrationTests implements SessionFactoryScopeAware {
6867
@InjectMongoCollection("items")
6968
private static MongoCollection<BsonDocument> mongoCollection;

src/main/java/com/mongodb/hibernate/internal/type/MongoStructJdbcType.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,8 @@ public Object[] extractJdbcValues(@Nullable Object rawJdbcValue, WrapperOptions
197197
new MongoArray(value.asArray().toArray()),
198198
options);
199199
} else {
200-
domainValue = toDomainValue(
201-
value,
202-
ValueConversions.Type.of(jdbcMapping.getMappedJavaType().getJavaType()));
200+
domainValue =
201+
toDomainValue(value, jdbcMapping.getMappedJavaType().getJavaTypeClass());
203202
}
204203
result[elementIdx++] = domainValue;
205204
}

src/main/java/com/mongodb/hibernate/internal/type/ValueConversions.java

Lines changed: 22 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@
2424
import com.mongodb.hibernate.internal.FeatureNotSupportedException;
2525
import com.mongodb.hibernate.jdbc.MongoArray;
2626
import java.lang.reflect.Array;
27-
import java.lang.reflect.ParameterizedType;
2827
import java.math.BigDecimal;
2928
import java.sql.JDBCType;
3029
import java.sql.PreparedStatement;
3130
import java.sql.ResultSet;
3231
import java.sql.SQLException;
3332
import java.sql.SQLFeatureNotSupportedException;
3433
import java.util.ArrayList;
35-
import java.util.Collection;
3634
import org.bson.BsonArray;
3735
import org.bson.BsonBinary;
3836
import org.bson.BsonBoolean;
@@ -82,12 +80,8 @@ private ValueConversions() {}
8280
return toBsonValue(v);
8381
} else if (value instanceof ObjectId v) {
8482
return toBsonValue(v);
85-
} else if (value instanceof MongoArray v) {
86-
return toBsonValue(v);
87-
} else if (value.getClass().isArray()) {
88-
return arrayToBsonValue(value);
89-
} else if (value instanceof Collection<?> v) {
90-
return toBsonValue(v);
83+
} else if (value instanceof Object[] v) {
84+
return arrayToBsonValue(v);
9185
} else {
9286
throw new SQLFeatureNotSupportedException(format(
9387
"Value [%s] of type [%s] is not supported",
@@ -148,7 +142,7 @@ public static BsonBinary toBsonValue(byte[] value) {
148142
* href="https://docs.jboss.org/hibernate/orm/6.6/userguide/html_single/Hibernate_User_Guide.html#basic-chararray">
149143
* Hibernate ORM maps {@code char[]} to {@link java.sql.JDBCType#VARCHAR} by default</a>.
150144
*
151-
* @see #toDomainValue(BsonString, Type.ArrayOrCollection)
145+
* @see #toDomainValue(BsonString)
152146
*/
153147
private static BsonString toBsonValue(char[] value) {
154148
return new BsonString(String.valueOf(value));
@@ -165,9 +159,6 @@ public static BsonArray toBsonValue(java.sql.Array value) throws SQLFeatureNotSu
165159
} catch (SQLException e) {
166160
throw fail(e.toString());
167161
}
168-
// Hibernate ORM always passes an `java.sql.Array` with contents of the Java array type to
169-
// `PreparedStatement.setArray`
170-
assertTrue(contents.getClass().isArray());
171162
return arrayToBsonValue(contents);
172163
}
173164

@@ -180,15 +171,7 @@ private static BsonArray arrayToBsonValue(Object value) throws SQLFeatureNotSupp
180171
return new BsonArray(elements);
181172
}
182173

183-
private static BsonArray toBsonValue(Collection<?> value) throws SQLFeatureNotSupportedException {
184-
var elements = new ArrayList<BsonValue>(value.size());
185-
for (var e : value) {
186-
elements.add(toBsonValue(e));
187-
}
188-
return new BsonArray(elements);
189-
}
190-
191-
static Object toDomainValue(BsonValue value, Type domainType) throws SQLFeatureNotSupportedException {
174+
static Object toDomainValue(BsonValue value, Class<?> domainType) throws SQLFeatureNotSupportedException {
192175
// TODO-HIBERNATE-48 decide if `value` is nullable and the method may return `null`
193176
assertNotNull(value);
194177
if (value instanceof BsonDocument v) {
@@ -204,26 +187,21 @@ static Object toDomainValue(BsonValue value, Type domainType) throws SQLFeatureN
204187
} else if (value instanceof BsonDecimal128 v) {
205188
return toDomainValue(v);
206189
} else if (value instanceof BsonString v) {
207-
if (domainType instanceof Type.Simple simpleType) {
208-
return toDomainValue(v, simpleType.type());
209-
} else if (domainType instanceof Type.ArrayOrCollection arrayOrCollectionType) {
210-
return toDomainValue(v, arrayOrCollectionType).getArray();
190+
if (domainType.isArray()) {
191+
return toDomainValue(v);
211192
} else {
212-
throw fail(domainType.toString());
193+
return toDomainValue(v, domainType);
213194
}
214195
} else if (value instanceof BsonBinary v) {
215196
return toDomainValue(v);
216197
} else if (value instanceof BsonObjectId v) {
217198
return toDomainValue(v);
218-
} else if (value instanceof BsonArray v) {
219-
if (!(domainType instanceof Type.ArrayOrCollection arrayOrCollectionDomainType)) {
220-
throw fail("VAKOTODO SQLException/RuntimeException about invalid data");
221-
}
222-
return toDomainValue(v, arrayOrCollectionDomainType).getArray();
199+
} else if (value instanceof BsonArray v && domainType.isArray()) {
200+
return toDomainValue(v, assertNotNull(domainType.getComponentType()));
223201
} else {
224202
throw new SQLFeatureNotSupportedException(format(
225-
"Value [%s] of type [%s] is not supported",
226-
value, value.getClass().getTypeName()));
203+
"Value [%s] of type [%s] is not supported for the domain type [%s]",
204+
value, value.getClass().getTypeName(), domainType));
227205
}
228206
}
229207

@@ -313,109 +291,29 @@ private static ObjectId toDomainValue(BsonObjectId value) {
313291
return value.getValue();
314292
}
315293

316-
public static MongoArray toArrayDomainValue(BsonValue value, Type.ArrayOrCollection domainArrayContentsType)
317-
throws SQLFeatureNotSupportedException {
318-
if (value instanceof BsonArray v) {
319-
return toDomainValue(v, domainArrayContentsType);
320-
} else if (value instanceof BsonString v) {
321-
return toDomainValue(v, domainArrayContentsType);
322-
} else {
323-
throw new RuntimeException(
324-
format("Invalid data: value [%s], domainArrayContentsType [%s]", value, domainArrayContentsType));
325-
}
294+
public static MongoArray toArrayDomainValue(BsonValue value) throws SQLFeatureNotSupportedException {
295+
return new MongoArray(toDomainValue(value.asArray(), Object.class));
326296
}
327297

328-
private static MongoArray toDomainValue(BsonArray value, Type.ArrayOrCollection domainArrayContentsType)
329-
throws SQLFeatureNotSupportedException {
298+
private static Object toDomainValue(BsonArray value, Class<?> elementType) throws SQLFeatureNotSupportedException {
330299
var size = value.size();
331-
var domainValueBuilder = MongoArray.builder(domainArrayContentsType, size);
300+
var result = Array.newInstance(elementType, size);
332301
for (int i = 0; i < size; i++) {
333-
var element = toDomainValue(value.get(i), domainArrayContentsType.elementType());
334-
domainValueBuilder.add(i, element);
302+
var element = toDomainValue(value.get(i), elementType);
303+
Array.set(result, i, element);
335304
}
336-
return domainValueBuilder.build();
305+
return result;
337306
}
338307

339308
/** @see #toBsonValue(char[]) */
340-
private static MongoArray toDomainValue(BsonString value, Type.ArrayOrCollection domainArrayContentsType) {
309+
private static char[] toDomainValue(BsonString value) {
341310
var charsAsString = toDomainValue(value, String.class);
342311
var size = charsAsString.length();
343-
var domainValueBuilder = MongoArray.builder(domainArrayContentsType, size);
312+
var result = new char[size];
344313
for (int i = 0; i < size; i++) {
345314
var element = charsAsString.charAt(i);
346-
domainValueBuilder.add(i, element);
347-
}
348-
return domainValueBuilder.build();
349-
}
350-
351-
public sealed interface Type permits Type.Simple, Type.ArrayOrCollection {
352-
sealed interface Simple extends Type permits SimpleType {}
353-
354-
// VAKOTODO rename to Plural
355-
sealed interface ArrayOrCollection extends Type permits ArrayType, CollectionType {
356-
Simple elementType();
357-
}
358-
359-
static Type of(java.lang.reflect.Type type) {
360-
if (type instanceof Class<?> klass) {
361-
return of(klass);
362-
} else if (type instanceof ParameterizedType parameterizedType) {
363-
if (!(parameterizedType.getRawType() instanceof Class<?> rawKlass)) {
364-
throw fail(type.toString());
365-
}
366-
if (Collection.class.isAssignableFrom(rawKlass)) { // VAKOTODO equals?
367-
var collectionTypeArguments = parameterizedType.getActualTypeArguments();
368-
assertTrue(collectionTypeArguments.length == 1);
369-
return new CollectionType(rawKlass, collectionTypeArguments[0]);
370-
} else {
371-
return of(rawKlass);
372-
}
373-
} else {
374-
throw fail(type.toString());
375-
}
376-
}
377-
378-
private static Type of(Class<?> type) {
379-
if (type.isArray() && !type.equals(byte[].class)) {
380-
return array(type);
381-
} else {
382-
return simple(type);
383-
}
384-
}
385-
386-
private static Simple simple(Class<?> type) {
387-
return new SimpleType(type);
388-
}
389-
390-
static ArrayOrCollection array(Class<?> type) {
391-
return new ArrayType(type);
392-
}
393-
394-
Class<?> type();
395-
}
396-
397-
private record SimpleType(Class<?> type) implements Type.Simple {}
398-
399-
private record ArrayType(Class<?> type, Simple elementType) implements Type.ArrayOrCollection {
400-
ArrayType(Class<?> arrayType) {
401-
this(arrayType, elementType(arrayType));
402-
}
403-
404-
private static Simple elementType(Class<?> arrayType) {
405-
return Type.simple(assertNotNull(arrayType.componentType()));
406-
}
407-
}
408-
409-
private record CollectionType(Class<?> type, Simple elementType) implements Type.ArrayOrCollection {
410-
CollectionType(Class<?> rawCollectionType, java.lang.reflect.Type collectionTypeArgument) {
411-
this(rawCollectionType, elementType(collectionTypeArgument));
412-
}
413-
414-
private static Simple elementType(java.lang.reflect.Type collectionTypeArgument) {
415-
if (!(collectionTypeArgument instanceof Class<?> collectionTypeArgumentClass)) {
416-
throw fail(); // VAKOTODO try Collection<?>/Collection<? extends>/Collection<? super>
417-
}
418-
return Type.simple(collectionTypeArgumentClass);
315+
result[i] = element;
419316
}
317+
return result;
420318
}
421319
}

src/main/java/com/mongodb/hibernate/jdbc/MongoArray.java

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -16,80 +16,16 @@
1616

1717
package com.mongodb.hibernate.jdbc;
1818

19-
import com.mongodb.hibernate.internal.type.ValueConversions;
20-
import java.lang.reflect.Array;
21-
import java.util.ArrayList;
22-
import java.util.List;
23-
2419
public final class MongoArray implements ArrayAdapter {
2520
private final Object contents;
2621

27-
private MongoArray(Object contents) {
22+
public MongoArray(Object contents) {
2823
this.contents = contents;
2924
}
3025

31-
public MongoArray(Object[] contents) {
32-
this((Object) contents);
33-
}
34-
3526
@Override
3627
public Object getArray() {
3728
// Hibernate ORM does not call `Connection.getTypeMap`/`setTypeMap`, therefore we are free to ignore it
3829
return contents;
3930
}
40-
41-
public static Builder builder(ValueConversions.Type.ArrayOrCollection contentsType, int size) {
42-
var type = contentsType.type();
43-
if (type.isArray()) {
44-
return new ArrayBuilder(Array.newInstance(contentsType.elementType().type(), size));
45-
} else {
46-
// VAKOTODO remove, it's no longer used
47-
return new CollectionBuilder(new ArrayList<>(size));
48-
}
49-
}
50-
51-
public abstract static class Builder {
52-
private Builder() {}
53-
54-
public abstract void add(int i, Object element);
55-
56-
public abstract MongoArray build();
57-
}
58-
59-
@SuppressWarnings("ArrayRecordComponent")
60-
private static final class ArrayBuilder extends Builder {
61-
private final Object contents;
62-
63-
ArrayBuilder(Object contents) {
64-
this.contents = contents;
65-
}
66-
67-
@Override
68-
public void add(int i, Object element) {
69-
Array.set(contents, i, element);
70-
}
71-
72-
@Override
73-
public MongoArray build() {
74-
return new MongoArray(contents);
75-
}
76-
}
77-
78-
private static final class CollectionBuilder extends Builder {
79-
private final List<Object> contents;
80-
81-
CollectionBuilder(List<Object> contents) {
82-
this.contents = contents;
83-
}
84-
85-
@Override
86-
public void add(int i, Object element) {
87-
contents.add(i, element);
88-
}
89-
90-
@Override
91-
public MongoArray build() {
92-
return new MongoArray(contents);
93-
}
94-
}
9531
}

src/main/java/com/mongodb/hibernate/jdbc/MongoResultSet.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434

3535
import static com.mongodb.hibernate.internal.MongoAssertions.assertFalse;
3636
import static com.mongodb.hibernate.internal.MongoAssertions.assertNotNull;
37-
import static com.mongodb.hibernate.internal.type.ValueConversions.toArrayDomainValue;
3837
import static java.lang.String.format;
3938

4039
import com.mongodb.client.MongoCursor;
@@ -196,8 +195,7 @@ public double getDouble(int columnIndex) throws SQLException {
196195
public @Nullable Array getArray(int columnIndex) throws SQLException {
197196
checkClosed();
198197
checkColumnIndex(columnIndex);
199-
return getValue(
200-
columnIndex, bsonValue -> toArrayDomainValue(bsonValue, ValueConversions.Type.array(Object[].class)));
198+
return getValue(columnIndex, ValueConversions::toArrayDomainValue);
201199
}
202200

203201
@Override

0 commit comments

Comments
 (0)