require "test/unit/testcase"
require "rexml/document"
require 'rexml/streamlistener'
require 'stringio'

module REXMLTests
  class MyListener
    include REXML::StreamListener
  end


  class StreamTester < Test::Unit::TestCase
    # Submitted by Han Holl
    def test_listener
      data = %Q{<session1 user="han" password="rootWeiler" />\n<session2 user="han" password="rootWeiler" />}

      b = RequestReader.new( data )
      b = RequestReader.new( data )
    end

    def test_ticket_49
      source = StringIO.new( <<-EOL )
      <!DOCTYPE foo [
        <!ENTITY ent "replace">
      ]>
      <a>&ent;</a>
      EOL
      REXML::Document.parse_stream(source, MyListener.new)
    end

    def test_ticket_10
      source = StringIO.new( <<-EOL )
      <!DOCTYPE foo [
        <!ENTITY ent "replace">
        <!ATTLIST a
         xmlns:human CDATA #FIXED "http://www.foo.com/human">
        <!ELEMENT bar (#PCDATA)>
        <!NOTATION n1 PUBLIC "-//HM//NOTATION TEST1//EN" 'urn:x-henrikmartensson.org:test5'>
      ]>
      <a/>
      EOL
      listener = MyListener.new
      class << listener
        attr_accessor :events
        def entitydecl( content )
          @events[ :entitydecl ] = true
        end
        def attlistdecl( element_name, attributes, raw_content )
          @events[ :attlistdecl ] = true
        end
        def elementdecl( content )
          @events[ :elementdecl ] = true
        end
        def notationdecl( content )
          @events[ :notationdecl ] = true
        end
      end
      listener.events = {}

      REXML::Document.parse_stream( source, listener )

      assert( listener.events[:entitydecl] )
      assert( listener.events[:attlistdecl] )
      assert( listener.events[:elementdecl] )
      assert( listener.events[:notationdecl] )
    end

    def test_entity
      listener = MyListener.new
      class << listener
        attr_accessor :entities
        def entity(content)
          @entities << content
        end
      end
      listener.entities = []

      source = StringIO.new(<<-XML)
<!DOCTYPE root [
<!ENTITY % ISOLat2
         SYSTEM "http://www.xml.com/iso/isolat2-xml.entities" >
%ISOLat2;
]>
<root/>
      XML
      REXML::Document.parse_stream(source, listener)

      assert_equal(["ISOLat2"], listener.entities)
    end
  end


  # For test_listener
  class RequestReader
    attr_reader :doc
    def initialize(io)
      @stack = []
      @doc = nil
      catch(:fini) do
        REXML::Document.parse_stream(io, self)
        raise IOError
      end
    end
    def tag_start(name, args)
      if @doc
        @stack.push(REXML::Element.new(name, @stack.last))
      else
        @doc = REXML::Document.new("<#{name}/>")
        @stack.push(@doc.root)
      end
      args.each do |attr,val|
        @stack.last.add_attribute(attr, val)
      end
    end
    def tag_end(name, *args)
      @stack.pop
      throw(:fini) if @stack.empty?
    end
    def text(str)
      @stack.last.text = str
    end
    def comment(str)
    end
    def doctype( name, pub_sys, long_name, uri )
    end
    def doctype_end
    end
  end
end
