Definitions
A content definition is a JSON schema v4 document that informs Cloud CMS of a new content type. The JSON schema semantics spell out the exact properties that a content type should have, the types of every element (such as whether a property is a string or a number), constraints and other nested aspects of the content type.
Definitions come in several flavors, the main ones being:
Cloud CMS lets you create adhoc content on the fly which means that you don't technically need definitions. You can just throw JSON content into Cloud CMS and everything works fine. However, definitions provide you with a structured way to automate server-side validation and data integrity checking ahead of write. This lets you assert that your data conforms to an expected schema.
If you create content that has a definition (i.e. a _type
property), the content will first run through JSON schema validation ahead of writing. If the JSON schema validation throws, the write is aborted and an error is returned.
Example
A content definition is just a node like any other node.
As a really simple example, you might define an article like this:
{
"_qname": "custom:article",
"_type": "d:type",
"type": "object",
"properties": {
"title": {
"type": "string"
},
"body": {
"type": "string"
},
"author": {
"type": "string",
"required": true
}
}
}
A content definition is simply a JSON schema document with a special _qname
property that identifies the definition's QName and a _type
property that indicates this is a type definition (d:type
). You might also choose to define an association (d:association
) or a feature (d:feature
).
With JSON schema, there's quite a lot you can do and the entirety of it isn't spelled out here. That said, Cloud CMS is fully complaint with v4 of the specification and so you can take full advantage of JSON schema to define your content types, constraints and properties.
QNames
A QName is a unique term within the Cloud CMS dictionary. The dictionary exists on a per-branch basis and is automatically recompiled every time you make a change to a definition. The compilation step wires together validation logic, behaviors and other runtime necessities so that your content is persisted properly going forward.
In Cloud CMS, every object has a QName. In most cases, this QName is auto-generated for you. For example, if you create a node and the node has ID 1234567890
, then by convention, it will be automatically assigned a QName of o:1234567890
.
A content definition explicitly declares its QName. In the example above, the content definition has a QName of custom:article
. Upon saving this node, the Cloud CMS dictionary will detect that a new type was added and will reserve the custom:article
namespace for this definition. Only one namespace is allowed per branch. If another definition comes along and tries to save itself as custom:article
, the save operation will fail.
Inheritance
Content definitions support inheritance. You can declare a new content definition that inherits from an existing definition. The new content definition will be bestowed with all of the properties, constraints and other aspects of the JSON schema from the parent definition. In addition, any behavioral bindings assigned to the parent will be ascribed to the child as well.
To do so, all you need to do is supply the _parent
attribute. Here is an example of a new article type that inherits from the previous one.
{
"_qname: "custom:article2",
"_type": "d:type",
"_parent": "custom:article",
"type": "object",
"properties": {
"score": {
"type": "number"
}
}
}
The new content type has a QName of custom:article2
and will inherit all of the properties and behaviors from custom:article
. In addition, it will define a new property called score
which is a number.
Properties
Cloud CMS supports the full range of JSON schema properties, constraints and validators. Properties can be nested as well and it is entirely encouraged that you use JSON to it's richest advantage. Cloud CMS will parse these properties at compile time and perform full validation across the entire JSON document.
Default Type (for ad-hoc content)
As mentioned, Cloud CMS supports ad-hoc content creation which means that you don't have to use definitions if you don't want to. Any ad-hoc created content will be of type n:node
. Content that is of type n:node
doesn't go through the same validation checks as custom content types.
Working with Definitions
You can work with definitions using Cloud CMS user interface, or using the Cloud CMS API within a programmatic fashion.
Cloud CMS
There are 2 choices in Cloud CMS on how to create and manage the Content Types:
- edit the JSON definition (simply go into your project, Manage Project, and click on Definitions menu item)
- use the Content Model Builder that makes it a bit easier to work with JSON schema. Check out the documentation on Content Model Builder.
Cloud CMS API
Let's look at some examples of working with definitions from the API.
Create a Definition
To create a definition, simply create a node like you normally would. Here is an example where we create the custom article from above.
// assume we have a branch
var branch = ...;
// create our definition
branch.createNode({
"_qname": "custom:article",
"_type": "d:type",
"type": "object",
"properties": {
"title": {
"type": "string"
},
"body": {
"type": "string"
},
"author": {
"type": "string",
"required": true
}
}
}).then(function() {
// ...
})
Afterwards, content instances of type custom:article
are created just as before. You only need to specify the _type
property of the new node.
// assume we have a branch
var branch = ...;
// create a few nodes
branch.createNode({
"_type": "custom:article",
"title": "Germany wins World Cup 2014",
"body": "...",
"author": "Franz Meuler"
});
branch.createNode({
"_type": "custom:article",
"title": "Bolivia training for World Cup 2018",
"body": "...",
"author": "Anita Barrios"
});
You can also query to find any nodes of type custom:article
.
// assume we have a branch
var branch = ...;
// find instances of type "custom:article"
branch.queryNodes({
"_type": "custom:article"
}).each(function() {
console.log("Found article: " + this.title);
});
Delete a Definition
To delete a definition, you find the node defining your definition and then delete it. Cloud CMS will handle all of the dictionary recompilation and will sort things out.
// assume we have a branch
var branch = ...;
// find our type (using it's qname) and then delete it
branch.queryNodes({
"_qname": "custom:article"
}).keepOne().del();
If there are existing content instances of type custom:article
, the attempt to delete the type will fail. The error message will indicate the IDs of the content instance nodes that must first be resolved. Those instances must either first be deleted or have their content type changed.
<a class='named-link' name='changing-a-content-instance's-type'>
Changing a Content Instance's Type
You can change a content instance's type at any time.
// assume we have a branch
var branch = ...;
// find instances of type "custom:article"
branch.queryNodes({
"_type": "custom:article"
}).each(function() {
// change each one back to n:node
this.changeTypeQName("n:node");
});
Default Content Definitions
Cloud CMS comes pre-installed with a library of ready-to-go definitions for a variety of cases.
Content Type Definitions
<thead>
<tr>
<th>QName</th>
<th>Title</th>
<th>Parent</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>blog:blog</td>
<td>Blog</td>
<td></td>
<td></td>
</tr>
<tr>
<td>blog:post</td>
<td>Blog Post</td>
<td></td>
<td></td>
</tr>
<tr>
<td>n:comment</td>
<td>Node</td>
<td>n:node</td>
<td>A comment</td>
</tr>
<tr>
<td>n:company</td>
<td>Comment</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>n:email_template</td>
<td>Email Template</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>n:form</td>
<td>Form</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>n:group</td>
<td>Group</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>n:heatmap</td>
<td>Heat Map</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>n:list</td>
<td>Data List</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>n:node</td>
<td>Node</td>
<td></td>
<td>A node</td>
</tr>
<tr>
<td>n:person</td>
<td>Person</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>n:role</td>
<td>Role</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>n:root</td>
<td>Root Node of Repository</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>n:rule</td>
<td>Rule</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>n:tag</td>
<td>Tag</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>wcm:page</td>
<td>WCM Page</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>wcm:template</td>
<td>WCM Page Template</td>
<td>n:node</td>
<td></td>
</tr>
<tr>
<td>workflow:package</td>
<td>Workflow Package</td>
<td>n:node</td>
<td></td>
</tr>
</tbody>
Association Type Definitions
<thead>
<tr>
<th>QName</th>
<th>Title</th>
<th>Parent</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>a:child</td>
<td>Child Association</td>
<td>a:owned</td>
<td></td>
</tr>
<tr>
<td>a:copied_from</td>
<td>Copied From Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:created</td>
<td>Created Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:deems_helpful</td>
<td>Deems Helpful Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:deems_spam</td>
<td>Deems Spam Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:deems_unhelpful</td>
<td>Deems Unhelpful Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:deleted</td>
<td>Deleted Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:dislikes</td>
<td>Dislikes Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:has_behavior</td>
<td>Has Behavior Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:has_comment</td>
<td>Has Comment Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:has_form</td>
<td>Has Form Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:has_lock</td>
<td>Has Lock Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:has_mount</td>
<td>Has Mount Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:has_rendition</td>
<td>Has Rendition Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:has_role</td>
<td>Has Role Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:has_tag</td>
<td>Has Tag Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:has_translation</td>
<td>Has Translation Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:likes</td>
<td>Likes Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>a:linked</td>
<td>Linked Association</td>
<td>n/a</td>
<td></td>
</tr>
<tr>
<td>a:list_item</td>
<td>List Item Association</td>
<td>a:owned</td>
<td></td>
</tr>
<tr>
<td>a:owned</td>
<td>Owned Association</td>
<td>n/a</td>
<td></td>
</tr>
<tr>
<td>a:updated</td>
<td>Updated Association</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>wcm:page_has_content</td>
<td>WCM Page has Content</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>workflow:package_has_item</td>
<td>Workflow Package has Item</td>
<td>a:linked</td>
<td></td>
</tr>
<tr>
<td>blog:has_post</td>
<td>Blog has Post</td>
<td>a:linked</td>
<td></td>
</tr>
</tbody>
Feature Definitions
For information on feature definitions and their use, check out Features.