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

org.fusesource.scalate.converter.JspParser.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.TemplateException
import util.parsing.input.{ Positional, CharSequenceReader, NoPosition, Position }
import org.fusesource.scalate.support.Text

sealed abstract class PageFragment extends Positional {
}

case class QualifiedName(
  prefix: String,
  name: String) extends Positional {

  val qualifiedName = prefix + ":" + name

  override def toString = qualifiedName
}

case class Attribute(
  name: String,
  value: Expression) extends Positional

case class CommentFragment(
  comment: Text) extends PageFragment

case class DollarExpressionFragment(
  code: Text) extends PageFragment {

  val toScala = ExpressionLanguage.asScala(code.toString)

  override def toString = "${" + toScala + "}"
}

case class TextFragment(
  text: Text) extends PageFragment {

  override def toString = text.toString

}

case class Element(
  qname: QualifiedName,
  attributes: List[Attribute],
  body: List[PageFragment]) extends PageFragment {

  val qualifiedName = qname.qualifiedName

  lazy val attributeMap: Map[String, Expression] = Map(attributes.map(a => a.name -> a.value): _*)

  /**
   * Returns the mandatory expression for the given attribute name or throw an expression if its not found
   */
  def attribute(name: String): Expression = attributeMap.get(name) match {
    case Some(e) => e
    case _ => throw new IllegalArgumentException("No '" + name + "' attribute on tag " + this)
  }
}

/**
 * Parser of JSP for the purposes of transformation to Scalate; so its not perfect but gives folks a head start
 *
 * @version $Revision : 1.1 $
 */
class JspParser extends MarkupScanner {

  protected val expressionParser = new ExpressionParser

  private def phraseOrFail[T](p: Parser[T], in: String): T = {
    val x = phrase(p)(new CharSequenceReader(in))
    x match {
      case Success(result, _) => result
      case NoSuccess(message, next) => throw new InvalidJspException(message, next.pos);
    }
  }

  def parsePage(in: String) = {
    phraseOrFail(page, in)
  }

  def page = rep(pageFragment)

  val pageFragment: Parser[PageFragment] = positioned(markup | expression | textFragment)

  val textFragment = upto(markup | expression) ^^ { TextFragment(_) }

  def elementTextContent = someUpto(closeElement | markup | expression) ^^ { TextFragment(_) }

  def markup: Parser[PageFragment] = element | emptyElement

  def emptyElement = (openElement("/>")) ^^ {
    case q ~ al => Element(q, al, Nil)
  }

  def element = (openElement(">") ~ rep(markup | expression | elementTextContent) ~ closeElement) ^^ {
    case (q ~ al) ~ b ~ q2 =>
      if (q != q2) throw new InvalidJspException("Expected close element of " + q + " but found " + q2, q2.pos)
      Element(q, al, b)
  }

  def qualifiedName: Parser[QualifiedName] = positioned(((IDENT <~ ":") ~ IDENT) ^^ { case p ~ n => QualifiedName(p, n) })

  def openElement(end: String) = "<" ~> qualifiedName ~ attributeList <~ end

  def closeElement: Parser[QualifiedName] = (" qualifiedName) <~ repS ~ ">"

  def attributeList = rep(attribute)

  def attribute = ((S ~> IDENT <~ repS <~ "=" <~ repS) ~ STRING) ^^ { case n ~ v => Attribute(n, toExpression(v)) }

  val expression = wrapped("${", "}") ^^ { DollarExpressionFragment(_) }

  def toExpression(text: String) = expressionParser.parseExpression(text)
}

class InvalidJspException(
  val brief: String,
  val pos: Position = NoPosition) extends TemplateException(brief + " at " + pos)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy