summaryrefslogtreecommitdiff
path: root/sources/scala/xml/dtd/Validation.scala
blob: 8d4f41dbccfad6cb8ffaa8c727317c9038d1f291 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package scala.xml.dtd ;

import scala.collection.mutable;
import scala.collection.Set;
import scala.collection.Map;
import ContentModel._ ;

class ElementValidator(namespace$$: String, elemSpec: RegExp) {
  final val namespace = namespace$$.intern();

  var autom:Autom = _;

  trait Autom {
    def run(s:Seq[Node]):Unit;
  }

  object TrivialAutom extends Autom {
    def run(s:Seq[Node]):Unit = {};
  }

  object EmptyAutom extends Autom {
    /** "not even entity references, PIs, etc" */
    def run(s:Seq[Node]):Unit =
      if( s.length != 0 )
        throw MakeValidationException.fromNonEmptyElement();

  }

  object TextAutom extends Autom {
    /** only text nodes, entity references, PIs, comments, etc" */
    def run(s:Seq[Node]):Unit = {
      val it = s.elements;
      while( it.hasNext ) {
        val n = it.next;
        if( n.typeTag$ >= 0 )
           throw MakeValidationException.fromUndefinedElement( n.label );
      }
    }
  }

  class MixedModeAutom(set:scala.collection.Set[String]) extends Autom {
    def run(s:Seq[Node]):Unit = {
      val it = s.elements;
      while( it.hasNext ) {
        val n = it.next;
        //if(( n.namespace == namespace )&& !set.contains( n.label )) // todo
          throw MakeValidationException.fromUndefinedElement( n.label );
      }
    }
  }

  autom = elemSpec match {
    case ANY_ => TrivialAutom;
    case Eps  => EmptyAutom;
    case PCDATA_ | Sequ( PCDATA_ ) => TextAutom
    case Star(z:Alt) if(( z.rs.length == 1 )&& (z.rs(0) match {
      case PCDATA_   => true
      case _         => false
    })) => new MixedModeAutom(getLabels( elemSpec ));
    case _    => TrivialAutom;
  }
  def validate( nodes:Seq[Node] ):Unit = autom.run( nodes );
}

/** only CDATA attributes, ignores attributes that have different namespace
* @param: attrSpec
*/
class AttributeValidator( namespace$$:String, attrSpec1: Seq[dtd.AttrDecl]) {
  final val namespace = namespace$$.intern();
  final val attrSpec = new mutable.HashMap[String,AttrDecl]();
  //var attribsTemplate:MetaData = Null;

  for( val adecl <- attrSpec1 ) {
    attrSpec.update( adecl.name, adecl )
  }

  var req = 0;
  val map = new mutable.HashMap[String,String]();

  // populate with special "<R" and default
  for( val key <- attrSpec.keys ) {
    attrSpec( key ).default match {
      case dtd.REQUIRED =>
        map.update( key, "<R" );
      req = req + 1;
      case dtd.DEFAULT( _, attValue ) =>
        map.update( key, attValue );
        //attribsTemplate =
          //new UnprefixedAttribute(key, attValue, attribsTemplate);
      //add( attribsTemplate, Attribute(namespace, key, attValue));
      case dtd.IMPLIED  =>
    }
  }

  /*
  def add(as:List[Attribute], x:Attribute):List[Attribute] = {
    if( x.namespace.length() == 0 )
      scala.xml.Attribute( namespace, x.key, x.value )::as;
    else
      x::as;
  };
  */

  def validate( attributes:MetaData ): MetaData = {
    var actualReq = 0;
    var nattribs: MetaData = Null;
    for( val b <- attributes ) {
      if( b.key == "xmlns" )
        {} // this should not get even here
      else /*if( b.namespace != namespace ) // this was to allow foreigns once
        nattribs = b.copy(nattribs);
      else */  attrSpec.get( b.key ) match {
        case Some( AttrDecl( key, tpe, df )) => df match {
          case DEFAULT( true, attValue ) =>
            if( b.value != attValue )
              MakeValidationException.fromFixedAttribute( key, attValue, b.value );
            else
              nattribs = b.copy(nattribs);
          case REQUIRED =>
            actualReq = actualReq + 1;
            nattribs = b.copy(nattribs);
          case _ =>
            nattribs = b.copy(nattribs);
        }
        case _ =>
          MakeValidationException.fromUndefinedAttribute( b.key )
      }
    }
    if( req - actualReq > 0 ) {
      var allKeys = new mutable.HashSet[String]();
      for( val AttrDecl( key, _, REQUIRED ) <- attrSpec.values )
        allKeys += key;
      for( val a <- nattribs )
        allKeys -= a.key;
      MakeValidationException.fromMissingAttribute( allKeys )
    }
    nattribs
  }
}