Treebuilder2

This is the example code for my blog JCR with Scala: Adding Properties in ASCII Art.

package com.day.scalademo.treebuilder2;

import org.apache.jackrabbit.core.TransientRepository
import javax.jcr.{Node, Property, SimpleCredentials}

object Treebuilder2 {
    import Extensions._

    def main(args: Array[String]) {
        val repository = new TransientRepository
        val session = repository.login(new SimpleCredentials("username", "password".toCharArray));

        try {
            val node = session.getRootNode ¦- "test"
            addSubtree(node)
            dump(node)
        }
        finally {
            session.logout
        }
    }

    def addSubtree(n: Node) {
        n ¦- "movies" -+ { n: Node =>
                     n ¦- "cast" -+ { n: Node =>
                                  n ¦= ("Gena Rowlands", "Victoria Snelling")
                                  n ¦= ("Winona Ryder", "Corky")
                                  n ¦= ("Roberto Benigni", "Taxi Driver")
                                    }
                     n ¦= ("title", "Night on Earth")
                     n ¦= ("length", 123L)
                     n ¦= ("ratings", 9L::8L::5L::Nil)
                     n ¦= ("languages", "en"::"it"::"fi"::"fr"::Nil)
                       }
        n ¦- "movies" -+ { n: Node =>
                     n ¦- "cast" -+ { n: Node =>
                                  n ¦= ("James Stewart", "Det. Ferguson")
                                  n ¦= ("Tom Helmore", "Gavin Elster")
                                  n ¦= ("Henry Jones", "Coroner")
                                    }
                     n ¦= ("title", "Vertigo")
                     n ¦= ("length", 124L)
                     n ¦= ("ratings", 10L::8L::7L::Nil)
                     n ¦= ("languages", "en"::Nil)
                       }
    }

    def dump(node: Node) {
        println(node.getPath)

        for (property <- node.properties) {
            if (property.getDefinition.isMultiple)
                for(value <- property.getValues)
                    println(property.getPath + " = " + value.getString)
            else
                println(property.getPath + " = " + property.getString)
        }

        for (child <- node.childNodes)
            dump(child)
    }

}

object Extensions {
    import javax.jcr.{Value, ValueFactory}

    implicit def extendNode(node: Node) = new NodeExtender(node)

    abstract class Val[-T](value: T) {
        def setOnNode(node: Node, name: String, factory: ValueFactory)
        def toValue(factory: ValueFactory): Value
    }

    implicit def longToVal(l: long) = new Val(l) {
        def setOnNode(node: Node, name: String, factory: ValueFactory) =
            node.setProperty(name, factory.createValue(l))

        def toValue(factory: ValueFactory) = factory.createValue(l)
    }

    implicit def stringToVal(s: String) = new Val(s) {
        def setOnNode(node: Node, name: String, factory: ValueFactory) =
            node.setProperty(name, factory.createValue(s))

        def toValue(factory: ValueFactory) = factory.createValue(s)
    }

    implicit def listToVal[T](seq: Seq[T])(implicit toVal: T => Val[T]) = new Val(seq) {
        def setOnNode(node: Node, name: String, factory: ValueFactory) = {
            val values = seq.map(toVal(_).toValue(factory)).toArray
            node.setProperty(name, values)
        }

        def toValue(factory: ValueFactory) = error("not applicable")
    }
}

protected class NodeExtender(node: Node) {
    private lazy val valueFactory = node.getSession.getValueFactory     

    def childNodes = new Iterator[Node] {
        val it = node.getNodes
        def hasNext = it.hasNext
        def next = it.nextNode
    }

    def properties = new Iterator[Property] {
        val it = node.getProperties
        def hasNext = it.hasNext
        def next = it.nextProperty
    }

    def -+[T](f: Node => T) = f(node)
    def ¦-(relPath: String) = node.addNode(relPath)
    def ¦-(relPath: String, tyqe: String) = node.addNode(relPath, tyqe)

    def ¦=[T <% Extensions.Val[T]](name: String, value: T) = value.setOnNode(node, name, valueFactory)
}

Leave a comment