Skip to content

Commit

Permalink
#20 - Add AnnotationUsage#toAnnotation
Browse files Browse the repository at this point in the history
  • Loading branch information
sebersole committed Jan 22, 2024
1 parent 0e34134 commit 1870608
Show file tree
Hide file tree
Showing 20 changed files with 183 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/main/java/org/hibernate/models/internal/AnnotationProxy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/

package org.hibernate.models.internal;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

import org.hibernate.models.spi.AnnotationDescriptor;
import org.hibernate.models.spi.AttributeDescriptor;

/**
* @author Steve Ebersole
*/
public class AnnotationProxy<A extends Annotation> implements InvocationHandler {
private final AnnotationDescriptor<A> annotationDescriptor;
private final Map<String,?> valueMap;

public AnnotationProxy(AnnotationDescriptor<A> annotationDescriptor, Map<String, ?> valueMap) {
this.annotationDescriptor = annotationDescriptor;
this.valueMap = valueMap;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
final AttributeDescriptor<Object> attributeDescriptor = annotationDescriptor.getAttribute( method.getName() );
return attributeDescriptor.getTypeDescriptor().unwrap( valueMap.get( method.getName() ) );
}


public static <A extends Annotation> A makeProxy(
AnnotationDescriptor<A> descriptor,
Map<String,?> valueMap) {
final AnnotationProxy<A> handler = new AnnotationProxy<>( descriptor, valueMap );
//noinspection unchecked
return (A) Proxy.newProxyInstance(
AnnotationProxy.class.getClassLoader(),
new Class<?>[] { descriptor.getAnnotationType() },
handler
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,13 @@ public ValueWrapper<List<V>,Object[]> resolveJkWrapper(SourceModelBuildingContex
}
return jdkValueWrapper;
}

@Override
public Object unwrap(List<V> value) {
final Object[] result = new Object[value.size()];
for ( int i = 0; i < value.size(); i++ ) {
result[i] = elementTypeDescriptor.unwrap( value.get(i) );
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public ValueExtractor<Annotation, Boolean> createJdkExtractor(SourceModelBuildin
//noinspection unchecked
return PassThruExtractor.PASS_THRU_EXTRACTOR;
}

@Override
public Object unwrap(Boolean value) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public ValueExtractor<Annotation, Byte> createJdkExtractor(SourceModelBuildingCo
//noinspection unchecked
return PassThruExtractor.PASS_THRU_EXTRACTOR;
}

@Override
public Object unwrap(Byte value) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public ValueExtractor<Annotation, Character> createJdkExtractor(SourceModelBuild
//noinspection unchecked
return PassThruExtractor.PASS_THRU_EXTRACTOR;
}

@Override
public Object unwrap(Character value) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,9 @@ public ValueExtractor<AnnotationInstance, ClassDetails> createJandexExtractor(So
public ValueExtractor<Annotation, ClassDetails> createJdkExtractor(SourceModelBuildingContext buildingContext) {
return org.hibernate.models.internal.jdk.ClassValueExtractor.JDK_CLASS_EXTRACTOR;
}

@Override
public Object unwrap(ClassDetails value) {
return value.toJavaClass();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public ValueExtractor<Annotation, Double> createJdkExtractor(SourceModelBuilding
//noinspection unchecked
return PassThruExtractor.PASS_THRU_EXTRACTOR;
}

@Override
public Object unwrap(Double value) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,9 @@ public ValueExtractor<Annotation, E> createJdkExtractor(SourceModelBuildingConte
//noinspection unchecked
return PassThruExtractor.PASS_THRU_EXTRACTOR;
}

@Override
public Object unwrap(E value) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public ValueExtractor<Annotation, Float> createJdkExtractor(SourceModelBuildingC
//noinspection unchecked
return PassThruExtractor.PASS_THRU_EXTRACTOR;
}

@Override
public Object unwrap(Float value) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public ValueExtractor<Annotation, Integer> createJdkExtractor(SourceModelBuildin
//noinspection unchecked
return PassThruExtractor.PASS_THRU_EXTRACTOR;
}

@Override
public Object unwrap(Integer value) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public ValueExtractor<Annotation, Long> createJdkExtractor(SourceModelBuildingCo
//noinspection unchecked
return PassThruExtractor.PASS_THRU_EXTRACTOR;
}

@Override
public Object unwrap(Long value) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ public ValueExtractor<Annotation, AnnotationUsage<A>> createJdkExtractor(SourceM
return resolveJdkExtractor( buildingContext );
}

@Override
public Object unwrap(AnnotationUsage<A> value) {
return value.toAnnotation();
}

public ValueExtractor<Annotation, AnnotationUsage<A>> resolveJdkExtractor(SourceModelBuildingContext buildingContext) {
if ( jdkExtractor == null ) {
jdkExtractor = new org.hibernate.models.internal.jdk.NestedValueExtractor<>( resolveJdkWrapper( buildingContext ) );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public ValueExtractor<Annotation, Short> createJdkExtractor(SourceModelBuildingC
//noinspection unchecked
return PassThruExtractor.PASS_THRU_EXTRACTOR;
}

@Override
public Object unwrap(Short value) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public ValueExtractor<Annotation, String> createJdkExtractor(SourceModelBuilding
//noinspection unchecked
return PassThruExtractor.PASS_THRU_EXTRACTOR;
}

@Override
public Object unwrap(String value) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Map;

import org.hibernate.models.UnknownAnnotationAttributeException;
import org.hibernate.models.internal.AnnotationProxy;
import org.hibernate.models.spi.MutableAnnotationUsage;
import org.hibernate.models.spi.AnnotationDescriptor;
import org.hibernate.models.spi.AnnotationTarget;
Expand Down Expand Up @@ -44,6 +45,11 @@ public AnnotationTarget getAnnotationTarget() {
return target;
}

@Override
public A toAnnotation() {
return AnnotationProxy.makeProxy( annotationDescriptor, values );
}

@Override
public <V> V findAttributeValue(String name) {
if ( values != null ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.lang.annotation.Annotation;
import java.util.Map;

import org.hibernate.models.internal.AnnotationProxy;
import org.hibernate.models.spi.MutableAnnotationUsage;
import org.hibernate.models.spi.AnnotationDescriptor;
import org.hibernate.models.spi.AnnotationTarget;
Expand Down Expand Up @@ -56,6 +57,11 @@ public AnnotationTarget getAnnotationTarget() {
return annotationTarget;
}

@Override
public A toAnnotation() {
return AnnotationProxy.makeProxy( annotationDescriptor, attributeValueMap );
}

@Override
public <W> W findAttributeValue(String name) {
//noinspection unchecked
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @author Steve Ebersole
*/
public class JdkAnnotationUsage<A extends Annotation> implements MutableAnnotationUsage<A> {
private final A annotation;
private final AnnotationDescriptor<A> annotationDescriptor;
private final AnnotationTarget location;

Expand All @@ -28,6 +29,7 @@ public JdkAnnotationUsage(
AnnotationDescriptor<A> annotationDescriptor,
AnnotationTarget location,
SourceModelBuildingContext buildingContext) {
this.annotation = annotation;
this.annotationDescriptor = annotationDescriptor;
this.location = location;

Expand All @@ -44,6 +46,11 @@ public AnnotationTarget getAnnotationTarget() {
return location;
}

@Override
public A toAnnotation() {
return annotation;
}

@Override
public <W> W findAttributeValue(String name) {
//noinspection unchecked
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/hibernate/models/spi/AnnotationUsage.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ default Class<A> getAnnotationType() {
*/
AnnotationTarget getAnnotationTarget();

/**
* Create the Annotation representation of this usage
*/
A toAnnotation();

/**
* The value of the named annotation attribute
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@ public interface ValueTypeDescriptor<V> {
ValueWrapper<V,?> createJdkWrapper(SourceModelBuildingContext buildingContext);

ValueExtractor<Annotation,V> createJdkExtractor(SourceModelBuildingContext buildingContext);

Object unwrap(V value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -224,4 +224,42 @@ void badAttributeNamesChecks(Index index) {
catch (UnknownAnnotationAttributeException expected) {
}
}

@Test
void testToAnnotationJandex() {
toAnnotationChecks( buildJandexIndex( SimpleEntity.class ) );
}

@Test
void testToAnnotationWithoutJandex() {
toAnnotationChecks( null );
}

private void toAnnotationChecks(Index index) {
final SourceModelBuildingContextImpl buildingContext = createBuildingContext( index, SimpleEntity.class );
final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry();

final ClassDetails classDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() );

{
final AnnotationUsage<CustomAnnotation> annotationUsage = classDetails.getAnnotationUsage( CustomAnnotation.class );
final CustomAnnotation annotation = annotationUsage.toAnnotation();
assertThat( annotation ).isNotNull();
}

{
final AnnotationUsage<Entity> annotationUsage = classDetails.getAnnotationUsage( Entity.class );
final Entity annotation = annotationUsage.toAnnotation();
assertThat( annotation.name() ).isEqualTo( "SimpleColumnEntity" );
}

{
final AnnotationUsage<Column> annotationUsage = classDetails.findFieldByName( "name" ).getAnnotationUsage( Column.class );
final Column annotation = annotationUsage.toAnnotation();
assertThat( annotation.name() ).isEqualTo( "description" );
assertThat( annotation.table() ).isEqualTo( "" );
assertThat( annotation.nullable() ).isFalse();
assertThat( annotation.unique() ).isTrue();
}
}
}

0 comments on commit 1870608

Please sign in to comment.