eXo Platform 3.5

## Chapter 9. NodeType Registration

eXo JCR implementation supports two ways of Nodetypes registration:

- From a NodeTypeValue POJO

- From an XML document (stream)

## Interfaces and methods

### ExtendedNodeTypeManager

The ExtendedNodeTypeManager (from JCR 1.11) interface provides the following methods related to registering node types:

    public static final int IGNORE_IF_EXISTS  = 0;

    public static final int FAIL_IF_EXISTS    = 2;

    public static final int REPLACE_IF_EXISTS = 4;

    /**

     * Registers node type using value object.

     */

    void registerNodeType(NodeTypeValue nodeTypeValue, int alreadyExistsBehaviour) throws RepositoryException;

    /**

     * Registers all node types using XML binding value objects from xml stream.

     */

    void registerNodeTypes(InputStream xml, int alreadyExistsBehaviour) throws RepositoryException;

    /**

     * Return <code>NodeTypeValue</code> for a given nodetype name. Used for

     * nodetype update. Value can be edited and registered via

     * <code>registerNodeType(NodeTypeValue nodeTypeValue, int alreadyExistsBehaviour)</code>

     */

    NodeTypeValue getNodeTypeValue(String ntName) throws NoSuchNodeTypeException, RepositoryException;

    /**

     * Registers or updates the specified <code>Collection</code> of

     * <code>NodeTypeValue</code> objects.

     */

    public NodeTypeIterator registerNodeTypes(Collection<NodeTypeValue> values,

                                                int alreadyExistsBehaviour) throws UnsupportedRepositoryOperationException,

                                                                           RepositoryException;

    /**

     * Unregisters the specified node type.

     */

    public void unregisterNodeType(String name) throws UnsupportedRepositoryOperationException,

                                                 NoSuchNodeTypeException,

                                                 RepositoryException;

    /**

     * Unregisters the specified set of node types.<p/> Used to unregister a set

     * of node types with mutual dependencies.

     */

    public void unregisterNodeTypes(String[] names) throws UnsupportedRepositoryOperationException,

                                                     NoSuchNodeTypeException,

                                                     RepositoryException;

### NodeTypeValue

The NodeTypeValue interface represents a simple container structure used to define node types which are then registered through the ExtendedNodeTypeManager.registerNodeType method. The implementation of this interface does not contain any validation logic.

    /**

     * @return Returns the declaredSupertypeNames.

     */

    public List<String> getDeclaredSupertypeNames();

    /**

     * @param declaredSupertypeNames

     *The declaredSupertypeNames to set.

     */

    public void setDeclaredSupertypeNames(List<String> declaredSupertypeNames);

    /**

     * @return Returns the mixin.

     */

    public boolean isMixin();

    /**

     * @param mixin

     *The mixin to set.

     */

    public void setMixin(boolean mixin);

    /**

     * @return Returns the name.

     */

    public String getName();

    /**

     * @param name

     *The name to set.

     */

    public void setName(String name);

    /**

     * @return Returns the orderableChild.

     */

    public boolean isOrderableChild();

    /**

     * @param orderableChild

     *The orderableChild to set.

     */

    public void setOrderableChild(boolean orderableChild);

    /**

     * @return Returns the primaryItemName.

     */

    public String getPrimaryItemName();

    /**

     * @param primaryItemName

     *The primaryItemName to set.

     */

    public void setPrimaryItemName(String primaryItemName);

    /**

     * @return Returns the declaredChildNodeDefinitionNames.

     */

    public List<NodeDefinitionValue> getDeclaredChildNodeDefinitionValues();

    /**

     * @param declaredChildNodeDefinitionNames

     *The declaredChildNodeDefinitionNames to set.

     */

    public void setDeclaredChildNodeDefinitionValues(List<NodeDefinitionValue> declaredChildNodeDefinitionValues);

    /**

     * @return Returns the declaredPropertyDefinitionNames.

     */

    public List<PropertyDefinitionValue> getDeclaredPropertyDefinitionValues();

    /**

     * @param declaredPropertyDefinitionNames

     *The declaredPropertyDefinitionNames to set.

     */

    public void setDeclaredPropertyDefinitionValues(List<PropertyDefinitionValue> declaredPropertyDefinitionValues);

### NodeDefinitionValue

The NodeDefinitionValue interface extends ItemDefinitionValue with the addition of writing methods, enabling the characteristics of a child node definition to be set, after that the NodeDefinitionValue is added to a NodeTypeValue.

    /**

     * @return Returns the declaredSupertypeNames.

     */

    public List<String> getDeclaredSupertypeNames();

    /**

     * @param declaredSupertypeNames

     *The declaredSupertypeNames to set.

     */

    public void setDeclaredSupertypeNames(List<String> declaredSupertypeNames);

    /**

     * @return Returns the mixin.

     */

    public boolean isMixin();

    /**

     * @param mixin

     *The mixin to set.

     */

    public void setMixin(boolean mixin);

    /**

     * @return Returns the name.

     */

    public String getName();

    /**

     * @param name

     *The name to set.

     */

    public void setName(String name);

    /**

     * @return Returns the orderableChild.

     */

    public boolean isOrderableChild();

    /**

     * @param orderableChild

     *The orderableChild to set.

     */

    public void setOrderableChild(boolean orderableChild);

    /**

     * @return Returns the primaryItemName.

     */

    public String getPrimaryItemName();

    /**

     * @param primaryItemName

     *The primaryItemName to set.

     */

    public void setPrimaryItemName(String primaryItemName);

    /**

     * @return Returns the declaredChildNodeDefinitionNames.

     */

    public List<NodeDefinitionValue> getDeclaredChildNodeDefinitionValues();

    /**

     * @param declaredChildNodeDefinitionNames

     *The declaredChildNodeDefinitionNames to set.

     */

    public void setDeclaredChildNodeDefinitionValues(List<NodeDefinitionValue> declaredChildNodeDefinitionValues);

    /**

     * @return Returns the declaredPropertyDefinitionNames.

     */

    public List<PropertyDefinitionValue> getDeclaredPropertyDefinitionValues();

    /**

     * @param declaredPropertyDefinitionNames

     *The declaredPropertyDefinitionNames to set.

     */

    public void setDeclaredPropertyDefinitionValues(List<PropertyDefinitionValue> declaredPropertyDefinitionValues);

### PropertyDefinitionValue

The PropertyDefinitionValue interface extends ItemDefinitionValue with the addition of writing methods, enabling the characteristics of a child property definition to be set, after that the PropertyDefinitionValue is added to a NodeTypeValue.

    /**

     * @return Returns the defaultValues.

     */

    public List<String> getDefaultValueStrings();

    /**

     * @param defaultValues The defaultValues to set.

     */

    public void setDefaultValueStrings(List<String> defaultValues);

    /**

     * @return Returns the multiple.

     */

    public boolean isMultiple();

    /**

     * @param multiple The multiple to set.

     */

    public void setMultiple(boolean multiple);

    /**

     * @return Returns the requiredType.

     */

    public int getRequiredType();

    /**

     * @param requiredType The requiredType to set.

     */

    public void setRequiredType(int requiredType);

    /**

     * @return Returns the valueConstraints.

     */

    public List<String> getValueConstraints();

    /**

     * @param valueConstraints The valueConstraints to set.

     */

    public void setValueConstraints(List<String> valueConstraints);

### ItemDefinitionValue

     /**

     * @return Returns the autoCreate.

     */

    public boolean isAutoCreate();

    /**

     * @param autoCreate The autoCreate to set.

     */

    public void setAutoCreate(boolean autoCreate);

    /**

     * @return Returns the mandatory.

     */

    public boolean isMandatory();

    /**

     * @param mandatory The mandatory to set.

     */

    public void setMandatory(boolean mandatory);

    /**

     * @return Returns the name.

     */

    public String getName();

    /**

     * @param name The name to set.

     */

    public void setName(String name);

    /**

     * @return Returns the onVersion.

     */

    public int getOnVersion();

    /**

     * @param onVersion The onVersion to set.

     */

    public void setOnVersion(int onVersion);

    /**

     * @return Returns the readOnly.

     */

    public boolean isReadOnly();

    /**

     * @param readOnly The readOnly to set.

     */

    public void setReadOnly(boolean readOnly);

## Node type registration

eXo JCR implementation supports various methods of the node-type registration.

### Run time registration from xml file.

    ExtendedNodeTypeManager nodeTypeManager = (ExtendedNodeTypeManager) session.getWorkspace()

                                                                 .getNodeTypeManager();

    InputStream is = MyClass.class.getResourceAsStream("mynodetypes.xml");

    nodeTypeManager.registerNodeTypes(is,ExtendedNodeTypeManager.IGNORE_IF_EXISTS );

### Run time registration using NodeTypeValue.

    ExtendedNodeTypeManager nodeTypeManager = (ExtendedNodeTypeManager) session.getWorkspace()

                                                                 .getNodeTypeManager();

    NodeTypeValue testNValue = new NodeTypeValue();

    List<String> superType = new ArrayList<String>();

    superType.add("nt:base");

    testNValue.setName("exo:myNodeType");

    testNValue.setPrimaryItemName("");

    testNValue.setDeclaredSupertypeNames(superType);

    List<PropertyDefinitionValue> props = new ArrayList<PropertyDefinitionValue>();

    props.add(new PropertyDefinitionValue("*",

                                          false,

                                          false,

                                          1,

                                          false,

                                          new ArrayList<String>(),

                                          false,

                                          0,

                                          new ArrayList<String>()));

    testNValue.setDeclaredPropertyDefinitionValues(props);

    nodeTypeManager.registerNodeType(testNValue, ExtendedNodeTypeManager.FAIL_IF_EXISTS);

## Changing existing node type

If you want to replace existing node type definition, you should pass ExtendedNodeTypeManager.REPLACE_IF_EXISTS as a second parameter for the method ExtendedNodeTypeManager.registerNodeType.

    ExtendedNodeTypeManager nodeTypeManager = (ExtendedNodeTypeManager) session.getWorkspace()

                                                                               .getNodeTypeManager();

    InputStream is = MyClass.class.getResourceAsStream("mynodetypes.xml");

    .....

    nodeTypeManager.registerNodeTypes(is,ExtendedNodeTypeManager.REPLACE_IF_EXISTS );

## Removing node type

### Note

Node type is only possibly removed when the repository does not contain this node type.

    nodeTypeManager.unregisterNodeType("myNodeType");

## Practical How to

### Adding new PropertyDefinition

    NodeTypeValue myNodeTypeValue = nodeTypeManager.getNodeTypeValue(myNodeTypeName);

    List<PropertyDefinitionValue> props = new ArrayList<PropertyDefinitionValue>();

    props.add(new PropertyDefinitionValue("tt",

                                          true,

                                          true,

                                          1,

                                          false,

                                          new ArrayList<String>(),

                                          false,

                                          PropertyType.STRING,

                                          new ArrayList<String>()));

    myNodeTypeValue.setDeclaredPropertyDefinitionValues(props);

    nodeTypeManager.registerNodeType(myNodeTypeValue, ExtendedNodeTypeManager.REPLACE_IF_EXISTS);

### Adding new child NodeDefinition

    NodeTypeValue myNodeTypeValue = nodeTypeManager.getNodeTypeValue(myNodeTypeName);

    List<NodeDefinitionValue> nodes = new ArrayList<NodeDefinitionValue>();

    nodes.add(new NodeDefinitionValue("child",

                                          false,

                                          false,

                                          1,

                                          false,

                                          "nt:base",

                                          new ArrayList<String>(),

                                          false));

    testNValue.setDeclaredChildNodeDefinitionValues(nodes);

    nodeTypeManager.registerNodeType(myNodeTypeValue, ExtendedNodeTypeManager.REPLACE_IF_EXISTS);

### Changing or removing existing PropertyDefinition or child NodeDefinition

Note that the existing data must be consistent before changing or removing a existing definition . JCR does not allow you to change the node type in the way in which the existing data would be incompatible with a new node type. But if these changes are needed, you can do it in several phases, consistently changing the node type and the existing data.

For example:

Add a new residual property definition with name "downloadCount" to the existing node type "myNodeType".

There are two limitations that do not allow us to make the task with a single call of registerNodeType method.

- Existing nodes of the type "myNodeType", which does not contain properties "downloadCount" that conflicts with node type what we need.

- Registered node type "myNodeType" will not allow us to add properties "downloadCount" because it has no such specific properties.

To complete the task, we need to make 3 steps:

- Change the existing node type "myNodeType" by adding the mandatory property "downloadCount".

- Add the node type "myNodeType" with the property "downloadCount" to all the existing node types.

- Change the definition of the property "downloadCount" of the node type "myNodeType" to mandatory.

### Changing the list of super types

    NodeTypeValue testNValue = nodeTypeManager.getNodeTypeValue("exo:myNodeType");

    List<String> superType  = testNValue.getDeclaredSupertypeNames();

    superType.add("mix:versionable");

    testNValue.setDeclaredSupertypeNames(superType);

    nodeTypeManager.registerNodeType(testNValue, ExtendedNodeTypeManager.REPLACE_IF_EXISTS);