All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fusesource.scalate.converter.JspConverter.scala Maven / Gradle / Ivy

/**
 * Copyright (C) 2009-2011 the original author or authors.
 * See the notice.md file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.fusesource.scalate.converter

import org.fusesource.scalate.support.Text
import util.matching.Regex.Match
import org.fusesource.scalate.util.Log

object ExpressionLanguage {
  protected val operators = Map("eq" -> "==", "ne" -> "!=",
    "gt" -> ">", "ge" -> ">=",
    "lt" -> "<", "le" -> "<=",
    "not" -> "!")

  protected val notEmptyRegex = """(\s|^)(not\s+empty)\s(.+)""".r
  protected val emptyRegex = """(\s|^)(empty)\s(.+)""".r
  protected val lengthRegex = """fn:length\((.+)\)""".r

  def asScala(el: String): String = {
    // lets switch the EL style indexing to Scala parens and switch single quotes to doubles
    var text = el.replace('[', '(').
      replace(']', ')').
      replace('\'', '\"')

    def space(m: Match): String = if (m.start == 0) "" else " "

    // "not empty xxx" => "!(xxx isEmpty)"
    text = notEmptyRegex.replaceAllIn(text, { m => space(m) + "!(" + m.subgroups.last + " isEmpty)" })

    // "empty whatever" => "whatever isEmpty"
    text = emptyRegex.replaceAllIn(text, { m => space(m) + m.subgroups.last + " isEmpty" })

    // replace EL operators
    for ((a, b) <- operators) {
      text = text.replaceAll("(\\s|^)" + a + "\\s", " " + b + " ")
    }

    // foo.bar => foo.getBar
    var first = true
    text = text.split('.').map(s =>
      if (!first && s.length > 0 && s(0).isUnicodeIdentifierStart) {
        "get" + s.capitalize
      } else {
        first = false
        s
      }).mkString(".")

    // fn:length(foo) => foo.size
    text = lengthRegex.replaceAllIn(text, { m => m.subgroups.last + ".size" })

    text
  }
}

trait IndentWriter {
  var out = new StringBuilder
  var indentLevel: Int = 0
  var indentText: String = "  "

  def reset(): Unit = {
    out = new StringBuilder
  }

  def indent[T](op: => T): T = { indentLevel += 1; val rc = op; indentLevel -= 1; rc }

  def println(line: String): this.type = {
    for (i <- 0 until indentLevel) {
      print(indentText)
    }
    print(line)
    println()
    this
  }

  def print(value: AnyRef): Unit = {
    out.append(value)
  }

  def println() = print("\n")

  def text = out.toString
}
object JspConverter extends Log
class JspConverter extends IndentWriter {
  import JspConverter._

  var coreLibraryPrefix: String = "c"
  var whenCount = 0

  def convert(jsp: String): String = {
    reset()

    val parser = new JspParser
    val result = parser.parsePage(jsp)
    convert(result)
    text
  }

  def convert(list: List[PageFragment]): Unit = {
    for (r <- list) {
      convert(r)
    }
  }

  def convert(fragment: PageFragment): Unit = fragment match {
    case e: Element => transform(e)
    case _ => print(fragment.toString)
  }

  def transform(e: Element): Unit = {
    e match {

      // core JSTL library
      case Element(QualifiedName(coreLibraryPrefix, name), attributes, body) =>
        name match {
          case "choose" =>
            whenCount = 0
            convert(body)
            print("#end")

          case "forEach" =>
            val varExp = e.attributeMap.getOrElse("var", textExpression("i"))
            print("#for(" + asUnquotedParam(varExp) + " <- ")

            e.attributeMap.get("items") match {
              case Some(exp) =>
                print(asParam(exp) + ")")

              case _ =>
                val begin = e.attribute("begin")
                val end = e.attribute("end")
                print(asUnquotedParam(begin) + ".to(" + asUnquotedParam(end))

                e.attributeMap.get("step") match {
                  case Some(step) => print(", " + asUnquotedParam(step))
                  case _ =>
                }
                print("))")
            }
            convert(body)
            print("#end")

          case "if" =>
            val exp = e.attribute("test")
            print("#if(" + asParam(exp) + ")")
            convert(body)
            print("#end")

          case "otherwise" =>
            print("#else")
            convert(body)

          case "out" =>
            val exp = e.attribute("value")
            print("${")
            e.attributeMap.get("escapeXml") match {
              case Some(TextExpression(Text("true"))) => print("escape(" + asParam(exp) + ")")
              case Some(TextExpression(Text("false"))) => print("unescape(" + asParam(exp) + ")")
              case Some(e) => print("value(" + asParam(exp) + ", " + asUnquotedParam(e) + ")")
              case _ => print(asParam(exp))
            }
            print("}")

          case "set" =>
            val exp = e.attribute("value")
            val name = e.attribute("var")
            print("#{ var " + asUnquotedParam(name) + " = " + asParam(exp) + " }#")

          case "when" =>
            val exp = e.attribute("test")
            print("#" + (if (whenCount == 0) "if" else "elseif") + "(" + asParam(exp) + ")")
            whenCount += 1
            convert(body)

          case "url" =>
            val exp = e.attribute("value")
            print("${uri(" + asParam(exp) + ")}")

          case _ =>
            warn("No converter available for tag <" + coreLibraryPrefix + ":" + name + ">: " + e)
            print(e)
        }
      case _ => print(e)
    }
  }

  def print(e: Element): Unit = {
    print("<" + e.qualifiedName)
    for (a <- e.attributes) {
      print(" " + a.name + "=\"" + asParam(a.value) + "\"")
    }
    print("/>")
  }

  protected def textExpression(s: String) = TextExpression(Text(s))

  /**
   * Returns the text of an expression as a numeric method parameter
   */
  protected def asUnquotedParam(exp: Expression): String = exp.asUnquotedParam

  /**
   * Returns the text of an expression as a method parameter
   */
  protected def asParam(exp: Expression): String = exp.asParam
  /**
   * Returns the text of an expression as a method parameter
   */
  protected def asJsp(exp: Expression): String = exp.asJsp

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy