This framework is created to ease everyday tasks regarding conversion between models. It is not directed to one of specific use case like json <-> model conversion but can be used in many.
To make use of this framework there is need to instantiate Gecon type object. It is provided from herd.gecon.core.engine module
Example:
Gecon gecon = Gecon{
provider = AutoProvider {
transformations = ScopeProvisioning {
scopes = [
`module herd.gecon.core.transformer`,
`module herd.gecon.collection.transformer`,
`module herd.gecon.json.transformer`
];
};
};
};This is minimal setup which is required for usage. Modules registered in this guide are providing required Transformations for:
- Basic data types transformations
- Generic data types transformations
- Collections transformations
- Json <-> Model transformations
There is only one instantiation parameter used and it is provider. It tells framework, on what components it will work on. Currently only Transformations can be provided. AutoProvider is used for such purpose. It works on scope based filtering. Basically it takes Transformation classes, begin available via scopes parameter and instantiates them, using available resources (currently only no args constructor). There is another parameter called exclusions in ScopeProvisioning class, allowing to reduce transformations availability for framework. Scope is alias of Module|Package|ClassDeclaration, that provides controll over instantiationing of transformations. Other way to provide Transformations is to use ManualProvider, which requires clients, to instantiate Transformations manually, but gives precise controll what and how is available for Gecon.
Gcon type object, can also be configured. Currently only Logging configuration is available to be altered. Logging provides ability to change priority, which is stadard ceylon.logging.priority.
What is Transformation? A Transformation is an interface defined by herd.gecon.core.engine, which provides a way for execution of Transformation.transform method. It takes source data and transform it, into provided result type. Although below interfeces doesn't extends Transformation interface (because of transformation method definition). They are wrapped using it and in most cases by Transofmormation in this guide, one of fallowing interfaces will be ment:
-
Conversion- Initial entry point for each transformation, takes source object and converts it into result type object. Whole flow can be implemented using singleConversionor it can delegate to other transformations. Default implementation of this interface isConverter, which should be used for definingConversion. -
Resolvance- Chooses implementation of specific interface, abstract class, or any other type which is ambigous in compile time. The most common use case is selecting collection implementation for interface likeList<String>. Should this beLinkedList<String>, or maybeArrayList<String>? This is handled by implementaton ofResolvanceinterface. Default implementation of this is interface isResolver, which should be used for definingResolvance. -
Creation- Creates specific result type object from provided result type and arguments.Creationcan be undestood as a constructor / initializer. In cases, where conversion is generic and type arguments are not available in compile type, it is sometimes usefull to delegate toCreation. Default implementation of this interface isCreator, which should be used for definingCreation. -
Mapping- Maps result type parts to source parts values usingDictionaryobject. Default implementation of this interface isMapper, which should be used for definingMapping. Example usecase is when, converting from json to model object and the naming of fields are different in model than in json.
Gecon type object has a transform method which will be used for all transformations.
Most commonly used transformation is Conversion implemented by Converter<Source,Result,ResultType> class. It has three type parameters as most of transformations:
- Source (Required) - A type of source data provided by framework to the converter,
- Result (Required) - A type of result data which will be produced by converter,
- ResultType (Defaulted :
Type<Result>) - A Type of result type, provided by the framework to work on, usable only for generic conversions andMatcherusers. By default inConversion.convertmethodresultTypeparameter isType<Result>, which is too less for some converters. They may require thatresultTypebeClass<Result>orClassOrInterface<Result>orUnionType<Result>etc. By constraining this type parameter, there is no need for assertations inConversion.convertmethod body.
Dummy specific converter definition:
shared class StringToNullConverter() extends Converter<String,Null>(){
shared actual Null convert(Delegator delegator, String source, Type<Null> resultType) => null;
}
When converter registered by Provider it takes Source and Result types and uses HashMap for storing them. Further when lookup in transformation flow it will be easly retreivable.
Dummy generic converter definition:
shared class AnythingToAnythingConverter() extends Converter<Anything,Anything,Type<Anything>>(){
shared actual Anything convert(Delegator delegator, Anything source, Type<Anything> resultType) {
value resolve = delegator.resolve(source, resultType);
return delegator.convert(source, resolve);
}
shared actual Matcher matcher => Matcher{
predicate(Anything source, Type<Anything> resultType) => (source is String|Null) && (resultType.subtypeOf(`String|Null`));
Integer priority = 0;
};
}In this case, registration takes Matcher definition. Whenever hashing fail, because for example Result type is interface, union type or abstract class. Registered Matchers are used for lookup. The search mechanism iterates over available Matchers and if Matcher.predicate method returns true and the Matcher.priority is the biggest in this lookup scope, then this Transformation will be used, in this case for conversion.
All examples in example source folder.
Examples definitions:
- Json to Model conversion -
module json.to.model - Model to Json conversion -
module model.to.json
The versioning of this project starts from 0. Is defined as referenced to version of herd.gecon.core.api module as a base, which is defined as CORE-API . Other modules should define it's version, based on this versioning so version of herd.gecon.core.engine module will be defined as CORE-API.ENGINE . If a module have it's own API. the versioning for this module will be CORE-API.OTHER-API.MODULE . Change in any API version may mean it is a compatibility break.
| Module name | Versioning pattern | Current version |
|---|---|---|
herd.gecon.core.api |
CORE_API | 0 |
herd.gecon.core.engine |
CORE_API.ENGINE | 0.0 |
herd.gecon.core.trnasformer |
CORE_API.TRANSFORMER | 0.0 |
herd.gecon.collection.transformer |
CORE_API.TRANSFORMER | 0.0 |
herd.gecon.json.transformer |
CORE_API.TRNASFORMER | 0.0 |
herd.gecon.test.extension |
EXTENSION | 0 |