Fork me on GitHub

Binding Examples

This library can be used in any environment where JCR and Hippo Repository API are available. However, just for simiplicty, the following examples are assumed to run in Hippo Updater Editor (a.k.a Groovy Updater).

WARNING: If you run the following demo scripts in production or in system having too many content, then it might cause a critical system overhead or problems. So, run the following demo scripts in a local test environment or change the XPath query to narrow the search result to a resonably small amount.

Binding a document from JSON

The following example groovy script reads JSON data from parametersMap, creates a document through FolderWorkflow, binds ContentNode object to document variant nodes and finally commits the changes through a DocumentWorkflow.

Name: Import a document from JSON
Description: For demonstration purpose, this example groovy script (a) unmarshal ContentNode from JSON, (b) creates a document handle and variant node, and (c) binds the ContentNode to the document variant node.
XPath query: /jcr:root
Parameters:
{
  "destination": "/content/documents/administration/labels",
  "data" :
  {
    "name" : "examplemessages",
    "primaryType" : "resourcebundle:resourcebundle",
    "mixinTypes" : [ "mix:referenceable" ],
    "properties" : [ {
      "name" : "resourcebundle:descriptions",
      "type" : "STRING",
      "multiple" : true,
      "values" : [ "Example resource bundle document" ]
    }, {
      "name" : "resourcebundle:id",
      "type" : "STRING",
      "multiple" : false,
      "values" : [ "org.example.messages" ]
    }, {
      "name" : "hippotranslation:locale",
      "type" : "STRING",
      "multiple" : false,
      "values" : [ "document-type-locale" ]
    }, {
      "name" : "resourcebundle:messages",
      "type" : "STRING",
      "multiple" : true,
      "values" : [ "Example Header Message", "Example Footer Message" ]
    }, {
      "name" : "resourcebundle:keys",
      "type" : "STRING",
      "multiple" : true,
      "values" : [ "header.text", "footer.text" ]
    }, {
      "name" : "hippotranslation:id",
      "type" : "STRING",
      "multiple" : false,
      "values" : [ "e9703ff4-d522-4238-bf3b-6016f959e88c" ]
    } ],
    "nodes" : [ ]
  }
}
              
Script >>>
package org.hippoecm.frontend.plugins.cms.admin.updater

import org.onehippo.repository.update.BaseNodeUpdateVisitor
import java.util.*
import javax.jcr.query.*
import org.apache.commons.lang.*
import org.hippoecm.repository.api.*
import org.hippoecm.repository.standardworkflow.*
import org.onehippo.repository.documentworkflow.*
import org.onehippo.forge.content.pojo.binder.*
import org.onehippo.forge.content.pojo.binder.jcr.*
import org.onehippo.forge.content.pojo.common.jcr.*
import org.onehippo.forge.content.pojo.common.util.*
import org.onehippo.forge.content.pojo.model.*
import com.fasterxml.jackson.databind.*

class UpdaterTemplate extends BaseNodeUpdateVisitor {

    def jcrSession
    def contentNodeBinder
    def bindingFilter
    def objectMapper

    void initialize(Session jcrSession) {
        this.jcrSession = jcrSession

        contentNodeBinder = new DefaultJcrContentNodeBinder()

        bindingFilter = new DefaultContentNodeJcrBindingItemFilter()
        bindingFilter.addPropertyPathExclude("jcr:localizedName")
        bindingFilter.addPropertyPathExclude("jcr:path")
        bindingFilter.addPropertyPathExclude("hippostdpubwf:*")
        bindingFilter.addPropertyPathExclude("hippo:availability")
        bindingFilter.addPropertyPathExclude("hippo:paths")
        bindingFilter.addPropertyPathExclude("hippo:related")
        bindingFilter.addPropertyPathExclude("hippostd:holder")
        bindingFilter.addPropertyPathExclude("hippostd:state")
        bindingFilter.addPropertyPathExclude("hippostd:stateSummary")

        objectMapper = new ObjectMapper();
    }

    boolean doUpdate(Node node) {
        log.debug "Visiting node ${node.path}"

        // unmarshal JSON to a ContentNode first
        def destination = parametersMap["destination"]
        def dataJson = parametersMap["data"].toString()
        def contentNode = objectMapper.readValue(dataJson, ContentNode.class)

        // let's create a document under the specific destination folderNode by an auto-generated name like the following
        def newDocumentName = "examplemessages-" + System.currentTimeMillis()
        def destinationFolderNode = jcrSession.getNode(destination)

        // The following lines before invoking #bind(node, contentNode, bindingFilter) are just an example
        // to get a draft document variant in the end using hippo workflow api, only for demonstration purpose.

        // using hippo folder workflow api, add a document.
        WorkflowManager workflowManager = ((HippoWorkspace) jcrSession.getWorkspace()).getWorkflowManager()
        FolderWorkflow folderWorkflow = (FolderWorkflow) workflowManager.getWorkflow("embedded", destinationFolderNode)
        String documentVariantPath = folderWorkflow.add("new-document", "resourcebundle:resourcebundle", newDocumentName)

        // get the document handle first
        Node documentVariantNode = jcrSession.getNode(documentVariantPath)
        Node documentHandleNode = documentVariantNode.getParent()

        // get an editable workflow from the document handle node
        EditableWorkflow documentWorkflow = (EditableWorkflow) workflowManager.getWorkflow("default", documentHandleNode)
        // obtain editable document variant (a.k.a, draft document variant)
        Document document = documentWorkflow.obtainEditableInstance()
        documentVariantNode = document.getNode(jcrSession)

        // finally, let's bind content node data to it! :-)
        contentNodeBinder.bind(documentVariantNode, contentNode, bindingFilter)

        // commit the draft variant
        document = documentWorkflow.commitEditableInstance()

        log.debug "Committed document at " + document.getNode(jcrSession).getPath()

        return false
    }

    boolean undoUpdate(Node node) {
        throw new UnsupportedOperationException('Updater does not implement undoUpdate method')
    }

}
              

Binding Binary Content from JSON

The following example groovy script reads JSON data from parametersMap, creates an imageset node through JCR API, binds ContentNode object to the imageset nodes.

Name: Import an Image Set from JSON
Description: For demonstration purpose, this example groovy script (a) unmarshal ContentNode from JSON, (b) creates an Image Set node, and (c) binds the ContentNode to the Image Set node.
XPath query: /jcr:root
Parameters:
{
  "destination": "/content/gallery",
  "data":
  {
    "name" : "coffee-example.jpg",
    "primaryType" : "hippogallery:imageset",
    "mixinTypes" : [ "mix:referenceable" ],
    "properties" : [ {
      "name" : "hippogallery:description",
      "type" : "STRING",
      "multiple" : false,
      "values" : [ "Description for coffee-example.jpg" ]
    }, {
      "name" : "hippogallery:filename",
      "type" : "STRING",
      "multiple" : false,
      "values" : [ "coffee-example.jpg" ]
    } ],
    "nodes" : [ {
      "name" : "hippogallery:thumbnail",
      "primaryType" : "hippogallery:image",
      "mixinTypes" : [ ],
      "properties" : [ {
        "name" : "hippogallery:height",
        "type" : "LONG",
        "multiple" : false,
        "values" : [ "39" ]
      }, {
        "name" : "hippogallery:width",
        "type" : "LONG",
        "multiple" : false,
        "values" : [ "60" ]
      }, {
        "name" : "jcr:lastModified",
        "type" : "DATE",
        "multiple" : false,
        "values" : [ "2013-11-12T11:09:00.000+01:00" ]
      }, {
        "name" : "jcr:data",
        "type" : "BINARY",
        "multiple" : false,
        "values" : [ "data:;base64,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" ]
      }, {
        "name" : "jcr:mimeType",
        "type" : "STRING",
        "multiple" : false,
        "values" : [ "image/jpeg" ]
      } ],
      "nodes" : [ ]
    }, {
      "name" : "hippogallery:original",
      "primaryType" : "hippogallery:image",
      "mixinTypes" : [ ],
      "properties" : [ {
        "name" : "hippogallery:height",
        "type" : "LONG",
        "multiple" : false,
        "values" : [ "99" ]
      }, {
        "name" : "hippogallery:width",
        "type" : "LONG",
        "multiple" : false,
        "values" : [ "150" ]
      }, {
        "name" : "jcr:lastModified",
        "type" : "DATE",
        "multiple" : false,
        "values" : [ "2013-11-12T11:09:00.000+01:00" ]
      }, {
        "name" : "jcr:data",
        "type" : "BINARY",
        "multiple" : false,
        "values" : [ "data:;base64,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" ]
      }, {
        "name" : "jcr:mimeType",
        "type" : "STRING",
        "multiple" : false,
        "values" : [ "image/jpeg" ]
      } ],
      "nodes" : [ ]
    } ]
  }
}
              
Script >>>
package org.hippoecm.frontend.plugins.cms.admin.updater

import org.onehippo.repository.update.BaseNodeUpdateVisitor
import java.util.*
import javax.jcr.query.*
import org.apache.commons.lang.*
import org.hippoecm.repository.api.*
import org.hippoecm.repository.standardworkflow.*
import org.onehippo.repository.documentworkflow.*
import org.onehippo.forge.content.pojo.binder.*
import org.onehippo.forge.content.pojo.binder.jcr.*
import org.onehippo.forge.content.pojo.common.jcr.*
import org.onehippo.forge.content.pojo.common.util.*
import org.onehippo.forge.content.pojo.model.*
import com.fasterxml.jackson.databind.*

class UpdaterTemplate extends BaseNodeUpdateVisitor {

    def jcrSession
    def contentNodeBinder
    def bindingFilter
    def objectMapper

    void initialize(Session jcrSession) {
        this.jcrSession = jcrSession

        contentNodeBinder = new DefaultJcrContentNodeBinder()

        bindingFilter = new DefaultContentNodeJcrBindingItemFilter()
        bindingFilter.addPropertyPathExclude("jcr:localizedName")
        bindingFilter.addPropertyPathExclude("jcr:path")
        bindingFilter.addPropertyPathExclude("hippostdpubwf:*")
        bindingFilter.addPropertyPathExclude("hippo:availability")
        bindingFilter.addPropertyPathExclude("hippo:paths")
        bindingFilter.addPropertyPathExclude("hippo:related")
        bindingFilter.addPropertyPathExclude("hippostd:holder")
        bindingFilter.addPropertyPathExclude("hippostd:state")
        bindingFilter.addPropertyPathExclude("hippostd:stateSummary")

        objectMapper = new ObjectMapper();
    }

    boolean doUpdate(Node node) {
        log.debug "Visiting node ${node.path}"

        // unmarshal JSON to a ContentNode first
        def destination = parametersMap["destination"]
        def dataJson = parametersMap["data"].toString()
        def contentNode = objectMapper.readValue(dataJson, ContentNode.class)

        // let's create an imageset under the specific destination folderNode
        def newImageSetName = contentNode.getName()
        def destinationFolderNode = jcrSession.getNode(destination)

        def handleNode = destinationFolderNode.addNode(newImageSetName, "hippo:handle")
        handleNode.addMixin("mix:referenceable")
        def imageSetNode = handleNode.addNode(newImageSetName, "hippogallery:imageset")
        imageSetNode.addMixin("mix:referenceable")
        contentNodeBinder.bind(imageSetNode, contentNode, bindingFilter)
        log.debug "Created imageset at " + imageSetNode.getPath()

        return false
    }

    boolean undoUpdate(Node node) {
        throw new UnsupportedOperationException('Updater does not implement undoUpdate method')
    }

}