PageRenderTime 15ms CodeModel.GetById 11ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 0ms

/scalate-core/src/main/scala/org/fusesource/scalate/scuery/NestedTransformer.scala

http://github.com/scalate/scalate
Scala | 64 lines | 26 code | 10 blank | 28 comment | 0 complexity | 8ffdbab85de84dd54df5334d3a2840ea MD5 | raw file
 1/**
 2 * Copyright (C) 2009-2011 the original author or authors.
 3 * See the notice.md file distributed with this work for additional
 4 * information regarding copyright ownership.
 5 *
 6 * Licensed under the Apache License, Version 2.0 (the "License");
 7 * you may not use this file except in compliance with the License.
 8 * You may obtain a copy of the License at
 9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18package org.fusesource.scalate.scuery
19
20import scala.xml.{ Node, NodeSeq }
21
22/**
23 * A transformer which makes it easy to create nested transformations by switching the thread local
24 * transformer used for the '$' methods when inside of a transform method.
25 *
26 * @version $Revision : 1.1 $
27 */
28class NestedTransformer {
29  private[this] val rootTransformer = new Transformer
30  private[this] val threadLocal = new ThreadLocal[Transformer] {
31    override def initialValue = rootTransformer
32  }
33
34  def $(cssSelector: String) = transformer.$(cssSelector)
35
36  def $(selector: Selector) = transformer.$(selector)
37
38  def apply(nodes: NodeSeq, ancestors: Seq[Node] = Nil) = transformer(nodes, ancestors)
39
40  def transformer: Transformer = threadLocal.get
41
42  /**
43   * Transforms the given nodes passing in a block which is used to configure a new transformer
44   * to transform the nodes. This method is typically used when performing nested transformations such
45   * as transforming one or more nodes when inside a transformation rule itself.
46   */
47  def transform(nodes: NodeSeq, ancestors: Seq[Node])(rules: Transformer => Unit): NodeSeq = {
48    val currentTransform = transformer
49    try {
50      val childTransform = transformer.createChild
51      threadLocal.set(childTransform)
52      rules(childTransform)
53      childTransform(nodes, ancestors)
54    } catch {
55      case e: Throwable =>
56        threadLocal.set(currentTransform)
57        throw e
58
59    }
60  }
61
62  def transform(nodes: NodeSeq)(rules: Transformer => Unit): NodeSeq = transform(nodes, Nil)(rules)
63
64}