When creating and talking about data models in Sophora, different terms are used depending on the level of detail and context, which mean the same things, specialise or are related to each other. These terms and their interrelationships are explained here. At the end, an example including code snippets should also help to clarify the picture.
Overview
The following table shows the terms commonly used in the Sophora DeskClient and Sophora documentation in different contexts.
Term | Sophora-API | JCR/CND | Spring Data Sophora | Comment |
---|---|---|---|---|
Document | ISophoraDocument | Node of a document type and its childnodes | SophoraDocumentEntity | Sophora object/entity |
Document type | NodeType | Node type with "sophora-mix:document " | Every document type is a node type. | |
Node | INode | Node of a node type | SophoraEntity (SophoraDocumentEntity or SophoraChildnodeEntity) | Root node of a document or one of its childnodes. |
Node type | NodeType | Node type | @NodeType | Not every node type is a document type. There are also reference types, group types, table row types, ... |
Mixin | - | Mixin | @Mixin | Set of property definitions and childnode definitions that can be added to a node type |
Property | IProperty (+ IValue) | Property | Data field in a node | |
Childnode | INode | Node | SophoraChildnodeEntity | A component, component box, table row, ... |
Reference | ReferenceValue | Property of type "reference " | Reference | There are "direct" references and components. |
Component | Component | Node of a node type that extends "sophora-nt:reference " | ReferenceEntity | The node type of a component is called the "reference type". The node is called a "reference node". |
Component group | ComponentGroup | - | Generic term for component list and component box | |
Component list | ComponentList | - | Does not exist at node and JCR level. | |
Component box | ComponentBox | Node of a node type that extends "sophora-extension-nt:group " | Group | The node type of a component box is called a "group type" or "box type". The node is called a "group node" or "box node". |
Document
In Sophora, documents are the objects/entities editors and administrators work with (index documents, article documents, configuration documents, ...). In documents, data and content are stored in a structured way. Sophora documents have their own life cycle, can be created, edited, saved, versioned, protected, released, published, set offline, deleted and restored. Export and import is possible, too.
Documents can be referenced to each other, either directly in a reference field or as a component. Typically, documents contain their own teaser content, usually a headline, a teaser text and a teaser image. These teaser contents can then be displayed in the website of the referencing document.
Technically, documents are instances (nodes) of a document type. Internally, documents are built up in a tree structure consisting of the document node (root of the document) and (several) child nodes, which in turn may have child nodes, etc. In each node, data is stored in properties.
To identify a document each Sophora document has 3 Ids:
- UUID: Automatically assigned, Sophora system-wide unique Id. E.g. "
837f36a9-b5f1-49c6-8558-ceb53405559b
" - External-Id: Id from a third party system, unique across Sophora systems. When a new document is created in Sophora, the UUID is assigned as External-Id (e.g. "
837f36a9-b5f1-49c6-8558-ceb53405559b
"). When importing a document from a third party system to Sophora, a system-wide unique Id must be assigned as External-Id (e.g. "imdb-image-of-the-movie-part-3
"). - Sophora-Id: Editorially definable, Sophora system-wide unique Id. It is composed of an Id stem and a number. The Id stem is editorially definable. The number is automatically added by the Sophora system. The Sophora Id is part of the URL of the Sophora document. E.g. "
hamburg-124
".
Document Type
A document type is a node type with the mixin "sophora-mix:document
".
Every document type is a node type, but not every node type is a document type.
Typical examples of document types are "index page" (or "homepage" or "overview"), "article" (or "story") and "image". However, document types can also be technically motivated, such as "filter" or "configuration".
Mixin
Mixins define a set of property definitions and childnode definitions that can be added to node types. In this way, different node types can be extended by the same properties and childnodes. E.g. the mixin "sophora-mix:document
" contains all the necessary fields to turn a node type into a document type (with state, id fields, life cycle properties, time control, ...).
Mixins have a name, which consists of a namespace and the actual name within the namespace. Both are separated by a colon. By convention, the namespace ends in "-mix
". E.g. "sophora-content-mix:teaserable
".
Node Type
Node types define which properties and child nodes can be stored in nodes of the respective node type. Each node has a node type.
Node types are used as document types, reference types, group types, table row types, ...
Node types have a name, which consists of a namespace and the actual name within the namespace. Both are separated by a colon. By convention, the namespace ends in "-nt
". E.g. "sophora-content-nt:story
".
In Sophora, node types can be configured via the node type configuration.
Node Type Configuration
Node types (and thus also document types) are configured via the node type configuration. Here it is determined how they are displayed in the UI (labels, icons, display in the search result, etc.), which input fields (properties/childnodes) appear on which form tab in the document editor, which values are permitted, which component groups exist, etc.
Node
A node a entity in which data is stored in a structured way. Each node has a name and a node type and may have properties and child nodes.
Depending on the node type, nodes can be the root node of a document (the document node) or a child node of the document, e.g. a reference node (component), a group/box node (component box), a table row node, ...
Property
A property is a data field for storing values of primitive data types (boolean, long, double, string, date, reference).
Properties have a name and a type. The name is composed of a namespace and the actual name within the namespace. Both are separated by a colon. In the CND, properties are marked with a "-
" and the type is in brackets behind it. E.g.
- "
- sophora-content:title (string)
", - "
- sophora-content:duration (long)
" or - "
- sophora:id (string)
".
In Sophora, properties are configured via their property configuration.
Property Configuration
In a property configuration, the display of a property in the UI is configured. Here, the input field type can be determined (text field, selection value field, date field, etc.), whether it is a mandatory field and which values are permitted. The same property can be configured differently in different uses.
Childnode
A childnode is a node below another node.
Childnodes have a name and a node type. The name is composed of a namespace and the actual name within the namespace. Both are separated by a colon. In the CND, childnodes are marked with a "+
" and the type is in brackets behind it. E.g.
- "
+ sophora-content:teaserImage (nt:base)
" or - "
+ sophora-content:teaserGroup (nt:base) multiple
".
In Sophora, childnodes are used to store more complex data structures (e.g. copytext or tables) or to map components and component groups.
Childnodes are configured via childnode configuration.
Childnode Configuration
In a childnode configuration, the display of a childnode in the UI is configured. Here, the input field type can be determined (copy text, dynamic table, ...) or a component structure can be set up and it can be specified which node types are permissible for the respective childnode. The same childnode can be configured differently in different uses.
Component
Components are references to (other) Sophora documents. In the document editor of the DeskClient they are displayed in the component structure and on the component tab.
In contrast to "direct" references, components offer the possibility to overwrite the contents of the referenced document and to store additional data at the reference. In the DeskClient this data is displayed in the component details of the document editor.
In addition, components can be time-controlled, which is made possible in the DeskClient on the scheduling tab of the document editor.
Technically, components are child nodes with a reference type.
All properties that are configured to the base tab in the node type configuration of a reference type appear in the DeskClient in the component details for a component. Properties that have the same name in the reference type as a property in the referenced document type overwrite the content from the referenced document. It is also possible to overwrite the components of a referenced document in the component structure using childnodes with the same name in the reference type and in the referenced document type.
Each component has a system-assigned, document-wide unique Childnode-Id.
Component Group
Component group is a generic term for the two technically different forms of component list and component box. Both are displayed in the document editor of the DeskClient in the component structure and on the component tab.
Component List
Components can be inserted into component lists.
Technically, component lists do not exist at node level or JCR/CND level, but are merely a visualized summary of reference nodes with the same name in the Sophora component model. This has the disadvantage that no properties can be set on these component groups.
Component Box
Components and other component boxes can be inserted into component boxes.
In contrast to component lists, component boxes have a node at node level and JCR/CND level under which the components and component boxes are located. For this reason component boxes may have a title or other domain specific properties.
Technically, component boxes are child nodes with a group type.
All properties that are configured to the base tab in the node type configuration of a group type appear in the DeskClient in the component details for a component. All childnodes of a component box that are configured also as component box appear in the component structure as sub component box of the component box.
Each component box has a system-assigned, document-wide unique Childnode-Id.
Reference
A reference to a (different) Sophora document.
Technically, this is always a property of the type "reference".
In Sophora, however, a distinction is made between "direct" references and components.
Direct references are simply realised as a reference property in the document type or in the node type of a dynamic table, e.g. "- sophora-content:indexDocument (reference)
".
Components, on the other hand, offer the possibility to overwrite the contents of the referenced document and to store additional data at the reference. But even there, the property "- sophora:reference (reference)
" is ultimately found in the node type "sophora-nt:reference
".
Reference Type
Reference types are node types derived from "sophora-nt:reference
".
Such types are used exclusively for components. By convention, these node types are named ending in "Ref
", e.g. "sophora-content-nt:storyRef
". Childnodes that have such a node type are also called reference nodes.
The node type "sophora-nt-reference
" defines the reference property "- sophora:reference (reference)
" as well as properties for time scheduling the component.
Group Type (Box Type)
Group types (or box types) are node types derived from "sophora-extension-nt:group
".
Such types are used exclusively for component boxes. By convention, these node types are named ending in "Group
", e.g. "sophora-content-nt:teaserGroup
". Childnodes that have such a node type are also called group nodes (or box nodes).
The node type "sophora-extension-nt:group
" defines a title property and a child node for the components in the component box.
Example
The following example sketches how to model articles on a homepage. For further information see the documentation about Document Modelling.
The node structure of the homepage document above is shown in the following screenshot.
Node types
CND of a homepage document type with properties for title and teasertext, a component list childnode for images and a component box childnode for teaser groups. The mixin "sophora-mix:document
" and the childnode configuration have to be set in the node type configuration.
<'nt'='http://www.jcp.org/jcr/nt/1.0'>
<'sophora-demo'='http://www.subshell.com/sophora-demo/1.0'>
<'sophora-demo-nt'='http://www.subshell.com/sophora-demo-nt/1.0'>
['sophora-demo-nt:homepage']
orderable
- 'sophora-demo:teasertext' (string)
- 'sophora-demo:title' (string)
+ 'sophora-demo:image' (nt:base) multiple
+ 'sophora-demo:teaserGroup' (nt:base) multiple
CND of an article document type with properties for title and teasertext, a component list childnode for images and a childnode for the copytext. The mixin "sophora-mix:document
" and the childnode configuration have to be set in the node type configuration.
<'nt'='http://www.jcp.org/jcr/nt/1.0'>
<'sophora-demo'='http://www.subshell.com/sophora-demo/1.0'>
<'sophora-demo-nt'='http://www.subshell.com/sophora-demo-nt/1.0'>
['sophora-demo-nt:artice']
orderable
- 'sophora-demo:teasertext' (string)
- 'sophora-demo:title' (string)
+ 'sophora-demo:copytext' (nt:base)
+ 'sophora-demo:image' (nt:base) multiple
CND of a reference type for articles (used as component). It is possible to override the title and teasertext of the referenced article. This reference type has to set in the node type configuration of the article document type.
<'sophora-demo'='http://www.subshell.com/sophora-demo/1.0'>
<'sophora-demo-nt'='http://www.subshell.com/sophora-demo-nt/1.0'>
<'sophora-nt'='http://www.subshell.com/sophora-nt/1.0'>
['sophora-demo-nt:articeRef'] > 'sophora-nt:reference'
orderable
- 'sophora-demo:teasertext' (string)
- 'sophora-demo:title' (string)
CND of a group type (box type) for articles in a homepage (used as component box). The concrete valid node types for the inherited childnode "sophora:extension:teaser
" have to be set in the node type configuration.
<'sophora-demo-nt'='http://www.subshell.com/sophora-demo-nt/1.0'>
<'sophora-extension-nt'='http://www.subshell.com/sophora-extension-nt/1.0'>
['sophora-demo-nt:teaserGroup'] > 'sophora-extension-nt:group'
orderable
The node type diagram shows the JCR/CND level of properties and childnodes of the homepage document and its referenced image and article documents.
Access content on API level
The following code sample shows how to access the content of the homepage document on node level.
import com.subshell.sophora.api.content.INode;
import com.subshell.sophora.client.ISophoraClient;
import com.subshell.sophora.client.ISophoraDocument;
import com.subshell.sophora.client.factories.SophoraClientBuilder;
import java.util.List;
import java.util.UUID;
public class ClientApiExample {
public static void main(String[] args) {
try (ISophoraClient client = SophoraClientBuilder.newBuilder("http://localhost:1196", "admin", "admin")
.login()
.build()) {
// get homepage document
UUID documentUuid = UUID.fromString("201f0629-c5bd-4527-a428-867cce861ce2");
ISophoraDocument document = client.getDocumentByUuid(documentUuid);
// get string property of homepage document
String title = document.getString("sophora-demo:title");
// get childnodes (component list)
List<INode> imageRefNodes = document.getNodesByName("sophora-demo:image");
for (INode imageRefNode : imageRefNodes) {
// get UUID of referenced image document
UUID referencedDocumentUuid = imageRefNode.getUUID("sophora:reference");
// get referenced image document
ISophoraDocument imageDocument = client.getDocumentByUuid(referencedDocumentUuid);
// ...
}
// get childnodes (component box)
List<INode> teaserGroupNodes = document.getNodesByName("sophora-demo:teaserGroup");
for (INode teaserGroupNode : teaserGroupNodes) {
// get string property of group
String groupTitle = teaserGroupNode.getString("sophora-extension:title");
// ...
// get childnodes (referenced documents of group)
List<INode> articleRefNodes = teaserGroupNode.getNodesByName("sophora-extension:teaser");
for (INode articleRefNode : articleRefNodes) {
// get UUID of referenced article document
UUID referencedDocumentUuid = articleRefNode.getUUID("sophora:reference");
// get referenced article document
ISophoraDocument articleDocument = client.getDocumentByUuid(referencedDocumentUuid);
// ...
}
}
}
}
}
To work with the component model instead of nodes you can use the ComponentsProvider
.
import com.subshell.sophora.client.ISophoraClient;
import com.subshell.sophora.client.ISophoraDocument;
import com.subshell.sophora.client.component.Component;
import com.subshell.sophora.client.component.ComponentBox;
import com.subshell.sophora.client.component.ComponentGroup;
import com.subshell.sophora.client.component.ComponentsProvider;
import com.subshell.sophora.client.factories.SophoraClientBuilder;
import java.util.List;
import java.util.UUID;
public class ComponentsProviderExample {
public static void main(String[] args) {
try (ISophoraClient client = SophoraClientBuilder.newBuilder("http://localhost:1196", "admin", "admin")
.login()
.build()) {
// get homepage document
UUID documentUuid = UUID.fromString("201f0629-c5bd-4527-a428-867cce861ce2");
ISophoraDocument document = client.getDocumentByUuid(documentUuid);
// get string property of homepage document
String title = document.getString("sophora-demo:title");
// get components of component groups
ComponentsProvider componentsProvider = new ComponentsProvider(document, client);
componentsProvider.loadElements();
List<ComponentGroup> componentGroups = componentsProvider.getGroups();
for (ComponentGroup componentGroup : componentGroups) {
if (componentGroup instanceof ComponentBox) {
// get title property of component box
ComponentBox componentBox = (ComponentBox) componentGroup;
String groupTitle = componentBox.getTitle();
// ...
}
List<Component> components = componentGroup.getChildComponents();
for (Component component : components) {
// get referenced document
ISophoraDocument referencedDocument = component.getDocument();
// ...
}
}
componentsProvider.dispose();
}
}
}
Access content with Spring Data Sophora
The Spring Data Sophora model classes for the node types above should look like the following code snippets. For further information see the documentation about Spring Data Sophora.
Model classes for document types (documents)
import com.subshell.sophora.spring.data.annotations.ChildNode;
import com.subshell.sophora.spring.data.annotations.NodeType;
import com.subshell.sophora.spring.data.annotations.PropertyNamespace;
import com.subshell.sophora.spring.data.repository.entities.SophoraDocumentEntity;
import java.util.ArrayList;
import java.util.List;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@NodeType(value = "sophora-demo-nt:homepage")
@PropertyNamespace("sophora-demo")
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class Homepage extends SophoraDocumentEntity {
private String teasertext;
private String title;
@ChildNode
private List<TeaserGroup> teaserGroup = new ArrayList<>();
@ChildNode
private List<ImageRef> image = new ArrayList<>();
}
import com.subshell.sophora.spring.data.annotations.ChildNode;
import com.subshell.sophora.spring.data.annotations.NodeType;
import com.subshell.sophora.spring.data.annotations.PropertyNamespace;
import com.subshell.sophora.spring.data.entities.copytext.Copytext;
import com.subshell.sophora.spring.data.repository.entities.SophoraDocumentEntity;
import java.util.ArrayList;
import java.util.List;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@NodeType(value = "sophora-demo-nt:article")
@PropertyNamespace("sophora-demo")
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class Article extends SophoraDocumentEntity {
private String teasertext;
private String title;
@ChildNode
private Copytext copytext;
@ChildNode
private List<ImageRef> image = new ArrayList<>();
}
Model classes for reference types (components)
import com.subshell.sophora.spring.data.annotations.NodeType;
import com.subshell.sophora.spring.data.annotations.PropertyNamespace;
import com.subshell.sophora.spring.data.entities.component.ReferenceEntity;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@NodeType("sophora-demo-nt:articleRef")
@PropertyNamespace("sophora-demo")
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ArticleRef extends ReferenceEntity<Article> {
private String teasertext;
private String title;
}
Model classes for group/box types (component boxes)
import com.subshell.sophora.spring.data.annotations.NodeType;
import com.subshell.sophora.spring.data.annotations.PropertyNamespace;
import com.subshell.sophora.spring.data.entities.component.Group;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@NodeType(value = "sophora-demo-nt:teaserGroup")
@PropertyNamespace("sophora-extension")
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TeaserGroup extends Group<Article> {
}