The Aggregate Conversion API allows client code to provide custom behavior for importing the serialized profile of an aggregate into the current profile. This process is referred to as "conversion" and/or "import" in this document.
IProfile
instanceThe following diagram presents an overview of the Aggregate Conversion API. The package names are omitted throughout this document to minimize clutter.
On this page: |
The main entrypoint is an implementation of IAggregateConverterFactory annotated with
, provided by client code and available on the classpath. While there could be multiple classes implementing this interface, there must be a single class on the classpath annotated with AquimaAggregateConverterFactory
AquimaAggregateConverterFactory
(practically, there should be a single bean implementing IAggregateConverterFactory
in the Spring context). If this requirement is not met, the following semantics are applied:
AquimaAggregateConverterFactory
This annotation extends the Spring @Component
annotation and marks a class as a Spring bean. To allow the class to be picked up and an instance of it made available in the Spring context, the package containing the implementation annotated with AquimaAggregateConverterFactory
should be included in a <component-scan>
element in the Spring context configuration.
IAggregateConverterFactory
This interface allows the AggregateDAO plugin to obtain a converter which is capable of converting a given aggregate from a given source version (the version in which the aggregate was saved) to a given target version (the current version). The only method of this interface is getAggregateConverter(aggregateName:String, source:ApplicationID, target:ApplicationID)
. This method should return an implementation of IAggregateConverter
capable of converting the given aggregate from the given source version to the given target version, or null if implicit conversion is desired.
To prevent accidental implicit conversions, the factory may return a "catch-all" implementation which may:
IAggregateConverter
This interfaces defines the API through which custom converters may hook into the conversion process. If a converter is available for a given aggregate/source/target combination, the default conversion process will first delegate to the custom converter. The converter may decide to do one of the following:
The interface provides five methods which are briefly described here and further detailed below:
addEntity
- this method notifies the converter that an entity should be importedsetAttribute
- this method notifies the converter that an attribute of an entity should be importedsetRelation
- this method notifies the converter that a (forward) relation of an entity should be importedpreProcess
- this method is called first, before all others and allows the converter to do any preprocessing or initializationpostProcess
- this method is called last, after all others and allows the converter to do any final processing or cleanupaddEntity(ctx:IEntityConversionContext):boolean
This method notifies the converter that an entity is about to be imported. Information about the entity can be obtained from the ctx
parameter.
The calling process can make the following guarantees related to this method:
setAttribute
and setRelation
methods are invoked for the same instanceThe calling process does not make any guarantees related to the following:
The method may choose to create the corresponding instance in the profile itself at the moment this method is invoked or at a later time, in which case it should return true to indicate that it will handle the conversion of this entity instance itself. In most cases, where nothing is changed between the source and target version, the converter may return false to allow the default process to import the entity instance.
If the entity instance is created at the moment the method is invoked, the converter may use ctx.setCurrentInstance(IEntityInstance)
to notify the conversion process of the existence of the new instance. The given current instance will become the current instance for the setAttribute
and setRelation
methods, meaning the following attributes and relations will be set on this instance.
setAttribute(ctx:IAttributeConversionContext):boolean
This method notifies the converter that an attribute is about to be imported. Information about the entity, entity instance and attribute is available in the ctx parameter.
The calling process can make the following guarantees related to this method:
addEntity
method for the corresponding entity instance has been invoked before this methodThe ctx.getCurrentInstance()
may be used to obtain the current entity instance on which this attribute should be set. Please note that the getCurrentInstance()
method may return null if the preceding addEntity
method returned true and it did not set a current instance.
The method may return true to indicate it will handle the attribute itself, or return false to allow the default conversion to import the attribute.
setRelation(ctx:IRelationConversionContext):boolean
This method notifies the converter that a relation is about to be imported. Information about the entity, entity instance and relation is available in the ctx parameter.
The calling process can make the following guarantees related to this method:
addEntity
method for the corresponding source entity instance has been invoked before this methodaddEntity
method will eventually be invokedThe calling process does not make any guarantees related to the following:
addEntity
method for the target instance will be invoked (only guarantee is that it will be after preProcess
and before postProcess
)
The ctx.getCurrentInstance()
method may be used to obtain the current entity instance, with the same remarks about null as for attributes.
The ctx.getRelationValue()
method will return the instance ID in the saved profile of the target entity instance. This instance may or may not have already been imported.
The ctx.hasInstance(GUID)
may be used to check whether the calling process knows that the target instance has already been imported. Please consult the documentation for IAggregateConversionContext.hasInstance(GUID)
for details.
The ctx.getInstance(GUID)
may be used to obtain the IEntityInstance
from the current profile associated with the given GUID. Please consult the documentation for IAggregateConversionContext.getInstance(GUID)
for details.
preProcess(ctx:IAggregateConversionContext):void
This method will be called before the conversion of a saved aggregate effectively starts. Implementations may use this opportunity to initialize, obtain and cache information from the current profile and metamodel for use in the subsequent addEntity
, setAttribute
and setRelation
method calls.
postProcess(ctx:IAggregateConversionContext):void
This method will be called last, after all entity instances, attributes and relations have been imported (or at least, their corresponding addEntity
, setAttribute
and setRelation
methods have been called). Implementations may use this opportunity to create additional entity instances in the current profile based on the information accumulated in the preceding addEntity
, setAttribute
and setRelation
method calls, as well as set attributes and relations on those instances. This method is most useful when there are complex changes (usually involving relations) between the source and target version. In those cases, information about the saved aggregate is progressively accumulated and then the complex conversions are made at the end in the postProcess
method.
AggregateConverterAdapter
This class is provided for convenience that simple implementations may extend. The pre- and post-process methods have an empty implementation, and all other methods return false. This class may be used as a base class when simple converters only need to implement one or two methods of the IAggregateConverter
interface.
IAggregateConversionContext
An object implementing this interface is provided as parameter to preProcess
and postProcess
methods of an IAggregateConverter
and can be used to obtain information about the source and target versions and the aggregate. It also provides access to the current profile and metamodel.
The IAggregateConversionContext
is the base interface of all conversion contexts in the conversion API and are accessible from any point of a converter.
getSourceVersion():ApplicationID
This method returns the application id at the time this aggregate was last saved. This can be used to determine the project name and version at the time the aggregate was last saved. The value returned by this method will be identical to the source parameter provided to the IAggregateConverterFactory.getAggregateConverter
method.
getTargetVersion():ApplicationID
This method returns the current application id (at the time the aggregate is converted). This can be used to determine the project name and version at the present time. This value returned by this method will be identical to the target parameter provided to the IAggregateConverterFactory.getAggregateConverter
method.
getAggregateName():String
This method returns the name of the aggregate being converted. This, together with the source version can be used to determine what entity instances to expect in the addEntity
method. The value returned by this method will be identical to the aggregateName
parameter provided to the IAggregateConverterFactory.getAggregateConverter
method.
getProfile():IProfile
This method returns the current profile. It can be used by the converter to obtain references to existing entity instances or to create new entity instances in the profile.
getMetaModel():IMetaModel
This method returns the current metamodel. It can be used by the converter to obtain information about aggregate, entity, attribute and relation definitions.
hasInstance(instanceId:GUID):boolean
This method checks whether for the given instanceId from the saved profile, an IEntityInstance
is known to have been imported into the current profile (where it has a different instance id). This method used in combination with getInstance(GUID)
is a convenient way for converter implementors to obtain an entity instance from the current profile which corresponds to an entity instance from the saved profile, freeing them of the need to maintain the mapping between saved and current profile themselves.
Note: a return value of true from this method does not guarantee that getInstance(GUID)
will not throw an exception, it only indicates whether a mapping is known. For example it is possible for implementors to delete the imported entity instance from the current profile after the mapping becomes known. However, if no entity instances are deleted by the converter implementor it is generally safe to assume that if hasInstance(GUID)
returns true for a given GUID, then getInstance(GUID)
for the same GUID will return an IEntityInstance
without throwing exceptions.
This method may be used in any of the methods of IAggregateConverter
.
getInstance(instanceId:GUID):boolean
This method returns the entity instance from the current profile, which is mapped to the given instance id from the saved profile. This method may return null if no mapping is known for the given instance id or may throw exceptions if a mapping is known but the entity instance cannot be found in the current profile (possibly because it was deleted by the implementor).
This method may be used in any of the methods of IAggregateConverter
, although in preProcess
no mappings will be known since the import hasn't started yet at that point.
IEntityConversionContextBase
This interface serves as a base interface for entity, attribute and relation conversion contexts and provides methods for obtaining information about the entity instance currently being imported.
getEntityName():String
This method returns the entity name of the entity instance currently being imported.
Note: using IEntityConversionContext.setCurrentInstance()
in addEntity
has no effect on the return value of this method in setAttribute
and setRelation
; it will always return the entity name in the saved profile
getInstanceId():GUID
This method returns the instance id in the saved profile of the entity instance currently being imported.
Note: using IEntityConversionContext.setCurrentInstance()
in addEntity
has no effect on the return value of this method in setAttribute
and setRelation
; it will always return the instance id from the saved profile
getInstanceName():String
This method returns the instance name in the saved profile of the entity instance currently being imported, or null if the saved entity instance doesn't have a name.
isRootInstance():boolean
This method checks whether the entity instance currently being imported is a root instance in the aggregate. An entity instance is a root instance if it is explicitly included in the aggregate. If the entity instance is not explicitly included, but was included anyway because of a relation, then it is not a root instance. This information may be used when entities are removed from an aggregate definition, but there might still be other instances that should remain due to relations to other instances.
IAttributeConversionContext
This interface extends IEntityConversionContextBase
and provides methods specific to attributes which allow obtaining information about the attribute currently being imported, as well as about the current entity instance on which attributes are set.
getAttributeName():String
This method returns the name of the attribute currently being imported.
getAttributeValue():String
This method returns the saved value of the attribute currently being imported. If the attribute is multivalued, then this method returns the value currently being imported.
isMultiValued():boolean
This method indicates whether the attribute currently being imported is multivalued. If an attribute or relation is multivalued, the setAttribute
method will be called multiple times for that attribute, once for each saved value.
getCurrentInstance():IEntityInstance
This method returns the current entity instance being imported into the profile or null:
IEntityInstance
if the preceding addEntity
method returned false, or if it called setCurrentInstance
with a non-null instanceaddEntity
method returned true and did not set a current instance using setCurrentInstance
IRelationConversionContext
This interface extends IEntityConversionContextBase
and provides methods specific to relations which allow obtaining information about the relation currently being imported, as well as about the current entity instance on which the relations are set.
getRelationName():String
This method returns the name of the relation currently being imported.
getRelationValue():GUID
This method returns the instance id in the saved profile of the related (target) entity instance. The value returned by this method can be used in hasInstance
and getInstance
to obtain the actual entity instance from the current profile, if has previously been imported.
getCurrentInstance():IEntityInstance
This method returns the current entity instance being imported into the profile or null:
IEntityInstance
if the preceding addEntity
method returned false, or if it called setCurrentInstance
with a non-null instanceaddEntity
method returned true and did not set a current instance using setCurrentInstance
IEntityConversionContext
This interface extends IEntityConversionContextBase
and adds the possibility of setting the current entity instance on which setAttribute and setRelation
will set attributes and relations.
setCurrentInstance(IEntityInstance):void
This method allows the converter implementor to specify a current entity instance from addEntity
, on which setAttribute
and setRelation
should set attributes or relations. If addEntity
returns false, the default import process will set the current instance. If addEntity
decides that it will handle the conversion of an entity instance itself, it may use setCurrentInstance
to allow the default conversion of attributes and relations to take places on this instance.