@Version("1.14.0")

Package com.adobe.cq.dam.cfm

Defines the basic API for creating and managing Content Fragments.

Main purpose of this API is to abstract the corresponding content structure and to provide convenience methods to manage a fragment.

It is important to understand that this API supports two substantially different types of Content Fragments:

  • Template-based fragments were the first incarnation of Content Fragments. Their structure is defined by a template, the elements are supporting textual content only. Changes in the template that was used for creating a fragment are not reflected in existing fragments.
  • Model-based fragments were the next step in the evolution. Their structure is defined by a model that allows to define typed elements (or fields). Changes in models are propagated to all existing fragments sharing the updated model.

Due to that evolution, some of the names in the API might be confusing to users that only know model-based fragments.

For example, both models and templates are represented by implementations of FragmentTemplate, although the name of the interface might suggest otherwise.

This also means that the actual type of a fragment is transparent to the user of the API. Type-based operations are converted back and forth to plain Strings for template-based Content Fragments (as they are only supporting textual content).

Elements

  • A content fragment is represented by an instance of ContentFragment.
  • Each fragment contains content elements. Elements carry semantically distinctive parts of the fragment (e.g. a title and content elements of a typical news article, like a slug line, the article itself, or a desired publication date).
  • Each element can have multiple variations of its content. This can be used for creating longer or shorter versions of the text, depending on the context. For example, a shorter version may be provided for creating a Twitter-optimized version of the content.

Each template-based content fragment must have at least one element, but can consist of multiple elements. Model-based fragments can also have zero elements. Variations are completely optional for both types.

Content is managed both on the element and the variation level. This means: To access an element's text, first retrieve the element, then use the respective methods to access its content.

Typed data

Model-based fragments introduced the notion of typed data: Each element (or field) has a certain data type assigned to it. If necessary, data is coerced into the appropriate format, e.g. the String "2" is coerced into the Integer 2 for non-fractional numeric fields.

Typed data is also supported in a basic way for template-based fragments - internally, all data is stored as text, but if the value is accessed through the FragmentData interface, the types will be coerced if necessary.

Due to these historical differences, all objects that are used to access the content of a fragment have two different ways to access it:

  • getContent()/setContent() to access the respective content based on text (aka Strings)
  • getValue()/setValue() to access the same content in a type-aware manner

It's recommended to use getValue()/setValue() whenever possible, although nothing prevents one to use the other approach or even combine both. getContent()/setContent() is not supposed to support each single use-case the type-aware approach supports and might reject some usages by throwing a ContentFragmentException.

Usage patterns

To create a ContentFragment from a Sling resource, simply adapt the resource to ContentFragment.

After adapting the resource, you can access and manipulate the fragment using the respective methods of the API.

Manipulating data through getValue()setValue() works as follows:

  1. Get the FragmentData object through the respective element-specific or variation-specific variation of getValue()
  2. Manipulate the data through the methods of FragmentData
  3. Persist the manipulated data by passing the FragmentData object to the corresponding getValue() method (of the element or the variation).

Note that the API doesn't assume auto-commit. This means that you have to commit the org.apache.sling.api.resource.ResourceResolver explicitly after manipulating the fragment.

Concurrency

The API is not designed for sharing its objects between multiple threads. Therefore the user has to take care of correct synchronization should the use case require shared access.

References

The com.adobe.cq.dam.cfm.converter API provides means to create an HTML representation for content that leverages other formats like plain text or Markdown. It also supports converting HTML back to these other formats. Therefore, supporting any format into another format is supported by first converting the original format into HTML, then convert the HTML into the target format.

The com.adobe.cq.dam.cfm.content API is leveraged for post-processing the content of a fragment instance, before it eventually gets rendered within a specific context. "Fragment instance" in this case means a single occurrence of the fragment in a page (for example).

Template-based vs. model-based fragments - the details

Version 1.1 of the API introduces typed data and models, extending the purely text-based fragments, based on templates, of version 1.0.

The content structure of both fragment types are different. The API hides these differences from the user. As mentioned before, the actual type of a fragment is transparent to the user of this API.

Mapping of certain concepts of model-based fragments to interfaces of this API:

Links to FragmentTemplate and ElementTemplate
Concept Class
model FragmentTemplate
field ElementTemplate