PageRenderTime 35ms CodeModel.GetById 29ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/scalate-core/src/main/scala/org/fusesource/scalate/scuery/support/Rule.scala

http://github.com/scalate/scalate
Scala | 117 lines | 70 code | 18 blank | 29 comment | 6 complexity | 97e6c5ce8d48c86b63f347327e9ca52a 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.support
 19
 20import xml.{ Elem, Node, NodeSeq }
 21import org.fusesource.scalate.scuery.XmlHelper._
 22import org.fusesource.scalate.util.Log
 23
 24object Rule extends Log {
 25  /**
 26   * Combines multiple rules to a single rule
 27   */
 28  def apply(a: Rule, b: Rule): Rule = {
 29    if (a.order <= b.order) {
 30      CompositeRule(a, b)
 31    } else {
 32      CompositeRule(b, a)
 33    }
 34  }
 35
 36  def apply(rules: Iterator[Rule]): Rule = apply(rules.toSeq)
 37
 38  def apply(rules: Seq[Rule]): Rule = {
 39    if (rules.size < 2) {
 40      rules(0)
 41    } else {
 42      val list = rules.sortWith(_.order < _.order)
 43      list.tail.foldLeft(list.head)(Rule(_, _))
 44    }
 45  }
 46}
 47import Rule._
 48
 49/**
 50 * Represents manipuluation rules
 51 *
 52 * @version $Revision : 1.1 $
 53 */
 54trait Rule {
 55  def apply(node: Node): NodeSeq
 56
 57  /**
 58   * Lets do simple rules first (like setting attributes, removing attributes), then changing contents
 59   * then finally completely transforming the node last
 60   */
 61  def order: Int = 0
 62}
 63
 64case class CompositeRule(first: Rule, second: Rule) extends Rule {
 65  def apply(node: Node) = {
 66    first(node).flatMap { second(_) }
 67  }
 68
 69  def toList: List[Rule] = toList(first) ::: toList(second)
 70
 71  protected def toList(rule: Rule): List[Rule] = rule match {
 72    case c: CompositeRule => c.toList
 73    case _ => rule :: Nil
 74  }
 75}
 76
 77case class ReplaceRule(fn: Node => NodeSeq) extends Rule {
 78  def apply(node: Node) = fn(node)
 79
 80  override def order: Int = 100
 81}
 82
 83case class ReplaceContentRule(fn: Node => NodeSeq) extends Rule {
 84  def apply(node: Node) = node match {
 85    case e: Elem =>
 86      val contents = fn(e)
 87      debug("Replacing content = " + contents)
 88      replaceContent(e, contents)
 89    case n => n
 90  }
 91}
 92
 93case class SetAttributeRule(name: String, fn: (Node) => String) extends Rule {
 94  def apply(node: Node) = node match {
 95    case e: Elem =>
 96      val value = fn(e)
 97      debug("Setting attribute %s to %s", name, value)
 98      setAttribute(e, name, value)
 99
100    case n => n
101  }
102
103  override def order = -1
104}
105
106case class SetSelectiveAttributeRule(name: String, fn: (Node) => String) extends Rule {
107  def apply(node: Node) = node match {
108    case e: Elem =>
109      val value = fn(e)
110      debug("Selectively setting attribute %s to %s", name, value)
111      if (e.attribute(name).isDefined) setAttribute(e, name, value) else e
112
113    case n => n
114  }
115
116  override def order = -1
117}