Ruby Yaml to Enum

From EggeWiki
Revision as of 21:27, 21 May 2007 by Brianegge (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
#!/bin/env ruby
#
# Single value enums are frequently needed and they usually require additional code to lookup or access the enum
# based on a value.  This Ruby script generates a .java enum based on a YAML input file
#
require 'yaml'
require 'erb'

def java_name(s)
    s.upcase.gsub('/', '_')
end

template = ERB.new <<-EOF
package <%= @package %>;

public enum <%= @enum %> {
    EMPTY(""),<% @enums.each do |i| %>
    <%= java_name(i) %>("<%= i %>")<%= (i == @enums[-1]) ? ';' : ',' %><% end %>

    private final String value;

    <%= @enum %>(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return value;
    }

    public static <%= @enum %> getValue(String value) {
        for (<%= @enum %> e : values()) {
            if (e.value.equals(value)) {
                return e;
            }
        }
        return EMPTY;
    }

}

EOF

if ARGV.size == 0 then
    srcDir = 'C:\\dev\\src\\java\\com'
    destDir = 'C:\\dev\\generated-src\\java\\com'
else
    srcDir = ARGV[0]
    destDir = ARGV[1]
end

class Fields
    attr_accessor :enums, :name, :package, :enum
    def initialize(file)
        @name = /(com.*)/.match( file.gsub('\\', '.').gsub('/', '.') )[1].gsub(/\.yml$/, '.java')
        @package = @name.split('.')[0..-3].join('.')
        @enum = @name.split('.')[-2]
    end
    # Support templating of member data.
    def get_binding
        binding
    end
end

if !File.directory?(destDir) then
    Dir.mkdir(destDir)
end

Dir.entries(srcDir).select{|f| File.file?(File.join(srcDir, f)) && File.extname(f) == ".yml" }.each do |f|

    file = File.join(srcDir, f)

    data = Fields.new(file)
    File.open( file, "r" ) do |yf|
        data.enums = YAML::load( yf )
        output = template.result(data.get_binding)
        destFile = File.join(destDir, data.enum + '.java')
        if !File.exists?(destFile) || File.read(destFile) != output then
            File.open(destFile, 'a+') do |dest|
                dest.write output
                dest.truncate(dest.pos)
            end
            puts "Updated #{destFile}"
        else
            puts "#{destFile} is up to date"
        end
    end
end

Sample Colors.yml

 - red
 - green
 - blue