# Haxe Serializer: Java Getter to Haxe Field/Method Mapping Analysis ## Overview This document contains a comprehensive analysis of ALL patterns for transforming Java getter calls into appropriate Haxe field/method access, extracted from the java-haxe-diff.md file. ## General Patterns ### 1. Simple Field Access Pattern (Most Common) Java getter `getX()` maps to Haxe field `x:Type` **Examples:** - `getName()` → `name:String` - `getDuration()` → `duration:Float` - `getTimeScale()` → `timeScale:Float` - `getLoop()` → `loop:Bool` - `getX()` → `x:Float` - `getY()` → `y:Float` - `getRotation()` → `rotation:Float` - `getScaleX()` → `scaleX:Float` - `getScaleY()` → `scaleY:Float` - `getShearX()` → `shearX:Float` - `getShearY()` → `shearY:Float` - `getWidth()` → `width:Float` - `getHeight()` → `height:Float` - `getColor()` → `color:Color` - `getAlpha()` → `alpha:Float` - `getMix()` → `mix:Float` - `getVisible()` → `visible:Bool` - `getIndex()` → `index:Int` ### 2. Array Field Access Pattern Java getter `getX()` returns array → Haxe field `x:Array` **Examples:** - `getTimelines()` → `timelines:Array` - `getBones()` → `bones:Array` or `bones:Array` or `bones:Array` (context-dependent) - `getChildren()` → `children:Array` - `getFrames()` → `frames:Array` - `getAttachmentNames()` → `attachmentNames:Array` - `getVertices()` → `vertices:Array` or `vertices:Array>` (context-dependent) - `getEvents()` → `events:Array` - `getDrawOrders()` → `drawOrders:Array>` - `getSlots()` → `slots:Array` or `slots:Array` (context-dependent) - `getTracks()` → `tracks:Array` - `getTriangles()` → `triangles:Array` - `getUVs()` → `uvs:Array` - `getRegionUVs()` → `regionUVs:Array` - `getEdges()` → `edges:Array` - `getLengths()` → `lengths:Array` - `getRegions()` → `regions:Array` - `getAnimations()` → `animations:Array` - `getSkins()` → `skins:Array` - `getConstraints()` → `constraints:Array>` or `constraints:Array>` - `getPhysicsConstraints()` → `physics:Array` - `getProperties()` → `properties:Array` - `getDeform()` → `deform:Array` ### 3. Method Remains Method Pattern Some getters remain as methods in Haxe, typically those that perform calculations or have side effects. **Examples:** - `getFrameCount()` → `getFrameCount():Int` - `getFrameEntries()` → `getFrameEntries():Int` - `getDuration()` → `getDuration():Float` (in Timeline classes) - `getSlotIndex()` → `getSlotIndex():Int` - `getBoneIndex()` → `getBoneIndex():Int` - `getConstraintIndex()` → `getConstraintIndex():Int` - `getData()` → `getData():T` (where T is the data type) - `getPose()` → `getPose():T` (where T is the pose type) - `getAppliedPose()` → `getAppliedPose():T` - `getSetupPose()` → `getSetupPose():T` - `getAnimationTime()` → `getAnimationTime():Float` - `getTrackComplete()` → `getTrackComplete():Float` - `getWorldRotationX()` → `getWorldRotationX():Float` - `getWorldRotationY()` → `getWorldRotationY():Float` - `getWorldScaleX()` → `getWorldScaleX():Float` - `getWorldScaleY()` → `getWorldScaleY():Float` - `getAttachments()` → `getAttachments():Array` - `getOffsetRotation()` → `getOffsetRotation():Float` - `getOffsetX()` → `getOffsetX():Float` - `getOffsetY()` → `getOffsetY():Float` - `getOffsetScaleX()` → `getOffsetScaleX():Float` - `getOffsetScaleY()` → `getOffsetScaleY():Float` - `getOffsetShearY()` → `getOffsetShearY():Float` ### 4. Special Property Access Pattern Some properties use Haxe's property syntax with get/set accessors. **Examples:** - `getName()` → `name(get, never):String` (in Attachment subclasses) - `getRootBone()` → `rootBone(get, never):Bone` - `getScaleY()` → `scaleY(get, default):Float` (in Skeleton) ### 5. Field Name Variations Some getters have slight variations in their Haxe field names. **Examples:** - `getInt()` → `intValue:Int` - `getFloat()` → `floatValue:Float` - `getString()` → `stringValue:String` - `getUpdateCache()` → `_updateCache:Array` (with underscore prefix) - `getPropertyIds()` → `propertyIds:Array` - `getDefaultSkin()` → `defaultSkin:Skin` ### 6. Type Reference Patterns Getters that reference other objects. **Examples:** - `getParent()` → `parent:Bone` or `parent:BoneData` (context-dependent) - `getTarget()` → `target:Bone` or `target:BoneData` (context-dependent) - `getSource()` → `source:Bone` or `source:BoneData` (context-dependent) - `getAttachment()` → `attachment:Attachment` or `attachment:VertexAttachment` (context-dependent) - `getSlot()` → `slot:Slot` or `slot:SlotData` (context-dependent) - `getBone()` → `bone:Bone` or `bone:BoneData` or `bone:BonePose` (context-dependent) - `getSkin()` → `skin:Skin` - `getAnimation()` → `animation:Animation` - `getRegion()` → `region:TextureRegion` - `getSequence()` → `sequence:Sequence` - `getParentMesh()` → `parentMesh:MeshAttachment` - `getEndSlot()` → `endSlot:SlotData` ## Context-Dependent Mappings ### 1. `getBones()` mapping depends on containing class: - In `Animation`: → `bones:Array` - In `BoneData`, `IkConstraintData`, `PathConstraintData`, `TransformConstraintData`, `Skin`: → `bones:Array` - In `IkConstraint`, `PathConstraint`, `TransformConstraint`: → `bones:Array` - In `BoundingBoxAttachment`, `ClippingAttachment`, `MeshAttachment`, `PathAttachment`, `VertexAttachment`: → `bones:Array` ### 2. `getVertices()` mapping depends on containing class: - In `DeformTimeline`: → `vertices:Array>` (2D array) - In `ClippingAttachment`, `MeshAttachment`, `PathAttachment`, `VertexAttachment`: → `vertices:Array` (1D array) ### 3. `getDuration()` mapping depends on containing class: - In `Animation`: → `duration:Float` (field) - In Timeline classes: → `getDuration():Float` (method) ### 4. Special Cases in Timeline Classes: All Timeline subclasses have these getters as methods: - `getFrameCount()` → `getFrameCount():Int` - `getFrameEntries()` → `getFrameEntries():Int` - `getDuration()` → `getDuration():Float` - `getPropertyIds()` → `propertyIds:Array` (field) - `getFrames()` → `frames:Array` (field) ### 5. Special Cases in Constraint Classes: - `getData()` → `getData():T` (method returning specific data type) - `getPose()` → `getPose():T` (method returning specific pose type) - `getAppliedPose()` → `getAppliedPose():T` (method returning specific pose type) ## Type Transformations ### Java to Haxe Type Mappings: - `int` → `Int` - `float` → `Float` - `double` → `Float` - `boolean` → `Bool` - `String` → `String` - `Array`/`List` → `Array` - `IntArray` → `Array` (custom type) - Object types remain the same (e.g., `Color` → `Color`) ## Special Edge Cases ### 1. Incomplete Mappings (marked as TODO in the file): - `BonePose.getInherit()` → TODO - `BoundingBoxAttachment.getVertices()` → TODO - `BoundingBoxAttachment.getWorldVerticesLength()` → TODO - `BoundingBoxAttachment.getTimelineAttachment()` → TODO - `BoundingBoxAttachment.getId()` → TODO - `BoundingBoxAttachment.getName()` → TODO ### 2. Inherited Methods: Some getters are inherited from parent classes and noted as such: - `getName()` in attachment classes inherits from `Attachment` - Properties in `FromRotate`, `FromScaleX`, etc. inherit from `FromProperty` - Properties in constraint data classes inherit from `PosedData` ### 3. Special Skeleton Fields: - `getUpdateCache()` → `_updateCache:Array` (private with underscore) - `getRootBone()` → `rootBone(get, never):Bone` (computed property) - `getScaleY()` → `scaleY(get, default):Float` (property with default) ### 4. DrawOrderTimeline Exception: - `getFrameCount()` → `frameCount:Int` (field instead of method, unlike other timelines) ### 5. Enum and Constant Mappings: - `getBlendMode()` → `blendMode:BlendMode` - `getPositionMode()` → `positionMode:PositionMode` - `getSpacingMode()` → `spacingMode:SpacingMode` - `getRotateMode()` → `rotateMode:RotateMode` - `getMixBlend()` → `mixBlend:MixBlend` - `getInherit()` → `inherit:Inherit` ## Summary The transformation rules can be categorized as: 1. **Default Rule**: `getX()` → `x:Type` (lowercase first letter, remove get prefix) 2. **Method Preservation**: Keep as method for calculated values or methods with side effects 3. **Special Properties**: Use Haxe property syntax for computed/readonly properties 4. **Context Awareness**: Same getter can map differently based on containing class 5. **Type Transformation**: Java primitive types map to Haxe equivalents 6. **Special Cases**: Some fields have custom names (e.g., `getInt()` → `intValue`) When implementing the Haxe serializer generator, these patterns should be applied in order of specificity: 1. Check for exact class + getter combinations first 2. Check for class-specific patterns (e.g., all Timeline getters) 3. Apply general transformation rules 4. Handle special cases and exceptions --- # Haxe Serializer Generator Implementation Plan Based on the comprehensive pattern analysis above, here's the implementation plan for a new Haxe serializer generator: ## Architecture Overview The new generator will use a **rule-based transformation system** with the following components: 1. **Mapping Database**: Load java-haxe-diff.md mappings into a structured lookup table 2. **Context-Aware Transformer**: Apply transformations based on class context 3. **Type System**: Handle Java-to-Haxe type conversions 4. **Code Generator**: Produce clean, idiomatic Haxe code ## Implementation Steps ### Phase 1: Build Mapping Infrastructure 1. **Parse java-haxe-diff.md** - Extract all type mappings into a structured format - Create lookup table: `Map>` - Store mapping type (field, method, property) and Haxe type info 2. **Create Transformation Rules Engine** - Rule priority system (specific → general) - Context-aware lookups (class + getter combination) - Fallback to general patterns ### Phase 2: Implement Core Transformations 1. **Getter-to-Field Transformer** - Check mapping database first - Apply general pattern: `getX()` → `x` - Handle special cases (getInt → intValue, etc.) 2. **Type Transformer** - Java primitives → Haxe types - Array handling (including nested arrays) - Generic type resolution 3. **Access Pattern Resolver** - Determine if result is field access or method call - Handle property syntax `name(get, never)` - Preserve method calls where needed ### Phase 3: Code Generation 1. **Property Code Generator** - Generate correct Haxe syntax based on mapping type - Handle nullable types properly - Generate enum switch statements with correct Haxe enum syntax 2. **Method Generator** - Handle abstract types with `Std.isOfType` - Generate proper casting syntax - Implement special methods (writeSkin, writeSkinEntry) ### Phase 4: Validation and Testing 1. **Compile-time Validation** - Generate code and attempt Haxe compilation - Report type errors with context 2. **Runtime Testing** - Compare serialization output with Java reference - Ensure all fields are properly serialized ## Key Design Decisions 1. **Data-Driven Approach**: Use the mapping file as the source of truth rather than hardcoded rules 2. **Explicit Over Implicit**: When in doubt, use the exact mapping from java-haxe-diff.md 3. **Fail-Fast**: If a mapping is missing or ambiguous, fail with a clear error message 4. **Type Safety**: Leverage Haxe's type system to catch errors at compile time ## Implementation Details ### Mapping Database Structure ```typescript interface HaxeMapping { kind: 'field' | 'method' | 'property'; haxeName: string; haxeType: string; propertyGetter?: string; // for (get, never) syntax } interface ClassMappings { className: string; getters: Map; } ``` ### Transformation Algorithm ``` 1. Load all mappings from java-haxe-diff.md 2. For each property in IR: a. Look up exact class + getter combination b. If not found, check for class-level patterns c. If not found, apply general transformation rules d. Transform type from Java to Haxe e. Generate appropriate access code ``` ### Special Handling 1. **Timeline Classes**: All timeline getters follow consistent patterns 2. **Constraint Classes**: Handle getData/getPose/getAppliedPose consistently 3. **Array Properties**: Detect 1D vs 2D arrays based on context 4. **Enum Values**: Generate proper Haxe enum access syntax 5. **Circular References**: Maintain visitedObjects tracking ## Error Handling 1. **Missing Mappings**: Log unmapped getters with class context 2. **Type Mismatches**: Detect and report Java/Haxe type incompatibilities 3. **Compilation Errors**: Capture and display Haxe compiler output ## Testing Strategy 1. **Unit Tests**: Test individual transformation rules 2. **Integration Tests**: Generate full serializer and compile 3. **Snapshot Tests**: Compare output with reference implementation This approach ensures accuracy, maintainability, and extensibility while leveraging the comprehensive mapping data we've collected.