# encoding: ASCII-8BIT # XSD4R - Generating class definition code # Copyright (C) 2000-2007 NAKAMURA, Hiroshi . # This program is copyrighted free software by NAKAMURA, Hiroshi. You can # redistribute it and/or modify it under the same terms of Ruby's license; # either the dual license version in 2003, or any later version. require 'xsd/codegen/gensupport' require 'xsd/codegen/moduledef' require 'xsd/codegen/methoddef' module XSD module CodeGen class ClassDef < ModuleDef include GenSupport def initialize(name, baseclass = nil) super(name) @baseclass = baseclass @classvar = [] @attrdef = [] end def def_classvar(var, value) var = var.sub(/\A@@/, "") unless safevarname?(var) raise ArgumentError.new("#{var} seems to be unsafe") end @classvar << [var, value] end def def_attr(attrname, writable = true, varname = nil) unless safevarname?(varname || attrname) raise ArgumentError.new("#{varname || attrname} seems to be unsafe") end @attrdef << [attrname, writable, varname] end def dump buf = "" unless @requirepath.empty? buf << dump_requirepath end buf << dump_emptyline unless buf.empty? package = @name.split(/::/)[0..-2] buf << dump_package_def(package) unless package.empty? buf << dump_comment if @comment buf << dump_class_def spacer = false unless @classvar.empty? spacer = true buf << dump_classvar end unless @const.empty? buf << dump_emptyline if spacer spacer = true buf << dump_const end unless @innermodule.empty? buf << dump_emptyline # always add 1 empty line spacer = true buf << dump_innermodule end unless @code.empty? buf << dump_emptyline if spacer spacer = true buf << dump_code end unless @attrdef.empty? buf << dump_emptyline if spacer spacer = true buf << dump_attributes end unless @methoddef.empty? buf << dump_emptyline if spacer spacer = true buf << dump_methods end buf << dump_class_def_end buf << dump_package_def_end(package) unless package.empty? buf.gsub(/^\s+$/, '') end private def dump_class_def name = @name.to_s.split(/::/) if @baseclass format("class #{name.last} < #{@baseclass}") else format("class #{name.last}") end end def dump_class_def_end str = format("end") end def dump_classvar dump_static( @classvar.collect { |var, value| %Q(@@#{var.sub(/^@@/, "")} = #{dump_value(value)}) }.join("\n") ) end def dump_attributes str = "" @attrdef.each do |attrname, writable, varname| varname ||= attrname if attrname == varname str << format(dump_accessor(attrname, writable), 2) end end @attrdef.each do |attrname, writable, varname| varname ||= attrname if attrname != varname str << "\n" unless str.empty? str << format(dump_attribute(attrname, writable, varname), 2) end end str end def dump_accessor(attrname, writable) if writable "attr_accessor :#{attrname}" else "attr_reader :#{attrname}" end end def dump_attribute(attrname, writable, varname) str = nil mr = MethodDef.new(attrname) mr.definition = "@#{varname}" str = mr.dump if writable mw = MethodDef.new(attrname + "=", 'value') mw.definition = "@#{varname} = value" str << "\n" + mw.dump end str end end end end if __FILE__ == $0 require 'xsd/codegen/classdef' include XSD::CodeGen c = ClassDef.new("Foo::Bar::HobbitName", String) c.def_require("foo/bar") c.comment = <<-EOD foo bar baz EOD c.def_const("FOO", 1) c.def_classvar("@@foo", "var".dump) c.def_classvar("baz", "1".dump) c.def_attr("Foo", true, "foo") c.def_attr("bar") c.def_attr("baz", true) c.def_attr("Foo2", true, "foo2") c.def_attr("foo3", false, "foo3") c.def_method("foo") do <<-EOD foo.bar = 1 \tbaz.each do |ele| \t ele end EOD end c.def_method("baz", "qux") do <<-EOD [1, 2, 3].each do |i| p i end EOD end m = MethodDef.new("qux", "quxx", "quxxx") do <<-EOD p quxx + quxxx EOD end m.comment = "hello world\n123" c.add_method(m) c.def_code <<-EOD Foo.new Bar.z EOD c.def_code <<-EOD Foo.new Bar.z EOD c.def_privatemethod("foo", "baz", "*arg", "&block") puts c.dump end