Hey,

Continuing the AssociationRole discussion, since we would want to make 
it possible to expose something in the interface which has methods for 
the state directly instead of going through the AssociationRole, and 
since we have also previously discussed how to get Concerns on top of 
Associations (i.e. when getting or setting an Association we want to 
intercept it and also do side-effects etc.), I've made a test that shows 
how to do this using Composites as wrappers.

Here's the test code I want to work:
Person person;
{
     EntityBuilder<Person> builder = unitOfWork.newEntityBuilder( 
Person.class );
     builder.stateOfComposite().name().set( "Rickard" );
     person = builder.newInstance();
}

CompanyEntity companyEntity;
{
     EntityBuilder<CompanyEntity> builder = unitOfWork.newEntityBuilder( 
CompanyEntity.class );

     companyEntity = builder.newInstance();
}

Employee employee;
{
     EntityBuilder<Employee> builder = 
unitOfWork.newEntityBuilder(Employee.class);
     builder.stateOfComposite().position().set( "CEO" );
     employee = builder.newInstance();
}

companyEntity.employees().add( role( person, employee) );
companyEntity.employees().remove( role( person, employee) );
---
In this case I want to be able to let employees() return a custom 
Employees collection instead of just a 
ManyAssociation<AssociationRole<Person,Employee>, and I also want to be 
able to do audit logging whenever I add or remove employees. The 
interfaces and mixins for this looks like so:
@Mixins( CompanyMixin.class )
interface CompanyEntity
     extends EntityComposite
{
     // Here there's a Domain concept instead
     // of a ManyAssociation being returned
     Employees employees();
}

interface Person
     extends EntityComposite
{
     Property<String> name();
}

interface Employee
     extends EntityComposite
{
     Property<String> position();
}

// Here is the Employees definition, which is a regular Composite
// that extends ManyAssociation
// Since it is a Composite I can also add Concerns to it
// The generic DecoratorMixin will simply delegate all methods
// to a CompositeBuilder.use()-supplied ManyAssociation
@Mixins( DecoratorMixin.class )
@Concerns( EmployeesAuditConcern.class )
interface Employees
     extends ManyAssociation<AssociationRole<Person, Employee>>, Composite
{
}

// Here I create the Employees Composite in the constructor as a
// wrapper of the regular ManyAssociation
public static abstract class CompanyMixin
     implements CompanyEntity
{
     Employees employees;

     public CompanyMixin( @Structure CompositeBuilderFactory cbf, 
@AssociationParameter( "employees" ) ManyAssociation employees )
     {
         this.employees = cbf.newCompositeBuilder( Employees.class 
).use( employees ).newInstance();
     }

     public Employees employees()
     {
         return employees;
     }
}

// This concern prints out hirings and firings,
// which are mapped to add/remove in ManyAssociation/Collection
public static abstract class EmployeesAuditConcern
     extends ConcernOf<Employees>
     implements Employees
{
     public boolean add( AssociationRole<Person, Employee> 
personEmployeeAssociationRole )
     {
         System.out.println("Hired 
"+personEmployeeAssociationRole.association().name()+" as 
"+personEmployeeAssociationRole.role().position());
         return next.add(personEmployeeAssociationRole);
     }

     public boolean remove( Object o )
     {
         AssociationRole<Person, Employee> personEmployeeAssociationRole 
= (AssociationRole<Person, Employee>) o;
         System.out.println("Fired 
"+personEmployeeAssociationRole.association().name()+" as 
"+personEmployeeAssociationRole.role().position());
         return next.remove( o );
     }
}
---
If you want you can add Property methods to Employees which get 
delegated to the AssociationRole.role() methods, thus hiding it.

The above works with a few minor modifications to the current Qi4j codebase.

This could be improved even more by making Employees a true domain 
concept, which does not expose the internal collection, but rather only 
domain methods. This will be shown in the next post (to keep the size of 
the posts down).

/Rickard

_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev

Reply via email to