require "test/unit/testcase"
require 'rexml/sax2listener'
require 'rexml/parsers/sax2parser'

class SAX2Tester < Test::Unit::TestCase
	include REXML
	def test_characters
		d = Document.new( "<A>@blah@</A>" )
		txt = d.root.text
		p = Parsers::SAX2Parser.new "<A>@blah@</A>"
		p.listen(:characters) {|x| assert_equal txt, x}
		p.listen(:characters, ["A"]) {|x| assert_equal txt,x}
		p.parse
	end

=begin
	def test_entity_replacement
		source = '<!DOCTYPE foo [
		<!ENTITY la "1234">
		<!ENTITY lala "--&la;--">
		<!ENTITY lalal "&la;&la;">
		]><a><la>&la;</la><lala>&lala;</lala></a>'
		sax = Parsers::SAX2Parser.new( source )
		results = []
		sax.listen(:characters) {|x| results << x }
		sax.parse
		assert_equal 2, results.size
		assert_equal '1234', results[0]
		assert_equal '--1234--', results[1]
	end
=end
	
	def test_sax2
		f = File.new("docs/documentation.xml")
		parser = Parsers::SAX2Parser.new( f )
		# Listen to all events on the following elements
		count = 0
		blok = proc { |uri,localname,qname,attributes|
			assert %w{ changelog bugs todo }.include?(localname),
			"Mismatched name; we got '#{qname}'\nArgs were:\n\tURI: #{uri}\n\tLOCALNAME: #{localname}\n\tQNAME: #{qname}\n\tATTRIBUTES: #{attributes.inspect}\n\tSELF=#{blok}"
			count += 1
		}

		start_document = 0
		end_document = 0 
		parser.listen( :start_document ) { start_document += 1 }
		parser.listen( :end_document ) { end_document += 1 }
		parser.listen( :start_element, %w{ changelog bugs todo }, &blok )
		# Listen to all events on the following elements.  Synonymous with
		# listen( :start_element, %w{ ... } )
		parser.listen( %w{ changelog bugs todo }, &blok )
		# Listen for all start element events
		parser.listen( :start_element ) { |uri,localname,qname,attributes|
		}
		listener = MySAX2Listener.new
		# Listen for all events
		parser.listen( listener )
		# Listen for all events on the given elements.  Does not include children
		# events.  Regular expressions work as well!
		parser.listen( %w{ /change/ bugs todo }, listener )
		# Test the deafening method
		blok = proc  { |uri,localname,qname,attributes|
			assert_fail "This listener should have been deafened!"
		}
		parser.listen( %w{ changelog }, &blok )
		parser.deafen( &blok )

		tc = 0
		parser.listen( :characters, %w{version} ) {|text|
			assert(text=~/@ANT_VERSION@/, "version was '#{text}'")
			tc += 1
		}
		
		begin 
			parser.parse
		rescue => exception
			if exception.kind_of? Test::Unit::AssertionFailedError
				raise exception
			end
			puts $!
			puts exception.backtrace
		end
		assert_equal 3, count
		assert_equal 1, tc
		assert_equal 1, start_document
		assert_equal 1, end_document
	end

	class KouListener
		include REXML::SAX2Listener
		attr_accessor :sdoc, :edoc
		attr_reader :selem, :decl, :pi
		def initialize
			@sdoc = @edoc = @selem = false
			@decl = 0
			@pi = 0
		end
		def start_document
			@sdoc = true
		end
		def end_document
			@edoc = true
		end
		def xmldecl( *arg )
			@decl += 1
		end
		def processing_instruction( *arg )
			@pi += 1
		end
		def start_element( *arg )
			@selem = true
		end
	end

	# Submitted by Kou
	def test_begin_end_document
		parser = Parsers::SAX2Parser.new("<a/>")

		kl = KouListener.new
		parser.listen(kl)
		sd = false
		ed = false
		parser.listen(:start_document) { sd = true }
		parser.listen(:end_document) { ed = true }

		parser.parse
		assert( sd, ':start_document block failed' )
		assert( ed, ':end_document block failed' )
		assert( kl.sdoc, ':start_document listener failed' )
		assert( kl.edoc, ':end_document listener failed' )
	end

	# Submitted by Kou
	def test_listen_before_start
		parser =  Parsers::SAX2Parser.new( "<?xml ?><?pi?><a><?pi?></a>")
		k1 = KouListener.new
		parser.listen( k1 )
		xmldecl = false
		pi = 0
		parser.listen( :xmldecl ) { xmldecl = true }
		parser.listen( :processing_instruction ) { pi += 1 }

		parser.parse

		assert( xmldecl, ':xmldecl failed' )
		assert_equal( 2, pi, ':processing_instruction failed' )
		assert( k1.decl, 'Listener for xmldecl failed' )
		assert_equal( 2, k1.pi, 'Listener for processing instruction failed' )
	end
end

class MySAX2Listener
	include REXML::SAX2Listener
end
