EntityTransformer¶
Overview¶
EntityTransformer is a bidirectional transformation engine that converts between canonical entity objects (TlinqEntity) and native platform-specific objects. It uses reflection and annotation-based configuration to map fields between different object representations, supporting complex mapping scenarios including arrays, lookups, and nested objects.
Package: com.perun.tlinq.entity
Purpose¶
This transformer pattern class serves as the core data mapping layer in the Tlinq framework, enabling: - Transformation from native platform objects to canonical TlinqEntity objects - Reverse transformation from canonical entities back to native format - Field-level mapping with support for multiple mapping strategies - Dynamic lookup resolution across related entities - Handling of master-detail relationships in documents
Class Fields¶
| Field | Type | Description |
|---|---|---|
canonicalClass |
Class |
The target canonical class being transformed to/from |
canonicalFields |
HashMap<String, Field> |
Cache of canonical class fields for efficient lookup |
sessionToken |
String |
Authentication token for the current session |
logger |
Logger |
Logger instance for tracking transformation operations |
Constructor¶
EntityTransformer(String canonicalClassName, String token)¶
Initializes the transformer for a specific canonical entity class.
Parameters:
- canonicalClassName - Fully qualified name of the canonical class
- token - Session authentication token
Throws:
- TlinqClientException - If the class is not found or is not a TlinqEntity descendant
Behavior: - Dynamically loads the canonical class using reflection - Validates that the class extends TlinqEntity - Caches all entity fields for efficient transformation
Core Transformation Methods¶
toCanonicalObject(Class targetClass, Object nativeObject)¶
Transforms a native platform object into a canonical TlinqEntity object.
Parameters:
- targetClass - The canonical entity class to transform to
- nativeObject - The native platform object to transform from
Returns: Instantiated and populated TlinqEntity object, or null if transformation fails
Mapping Strategy:
- Iterates through all fields in the native object
- Processes @TlinqEntityField annotations for direct field mappings
- Processes @TlinqLookupField annotations for lookup-based mappings
- Supports array lookups, model lookups, and selection-based lookups
toNative(String factoryName, Object canonicalEntity)¶
Transforms a canonical TlinqEntity object back into a native platform object.
Parameters:
- factoryName - Name of the factory configuration to use for mapping
- canonicalEntity - The canonical entity to transform
Returns: Instantiated and populated native object
Throws:
- TlinqClientException - If configuration errors occur or mapping fails
Mapping Strategy:
- Retrieves field mapping configuration from EntityConfig
- Applies mapping based on configured FieldMappingType
- Handles nested TlinqEntity conversions recursively
- Skips fields marked with @TlinqCriteriaField annotation
Field Assignment Methods¶
assignTargetValue(Class targetClass, Object nativeObject, TlinqEntity targetObject, Field field)¶
Handles direct field-to-field mapping using @TlinqEntityField annotation.
Parameters:
- targetClass - The canonical entity class
- nativeObject - Source native object
- targetObject - Destination canonical entity
- field - The field being mapped
Behavior: - Extracts the field value from the native object - Handles both scalar values and array values - Uses annotation index property to extract specific array elements - Sets the value in the target canonical object
assignKeyValueLookup(Class targetClass, Object nativeObject, TlinqEntity targetObject, Field field, int valueIndex, String targetFieldName)¶
Handles index-based array lookup mapping.
Parameters:
- targetClass - The canonical entity class
- nativeObject - Source native object
- targetObject - Destination canonical entity
- field - The field containing the array
- valueIndex - Index of the element to extract
- targetFieldName - Name of the target field in canonical entity
Behavior: - Validates that the field value is an array - Extracts the element at the specified index - Assigns the value to the target field
assignModelLookup(Class targetClass, Object nativeObject, TlinqEntity targetObject, Field field, TlinqLookupField ann)¶
Placeholder for model-based lookup mapping (currently not implemented).
Parameters:
- targetClass - The canonical entity class
- nativeObject - Source native object
- targetObject - Destination canonical entity
- field - The field requiring lookup
- ann - The lookup field annotation
Supported Mapping Types¶
The transformer supports the following mapping strategies in the reverse (canonical to native) transformation:
DirectMapping¶
Maps field values directly between canonical and native objects. Automatically handles nested TlinqEntity conversions.
ArrayMapping¶
Maps collections and arrays between canonical and native representations. Supports element-level TlinqEntity conversion for master-detail relationships.
IndexMapping¶
Maps a canonical field value to a specific index within a native array. Creates or extends arrays as needed.
ModelLookup¶
Reserved for cases where the canonical object was populated via lookup. Creates native object with only the ID populated (currently not fully implemented).
NestedMapping¶
Similar to DirectMapping but specifically for nested entity relationships (currently not fully implemented).
MapConversion¶
Reserved for creating map structures with field names as keys (currently not fully implemented).
NoMapping¶
Indicates no reverse mapping is required, typically for lookup values with embedded IDs.
Annotation Support¶
The transformer recognizes and processes the following annotations:
- @TlinqEntityField - Marks fields for direct mapping with optional array indexing
- @TlinqLookupField - Defines lookup-based field resolution strategies
- @TlinqCriteriaField - Marks fields as criteria-only (excluded from native transformation)
Error Handling¶
The transformer includes comprehensive error handling: - Logs field access errors at SEVERE level - Validates class types and inheritance - Throws TlinqClientException for configuration errors - Gracefully handles missing or null fields during transformation
Usage Example¶
// Initialize transformer for a canonical entity class
EntityTransformer transformer = new EntityTransformer(
"com.example.entities.Product",
sessionToken
);
// Transform native object to canonical
Product canonicalProduct = (Product) transformer.toCanonicalObject(
Product.class,
nativeProductObject
);
// Transform canonical back to native
Object nativeProduct = transformer.toNative(
"odoo",
canonicalProduct
);
Dependencies¶
- TlinqEntity - Base interface for canonical entities
- EntityConfig - Configuration for entity mappings
- ClientConfig - Global client configuration singleton
- TypeUtil - Reflection utilities for type manipulation
- TlinqClientException - Framework exception class
Thread Safety¶
This class is thread-safe when used as intended. The canonicalFields cache is populated once during construction and is subsequently read-only. Since the recommended usage pattern is to create a new EntityTransformer instance for each transformation operation, no concurrent modification issues arise.
Safe usage pattern:
// Create a new instance for each transformation
EntityTransformer transformer = new EntityTransformer("com.example.Product", token);
Product result = (Product) transformer.toCanonicalObject(Product.class, nativeObject);
Note: If you choose to reuse instances across multiple threads, the class is safe as long as the canonicalClass remains the same, since canonicalFields is effectively immutable after construction.
Performance Considerations¶
- Field lookups are cached in the constructor for efficiency
- Reflection operations may impact performance for large-scale transformations
- Array operations create new arrays rather than modifying in place
- Logger level should be set appropriately to avoid excessive logging overhead