Imported File#ftype spec from rubyspecs.
[rbx.git] / lib / rexml / validation / validation.rb
blob160ea96b3155098315b425e8c45cd7b39731544a
1 require 'rexml/validation/validationexception'
3 module REXML
4   module Validation
5     module Validator
6       NILEVENT = [ nil ]
7       def reset
8         @current = @root
9         @root.reset
10         @root.previous = true
11         @attr_stack = []
12         self
13       end
14       def dump
15         puts @root.inspect
16       end
17       def validate( event ) 
18         #puts "Current: #@current"
19         #puts "Event: #{event.inspect}"
20         @attr_stack = [] unless defined? @attr_stack
21         match = @current.next(event)
22         raise ValidationException.new( "Validation error.  Expected: "+
23           @current.expected.join( " or " )+" from #{@current.inspect} "+
24           " but got #{Event.new( event[0], event[1] ).inspect}" ) unless match
25         @current = match
27         # Check for attributes
28         case event[0]
29         when :start_element
30           #puts "Checking attributes"
31           @attr_stack << event[2]
32           begin
33             sattr = [:start_attribute, nil]
34             eattr = [:end_attribute]
35             text = [:text, nil]
36             k,v = event[2].find { |k,v| 
37               sattr[1] = k
38               #puts "Looking for #{sattr.inspect}"
39               m = @current.next( sattr )
40               #puts "Got #{m.inspect}"
41               if m 
42                 # If the state has text children...
43                 #puts "Looking for #{eattr.inspect}"
44                 #puts "Expect #{m.expected}"
45                 if m.matches?( eattr )
46                   #puts "Got end"
47                   @current = m
48                 else
49                   #puts "Didn't get end"
50                   text[1] = v
51                   #puts "Looking for #{text.inspect}"
52                   m = m.next( text )
53                   #puts "Got #{m.inspect}"
54                   text[1] = nil
55                   return false unless m
56                   @current = m if m
57                 end
58                 m = @current.next( eattr )
59                 if m
60                   @current = m
61                   true
62                 else
63                   false
64                 end
65               else
66                 false
67               end
68             }
69             event[2].delete(k) if k
70           end while k
71         when :end_element
72           attrs = @attr_stack.pop
73           raise ValidationException.new( "Validation error.  Illegal "+
74             " attributes: #{attrs.inspect}") if attrs.length > 0
75         end
76       end
77     end
79     class Event
80       def initialize(event_type, event_arg=nil )
81         @event_type = event_type
82         @event_arg = event_arg
83       end
85       attr_reader :event_type
86       attr_accessor :event_arg
88       def done?
89         @done
90       end
92       def single?
93         return (@event_type != :start_element and @event_type != :start_attribute)
94       end
96       def matches?( event )
97         #puts "#@event_type =? #{event[0]} && #@event_arg =? #{event[1]} "
98         return false unless event[0] == @event_type
99         case event[0]
100         when nil
101           return true
102         when :start_element
103           return true if event[1] == @event_arg
104         when :end_element
105           return true
106         when :start_attribute
107           return true if event[1] == @event_arg
108         when :end_attribute
109           return true
110         when :end_document
111           return true
112         when :text
113           return (@event_arg.nil? or @event_arg == event[1])
114 =begin
115         when :processing_instruction
116           false
117         when :xmldecl
118           false
119         when :start_doctype
120           false
121         when :end_doctype
122           false
123         when :externalentity
124           false
125         when :elementdecl
126           false
127         when :entity
128           false
129         when :attlistdecl
130           false
131         when :notationdecl
132           false
133         when :end_doctype
134           false
135 =end
136         else
137           false
138         end
139       end
141       def ==( other )
142         return false unless other.kind_of? Event
143         @event_type == other.event_type and @event_arg == other.event_arg
144       end
146       def to_s
147         inspect
148       end
150       def inspect
151         "#{@event_type.inspect}( #@event_arg )"
152       end
153     end
154   end