mardi 20 octobre 2015

Dynamic Beans with Generics

So i have two database tables which hold different types of beans. The first table named: Export is made up of a number of different bean names which are implement the Exporter interface defined as:

public interface Exporter<ExportType> {
    List<ExportType> export();  
}

The second table, named Export Action is made up of action beans that operate on the exported objects that are returned from the Exporter bean. There are two types of action beans, TRANSFORM beans which basically take as input the output from the exporter bean, and transform it into a different object, as defined by the second generic parameter type. The interface for this bean is defined as:

public interface ExportTransform<ExportType, TransformType> {
    List<TransformType> transform(List<ExportType> exportObjects);
}

The other type of action bean is a PROCESS bean. These beans take the output from the transformation and process them (persists them) and returns the entity objects back. This process interface is defined as:

public interface ExportPostProcess<TransformType, ProcessResult> {
    List<ProcessResult> postProcess(List<TransformType> transformObjects);
}

For this example, here's some example data for these two tables:

Table: Export

|----------------------------------------------------------------------------------|
|   ID    |        Bean Name       |   Creation Time     |    Modification Time    |
|----------------------------------------------------------------------------------|
|    1    |    documentExporter    | 2010-10-09 10:10:09 |   2010-10-10 12:09:10   |
|----------------------------------------------------------------------------------|

Table: Export Action

|------------------------------------------------------------------|
|   ID    |     Type     |          Bean Name          | Export ID |
|------------------------------------------------------------------|
|    1    |  TRANSFORM   | documentRulesetTransformer  |     1     |
|    1    |   PROCESS    |       rulesetProcessor      |     1     |
|------------------------------------------------------------------|

These beans have been implemented the corresponding interfaces as follows:

@Component
public class DocumentExporter implements Exporter<Document> {

    public List<Document> export() {
        // export
        return Collections.emptyList();
    }

}

@Component
public class DocumentRulesetTransformer implements ExportTransform<Document, RulesetVO> {

    public List<RulesetVO> transform(List<Document> transformObjects) {
        // transform
        return Collections.emptyList();
    }

}

@Component
public class RulesetProcessor implements ExportPostProcess<RulesetVO, Ruleset> {

    public List<Ruleset> postProcess(List<RulesetVO> transformObjects) {
        // process
        return Collections.emptyList();
    }

}

Finally... My question is.. what is the best way to manage this in terms of generics without needing a bunch of explicit casts or @SupressWarnings("unchecked") everywhere? Considering this data is dynamic, and so are the bean implementations.

Currently I have code like the following (simplified for readability):

Set<Export> exportBeans = exportRepository.findAll();
exportBeans.forEach(export -> {

    Exporter<?> exporter = applicationContext.getBean(export.getBeanName(), Exporter<?>.class);
    List<?> exportObjects = exporter.export();

    ExportTransform<?, ?> transformer = export.getActions.get(ActionType.TRANSFORM);
    List<?> transformedObjects = transformer.transform(exportObjects);

    ExportPostProcess<?, ?> postProcessor = export.getActions.get(ActionType.PROCESS);
    List<?> processedObjects = postProcessor.postProcess(transformObjects);

});

At the moment, I have to use reflection to validate the bean implementations are supported as per their generic types. I.E the rulesetProcess¬ bean is able to accept the result of thedocumentResultTransformer` bean. Which is cumbersome and nasty. I would love to think there was something I could utilize which takes care of this for me to some degree.

Any help would be greatly appreciated.





Aucun commentaire:

Enregistrer un commentaire