Skip to content

Commit 72776d7

Browse files
committed
#107 - hibernate-models-bytebuddy
1 parent 8ba7162 commit 72776d7

File tree

18 files changed

+245
-129
lines changed

18 files changed

+245
-129
lines changed

buildSrc/src/main/groovy/shared-testing.gradle

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ plugins {
1111
// Wire in the shared-tests
1212
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1313

14-
// link the
1514
configurations {
1615
sharedTestClasses {
1716
canBeConsumed = false
@@ -24,22 +23,20 @@ configurations {
2423
sharedTestRuntimeClasspath {
2524
canBeConsumed = false
2625
canBeResolved = true
27-
extendsFrom testRuntimeClasspath
2826
}
2927
}
3028

3129
dependencies {
3230
testImplementation project( ":hibernate-models-testing" )
3331

34-
sharedTestClasses project(path: ':hibernate-models', configuration: 'exposedTestClasses')
35-
sharedTestResources project(path: ':hibernate-models', configuration: 'exposedTestResources')
36-
sharedTestRuntimeClasspath project(path: ':hibernate-models', configuration: 'exposedTestRuntimeClasspath')
32+
sharedTestClasses project(path: ':hibernate-models', configuration: 'exportedTestClasses')
33+
sharedTestResources project(path: ':hibernate-models', configuration: 'exportedTestResources')
34+
35+
sharedTestRuntimeClasspath project(path: ':hibernate-models', configuration: 'exportedTestRuntimeClasspath')
3736
}
3837

3938
tasks.named( "test", Test ) {
40-
// use the configurations defined above, which depends on the configurations in `:architecture-tests`
4139
testClassesDirs += configurations.sharedTestClasses
42-
4340
classpath += configurations.sharedTestResources
4441
classpath += configurations.sharedTestRuntimeClasspath
4542
}

hibernate-models-bytebuddy/src/main/java/org/hibernate/models/bytebuddy/internal/ClassDetailsImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public class ClassDetailsImpl extends AbstractAnnotationTarget implements ClassD
5252

5353
public ClassDetailsImpl(TypeDescription typeDescription, ByteBuddyModelsContext modelContext) {
5454
super( modelContext );
55+
assert !typeDescription.isPrimitive();
5556
this.typeDescription = typeDescription;
5657
this.superClassDetails = determineSuperType( typeDescription, modelContext );
5758
}

hibernate-models-bytebuddy/src/main/java/org/hibernate/models/bytebuddy/internal/ClassDetailsRegistryImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public ClassDetailsRegistryImpl(ByteBuddyModelContextImpl context) {
2525
}
2626

2727
@Override
28-
protected ClassDetailsBuilder getClassDetailsBuilder() {
28+
public ClassDetailsBuilder getClassDetailsBuilder() {
2929
return classDetailsBuilder;
3030
}
3131

hibernate-models-bytebuddy/src/main/java/org/hibernate/models/bytebuddy/internal/ModelBuilders.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ public static ClassDetails buildDetails(String name, ByteBuddyModelsContext mode
5757
return null;
5858
}
5959

60+
if ( name.startsWith( "[" ) ) {
61+
// always handle arrays via the JDK builder
62+
return null;
63+
}
64+
6065
if ( "void".equals( name ) ) {
6166
name = Void.class.getName();
6267
}
@@ -149,6 +154,14 @@ public static Class<?> resolvePrimitiveClass(String className) {
149154
return Float.class;
150155
}
151156

157+
if ( "char".equals( className ) ) {
158+
return char.class;
159+
}
160+
161+
if ( Character.class.getSimpleName().equals( className ) || Character.class.getName().equals( className ) ) {
162+
return Character.class;
163+
}
164+
152165
return null;
153166
}
154167

hibernate-models-bytebuddy/src/main/java/org/hibernate/models/bytebuddy/internal/TypeSwitchStandard.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import java.util.ArrayList;
88
import java.util.Collections;
9+
import java.util.HashSet;
910
import java.util.List;
1011

1112
import org.hibernate.models.bytebuddy.spi.TypeSwitch;
@@ -97,23 +98,45 @@ public TypeDetails caseWildcardType(TypeDefinition typeDescription, SourceModelB
9798
final TypeList.Generic bound;
9899
final boolean isExtends;
99100

100-
if ( ! (upperBounds instanceof TypeList.Generic.Empty) ) {
101+
if ( isExtends( upperBounds, lowerBounds ) ) {
101102
bound = upperBounds;
102103
isExtends = true;
103104
}
104-
else if ( ! (lowerBounds instanceof TypeList.Generic.Empty) ) {
105+
else {
105106
bound = lowerBounds;
106107
isExtends = false;
107108
}
108-
else {
109-
throw new IllegalArgumentException( "What?" );
110-
}
111109

112110
return new WildcardTypeDetailsImpl( TypeSwitcher.switchType( bound.get( 0 ), this, buildingContext ), isExtends );
113111
}
114112

113+
private boolean isExtends(TypeList.Generic upperBounds, TypeList.Generic lowerBounds) {
114+
if ( lowerBounds.isEmpty() ) {
115+
return true;
116+
}
117+
118+
return upperBounds.isEmpty();
119+
}
120+
121+
private HashSet<String> typeVariableIdentifiers;
122+
115123
@Override
116124
public TypeDetails caseTypeVariable(TypeDefinition typeDescription, SourceModelBuildingContext buildingContext) {
125+
final boolean isTypeVariableRef;
126+
if ( typeVariableIdentifiers == null ) {
127+
typeVariableIdentifiers = new HashSet<>();
128+
typeVariableIdentifiers.add( typeDescription.getActualName() );
129+
isTypeVariableRef = false;
130+
}
131+
else {
132+
final boolean newlyAdded = typeVariableIdentifiers.add( typeDescription.getActualName() );
133+
isTypeVariableRef = !newlyAdded;
134+
}
135+
136+
if ( isTypeVariableRef ) {
137+
return new TypeVariableReferenceDetailsImpl( typeDescription.getActualName() );
138+
}
139+
117140
return new TypeVariableDetailsImpl(
118141
typeDescription.getActualName(),
119142
declaringType,
@@ -125,6 +148,12 @@ public TypeDetails caseTypeVariable(TypeDefinition typeDescription, SourceModelB
125148
public TypeDetails caseTypeVariableReference(
126149
TypeDefinition typeDescription,
127150
SourceModelBuildingContext buildingContext) {
151+
// todo : This is not actually correct I think. From the Byte Buddy javadocs:
152+
// > Represents a type variable that is merely symbolic and is not
153+
// > attached to a net.bytebuddy.description.TypeVariableSource and does
154+
// > not defined bounds.
155+
// - but I am unsure of an actual scenario this is attempting to describe
156+
// to be able to test it out
128157
return new TypeVariableReferenceDetailsImpl( typeDescription.getActualName() );
129158
}
130159

hibernate-models-bytebuddy/src/main/java/org/hibernate/models/bytebuddy/internal/values/ArrayValueConverter.java

Lines changed: 156 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@
44
*/
55
package org.hibernate.models.bytebuddy.internal.values;
66

7-
import java.lang.reflect.Field;
8-
import java.util.List;
97

10-
import org.hibernate.models.ModelsException;
11-
import org.hibernate.models.bytebuddy.spi.ByteBuddyModelsContext;
8+
import java.lang.annotation.Annotation;
9+
10+
import org.hibernate.models.bytebuddy.internal.AnnotationUsageBuilder;
1211
import org.hibernate.models.bytebuddy.spi.ValueConverter;
12+
import org.hibernate.models.spi.AnnotationDescriptor;
13+
import org.hibernate.models.spi.AnnotationDescriptorRegistry;
1314
import org.hibernate.models.spi.SourceModelBuildingContext;
1415
import org.hibernate.models.spi.ValueTypeDescriptor;
1516

17+
import net.bytebuddy.description.annotation.AnnotationDescription;
1618
import net.bytebuddy.description.annotation.AnnotationValue;
1719

1820
/**
@@ -28,46 +30,171 @@ public ArrayValueConverter(ValueTypeDescriptor<V> elementTypeDescriptor) {
2830
}
2931

3032
@Override
31-
public V[] convert(AnnotationValue<?,?> byteBuddyValue, SourceModelBuildingContext modelContext) {
32-
assert byteBuddyValue != null;
33+
public V[] convert(AnnotationValue<?,?> annotationValue, SourceModelBuildingContext modelContext) {
34+
assert annotationValue != null;
35+
36+
final Class<?> elementValueType = elementTypeDescriptor.getValueType();
37+
38+
if ( Boolean.class == elementValueType ) {
39+
return convertBooleanArray( annotationValue, modelContext );
40+
}
41+
42+
if ( Byte.class == elementValueType ) {
43+
return convertByteArray( annotationValue, modelContext );
44+
}
3345

34-
// UGH...
35-
final List<AnnotationValue<?,?>> byteBuddyValues = extractValueValues( byteBuddyValue, modelContext );
46+
if ( Short.class == elementValueType ) {
47+
return convertShortArray( annotationValue, modelContext );
48+
}
49+
50+
if ( Integer.class == elementValueType ) {
51+
return convertIntArray( annotationValue, modelContext );
52+
}
3653

37-
final V[] result = elementTypeDescriptor.makeArray( byteBuddyValues.size(), modelContext );
38-
final ValueConverter<V> elementWrapper = modelContext.as( ByteBuddyModelsContext.class ).getValueConverter( elementTypeDescriptor );
54+
if ( Long.class == elementValueType ) {
55+
return convertLongArray( annotationValue, modelContext );
56+
}
57+
58+
if ( double.class == elementValueType ) {
59+
return convertDoubleArray( annotationValue, modelContext );
60+
}
3961

40-
for ( int i = 0; i < byteBuddyValues.size(); i++ ) {
41-
result[i] = elementWrapper.convert( byteBuddyValues.get(i), modelContext );
62+
if ( float.class == elementValueType ) {
63+
return convertFloatArray( annotationValue, modelContext );
4264
}
43-
return result;
65+
66+
if ( Character.class == elementValueType ) {
67+
return convertCharacterArray( annotationValue, modelContext );
68+
}
69+
70+
if ( elementValueType.isAnnotation() ) {
71+
return convertNestedAnnotationArray( annotationValue, modelContext );
72+
}
73+
74+
final Class<?> arrayType = elementValueType.arrayType();
75+
//noinspection unchecked
76+
return (V[]) annotationValue.resolve( arrayType );
4477
}
4578

46-
private List<AnnotationValue<?, ?>> extractValueValues(
47-
AnnotationValue<?, ?> byteBuddyValue,
79+
private V[] convertBooleanArray(
80+
AnnotationValue<?, ?> annotationValue,
4881
SourceModelBuildingContext modelContext) {
49-
try {
50-
//noinspection unchecked
51-
return (List<AnnotationValue<?,?>>) getValuesField( modelContext ).get( byteBuddyValue );
82+
final boolean[] resolved = annotationValue.resolve( boolean[].class );
83+
final Boolean[] result = (Boolean[]) elementTypeDescriptor.makeArray( resolved.length, modelContext );
84+
for ( int i = 0; i < resolved.length; i++ ) {
85+
result[i] = resolved[i];
5286
}
53-
catch (IllegalAccessException e) {
54-
throw new ModelsException( "Could not access Byte Buddy's `AnnotationValue.ForDescriptionArray#values` field", e );
87+
//noinspection unchecked
88+
return (V[]) result;
89+
}
90+
91+
private V[] convertByteArray(
92+
AnnotationValue<?, ?> annotationValue,
93+
SourceModelBuildingContext modelContext) {
94+
final byte[] resolved = annotationValue.resolve( byte[].class );
95+
final Byte[] result = (Byte[]) elementTypeDescriptor.makeArray( resolved.length, modelContext );
96+
for ( int i = 0; i < resolved.length; i++ ) {
97+
result[i] = resolved[i];
5598
}
99+
//noinspection unchecked
100+
return (V[]) result;
56101
}
57102

58-
private Field getValuesField(SourceModelBuildingContext modelContext) {
59-
return ARRRRGGGGHHHHH;
103+
private V[] convertShortArray(
104+
AnnotationValue<?, ?> annotationValue,
105+
SourceModelBuildingContext modelContext) {
106+
final short[] resolved = annotationValue.resolve( short[].class );
107+
final Short[] result = (Short[]) elementTypeDescriptor.makeArray( resolved.length, modelContext );
108+
for ( int i = 0; i < resolved.length; i++ ) {
109+
result[i] = resolved[i];
110+
}
111+
//noinspection unchecked
112+
return (V[]) result;
60113
}
61114

62-
private static Field ARRRRGGGGHHHHH;
115+
private V[] convertIntArray(
116+
AnnotationValue<?, ?> annotationValue,
117+
SourceModelBuildingContext modelContext) {
118+
final int[] resolved = annotationValue.resolve( int[].class );
119+
final Integer[] result = (Integer[]) elementTypeDescriptor.makeArray( resolved.length, modelContext );
120+
for ( int i = 0; i < resolved.length; i++ ) {
121+
result[i] = resolved[i];
122+
}
123+
//noinspection unchecked
124+
return (V[]) result;
125+
}
126+
127+
private V[] convertLongArray(
128+
AnnotationValue<?, ?> annotationValue,
129+
SourceModelBuildingContext modelContext) {
130+
final long[] resolved = annotationValue.resolve( long[].class );
131+
final Long[] result = (Long[]) elementTypeDescriptor.makeArray( resolved.length, modelContext );
132+
for ( int i = 0; i < resolved.length; i++ ) {
133+
result[i] = resolved[i];
134+
}
135+
//noinspection unchecked
136+
return (V[]) result;
137+
}
138+
139+
private V[] convertDoubleArray(
140+
AnnotationValue<?, ?> annotationValue,
141+
SourceModelBuildingContext modelContext) {
142+
final double[] resolved = annotationValue.resolve( double[].class );
143+
final Double[] result = (Double[]) elementTypeDescriptor.makeArray( resolved.length, modelContext );
144+
for ( int i = 0; i < resolved.length; i++ ) {
145+
result[i] = resolved[i];
146+
}
147+
//noinspection unchecked
148+
return (V[]) result;
149+
}
150+
151+
private V[] convertFloatArray(
152+
AnnotationValue<?, ?> annotationValue,
153+
SourceModelBuildingContext modelContext) {
154+
final float[] resolved = annotationValue.resolve( float[].class );
155+
final Float[] result = (Float[]) elementTypeDescriptor.makeArray( resolved.length, modelContext );
156+
for ( int i = 0; i < resolved.length; i++ ) {
157+
result[i] = resolved[i];
158+
}
159+
//noinspection unchecked
160+
return (V[]) result;
161+
}
63162

64-
static {
65-
try {
66-
ARRRRGGGGHHHHH = AnnotationValue.ForDescriptionArray.class.getDeclaredField( "values" );
67-
ARRRRGGGGHHHHH.setAccessible( true );
163+
private V[] convertCharacterArray(
164+
AnnotationValue<?, ?> annotationValue,
165+
SourceModelBuildingContext modelContext) {
166+
final char[] resolved = annotationValue.resolve( char[].class );
167+
final Character[] result = (Character[]) elementTypeDescriptor.makeArray( resolved.length, modelContext );
168+
for ( int i = 0; i < resolved.length; i++ ) {
169+
result[i] = resolved[i];
68170
}
69-
catch (Exception e) {
70-
throw new ModelsException( "Could not access Byte Buddy's `AnnotationValue.ForDescriptionArray#values` field", e );
171+
//noinspection unchecked
172+
return (V[]) result;
173+
}
174+
175+
private V[] convertNestedAnnotationArray(
176+
AnnotationValue<?, ?> annotationValue,
177+
SourceModelBuildingContext modelContext) {
178+
final AnnotationDescriptorRegistry descriptorRegistry = modelContext.getAnnotationDescriptorRegistry();
179+
180+
//noinspection unchecked
181+
final Class<? extends Annotation> annotationType = (Class<? extends Annotation>) elementTypeDescriptor.getValueType();
182+
final AnnotationDescriptor<? extends Annotation> annotationDescriptor = descriptorRegistry.getDescriptor( annotationType );
183+
184+
final AnnotationDescription[] resolved = annotationValue.resolve( AnnotationDescription[].class );
185+
final Annotation[] result = (Annotation[]) elementTypeDescriptor.makeArray( resolved.length, modelContext );
186+
187+
for ( int i = 0; i < resolved.length; i++ ) {
188+
final AnnotationDescription annotationDescription = resolved[i];
189+
final Annotation usage = AnnotationUsageBuilder.makeUsage(
190+
annotationDescription,
191+
annotationDescriptor,
192+
modelContext
193+
);
194+
result[i] = usage;
71195
}
196+
197+
//noinspection unchecked
198+
return (V[]) result;
72199
}
73200
}

hibernate-models-bytebuddy/src/main/java/org/hibernate/models/bytebuddy/internal/values/ArrayValueExtractor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
public class ArrayValueExtractor<V> extends AbstractValueExtractor<V[]> {
1818
private final ValueConverter<V[]> wrapper;
1919

20-
public ArrayValueExtractor(ValueConverter<V[]> wrapper) {
20+
public ArrayValueExtractor(ValueConverter wrapper) {
2121
this.wrapper = wrapper;
2222
}
2323

0 commit comments

Comments
 (0)