Document Modelling

Document Model - Terms, Concepts and Interrelationships

Learn about the terms, concepts and interrelationships of a Sophora data model.

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.

Overview of document model terms in different contexts
TermSophora-APIJCR/CNDSpring Data SophoraComment
DocumentISophoraDocumentNode of a document type and its childnodesSophoraDocumentEntitySophora object/entity
Document typeNodeTypeNode type with "sophora-mix:document"Every document type is a node type.
NodeINodeNode of a node typeSophoraEntity (SophoraDocumentEntity or SophoraChildnodeEntity)Root node of a document or one of its childnodes.
Node typeNodeTypeNode type@NodeTypeNot every node type is a document type. There are also reference types, group types, table row types, ...
Mixin-Mixin@MixinSet of property definitions and childnode definitions that can be added to a node type
PropertyIProperty (+ IValue)PropertyData field in a node
ChildnodeINodeNodeSophoraChildnodeEntityA component, component box, table row, ...
ReferenceReferenceValueProperty of type "reference"ReferenceThere are "direct" references and components.
ComponentComponentNode of a node type that extends "sophora-nt:reference"ReferenceEntityThe node type of a component is called the "reference type". The node is called a "reference node".
Component groupComponentGroup-Generic term for component list and component box
Component listComponentList-Does not exist at node and JCR level.
Component boxComponentBoxNode of a node type that extends "sophora-extension-nt:group"GroupThe 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.

A homepage document in the document editor of the Sophora DeskClient
A homepage document in the document editor of the Sophora DeskClient

The node structure of the homepage document above is shown in the following screenshot.

Node structure of a homepage document
Node structure of a homepage document

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.

Node type diagram of a homepage document
Node type diagram of a homepage document

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> {
}

Last modified on 7/16/21

The content of this page is licensed under the CC BY 4.0 License. Code samples are licensed under the MIT License.

Icon