#! /usr/bin/env ruby # # ActiveFacts: Read a model (CQL, ORM, etc), run a compositor, then a generator # # Copyright (c) 2009 Clifford Heath. Read the LICENSE file. # ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) require 'bundler/setup' # Set up gems listed in the Gemfile. $:.unshift File.dirname(File.expand_path(__FILE__))+"/../lib" require 'activefacts/loadable' require 'activefacts/metamodel' require 'activefacts/compositions' require 'activefacts/generator' # Parse options into a hash, and values for each option into a hash options = {} while ARGV[0] =~ /^-/ option, value = ARGV.shift.split(/=/, 2) options[option.sub(/^-*/,'')] = (value =~ /,/ ? value.split(',') : Array(value)). inject({}){|h,s| k, v = s.split(/=/, 2); h[k] = v || true; h } end # Load and enumerate all available compositors: compositions_path = "activefacts/compositions" Loadable.new(compositions_path). enumerate. select do |filename| begin require(pathname = compositions_path+"/"+filename) rescue LoadError => e rescue Exception => e puts "Can't load #{pathname}: #{e.class}: #{e.message} #{e.backtrace[0]}" end end # Load and enumerate all available generators generators_path = "activefacts/generator" Loadable.new(generators_path). enumerate. select do |filename| begin require(pathname = generators_path+"/"+filename) rescue LoadError => e rescue Exception => e puts "Can't load #{pathname}: #{e.class}: #{e.message} #{e.backtrace[0]}" end end if options['help'] puts "Available compositors:\n\t#{ActiveFacts::Compositions.compositors.keys.sort*"\n\t"}\n\n" puts "Available generators:\n\t#{ActiveFacts::Generators.generators.keys.sort*"\n\t"}\n\n" exit end # Arrange the requested compositors and generators: compositors = [] generators = [] options.clone.each do |option, mode| if action = ActiveFacts::Compositions.compositors[option] options.delete(option) compositors << [action, mode] elsif action = ActiveFacts::Generators.generators[option] options.delete(option) generators << [action, mode] end if mode && mode['help'] puts "REVISIT: Help for #{option} is not yet available" end end # Process each input file: ARGV.each do |arg| filename, input_options = *arg.split(/=/, 2) # Load the correct file type input method pathname, basename, extension = * /(?:(.*)[\/\\])?(.*)\.([^.]*)$/.match(filename).captures input_handler = "activefacts/input/#{extension}" require input_handler input_class = extension.upcase input_klass = ActiveFacts::Input.const_get(input_class.to_sym) raise "Expected #{input_handler} to define #{input_class}" unless input_klass # Read the input file: vocabulary = if input_klass begin input_klass.readfile(filename, *input_options) rescue => e $stderr.puts "#{e.message}" if trace :exception $stderr.puts "\t#{e.backtrace*"\n\t"}" else $stderr.puts "\t#{e.backtrace[0]}" end exit 1 end end exit 0 unless vocabulary vocabulary.finalise unless vocabulary == true # Run each compositor compositors.each do |compositor_klass, mode| compositor = compositor_klass.new(vocabulary.constellation, basename, mode||{}) compositor.generate # Run each generator generators.each do |generator, mode| output = generator.new(compositor.composition, mode||{}).generate puts output if output end end end