module Maven module Tools class Visitor def initialize( io = STDOUT ) @io = io end def indent @indent ||= '' end def inc @indent = @indent + ' ' end def dec @indent = @indent[ 0..-3 ] end def start_raw_tag( name, attr = {} ) @io << "#{indent}<#{name}" attr.each do |k,v| @io << "\n" vv = v.gsub( /"/, '"' ) @io << "#{indent} #{k.to_s[1..-1]}=\"#{vv}\"" end @io << ">\n" inc end def end_raw_tag( name ) dec @io << "#{indent}\n" end def start_tag( name, attr = {} ) start_raw_tag( camel_case_lower( name ), attr ) end def end_tag( name ) end_raw_tag( camel_case_lower( name ) ) end def tag( name, value ) if value != nil if value.respond_to? :to_xml @io << "#{indent}#{value.to_xml}\n" else name = camel_case_lower( name ) @io << "#{indent}<#{name}>#{escape_value( value )}\n" end end end def raw_tag( name, value ) unless value.nil? @io << "#{indent}<#{name}>#{escape_value( value )}\n" end end def camel_case_lower( str ) str = str.to_s str.split( '_' ).inject([]) do |buffer, e| buffer.push( buffer.empty? ? e : e.capitalize ) end.join end def accept_project( project ) accept( 'project', project ) @io.close if @io.respond_to? :close nil end def accept( name, model ) if model start_tag( name ) visit( model ) end_tag( name ) end end def accept_array( name, array ) unless array.empty? start_tag( name ) n = name.to_s.sub( /ies$/, 'y' ).sub( /s$/, '' ) case array.first when Maven::Tools::Base array.each do |i| start_tag( n ) visit( i ) end_tag( n ) end when Hash array.each do |i| accept_hash( n, i ) end else array.each do |i| tag( n, i ) end end end_tag( name ) end end def accept_raw_hash( name, hash ) unless hash.empty? attr = hash.select do |k, v| [ k, v ] if k.to_s.match( /^@/ ) end start_tag( name, attr ) hash.each do |k, v| case v when Array accept_array( k, v ) else raw_tag( k, v ) unless k.to_s.match( /^@/ ) end end end_tag( name ) end end def accept_hash( name, hash ) unless hash.empty? attr = hash.select do |k, v| [ k, v ] if k.to_s.match( /^@/ ) end # workaround error with :configuration => :gems => { ... } method = name == :gems ? :raw_tag : :tag start_tag( name, attr ) hash.each do |k, v| case v when Array accept_array( k, v ) when Hash accept_hash( k, v ) else send( method, k, v ) unless k.to_s.match( /^@/ ) end end end_tag( name ) end end def escape_value( value ) value = value.to_s.dup value.gsub!( /&/, '&' ) # undo double quote, somehow xyz.gemspec.rz have encoded values value.gsub!( /&(amp|lt|gt);/, '&\1;' ) value.gsub!( //, '>' ) value end def visit( model ) model.attributes.each do |k, v| if k == :properties accept_raw_hash( k, v ) else case v when Base accept( k, v ) when Array accept_array( k, v ) when Hash accept_hash( k, v ) else tag( k, v ) end end end end end end end