The core of the Assembler is the
assemble()
method, which takes a content item representing
a cartridge instance configuration and invokes cartridge handlers to process it
into a response content item.
The Assembler uses the visitor pattern to traverse the input content item and any child content items, and invokes the appropriate cartridge handler (if any) for each of them.
The Assembler makes two passes over the input content item:
In the first pass, the Assembler calls
CartridgeHandler.initialize()
followed byCartridgeHandler.preprocess()
on each content item in the tree. This is a pre-order traversal of the tree (working from the top of the tree down through its children), so cartridge handlers may add or modify child content items at this stage.In the second pass, the Assembler calls
CartridgeHandler.process()
on each content item, which returns the response content item for that cartridge. This is a post-order traversal of the tree (working from the bottom up), so child content items are processed before the parent. The response object for the root content item of the tree (the content item originally passed in as input to the firstassemble()
call) contains the response objects for all its child cartridges.
The default implementation of the Assembler uses Spring to map each cartridge to the appropriate handler based on its content type. This content type corresponds to the template identifier that was used to create the content item object. If no cartridge handler is defined for a particular content type, the instance configuration is passed through as the response model.
For example, consider the following content item:
NestingDollContentItemSubclass nestingDoll
This content item represents a Russian Nesting Doll. It includes properties for its name, color, and its child content item:
nestingDoll.name = "Nesting Doll" nestingDoll.color = red nestingDoll.child = secondNestingDoll
The
secondNestingDoll
contained within is green. It
contains a
thirdNestingDoll
, which is blue. Assuming there is no
cartridge handler for
NestingDollContentItemSubclass
, an
assemble(nestingDoll)
call executes the following:
The pre-order traversal starts. There is no cartridge handler for
NestingDollContentItemSubclass
, so noinitialize()
orpreprocess()
calls are made fornestingDoll
.Similarly, no calls are made for
secondNestingDoll
orthirdNestingDoll
. At this point, the pre-order traversal is complete.The post-order traversal starts. The
thirdNestingDoll
object is returned as-is, since there is no handler to invoke aprocess()
method.Similarly, the
secondNestingDoll
andnestingDoll
objects are returned, unmodified. Serialized to JSON, the response looks like the following:@type": "NestingDollTemplateType", "name": "Nesting Doll", "color": "red", "child": [ { @type": "NestingDollTemplateType", "name": "Second Nesting Doll", "color": "green" "child": [ { @type": "NestingDollTemplateType", "name": "Third Nesting Doll", "color": "blue" "child": [] } ], }, ]
What if you create a cartridge handler for
NestingDollContentItemSubclass
that doesn't override
the
initialize()
or
preprocess()
methods, but implements logic to add a
property
colorType
of value
warm
or
cool
, based on the
color
property? Steps 1-2 above don't change, but Step
3 invokes the new logic, and the property shows up in the response:
@type": "NestingDollTemplateType", "name": "Nesting Doll", "color": "red", "colorType": "warm", "child": [ { @type": "NestingDollTemplateType", "name": "Second Nesting Doll", "color": "green", "colorType": "cool", "child": [ { @type": "NestingDollTemplateType", "name": "Third Nesting Doll", "color": "blue", "colorType": "cool", } ], }, ]
A content item is
a set of
key:value
pairs where the key is a property name and the
value may be any primitive type, or another content item. The
com.endeca.infront.assembler ContentItem
interface extends
java.util.Map
.
Content
items in the Assembler represent either structural components of an application
page, or GUI components on the page itself. A call to the
Assembler.assemble(ContentItem)
method accepts as input
a
ContentItem
containing configuration, and returns a
content item as output. The response content item can encompass an entire page
in an application, with each sub-section of the page (such as the search box or
the search results list) represented as its own nested content item.
Note
In the default implementation of the Assembler, the
ContentItem
interface is implemented by the
com.endeca.infront.assembler.BasicContentItem
class.
The navigation cartridges in the
package extend this implementation for their
individual use cases.
The default
Assembler implementation typically takes a
ContentInclude
or
ContentSlotConfig
object as input to the Assembler. The
first specifies a content item by URI, while the second retrieves a content
item from a specified folder according to template type and ID restrictions,
trigger criteria, and content item priority.
Both methods retrieve the associated configuration for the content item in Workbench.
A
ContentInclude
object defines a single content item to
pass into the Assembler (though keep in mind that a content item may contain
additional content items as children). It resolves a URI to a content item
within a configured content source (typically the Endeca Configuration
Repository).
Unlike a
ContentInclude
object, which explicitly specifies a
content item to pass as input to the Assembler, the
ContentSlotConfig
object defines a set of criteria for
dynamically retrieving one or more content items at runtime. In most cases the
content administrator creates and populates
ContentSlotConfig
objects through editors in
Experience Manager, although you can still programatically instantiate them if
necessary.
The dynamic content slot is populated based on the following restrictions:
Content paths — The path or paths to content folders in Experience Manager. Any content items within the specified folders or within sub-folders are considered valid for retrieval.
Template types (Optional) — The types of content item to retrieve, based on the
type
attribute of the cartridge template used to create it. For example, a Record Spotlight slot in the Discover Electronics reference application is restricted to content items created from a template withtype="SecondaryContent"
.Template IDs (Optional) — The template IDs to match against. This is a narrower restriction than restricting by template
type
, and instead restricts based on a unique templateid
. For example, a Record Spotlight slot in the Discover Electronics reference application is restricted to content items created from a template withid="RecordSpotlight"
.Rule Limit — The number of matching content items to retrieve. This is applied after the above restrictions, and after checking for triggered content items.
When the list of possible content items has been narrowed down, the
ContentSlotHandler
issues a content trigger request.
This checks valid content items against any triggers defined in Experience
Manager. Trigger criteria can include:
The list of results is limited to triggered content items and ordered
by the priority assigned to each content item in Experience Manager. The number
of results is truncated to the value specified for the content slot (also
specified on
ContentSlotConfig
). The Assembler then processes the
content items and returns them in its response.
Content items may
contain other content items, which can include both
ContentInclude
references and
ContentSlotConfig
definitions
For example, in Discover Electronics the
/browse
path corresponds to a page within the
sitemap. The browse page consists of a content slot that references the Web
folder.
Most of the pages within the Web Browse Pages folder
contain a mixture of static and dynamic content items. As the Assembler
processes the query for
http://www.example.com/discover/browse
(assuming no
search terms or refinement selections), the following steps occur:
The Assembler is invoked with a
ContentInclude
item with the URI/pages/browse
.The Assembler invokes the
ContentIncludeHandler
to retrieve the configuration for the browse page, which is aContentSlotConfig
that specifies a single content item from the Three-Column Page collection.The Assembler invokes the
ContentSlotHandler
to retrieve the highest priority content item within the Three-Column Page collection. In this case, it is the Default Browse Page, which is aThreeColumnPage
.There is no cartridge handler configured to process the
ThreeColumnPage
, but it contains child content items, so the Assembler goes on to process the child content items:It passes the configuration for the search box cartridge through to the response object.
It invokes the
BreadcrumbsHandler
to process the breadcrumbs cartridge.It invokes the
ContentSlotHandler
to process the navigation slot, which in turn retrieves the Default Guided Navigation configuration from the Guided Navigation collection and invokesDimensionNavigationHandler
to process it.It invokes the
SearchAdjustmentsHandler
to process the search adjustments cartridge.It invokes the
ContentSlotHandler
to process the results list slot, which in turn retrieves the Default Results List configuration from the Results List collection and invokesResultsListHandler
to process it.It invokes the
RecordSpotlightHandler
to process the spotlight records.