lib/jaxb2ruby/classes.rb
require "forwardable"
module JAXB2Ruby
class ClassName < String # :nodoc:
attr :module
attr :outter_class # if java inner class, if any
attr :name # module + outter_class + basename
attr :basename
# Turn a java class name into a ruby class name, with accessors for various parts
def initialize(java_name, rubymod = nil)
pkg = java_name.split(JAVA_PKG_SEP)
pkg = rubymod ? [rubymod, ns2mod(pkg[-1])] : pkg.map { |part| ns2mod(part) }
parts = pkg.pop.split(JAVA_CLASS_SEP)
@basename = parts.pop
@outter_class = parts.join(RUBY_PKG_SEP)
@module = rubymod || pkg.join(RUBY_PKG_SEP)
@name = [@module, @outter_class, @basename].reject(&:empty?).join(RUBY_PKG_SEP)
super @name
end
private
def ns2mod(pkg)
pkg.sub(/\A_/, "V").camelize
end
end
class Namespace < String # :nodoc:
counter = 0
@@prefixes = Hash.new { |h,ns| h[ns] = "ns#{counter+=1}".freeze }
attr :name
attr :prefix
def initialize(name)
@name = name
@prefix = @@prefixes[name]
super
end
end
class Node
attr :type
attr :name
attr :local_name
attr :namespace
attr :accessor
attr :default
def initialize(name, options = {})
@name = @local_name = name
@accessor = (options[:accessor] || name).underscore
# If this conflicts with a Java keyword it will start with an underscore
@accessor.sub!(/\A_/, "")
@namespace = options[:namespace]
@name = sprintf "%s:%s", @namespace.prefix, @local_name if @namespace
@default = options[:default]
@required = !!options[:required]
@type = options[:type]
# TODO: this isn't used. Future plans?
@array = !!options[:array]
@hash = false
# Uhhhh, I think this might need some revisiting, esp. with xsd:enumeration
if @type.is_a?(Array)
@accessor = @accessor.pluralize
if @type.one?
@array = true
@type = @type.shift
else
@hash = true
end
end
end
def hash?
@hash
end
def array?
@array
end
def required?
@required
end
end
class Attribute < Node; end
class Element < Node
attr :children
attr :attributes
def initialize(name, options = {})
super
@text = !!options[:text]
@root = !!options[:root]
@nillable = !!options[:nillable]
@children = options[:children] || []
@attributes = options[:attributes] || []
end
def nillable?
@nillable
end
def root?
@root
end
def text?
@text
end
end
class RubyClass
extend Forwardable
attr :module
attr :outter_class
attr :superclass
attr :element
def_delegators :@type, :name, :basename, :to_s
def initialize(type, element, dependencies = nil, superclass = nil)
@type = type
@element = element
@dependencies = dependencies || []
@superclass = superclass
@module = @type.module.dup unless @type.module.empty?
@outter_class = @type.outter_class.dup unless @type.outter_class.empty?
[@module, @outter_class].each do |v|
v.extend Enumerable
# v may be NilClass
def v.each(&block)
( nil? ? [] : split(RUBY_PKG_SEP) ).each(&block)
end
end
end
def filename
"#{basename.underscore}.rb"
end
def directory
File.dirname(path)
end
# This class's path, for passing to +require+.
# <code>Foo::Bar::OneTwo</code> will be turned into <code>foo/bar/one_two</code>.
#
def path
@path ||= make_path(@module.to_a.concat(outter_class.to_a).push(filename))
end
# Paths for all of this class's dependencies, for passing to +require+.
#
def requires
@requires ||= @dependencies.map { |e| make_path(e.split(RUBY_PKG_SEP)) }.sort.uniq
end
private
def make_path(modules)
modules.map { |name| name.underscore }.join("/")
end
end
end