#!/usr/bin/env ruby

# We subclass the generic RDF parser, teaching it about REXML, the 
# pure Ruby XML parser.
#
# danbri@w3.org
# $Id: REXRDFParser.rb,v 1.6 2003/04/05 10:05:07 danbri Exp $
#
# TODO: namespace state is broken. We should push onto a stack, and 
# maintain a notion of current mappings from short names to URIs.

# RubyRDF / RDF Parser. Based on code contributed from
# RDF4R RDF Parser, Copyright © 2002 Brandt Kurowski (brandt@kurowski.net)
# packaged as part of RubyRDF, see http://www.w3.org/2001/12/rubyrdf/intro.html
# All Rights Reserved. This work is distributed under the W3C® Software 
# License [1] in the hope that it will be useful, but WITHOUT ANY 
# WARRANTY; without even the implied warranty of MERCHANTABILITY or 
# FITNESS FOR A PARTICULAR PURPOSE. 
# [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231


require 'rexml/document'
require 'RDF4R/Driver/RDFParser'

#require 'RDF4R/Consumer/Standard'
#require 'RDF4R/Driver/SimpleData'
#require 'basicrdf'

###############################################################################
#
#

class REXRDFParser
  include RDF4R::Driver::RDFParser

# Since removing the XMLParser superclass, I've added: :base_uri, :consumer
  attr_accessor :ns, :base_uri, :consumer
  
  def initialize
    @ns={}
    super
  end #todo: check this

  # return expanded string with ';' separator if namespace has been declared.
  # todo: stack of in-scope namespaces; xmlbase; 
  #
  def expand_ns(data)
    full=data
    if (data =~ /(\w+):(.*)/) 
      # puts "Expanding element name: pre=#{$1} post=#{$2} full='#{@ns[$1]}#{$2}'\n"
      full="#{@ns[$1]};#{$2}"
    else
      # puts "Element is in default namespace. def=#{@ns['DEFAULT']} "
      full="#{@ns['DEFAULT']};#{data}"
    end
    # puts "expand_ns returning: #{full}"
    return full
  end

  def REXRDFParser.process(source, base, consumer)
    p = REXRDFParser.new
    p.base_uri=base 				### fixme -- trim from last '/' ?
    p.consumer = consumer 			# tell the rdf parser where to store triples
    #puts "Starting to process stream: '#{source}', '#{base}', '#{consumer}'\n"
    REXML::Document.parse_stream(source,p) 
    p.consumer.models    
  end
  

  #### REXML XML Parser event stream: handler functions #######################

  def tag_start(data,attrs)
    # puts "tag_start!: #{data}, #{attrs}\n"
    # puts "NS dump: '#{@ns.inspect}' \n\n"
    attrs.each do |k,v|
      att=k
      nsuri=v
      next unless (att =~ /^xmlns/)
      # puts "Got attribute: '#{a.inspect}' \n"
      prefix = $1 if (att =~ /^xmlns:(.*)/)
      # puts "Got namespace: '#{prefix}'-> '#{nsuri}'" if prefix
      @ns['DEFAULT']=nsuri if (prefix==nil)
      if (prefix)
        @ns[prefix]=nsuri # 
        # puts  "NS dump: '#{@ns.inspect}' \n\n"
      end
    end
    full=expand_ns(data)  
    full_attrs={}

    attrs.each do |k,v|
      next if (k =~ /^xmlns/) # ignore xmlns attributes
      fa=expand_ns(k)
      nav=v
      # puts "\nEXPANSION: new value='#{nav}' full attr='#{fa}' "
      full_attrs[fa]=nav
    end
    # puts "Expanded attribs: #{full_attrs.inspect} \n"
    startElement(full,full_attrs)
  end

  def tag_end(data)
    # puts "tag_end!: #{data}"
    endElement(data)
  end

  def comment(data)
    # puts "comment! #{data}"
  end

  def text(data="")
    return if data==""
    # puts "text!: '#{data}'"
    character(data)
  end

  def xmldecl(data,d2,d3)
    #puts "xmldecl!: #{data}, #{d2}, #{d3}\n"
  end


  #### End REXML handlers ####

end #### end of REXML-based RDF parser class definition



######################################################################################


## Notes:
## Expat calls from RDF4R's Expat based XMLParser RDF class:
#
# def initialize(parser, parent, name, attrs)
# def handleXMLattrs(attrs)
# def handleRDFattrs(attrs)
# def get_resource(element)
# def initialize(encoding = nil, nssep = nil)
# def transition(element)
# def startElement(name, attrs)
# def endElement(name)
# def character(text)
# def parse_name(name)
# def XMLParser.process(source, base, consumer)

#      def XMLParser.process(source, base, consumer)
#        p = XMLParser.new(nil, ';')
#        p.base_uri = base.kind_of?(URI::Generic) ? base : URI.parse(base)
#                                p.consumer = consumer
#        begin
#          p.parse(source)
#        rescue XMLParserError
#          $stderr.puts %Q{in #{source.path}} if source.kind_of? File
#          $stderr.puts %Q{at #{source.lineno}}
#          raise $!
#        end
#        p.consumer.models
#      end

