require 'facets' module Ivy # Base class with general logic to call a Ivy ant target class Target attr_reader :params def initialize(ant) @ant = ant end # Executes this ivy target with given parameters returning a result. # __params__ can be a single Hash or an Array with or without a Hash as last value. # every value in array will be converted to string and set to __true__. # # I.e. [:force, 'validate', {'name' => 'Blub'}] # results in parameters {'force'=>true, 'validate' => true, 'name'=>'Blub'} def execute(*params) @params = {} params.pop.each { |key, value| @params[key] = value } if Hash === params.last params.each { |key| @params[key.to_s] = true } validate before_hook execute_ivy create_return_values ensure after_hook end protected # Validates provided hash of parameters, raises an exception if any mandatory parameter is # missing or an unknown parameter has been provided. def validate unknown = params.keys - symbols(parameter) raise ArgumentError, "Unknown parameters '#{unknown.join(', ')}' for #{self.class}" unless unknown.empty? missing = symbols(mandatory_parameter).find_all { |p| params.keys.member?(p) == false } raise ArgumentError, "Missing mandatory parameters '#{missing.join(', ')}' for #{self.class}" unless missing.empty? end # Hook method called after validation but before #execute_ivy # overwrite for special actions needed def before_hook end # After hook is always called for #execute within +ensure+ block # overwrite for special clean up def after_hook end # Helper to call the nested ant targets recursively if nessecary. Must be called within +do+ +end+ # block of ant target to work. def call_nested(nested) if nested nested.each do |method, paramlist| [paramlist].flatten.each do |params| if params.member? :nested p = params.dup nest = p.delete(:nested) @ant.send(method, p, &lambda {call_nested(nest)}) else @ant.send(method, params) end end end end end # Creates the result for the execution by default it iterates of the ant properties and fetches # all properties that match the result properties for target as a hash. Overwrite to provide # a different result def create_return_values result_properties end # Fetches all result properties for called target and returns them as hash def result_properties result = ant_properties.map do |p| rp = result_property_values.find { |rp| rp.matcher === p[0] } rp ? [p[0], rp.parse(p[1])].flatten : nil end.compact.to_h(:multi) result.update_values do |v| case v.size when 0 nil when 1 v[0] else v end end result end def mandatory_parameter parameter.find_all {|p| p.mandatory? } end def symbols(params) params.map{|p| p.symbol} end def ant_properties @ant.project.properties end def ant_references @ant.project.references end end COMMA_SPLITTER = Proc.new {|value| value.to_s.split(',').map(&:strip)} Parameter = Struct.new(:symbol, :mandatory) do def mandatory? mandatory end end ResultValue = Struct.new(:matcher, :parser) do def parse(value) parser ? parser.call(value) : value end end end