Skip to content

Commit b158650

Browse files
committed
#74 - Add the ability to display a ClassDetails (including its MemberDetails) with its AnnotationUsages
1 parent 791da26 commit b158650

File tree

11 files changed

+262
-0
lines changed

11 files changed

+262
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
* Copyright: Red Hat Inc. and Hibernate Authors
6+
*/
7+
8+
package org.hibernate.models.internal;
9+
10+
import java.util.Locale;
11+
12+
import org.hibernate.models.spi.RenderingCollector;
13+
14+
/**
15+
* @author Steve Ebersole
16+
*/
17+
public class RenderingCollectorImpl implements RenderingCollector {
18+
private final StringBuilder buffer = new StringBuilder();
19+
private int currentIndentation = 0;
20+
21+
@Override
22+
public void addLine(String line) {
23+
buffer.append( " " .repeat( currentIndentation ) );
24+
buffer.append( line );
25+
buffer.append( "\n" );
26+
}
27+
28+
@Override
29+
public void addLine(String pattern, Object... args) {
30+
buffer.append( " " .repeat( currentIndentation ) );
31+
buffer.append( String.format( Locale.ROOT, pattern, args ) );
32+
buffer.append( "\n" );
33+
}
34+
35+
@Override
36+
public void addLine() {
37+
buffer.append( "\n" );
38+
}
39+
40+
@Override
41+
public void indent(int depth) {
42+
currentIndentation += (depth * 4);
43+
}
44+
45+
@Override
46+
public void unindent(int depth) {
47+
currentIndentation -= (depth * 4);
48+
assert currentIndentation >= 0;
49+
}
50+
51+
@Override
52+
public String toString() {
53+
return buffer.toString();
54+
}
55+
}

src/main/java/org/hibernate/models/spi/AnnotationDescriptor.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,14 @@ default MethodDetails asMethodDetails() {
128128
default RecordComponentDetails asRecordComponentDetails() {
129129
throw new IllegalCastException( "AnnotationDescriptor cannot be cast to a RecordComponentDetails" );
130130
}
131+
132+
@Override
133+
default void render() {
134+
throw new UnsupportedOperationException( "Not yet implemented" );
135+
}
136+
137+
@Override
138+
default void render(RenderingCollector collector) {
139+
throw new UnsupportedOperationException( "Not yet implemented" );
140+
}
131141
}

src/main/java/org/hibernate/models/spi/AnnotationTarget.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,10 @@ default <T, A extends Annotation> T fromAnnotations(
326326
*/
327327
RecordComponentDetails asRecordComponentDetails();
328328

329+
void render();
330+
331+
void render(RenderingCollector collector);
332+
329333
/**
330334
* Subset of {@linkplain ElementType annotation targets} supported for mapping annotations
331335
*/

src/main/java/org/hibernate/models/spi/AnnotationUsage.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import java.lang.annotation.Annotation;
1010
import java.util.List;
1111

12+
import org.hibernate.models.internal.RenderingCollectorImpl;
13+
1214
/**
1315
* Describes the usage of an {@linkplain AnnotationDescriptor annotation class} on one of its
1416
* allowable {@linkplain AnnotationTarget targets}.
@@ -126,4 +128,29 @@ default <X extends Annotation> AnnotationUsage<X> getNestedUsage(String name) {
126128
default <E> List<E> getList(String name) {
127129
return getAttributeValue( name );
128130
}
131+
132+
default void render() {
133+
final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl();
134+
render( renderingCollector );
135+
renderingCollector.render();
136+
}
137+
138+
default void render(RenderingCollector collector) {
139+
final List<AttributeDescriptor<?>> attributes = getAnnotationDescriptor().getAttributes();
140+
if ( attributes.isEmpty() ) {
141+
collector.addLine( "@%s", getAnnotationType().getName() );
142+
}
143+
else {
144+
collector.addLine( "@%s(", getAnnotationType().getName() );
145+
collector.indent( 2 );
146+
attributes.forEach( (attribute) -> attribute.getTypeDescriptor().render(
147+
collector,
148+
attribute.getName(),
149+
getAttributeValue( attribute.getName() )
150+
) );
151+
152+
collector.unindent( 2 );
153+
collector.addLine( ")" );
154+
}
155+
}
129156
}

src/main/java/org/hibernate/models/spi/ClassDetails.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.function.Predicate;
1212

1313
import org.hibernate.models.IllegalCastException;
14+
import org.hibernate.models.internal.RenderingCollectorImpl;
1415
import org.hibernate.models.internal.SimpleClassDetails;
1516
import org.hibernate.models.internal.util.IndexedConsumer;
1617

@@ -270,4 +271,51 @@ default MethodDetails asMethodDetails() {
270271
default RecordComponentDetails asRecordComponentDetails() {
271272
throw new IllegalCastException( "ClassDetails cannot be cast to RecordComponentDetails" );
272273
}
274+
275+
@Override
276+
default void render() {
277+
final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl();
278+
render( renderingCollector );
279+
renderingCollector.render();
280+
}
281+
282+
@Override
283+
default void render(RenderingCollector collector) {
284+
getAllAnnotationUsages().forEach( (usage) -> usage.render( collector ) );
285+
286+
final String pattern = isRecord()
287+
? "record %s {"
288+
: "class %s {";
289+
290+
collector.addLine( pattern, getName() );
291+
collector.indent( 1 );
292+
293+
collector.addLine( "// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
294+
collector.addLine( "// fields" );
295+
getFields().forEach( (fieldDetails) -> {
296+
fieldDetails.render( collector );
297+
collector.addLine();
298+
} );
299+
collector.addLine();
300+
301+
collector.addLine( "// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
302+
collector.addLine( "// methods" );
303+
getMethods().forEach( (methodDetails) -> {
304+
methodDetails.render( collector );
305+
collector.addLine();
306+
} );
307+
collector.addLine();
308+
309+
if ( isRecord() ) {
310+
collector.addLine( "// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
311+
collector.addLine( "// record components" );
312+
getRecordComponents().forEach( (recordComponentDetails) -> {
313+
recordComponentDetails.render( collector );
314+
collector.addLine();
315+
} );
316+
}
317+
318+
collector.unindent( 1 );
319+
collector.addLine( "}" );
320+
}
273321
}

src/main/java/org/hibernate/models/spi/FieldDetails.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import org.hibernate.models.IllegalCastException;
1010
import org.hibernate.models.internal.ModifierUtils;
11+
import org.hibernate.models.internal.RenderingCollectorImpl;
1112

1213
/**
1314
* Models a {@linkplain java.lang.reflect.Field field} in a {@linkplain ClassDetails class}
@@ -44,4 +45,18 @@ default MethodDetails asMethodDetails() {
4445
default RecordComponentDetails asRecordComponentDetails() {
4546
throw new IllegalCastException( "FieldDetails cannot be cast to RecordComponentDetails" );
4647
}
48+
49+
@Override
50+
default void render() {
51+
final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl();
52+
render( renderingCollector );
53+
renderingCollector.render();
54+
}
55+
56+
@Override
57+
default void render(RenderingCollector collector) {
58+
forAllAnnotationUsages( (usage) -> usage.render( collector ) );
59+
// todo : would be nice to render the type-details to include generics, etc
60+
collector.addLine( "%s %s", getType().determineRawClass().getName(), getName() );
61+
}
4762
}

src/main/java/org/hibernate/models/spi/MethodDetails.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.List;
1111

1212
import org.hibernate.models.IllegalCastException;
13+
import org.hibernate.models.internal.RenderingCollectorImpl;
1314

1415
import static org.hibernate.models.internal.ModifierUtils.hasPersistableMethodModifiers;
1516

@@ -70,4 +71,30 @@ default MethodDetails asMethodDetails() {
7071
default RecordComponentDetails asRecordComponentDetails() {
7172
throw new IllegalCastException( "MethodDetails cannot be cast to RecordComponentDetails" );
7273
}
74+
75+
@Override
76+
default void render() {
77+
final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl();
78+
render( renderingCollector );
79+
renderingCollector.render();
80+
}
81+
82+
@Override
83+
default void render(RenderingCollector collector) {
84+
forAllAnnotationUsages( (usage) -> usage.render( collector ) );
85+
86+
// todo : would be nice to render the type-details to include generics, etc
87+
collector.addLine(
88+
"%s %s (%s)",
89+
getType() == null
90+
? "void"
91+
: getType().determineRawClass().getName(),
92+
getName(),
93+
getMethodKind().name()
94+
);
95+
96+
collector.indent( 2 );
97+
getArgumentTypes().forEach( (arg) -> collector.addLine( " - %s", arg.getName() ) );
98+
collector.unindent( 2 );
99+
}
73100
}

src/main/java/org/hibernate/models/spi/RecordComponentDetails.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package org.hibernate.models.spi;
99

1010
import org.hibernate.models.IllegalCastException;
11+
import org.hibernate.models.internal.RenderingCollectorImpl;
1112

1213
import static org.hibernate.models.spi.AnnotationTarget.Kind.RECORD_COMPONENT;
1314

@@ -46,4 +47,19 @@ default MethodDetails asMethodDetails() {
4647
default RecordComponentDetails asRecordComponentDetails() {
4748
return this;
4849
}
50+
51+
@Override
52+
default void render() {
53+
final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl();
54+
render( renderingCollector );
55+
renderingCollector.render();
56+
}
57+
58+
@Override
59+
default void render(RenderingCollector collector) {
60+
forAllAnnotationUsages( (usage) -> usage.render( collector ) );
61+
// todo : would be nice to render the type-details to include generics, etc
62+
collector.addLine( "%s %s", getType().determineRawClass().getName(), getName() );
63+
}
64+
4965
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
* Copyright: Red Hat Inc. and Hibernate Authors
6+
*/
7+
8+
package org.hibernate.models.spi;
9+
10+
/**
11+
* @author Steve Ebersole
12+
*/
13+
public interface RenderingCollector {
14+
void addLine(String line);
15+
void addLine(String pattern, Object... args);
16+
void addLine();
17+
18+
void indent(int depth);
19+
void unindent(int depth);
20+
21+
default void render() {
22+
System.out.println( toString() );
23+
}
24+
}

src/main/java/org/hibernate/models/spi/ValueTypeDescriptor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,8 @@ public interface ValueTypeDescriptor<V> {
4242
ValueExtractor<Annotation,V> createJdkExtractor(SourceModelBuildingContext buildingContext);
4343

4444
Object unwrap(V value);
45+
46+
default void render(RenderingCollector collector, String name, Object attributeValue) {
47+
collector.addLine( "%s=%s", name, "..." );
48+
}
4549
}

0 commit comments

Comments
 (0)