The Compact Namespace and Node Type Definition (CND) notation provides a compact standardized syntax for defining node types and making namespace declarations. The notation is intended both for documentation and for programmatically registering node types (if you are unfamiliar with JCR node types, you may want to read the general Node Types section first).

Here is a "worst-case scenario" example that demonstrates all the features of the notation:

/*  An example node type definition */

// The namespace declaration
<ns = 'http://namespace.com/ns'>

// Node type name
[ns:NodeType]

// Supertypes
> ns:ParentType1, ns:ParentType2

// This node type supports orderable child nodes
orderable

// This is a mixin node type
mixin

// Nodes of this node type have a property called 'ex:property' of type

STRING - ex:property (string)

// The default values for this
// (multi-value) property are...
= 'default1', 'default2'

// This property is the primary item
primary

// and it is...
mandatory autocreated protected

// and multi-valued
multiple

// It has an on-parent-version setting of ...
version

// The constraint settings are...
< 'constraint1', 'constraint2'

// Nodes of this node type have a child node called ns:node which must be

of // at least the node types ns:reqType1 and ns:reqType2 + ns:node (ns:reqType1, ns:reqType2)

// and the default primary node type of the child node is...
= ns:defaultType

// This child node is...
mandatory autocreated protected

// and supports same name siblings
multiple

// and has an on-parent-version setting of ...
version

This definition can be written more compactly and with indentation:

/*  An example node type definition */
<ns = 'http://namespace.com/ns'>
[ns:NodeType]

ns:ParentType1, ns:ParentType2 orderable mixin - ex:property (string) = 'default1', 'default2' primary mandatory autocreated protected multiple version < 'constraint1', 'constraint2' + ns:node (ns:reqType1, ns:reqType2) = ns:defaultType mandatory autocreated protected multiple version

or, using short forms for the attributes, even like this:

<ns='http://namespace.com/ns'>
[ns:NodeType]

ns:ParentType1, ns:ParentType2 o m -ex:property='default1','default2' ! m a p * version <'constraint1', 'constraint2' +ns:node(ns:reqType1,ns:reqType2)=ns:defaultType m a p * version

Grammar

The following grammar defines the CND notation. Terminal symbols are in double quotes.

ns_mapping ::= "<" prefix "=" uri ">"

prefix ::= string

uri ::= string

node_type_def ::= node_type_name [supertypes]

[options] {property_def | child_node_def}

"

options ::= orderable_opt | mixin_opt | orderable_opt
        mixin_opt | mixin_opt orderable_opt

orderable_opt ::= "orderable" | "ord" | "o"

mixin_opt ::= "mixin" | "mix" | "m"

property_def ::= "-" property_name [property_type_decl]
 [default_values]

[attributes] [value_constraints]

property_type_decl ::= "(" property_type ")"

property_type ::= "STRING" | "String" |"string" |
          "BINARY" | "Binary" | "binary" |
          "LONG" | "Long" | "long" |
          "DOUBLE" | "Double" | "double" |
          "BOOLEAN" | "Boolean" | "boolean" |
          "DATE" | "Date" | "date" |
          "NAME | "Name | "name" |
          "PATH" | "Path" | "path" |
          "REFERENCE" | "Reference" |
             "reference" |
          "UNDEFINED" | "Undefined" |
             "undefined" | "*"

default_values ::= "=" string_list

value_constraints ::= "<" string_list

node_def ::= "+" node_name [required_types]
 [default_type]

[attributes]

required_types ::= "(" string_list ")"

default_type ::= "=" string

attributes ::= "primary" | "pri" | "!" |
           "autocreated" | "aut" | "a" |
           "mandatory" | "man" | "m" |
           "protected" | "pro" | "p" |
           "multiple" | "mul" | "*" |
           "COPY" | "Copy" | "copy" |
           "VERSION" | "Version" | "version" |
           "INITIALIZE" | "Initialize" |
          "initialize" |
           "COMPUTE" | "Compute" | "compute" |
           "IGNORE" | "Ignore" | "ignore" |
           "ABORT" | "Abort" | "abort"

string_list ::= string {"," string}

string ::= quoted_string | unquoted_string

quoted_string :: = "'" unquoted_string "'"

unquoted_string ::= [A-Za-z0-9:_]

+

CND Notation in Detail

A CND consists of zero or more blocks, each of which is either namespace declaration or a node type definition. Namespace prefixes referenced in a node type definition block must be declared in a preceding namespace declaration block.

Namespace Declaration

prefix ::= string

uri ::= string

A namespace declaration consists of prefix/URI pair. The prefix must be a valid JCR namespace prefix, which is the same as a valid XML namespace prefix. The URI can in fact be any string. Just as in XML, it need not actually be a URI, though adhering to that convention is recommended.

Node Type Definition

[options] {property_def | child_node_def}

A node type definition consists of a node type name followed by an optional supertypes block, an optional options block and zero or more blocks, each either a property or node definition.

Node Type Name

"

The node type name is delimited by square brackets and must be a valid JCR name. It may be single-quoted (see Quoting, below). This element is the only strictly required element within a node type definition, though a definition consisting only of a node type name would simply define a new node type identical to nt:base.

Supertypes

After the node type name comes the optional list of supertypes. If this element is not present and the node type is not a mixin (see ?1.3.5 Options), then a supertype of nt:base is assumed. If present, the element consists of a greater-than sign followed by a comma delimited list of node type names, each of which may optionally be single-quoted (see Quoting below). In Jackrabbit, multiple inheritance of node types is supported, so this list can be greater than one item in length.

Options

        mixin_opt | mixin_opt orderable_opt

orderable_opt ::= "orderable" | "ord" | "o"

mixin_opt ::= "mixin" | "mix" | "m"

The option indicators follow the node type name and optional supertype list.

If the keyword orderable (or a short form) is present, then the orderable child node setting of the node type is true. If the keyword is missing, then the setting is false.

If the keyword mixin (or a short form) is present, then this is a mixin node type. If the keyword is missing, then this is a primary node type.

Property Definition

 [default_values]

[attributes] [value_constraints]

A property definition consists of a minus sign followed by a property name, followed in turn by optional elements defining the property type, the default values, the property attributes and the value constraints.

Property Name

The property name must be a valid JCR name or *, to indicate a residual property definition. It may be single-quoted.

Property Type

property_type ::= "STRING" | "String |"string" |
          "BINARY" | "Binary" | "binary" |
          "LONG" | "Long" | "long" |
          "DOUBLE" | "Double" | "double" |
          "BOOLEAN" | "Boolean" | "boolean" |
          "DATE" | "Date" | "date" |
          "NAME | "Name | "name" |
          "PATH" | "Path" | "path" |
          "REFERENCE" | "Reference" | "reference" |
          "UNDEFINED" | "Undefined" | "undefined" | "*"

The property type is indicated by a keyword delimited by parentheses. If the property type declaration is missing a type of STRING is assumed.

Default Values

The default value or values, in the case of a multi-value property, are indicated by an equal sign followed by either a single value in string form or a comma-delimited list of values. The values may be single-quoted. If the default value definition is missing then no default value is set.

Attributes

           "autocreated" | "aut" | "a" |
           "mandatory" | "man" | "m" |
           "protected" | "pro" | "p" |
           "multiple" | "mul" | "*" |
           "COPY" | "Copy" | "copy" |
           "VERSION" | "Version" | "version" |
           "INITIALIZE" | "Initialize" | "initialize" |
           "COMPUTE" | "Compute" | "compute" |
           "IGNORE" | "Ignore" | "ignore" |
           "ABORT" | "Abort" | "abort"

The attribute indicators describe the characteristics of the property. The presence of an attribute keyword indicates that the corresponding characteristic applies to this property. It's absence indicates that the corresponding characteristic does not apply.

The primary keyword indicates that this property is the primary item. It may appear on a maximum of one property or child node definition within a node type definition.

The multiple keyword indicates that this property is multi-valued.

A maximum of one on-version indicator may be present. If none is present then an on-version setting of COPY is assumed.

Value Constraints

Value constraint are specified by a less-than sign followed by a comma-delimited list of constraint strings, each optionally single-quoted.

Child Node Definition

 [default_type]

[attributes]

A child node definition consists of a plus sign followed by a property name, followed in turn by optional elements defining the required primary node types, the default node type, and the node attributes.

Node Name

The node name must be a valid JCR name or *, to indicate a residual child node definition. It may be single-quoted.

Required Primary Node Types

The required node types of the child node are indicated by a comma-delimited list of node types, within parentheses. If this element is missing then a required primary node type of nt:base is assumed. This is the least restrictive setting possible.

Default Primary Node Type

The default primary node type is indicated by an equals-sign followed by a node type name, which may be single-quoted. If this element is missing then no default primary node type is set.

Attributes

           "autocreated" | "aut" | "a" |
           "mandatory" | "man" | "m" |
           "protected" | "pro" | "p" |
           "multiple" | "mul" | "*" |
           "COPY" | "Copy" | "copy" |
           "VERSION" | "Version" | "version" |
           "INITIALIZE" | "Initialize" | "initialize" |
           "COMPUTE" | "Compute" | "compute" |
           "IGNORE" | "Ignore" | "ignore" |
           "ABORT" | "Abort" | "abort"

The attribute indicators describe the characteristics of the child node. The presence of an attribute keyword indicates that the corresponding characteristic applies to this child node. It's absence indicates that the corresponding characteristic does not apply.

The primary keyword indicates that this child node is the primary item. It may appear on a maximum of one property or child node definition within a node type definition.

The multiple keyword indicates that this child node may have same-name siblings.

A maximum of one on-version indicator may be present. If none is present then an on-version setting of COPY is assumed.

Quoting

string ::= quoted_string | unquoted_string

quoted_string :: = "'" unquoted_string "'"

unquoted_string ::= /* a string */

Single quotes (') are used to allow for strings (i.e., names, prefixes, URIs, values or constraint strings) with characters that would otherwise be interpreted as delimiters.

Escaping

The standard Java escape sequences are also supported:

\n newline
\t tab
\b backspace
\f form feed
\r return
\" double quote
\' single quote
\\ back slash
\uHHHH Unicode character in hexadecimal

Comments

Comment can also be included in the notation using either of the standard Java forms:

// A comment

/* Another comment */

Whitespace and Short Forms

The notation can be compacted by taking advantage of the following the fact that spacing around keychars (

, - ( ) = <), newlines and indentation are not required. So, the following is also well-formed:

[x]

y,z orderable mixin -p(date)=a,b primary mandatory autocreated protected multiple version <c,d

Additionally, though spaces are required around the keywords (orderable, mixin, date, mandatory, etc.), short forms for keywords can be used. So, this:

[x]

y,z o m-p(date)=a,b ! m a p * version <c,d

is well-formed (but perhaps not recommended!).

Why this Weird Notation?

Here's why:

Old Documentation Notation

Here is the definition of the built-in node type nt:resource using the old documentation notation (used in v1.0 of the JCR specification, for example):

NodeTypeName
  nt:resource
Supertypes
  nt:base
  mix:referenceable
IsMixin
  false
HasOrderableChildNodes
  false
PrimaryItemName
  jcr:data
PropertyDefinition
  Name jcr:encoding
  RequiredType STRING
  ValueConstraints []
  DefaultValues null
  AutoCreated false
  Mandatory false
  OnParentVersion COPY
  Protected false
  Multiple false
PropertyDefinition
  Name jcr:mimeType
  RequiredType STRING
  ValueConstraints []
  DefaultValues null
  AutoCreated false
  Mandatory true
  OnParentVersion COPY
  Protected false
  Multiple false
PropertyDefinition
  Name jcr:data
  RequiredType BINARY
  ValueConstraints []
  DefaultValues null
  AutoCreated false
  Mandatory true
  OnParentVersion COPY
  Protected false
  Multiple false
PropertyDefinition
  Name jcr:lastModified
  RequiredType DATE
  ValueConstraints []
  DefaultValues null
  AutoCreated false
  Mandatory true
  OnParentVersion IGNORE
  Protected false
  Multiple false

Old Configuration Notation

Here is the same node type in the standard XML notation (used in configuration files in the Jackrabbit project, for example):

<nodeType name="nt:resource"
      isMixin="false"
      hasOrderableChildNodes="false"
      primaryItemName="jcr:data">
    <supertypes>
    <supertype>nt:base</supertype>
    <supertype>mix:referenceable</supertype>
    </supertypes>
    <propertyDefinition name="jcr:encoding"
            requiredType="String"
            autoCreated="false"
            mandatory="false"
            onParentVersion="COPY"
            protected="false"
            multiple="false"/>
    <propertyDefinition name="jcr:mimeType"
            requiredType="String"
            autoCreated="false"
            mandatory="true"
            onParentVersion="COPY"
            protected="false"
            multiple="false"/>
    <propertyDefinition name="jcr:data"
            requiredType="Binary"
            autoCreated="false"
            mandatory="true"
            onParentVersion="COPY"
            protected="false"
            multiple="false"/>
    <propertyDefinition name="jcr:lastModified"
            requiredType="Date"
            autoCreated="false"
            mandatory="true"
            onParentVersion="IGNORE"
            protected="false"
            multiple="false"/>
</nodeType>

New Format

And, here it is in the new CND notation:

[nt:resource]

mix:referenceable - jcr:encoding - jcr:mimeType mandatory - jcr:data (binary) mandatory - jcr:lastModified (date) mandatory ignore

Case closed.

Syntax hightlighting for text editors

Here is a TextMate bundle for CND syntax highlighting: ^CND.zip