Skip to content

Commit 1aff6dd

Browse files
authored
Final updates to parser writer code (#4)
* Be more permissive with validations when concerning subtypes of custom parsers * Working primitivea rray expected parsers * GWT-incompatible first attempt * Working GWT compatible primitive collection parser * Enhance type validation in parser generation by including checks for interfaces and wildcards. Update method names for clarity and improve handling of unsupported types in map field parsing. * Fix test * Get the proper package name * Update documentation * Review comments * Remove lines
1 parent 297a793 commit 1aff6dd

18 files changed

Lines changed: 738 additions & 586 deletions

gwt-beans-codegen-core/architecture.md

Lines changed: 147 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88

99
The main orchestrator (`ParserGenerator`) that coordinates the generation process:
1010

11-
- Accepts configuration parameters
12-
- Initiates type analysis
11+
- Accepts configuration parameters (root class, output directory, parser package, custom parser directory)
12+
- Initiates type analysis via TypeAnalyzer
1313
- Manages the generation workflow
14-
- Handles file output
14+
- Handles file output and directory cleanup
15+
- Provides command-line interface with argument parsing
16+
- Supports version and git hash tracking for @Generated annotations
1517

1618
#### 2. Type Analyzer
1719

@@ -21,31 +23,52 @@ The `TypeAnalyzer` component performs deep inspection of Java classes:
2123
- Handles type hierarchies and dependencies
2224
- Filters out primitive types and built-in classes
2325
- Manages type name collisions
26+
- Supports polymorphic type discovery via @JsonSubTypes
27+
- Validates unsupported types and throws appropriate exceptions
28+
- Tracks custom parser types to avoid generation conflicts
2429

2530
#### 3. Parser Writers
2631

27-
Two specialized writers handle different aspects of parser generation:
32+
Specialized writers handle different aspects of parser generation:
2833

29-
##### Root Parser Writer
34+
##### ParserWriter
3035

31-
- Generates the main entry point parser
32-
- Handles top-level configuration
33-
- Manages the primary parsing logic
36+
- Main writer that coordinates parser generation for all discovered types
37+
- Manages output directory and file writing
38+
- Handles generator metadata (name, version, git hash)
39+
- Creates parser class specifications with proper annotations
3440

35-
##### Sub-Type Parser Writer
41+
##### ParserWriterUtils
3642

37-
- Generates parsers for nested and dependent types
38-
- Handles complex type relationships
39-
- Manages naming conflicts for nested types
40-
41-
#### 4. Parser Writer Utils
42-
43-
Shared utilities for parser generation:
44-
45-
- Code block generation
43+
- Shared utilities for parser generation
44+
- Code block generation for different field types
4645
- File I/O operations
4746
- Type conversion utilities
4847
- Common parsing patterns
48+
- Custom parser registry management
49+
- Polymorphic parser generation logic
50+
51+
#### 4. Field Parsers
52+
53+
Specialized parsers for different field types:
54+
55+
- **SimpleFieldParser**: Handles primitives and wrappers (String, int, boolean, etc.)
56+
- **EnumFieldParser**: Handles enum types with @JsonCreator support
57+
- **CollectionFieldParser**: Handles List, Set, and object arrays
58+
- **MapFieldParser**: Handles Map types with String/Enum/complex keys
59+
- **PrimitiveArrayFieldParser**: Handles primitive arrays (int[], double[], etc.)
60+
- **CustomObjectFieldParser**: Handles custom objects requiring generated parsers
61+
62+
#### 5. Configuration Validator
63+
64+
The `ConfigurationValidator` ensures type compatibility:
65+
66+
- Validates class structure and annotations
67+
- Checks for polymorphic type requirements (@JsonTypeInfo, @JsonSubTypes)
68+
- Validates field types and key types for maps
69+
- Ensures proper constructor availability
70+
- Validates getter/setter pairs
71+
- Provides detailed error reporting with visual indicators
4972

5073
### Generated Parser Structure
5174

@@ -54,58 +77,109 @@ Each generated parser follows a consistent pattern:
5477
```java
5578
@Generated(
5679
value = "nl.aerius.codegen.ParserGenerator",
57-
date = "timestamp"
80+
comments = "version: x.x.x (git: abc123)"
5881
)
5982
public class TypeNameParser {
83+
public static TypeName parse(final String jsonText) {
84+
if (jsonText == null) {
85+
return null;
86+
}
87+
return parse(JSONObjectHandle.fromText(jsonText));
88+
}
89+
6090
public static TypeName parse(final JSONObjectHandle obj) {
6191
if (obj == null) {
6292
return null;
6393
}
6494
final TypeName config = new TypeName();
65-
// Field parsing logic
95+
parse(obj, config);
6696
return config;
6797
}
98+
99+
public static void parse(final JSONObjectHandle obj, final TypeName config) {
100+
if (obj == null || config == null) {
101+
return;
102+
}
103+
// Field parsing logic with null checks
104+
}
105+
}
106+
```
107+
108+
For polymorphic types, the main parse method includes switch-based type discrimination:
109+
110+
```java
111+
public static BaseType parse(final JSONObjectHandle obj) {
112+
if (obj == null) {
113+
return null;
114+
}
115+
116+
final String typeName = obj.getString("_type");
117+
switch (typeName) {
118+
case "TypeA":
119+
return SubTypeAParser.parse(obj);
120+
case "TypeB":
121+
return SubTypeBParser.parse(obj);
122+
default:
123+
throw new RuntimeException("Unknown type name '" + typeName + "'");
124+
}
68125
}
69126
```
70127

71128
## Data Flow
72129

73130
1. **Type Discovery**
74131

75-
- Root class analysis
76-
- Recursive type scanning
77-
- Dependency resolution
78-
79-
2. **Parser Generation**
132+
- Root class analysis via reflection
133+
- Recursive type scanning through fields and generic parameters
134+
- Polymorphic subtype discovery via @JsonSubTypes
135+
- Dependency resolution and ordering
136+
- Custom parser type filtering
80137

81-
- Template selection
82-
- Code generation
83-
- File writing
138+
2. **Validation**
84139

85-
3. **Validation**
86140
- Type compatibility checks
87-
- Name collision detection
88-
- Output verification
141+
- Polymorphic annotation validation
142+
- Constructor and accessor validation
143+
- Map key type validation
144+
- Error reporting with visual indicators
145+
146+
3. **Parser Generation**
147+
148+
- Template selection based on type category
149+
- Code generation using JavaPoet
150+
- Field-specific parsing logic generation
151+
- Polymorphic parser generation for base types
152+
- Custom parser integration
153+
154+
4. **File Output**
155+
- Directory cleanup and creation
156+
- Java file writing with proper formatting
157+
- Import statement management
158+
- Custom parser import tracking
89159

90160
## Design Decisions
91161

92162
### 1. Static Parse Methods
93163

94-
- Parsers use static methods for simplicity
164+
- Parsers use static methods for simplicity and performance
95165
- No state maintenance required
96166
- Easy to use in streaming contexts
167+
- Consistent with utility class patterns
97168

98169
### 2. Null Safety
99170

100171
- All parsers handle null inputs gracefully
101-
- Clear null checking patterns
102-
- Type-safe output
172+
- Clear null checking patterns with early returns
173+
- Type-safe output with proper null handling
174+
- Consistent null behavior across all parsers
103175

104176
### 3. Error Handling
105177

106178
- Early validation of input types
107-
- Clear error messages
179+
- Clear error messages with context
108180
- Fail-fast approach for invalid configurations
181+
- UnsupportedTypeException for unsupported types
182+
- Detailed validation reporting with visual indicators
109183

110184
### 4. Custom Parser Integration
111185

@@ -122,26 +196,50 @@ public class CustomTypeParser {
122196

123197
Integration points:
124198

125-
- Custom parser discovery
126-
- Type resolution
127-
- Parser registration
128-
- Error handling for custom parsers
199+
- Custom parser discovery via directory scanning
200+
- Type resolution and registration
201+
- Import tracking for generated code
202+
- Validation bypass for custom parser types
203+
204+
### 5. Polymorphic Type Support
205+
206+
- Automatic discovery of @JsonSubTypes annotations
207+
- Generation of switch-based type discrimination
208+
- Support for @JsonTypeInfo with NAME discriminator
209+
- Validation of polymorphic type requirements
210+
- Proper subtype parser generation and integration
129211

130-
### 5. Performance Considerations
212+
### 6. Performance Considerations
131213

132214
1. **Type Analysis & Generation**
133215

134-
- Caching of type information
216+
- Caching of type information during analysis
135217
- Lazy loading of dependent types
136218
- Memory-efficient type hierarchy traversal
137219
- Optimized template processing
138-
- Efficient string handling
139-
- Minimized object creation
220+
- Efficient string handling and code generation
221+
- Minimized object creation during generation
140222

141223
2. **Runtime Performance**
142-
- Efficient null checking
143-
- Optimized collection handling
144-
- Memory usage patterns
145-
- Performance metrics collection
146-
- Memory usage tracking
147-
- Generation time profiling
224+
- Efficient null checking patterns
225+
- Optimized collection handling with specific forEach methods
226+
- Memory usage patterns for large collections
227+
- Performance metrics collection capabilities
228+
- Memory usage tracking during generation
229+
- Generation time profiling support
230+
231+
### 7. Testing Strategy
232+
233+
- **Expected Parser Tests**: Validate reference implementation
234+
- **Generated Parser Tests**: Validate generated code functionality
235+
- **Round-trip Tests**: JSON → Object → JSON validation
236+
- **Validation Tests**: Type compatibility and error handling
237+
- **Custom Parser Tests**: Integration and discovery validation
238+
- **Unsupported Type Tests**: Error handling for invalid types
239+
240+
### 8. GWT Compatibility
241+
242+
- Uses nl.aerius.wui.service.json.JSONObjectHandle for GWT compatibility
243+
- Avoids Java 8+ features and unsupported types
244+
- Maintains compatibility with GWT compilation
245+
- Supports GWT-specific JSON handling patterns

gwt-beans-codegen-core/development-plan.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ We're building a JSON parser generator that will replace GWT-RPC serialization.
2121
- Map<String, String>, HashMap<String, Integer>
2222
- LinkedHashMap<String, Double>
2323
- All primitive arrays (int[], long[], double[], float[], byte[], short[], char[], boolean[])
24+
- Object arrays (String[], Integer[], etc.)
2425

2526
3. **Object Support**
2627

2728
- Custom object references
2829
- Null handling for all types
2930
- Custom parser integration
31+
- Polymorphic type support with @JsonTypeInfo and @JsonSubTypes
3032

3133
4. **Complex Types**
3234
- List<CustomObject>
@@ -38,12 +40,27 @@ We're building a JSON parser generator that will replace GWT-RPC serialization.
3840
- Map<Enum, String>
3941
- Map<Enum, CustomObject>
4042
- Map<Enum, primitive types>
43+
- Nested collections and maps (2+ levels)
44+
- Complex key types with fromStringValue() methods
45+
46+
5. **Polymorphic Support**
47+
- @JsonTypeInfo with NAME discriminator
48+
- @JsonSubTypes for concrete implementations
49+
- Automatic subtype discovery and parser generation
50+
- Switch-based polymorphic parsing
51+
52+
6. **Validation & Testing**
53+
- Comprehensive type validation
54+
- Custom parser discovery and integration
55+
- Round-trip testing (JSON → Object → JSON)
56+
- Generated vs expected parser comparison
57+
- Unsupported type detection and error handling
4158

4259
### Remaining Implementation Tasks
4360

44-
1. **Complex Nested Structures** [HIGH]
61+
1. **Complex Nested Structures** [MEDIUM]
4562

46-
- Deeply nested collections (3+ levels)
63+
- Deeply nested collections (3+ levels) - partially working
4764
- Examples to implement:
4865
```java
4966
class ComplexNested {
@@ -60,15 +77,15 @@ We're building a JSON parser generator that will replace GWT-RPC serialization.
6077
- Add usage examples and best practices
6178
- Document performance considerations
6279

63-
3. **Testing Strategy** [HIGH]
80+
3. **Testing Strategy** [MEDIUM]
6481

6582
- Add performance benchmarks for different type combinations
6683
- Create stress tests for deeply nested structures
6784
- Add memory usage tests for large collections
6885
- Implement test coverage reporting
6986
- Add integration tests with real-world scenarios
7087

71-
4. **Performance Optimization** [MEDIUM]
88+
4. **Performance Optimization** [LOW]
7289
- Profile parser generation for large type hierarchies
7390
- Optimize memory usage during type analysis
7491
- Cache frequently used type information
@@ -96,10 +113,12 @@ The following types will NOT be supported due to GWT compatibility or design dec
96113
- Calendar
97114

98115
4. **Collection Limitations**
99-
- Map with non-String keys (except enums)
116+
- Map with non-String keys (except enums and supported primitive wrappers)
100117
- Queue and Deque implementations
101118
- SortedSet/TreeSet
102119
- SortedMap/TreeMap
120+
- Generic types with wildcards
121+
- Inner classes (must be top-level)
103122

104123
## Development Constraints
105124

@@ -129,6 +148,8 @@ The following types will NOT be supported due to GWT compatibility or design dec
129148
- Custom parsers sourced from original location
130149
- Uses Jackson for test serialization
131150
- Keep type analysis and parsing logic separate
151+
- Polymorphic types require both @JsonTypeInfo and @JsonSubTypes annotations
152+
- Interfaces must be annotated with @JsonTypeInfo for polymorphic handling
132153

133154
### Migration Guide
134155

0 commit comments

Comments
 (0)