# Copyright (C) 2001 Tobias Peters <t-peters@berlios.de>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed 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.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA  02111-1307, USA.

class Idl_Attribute
  attr_reader :interface
  attr_reader :name
  attr_reader :ptype
  attr_reader :idl_module

  def is_readonly?
    @is_readonly
  end

  def raises_exception_on_setting?
    (@is_readonly) ? false : (@raises_exception_on_setting)
  end

  def raises_exception_on_retrieval?
    @raises_exception_on_retrieval
  end

  def to_s
    @name
  end

  def initialize(idl_module, interface, remaining_lines)
    @idl_module = idl_module
    @interface = interface
    @raises_exception_on_retrieval = false
    @raises_exception_on_setting = false

    # check if attribute is readonly
    if (remaining_lines[0] =~ /readonly\s/)
      @is_readonly = true
      remaining_lines[0] = remaining_lines[0].sub(/readonly/, " ")
    else
      @is_readonly = false
    end

    # extract attribute type and name
    remaining_lines[0] = remaining_lines[0].sub(/attribute/, " ")
    match  = /\s*([^\s].*[^\s])\s+([^\s]+)\s*;/.match(remaining_lines[0])
    @ptype = match[1]
    @name  = match[2]
    remaining_lines.delete_at(0)

    if ($verbose)
      puts ("Attribute: #{@ptype} #{interface.name()}::#{@name}" +
	    (@is_readonly ? " (readonly)" : ""))
    end


    # the information wether this attribute raises exceptions on setting or
    # retrieval is contained in comments in lines immediately following the line
    # with the attribute declaration. Search for such comments:
    while (remaining_lines[0] =~ /\/\/\s*raises/)
      # next line contains "//raises"
      case (remaining_lines[0])
      when /setting/
	@raises_exception_on_setting = true
	puts ("...raises exception on setting") if ($verbose)
      when /retrieval/
	@raises_exception_on_retrieval = true
	puts ("...raises exception on retrieval") if ($verbose)
      end
      remaining_lines.delete_at(0)
    end
  end

  ####################
  def create_ruby_code()
    # We are cheating here. We pretend that reading or writing an attribute
    # is a method, and use Idl_Method to provide the appropriate Code.
    if (not is_readonly?)
      # Code for writing
      method_name = "set_" + @name
      idl_method = ["  void #{method_name}(in #{@ptype} #{@name})\n"]
      if (self.raises_exception_on_setting?)
	idl_method <<
	  "                                        raises(DOMException);\n"
      end
      idl_method << "  \n"
      method = Idl_Method.new(@idl_module, @interface,
			      idl_method, "is attribute")
      method.create_ruby_code()
    end

    # Code for reading
    method_name = @name
    idl_method = ["  #{ptype} #{method_name}()\n"]
    if (self.raises_exception_on_retrieval?)
      idl_method <<
	"                                        raises(DOMException);\n"
    end
    idl_method << "  \n"
    method = Idl_Method.new(@idl_module, @interface,
			    idl_method, "is attribute")
    method.create_ruby_code()
  end


  ###################
  def create_cpp_code(gdome_cpp_hh, gdome_cpp_cc)
    # We are cheating here. We pretend that reading or writing an attribute
    # is a method, and use Idl_Method to provide the appropriate Code.
    if (not is_readonly?)
      # Code for writing
      method_name = "set_" + @name
      idl_method = ["  void #{method_name}(in #{@ptype} #{@name})\n"]
      if (self.raises_exception_on_setting?)
	idl_method <<
	  "                                        raises(DOMException);\n"
      end
      idl_method << "  \n"
      method = Idl_Method.new(@idl_module, @interface,
			      idl_method, "is attribute")
      method.create_cpp_code(gdome_cpp_hh, gdome_cpp_cc)
    end

    # Code for reading
    method_name = @name
    idl_method = ["  #{ptype} #{method_name}()\n"]
    if (self.raises_exception_on_retrieval?)
      idl_method <<
	"                                        raises(DOMException);\n"
    end
    idl_method << "  \n"
    method = Idl_Method.new(@idl_module, @interface,
			    idl_method, "is attribute")
    method.create_cpp_code(gdome_cpp_hh, gdome_cpp_cc)
  end
end
