Skip to content

Commit 15a4b3d

Browse files
committed
fix up a bunch more unchecked casts
1 parent aaf0f6b commit 15a4b3d

File tree

6 files changed

+131
-109
lines changed

6 files changed

+131
-109
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/ValueBindJpaCriteriaParameter.java

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ private ValueBindJpaCriteriaParameter(ValueBindJpaCriteriaParameter<T> original)
4040

4141
@Override
4242
public ValueBindJpaCriteriaParameter<T> copy(SqmCopyContext context) {
43-
final ValueBindJpaCriteriaParameter<T> existing = context.getCopy( this );
43+
final var existing = context.getCopy( this );
4444
return existing != null
4545
? existing
4646
: context.registerCopy( this, new ValueBindJpaCriteriaParameter<>( this ) );
@@ -59,34 +59,43 @@ public void appendHqlString(StringBuilder hql, SqmRenderContext context) {
5959
// but for equals/hashCode, use equals/hashCode of the underlying value, if available, from the nodes JavaType
6060

6161
@Override
62-
public final boolean equals(@Nullable Object o) {
63-
if ( this == o ) {
62+
public final boolean equals(@Nullable Object object) {
63+
if ( this == object ) {
6464
return true;
6565
}
66-
if ( o instanceof ValueBindJpaCriteriaParameter<?> that ) {
67-
if ( value == null ) {
68-
return that.value == null && Objects.equals( getNodeType(), that.getNodeType() );
66+
else if ( object instanceof ValueBindJpaCriteriaParameter<?> that ) {
67+
if ( this.value == null || that.value == null ) {
68+
return this.value == that.value
69+
&& Objects.equals( this.getNodeType(), that.getNodeType() );
6970
}
70-
final var javaType = getJavaTypeDescriptor();
71-
if ( that.value != null ) {
72-
if ( javaType != null ) {
73-
//noinspection unchecked
74-
return javaType.equals( that.getJavaTypeDescriptor() ) && javaType.areEqual( value, (T) that.value );
71+
else {
72+
final var thisJavaType = getJavaTypeDescriptor();
73+
final var thatJavaType = that.getJavaTypeDescriptor();
74+
if ( thisJavaType == null || thatJavaType == null ) {
75+
return thisJavaType == thatJavaType
76+
&& this.value.equals( that.value );
7577
}
7678
else {
77-
return that.getJavaTypeDescriptor() == null && value.equals( that.value );
79+
return thisJavaType.equals( thatJavaType )
80+
&& thisJavaType.areEqual( value, thisJavaType.cast( that.value ) );
7881
}
7982
}
8083
}
81-
return false;
84+
else {
85+
return false;
86+
}
8287
}
8388

8489
@Override
8590
public int hashCode() {
8691
if ( value == null ) {
8792
return 0;
8893
}
89-
final var javaType = getJavaTypeDescriptor();
90-
return javaType == null ? value.hashCode() : javaType.extractHashCode( value );
94+
else {
95+
final var javaType = getJavaTypeDescriptor();
96+
return javaType == null
97+
? value.hashCode()
98+
: javaType.extractHashCode( value );
99+
}
91100
}
92101
}

hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ArrayConverter.java

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,93 +4,87 @@
44
*/
55
package org.hibernate.type.descriptor.converter.internal;
66

7-
import java.lang.reflect.Array;
8-
97
import org.hibernate.internal.build.AllowReflection;
8+
import org.hibernate.type.BasicType;
109
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
1110
import org.hibernate.type.descriptor.java.JavaType;
1211

12+
import static java.lang.reflect.Array.newInstance;
13+
import static org.hibernate.internal.util.ReflectHelper.arrayClass;
14+
1315
/**
1416
* Given a {@link BasicValueConverter} for array elements, handles conversion
1517
* to and from an array of the converted element type.
1618
*
1719
* @param <E> the unconverted element type
1820
* @param <F> the converted element type
19-
* @param <T> the unconverted array type
20-
* @param <S> the converted array type
21+
* @param <T> the unconverted array type (same as {@code E[]})
2122
*/
2223
@AllowReflection
23-
public class ArrayConverter<T, S, E, F> implements BasicValueConverter<T, S> {
24+
public class ArrayConverter<T, E, F> implements BasicValueConverter<T, F[]> {
2425

2526
private final BasicValueConverter<E, F> elementConverter;
2627
private final JavaType<T> domainJavaType;
27-
private final JavaType<S> relationalJavaType;
28+
private final JavaType<F[]> relationalJavaType;
29+
private final Class<E[]> arrayClass;
2830

2931
public ArrayConverter(
3032
BasicValueConverter<E, F> elementConverter,
3133
JavaType<T> domainJavaType,
32-
JavaType<S> relationalJavaType) {
34+
JavaType<F[]> relationalJavaType,
35+
BasicType<E> elementType) {
3336
this.elementConverter = elementConverter;
3437
this.domainJavaType = domainJavaType;
3538
this.relationalJavaType = relationalJavaType;
39+
this.arrayClass = arrayClass( elementType.getJavaType() );
3640
}
3741

3842
@Override
39-
public T toDomainValue(S relationalForm) {
43+
public T toDomainValue(F[] relationalForm) {
4044
if ( relationalForm == null ) {
4145
return null;
4246
}
4347
else {
44-
final Class<E> elementClass = elementConverter.getDomainJavaType().getJavaTypeClass();
45-
if ( relationalForm.getClass().getComponentType() == elementClass) {
46-
//noinspection unchecked
47-
return (T) relationalForm;
48-
}
49-
else {
50-
//noinspection unchecked
51-
return convertTo( (F[]) relationalForm, elementClass );
52-
}
48+
final var elementClass =
49+
elementConverter.getDomainJavaType().getJavaTypeClass();
50+
return relationalForm.getClass().getComponentType() == elementClass
51+
? domainJavaType.cast( relationalForm )
52+
: convertTo( relationalJavaType.cast( relationalForm ), elementClass );
5353
}
5454
}
5555

5656
private T convertTo(F[] relationalArray, Class<E> elementClass) {
5757
//TODO: the following implementation only handles conversion between non-primitive arrays!
58-
//noinspection unchecked
59-
final E[] domainArray = (E[]) Array.newInstance( elementClass, relationalArray.length );
58+
final var domainArray =
59+
arrayClass.cast( newInstance( elementClass, relationalArray.length ) );
6060
for ( int i = 0; i < relationalArray.length; i++ ) {
6161
domainArray[i] = elementConverter.toDomainValue( relationalArray[i] );
6262
}
63-
//noinspection unchecked
64-
return (T) domainArray;
63+
return domainJavaType.cast( domainArray );
6564
}
6665

6766
@Override
68-
public S toRelationalValue(T domainForm) {
67+
public F[] toRelationalValue(T domainForm) {
6968
if ( domainForm == null ) {
7069
return null;
7170
}
7271
else {
73-
final Class<F> elementClass = elementConverter.getRelationalJavaType().getJavaTypeClass();
74-
if ( domainForm.getClass().getComponentType() == elementClass) {
75-
//noinspection unchecked
76-
return (S) domainForm;
77-
}
78-
else {
79-
//noinspection unchecked
80-
return convertFrom((E[]) domainForm, elementClass);
81-
}
72+
final Class<F> elementClass =
73+
elementConverter.getRelationalJavaType().getJavaTypeClass();
74+
return domainForm.getClass().getComponentType() == elementClass
75+
? relationalJavaType.cast( domainForm )
76+
: convertFrom( arrayClass.cast( domainForm ), elementClass );
8277
}
8378
}
8479

85-
private S convertFrom(E[] domainArray, Class<F> elementClass) {
80+
private F[] convertFrom(E[] domainArray, Class<F> elementClass) {
8681
//TODO: the following implementation only handles conversion between non-primitive arrays!
87-
//noinspection unchecked
88-
final F[] relationalArray = (F[]) Array.newInstance( elementClass, domainArray.length );
82+
final var relationalArray =
83+
relationalJavaType.cast( newInstance( elementClass, domainArray.length ) );
8984
for ( int i = 0; i < domainArray.length; i++ ) {
9085
relationalArray[i] = elementConverter.toRelationalValue( domainArray[i] );
9186
}
92-
//noinspection unchecked
93-
return (S) relationalArray;
87+
return relationalArray;
9488
}
9589

9690
@Override
@@ -99,7 +93,7 @@ public JavaType<T> getDomainJavaType() {
9993
}
10094

10195
@Override
102-
public JavaType<S> getRelationalJavaType() {
96+
public JavaType<F[]> getRelationalJavaType() {
10397
return relationalJavaType;
10498
}
10599

hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import org.hibernate.type.spi.TypeConfiguration;
2121

2222

23-
import static java.lang.reflect.Array.newInstance;
23+
import static org.hibernate.internal.util.ReflectHelper.arrayClass;
2424

2525
@AllowReflection
2626
public abstract class AbstractArrayJavaType<T, E> extends AbstractClassJavaType<T>
@@ -98,16 +98,16 @@ <F> BasicType<T> createTypeUsingConverter(
9898
ColumnTypeInformation columnTypeInformation,
9999
JdbcTypeIndicators indicators,
100100
BasicValueConverter<E, F> valueConverter) {
101-
final var convertedElementClass = valueConverter.getRelationalJavaType().getJavaTypeClass();
102-
final var convertedArrayClass = newInstance( convertedElementClass, 0 ).getClass();
101+
final var convertedArrayClass =
102+
arrayClass( valueConverter.getRelationalJavaType().getJavaTypeClass() );
103103
final var relationalJavaType =
104104
typeConfiguration.getJavaTypeRegistry()
105105
.resolveDescriptor( convertedArrayClass );
106106
return new ConvertedBasicArrayType<>(
107107
elementType,
108108
arrayJdbcType( typeConfiguration, elementType, columnTypeInformation, indicators ),
109109
this,
110-
new ArrayConverter<>( valueConverter, this, relationalJavaType )
110+
new ArrayConverter<>( valueConverter, this, relationalJavaType, elementType )
111111
);
112112
}
113113

hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -299,52 +299,71 @@ public <X> T[] wrap(X value, WrapperOptions options) {
299299
}
300300
}
301301

302-
final var elementJavaType = getElementJavaType();
303-
if ( value instanceof Object[] raw ) {
304-
final var componentClass = elementJavaType.getJavaTypeClass();
305-
//noinspection unchecked
306-
final var wrapped = (T[]) newInstance( componentClass, raw.length );
307-
if ( componentClass.isAssignableFrom( value.getClass().getComponentType() ) ) {
308-
for (int i = 0; i < raw.length; i++) {
309-
//noinspection unchecked
310-
wrapped[i] = (T) raw[i];
311-
}
312-
}
313-
else {
314-
for ( int i = 0; i < raw.length; i++ ) {
315-
wrapped[i] = elementJavaType.wrap( raw[i], options );
316-
}
317-
}
318-
return wrapped;
302+
if ( value instanceof Object[] array ) {
303+
return wrapObjectArray( value, array, options );
319304
}
320305
else if ( value instanceof byte[] bytes ) {
321306
return fromBytes( bytes );
322307
}
323308
else if ( value instanceof BinaryStream binaryStream ) {
324-
// When the value is a BinaryStream, this is a deserialization request
309+
// When the value is a BinaryStream,
310+
// this is a deserialization request
325311
return fromBytes( binaryStream.getBytes() );
326312
}
327-
else if ( elementJavaType.isInstance( value ) ) {
328-
// Support binding a single element as parameter value
329-
//noinspection unchecked
330-
final var wrapped = (T[]) newInstance( elementJavaType.getJavaTypeClass(), 1 );
331-
//noinspection unchecked
332-
wrapped[0] = (T) value;
333-
return wrapped;
334-
}
335313
else if ( value instanceof Collection<?> collection ) {
336-
//noinspection unchecked
337-
final var wrapped = (T[]) newInstance( elementJavaType.getJavaTypeClass(), collection.size() );
338-
int i = 0;
339-
for ( Object e : collection ) {
340-
wrapped[i++] = elementJavaType.wrap( e, options );
341-
}
342-
return wrapped;
314+
return wrapCollection( collection, options );
315+
}
316+
else if ( getElementJavaType().isInstance( value ) ) {
317+
// Support binding a single element as a parameter value
318+
return wrapSingleElement( value, options );
343319
}
344320

345321
throw unknownWrap( value.getClass() );
346322
}
347323

324+
private T[] wrapCollection(Collection<?> collection, WrapperOptions options) {
325+
final var arrayClass = getJavaTypeClass();
326+
final var elementJavaType = getElementJavaType();
327+
final var wrapped = newArray( arrayClass, elementJavaType, collection.size() );
328+
int i = 0;
329+
for ( Object element : collection ) {
330+
wrapped[i++] = elementJavaType.wrap( element, options );
331+
}
332+
return wrapped;
333+
}
334+
335+
private < X> T[] wrapSingleElement(X value, WrapperOptions options) {
336+
final var arrayClass = getJavaTypeClass();
337+
final var elementJavaType = getElementJavaType();
338+
final var wrapped = newArray( arrayClass, elementJavaType, 1 );
339+
wrapped[0] = elementJavaType.wrap( value, options );
340+
return wrapped;
341+
}
342+
343+
private <X> T[] wrapObjectArray(X value, Object[] array, WrapperOptions options) {
344+
final var arrayClass = getJavaTypeClass();
345+
final var elementJavaType = getElementJavaType();
346+
final var wrapped = newArray( arrayClass, elementJavaType, array.length );
347+
// I suppose this code was there as an optimization,
348+
// but it doesn't really look necessary to me
349+
// if ( elementJavaType.getJavaTypeClass()
350+
// .isAssignableFrom( value.getClass().getComponentType() ) ) {
351+
// for ( int i = 0; i < array.length; i++) {
352+
// wrapped[i] = elementJavaType.cast( array[i] );
353+
// }
354+
// }
355+
// else {
356+
for ( int i = 0; i < array.length; i++ ) {
357+
wrapped[i] = elementJavaType.wrap( array[i], options );
358+
}
359+
// }
360+
return wrapped;
361+
}
362+
363+
private static <T> T[] newArray(Class<T[]> arrayClass, JavaType<T> elementJavaType, int length) {
364+
return arrayClass.cast( newInstance( elementJavaType.getJavaTypeClass(), length ) );
365+
}
366+
348367
private static <T> byte[] toBytes(T[] array) {
349368
if ( array.getClass().getComponentType().isEnum() ) {
350369
final byte[] bytes = new byte[array.length];
@@ -364,21 +383,19 @@ private static <T> byte[] toBytes(T[] array) {
364383

365384
private T[] fromBytes(byte[] bytes) {
366385
final var elementClass = getElementJavaType().getJavaTypeClass();
386+
final var arrayClass = getJavaTypeClass();
367387
if ( elementClass.isEnum() ) {
368-
final T[] enumConstants = elementClass.getEnumConstants();
369-
final var array = (Object[]) newInstance( elementClass, bytes.length );
388+
final var enumConstants = elementClass.getEnumConstants();
389+
final var array = newArray( arrayClass, getElementJavaType(), bytes.length );
370390
for (int i = 0; i < bytes.length; i++ ) {
371391
// null enum value was encoded as -1
372392
array[i] = bytes[i] == -1 ? null : enumConstants[bytes[i]];
373393
}
374-
//noinspection unchecked
375-
return (T[]) array;
376-
394+
return array;
377395
}
378396
else {
379397
// When the value is a byte[], this is a deserialization request
380-
//noinspection unchecked
381-
return (T[]) SerializationHelper.deserialize(bytes);
398+
return arrayClass.cast( SerializationHelper.deserialize( bytes ) );
382399
}
383400
}
384401

0 commit comments

Comments
 (0)