alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (ElementValidator.scala)

This example Scala source code file (ElementValidator.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Scala tags/keywords

atom, attrdecl, boolean, boolean, contentmodel, elements, list, list, none, none, seq, some, string, string

The Scala ElementValidator.scala source code

/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2002-2011, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://www.scala-lang.org/           **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */



package scala.xml
package dtd

import PartialFunction._
import ContentModel.ElemName
import MakeValidationException._    // @todo other exceptions

import scala.util.automata._
import scala.collection.mutable.BitSet

/** validate children and/or attributes of an element
 *  exceptions are created but not thrown.
 */
class ElementValidator() extends Function1[Node,Boolean] {
  
  private var exc: List[ValidationException] = Nil

  protected var contentModel: ContentModel           = _
  protected var dfa:          DetWordAutom[ElemName] = _
  protected var adecls:       List[AttrDecl]         = _

  /** set content model, enabling element validation */
  def setContentModel(cm: ContentModel) = {
    contentModel = cm
    cm match {
      case ELEMENTS(r) =>
        val nfa = ContentModel.Translator.automatonFrom(r, 1)
        dfa = new SubsetConstruction(nfa).determinize
      case _ =>
        dfa = null
    }
  }

  def getContentModel = contentModel

  /** set meta data, enabling attribute validation */
  def setMetaData(adecls: List[AttrDecl]) { this.adecls = adecls }

  def getIterable(nodes: Seq[Node], skipPCDATA: Boolean): Iterable[ElemName] = {
    def isAllWhitespace(a: Atom[_]) = cond(a.data) { case s: String if s.trim == "" => true }
    
    nodes.filter {
      case y: SpecialNode => y match {
        case a: Atom[_] if isAllWhitespace(a) => false  // always skip all-whitespace nodes
        case _                                => !skipPCDATA
      }
      case x                                  => x.namespace eq null
    } . map (x => ElemName(x.label))
  }  

  /** check attributes, return true if md corresponds to attribute declarations in adecls.
   */
  def check(md: MetaData): Boolean = {
    val len: Int = exc.length
    var ok = new BitSet(adecls.length)
    
    for (attr <- md) {
      def attrStr = attr.value.toString
      def find(Key: String): Option[AttrDecl] = {
        adecls.zipWithIndex find {
          case (a @ AttrDecl(Key, _, _), j) => ok += j ; return Some(a)
          case _                            => false
        }
        None
      }

      find(attr.key) match {
        case None =>
          exc ::= fromUndefinedAttribute(attr.key)

        case Some(AttrDecl(_, tpe, DEFAULT(true, fixedValue))) if attrStr != fixedValue => 
          exc ::= fromFixedAttribute(attr.key, fixedValue, attrStr)

        case _ =>
      }
    }
    
    adecls.zipWithIndex foreach {
      case (AttrDecl(key, tpe, REQUIRED), j) if !ok(j) => exc ::= fromMissingAttribute(key, tpe)
      case _ =>
    }

    exc.length == len //- true if no new exception
  }

  /** check children, return true if conform to content model
   *  @note contentModel != null
   */
  def check(nodes: Seq[Node]): Boolean = contentModel match {
    case ANY    => true
    case EMPTY  => getIterable(nodes, false).isEmpty
    case PCDATA => getIterable(nodes, true).isEmpty
    case MIXED(ContentModel.Alt(branches @ _*))  =>   // @todo
      val j = exc.length
      def find(Key: String): Boolean =
        branches exists { case ContentModel.Letter(ElemName(Key)) => true ; case _ => false }
      
      getIterable(nodes, true) map (_.name) filterNot find foreach {
        exc ::= MakeValidationException fromUndefinedElement _
      }
      (exc.length == j)   // - true if no new exception

    case _: ELEMENTS =>
      dfa isFinal {
        getIterable(nodes, false).foldLeft(0) { (q, e) =>
          (dfa delta q).getOrElse(e, throw ValidationException("element %s not allowed here" format e))
        }
      }
  }

  /** applies various validations - accumulates error messages in exc
   *  @todo fail on first error, ignore other errors (rearranging conditions)
   */
  def apply(n: Node): Boolean =
    //- ? check children
    ((contentModel == null) || check(n.child)) &&
    //- ? check attributes
    ((adecls == null) || check(n.attributes))
}

Other Scala examples (source code examples)

Here is a short list of links related to this Scala ElementValidator.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.