Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Aggregator API

The Aggregator API turns CMS source data into new, prepared data structures – for example, for delivery to frontends, search indexes, or other consumers.

The API is clearly layered. Each role has a well-defined responsibility:

Role Purpose
Resolver Reads raw source data (Source)
Assembler Builds typed domain objects from a Resolver
Aggregator Composes the target structure into an OutputNode
OutputNode Hierarchical target data structure (Target)
Visitor Traverses an OutputNode (serialization, analyses)

Data flow

flowchart LR
    Source[("Source data<br/>(CMS, Map, JSON, ...)")]
    Resolver["Resolver<br/><i>read-only view</i>"]
    Assembler["Assembler<br/><i>optional</i>"]
    Domain[["Domain objects<br/>(Link, Text, ...)"]]
    Aggregator["Aggregator"]
    Output[("OutputNode<br/><i>target structure</i>")]
    Visitor["Visitor"]
    Target[["PHP / JSON / Map /<br/>TranslatableTexts ..."]]

    Source --> Resolver
    Resolver --> Assembler
    Assembler --> Domain
    Resolver --> Aggregator
    Domain --> Aggregator
    Aggregator --> Output
    Output --> Visitor
    Visitor --> Target
Loading

When do I use what?

Question Answer
How do I get individual values from a source? Resolver
How do I build a typed value object (e.g. Link)? Assembler
How do I write results into the target structure? Aggregator + OutputNode
How do I structure the data hierarchy to be generated? OutputNode (optionally with sub-aggregators)
How do I serialize the result (PHP, JSON, Map) or evaluate it? Visitor
How do I deliver the same structure in multiple languages? Translations

How it fits together

In a typical aggregation, all roles work together:

public class LinkListAggregator implements Aggregator {

  private final LinkListAssembler linkListAssembler;

  @Override
  public void aggregate(Resolver source, OutputNode output) {
    //                  ^^^^^^^^         ^^^^^^^^^^
    //                  RESOLVER         OUTPUTNODE
    //                  (Source)         (Target)

    linkListAssembler.assemble(LinkListRequest.of(source, options), null)
        //  ^^^^^^^^^
        //  ASSEMBLER returns a typed domain object
        .ifPresent(linkList -> output.put("linkList", linkList));
    //                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    //                         AGGREGATOR writes into the OutputNode
  }
}

Assemblers are optional: for simple fields, an Aggregator can read directly from the Resolver and write to the OutputNode. Only when constructing a value involves multiple steps (several fields, derived values, business rules, external resolutions) is a dedicated Assembler worthwhile.

Documentation at a glance

The documentation is organized by genre:

Genre Directory Content
Reference docs/reference/ Role reference: Resolver, Assembler, Aggregator, OutputNode, Visitor
How-To docs/how-to/ Task-oriented: Aggregator plugin project, Assembler customization, Translations pipeline
Concept docs/concepts/ Background & design decisions: Translatable values: immutability & identity

About

Aggregator API for the IES CMS: turns CMS source data into prepared target structures (PHP, JSON, Map, ...) via a layered pipeline of resolvers, assemblers, aggregators, output nodes and visitors.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages