Scan, parse, and compile expression, then return this ExprStub upon success. Throws an CascadingException upon failure.
# File lib/cascading/expr_stub.rb, line 61 def compile evaluator self end
Evaluates this ExprStub given a hash mapping argument names to argument values. Names may be strings or symbols. Throws an CascadingException upon failure.
# File lib/cascading/expr_stub.rb, line 69 def eval(actual_args) actual_args = actual_args.inject({}) do |string_keys, (arg, value)| string_keys[arg.to_s] = specific_to_java(value, @types[arg.to_s]) string_keys end args, values = split_hash(actual_args) unused = validate_fields(args) return self.eval(actual_args.reject{ |arg, value| unused.include?(arg) }) unless unused.empty? evaluate(values) end
Extract Java names and types from @types hash. Cascading constructors often require two separate Java Arrays in this fashion.
# File lib/cascading/expr_stub.rb, line 26 def names_and_types names, types = split_hash(@types) [names.to_java(java.lang.String), types.to_java(java.lang.Class)] end
Prints the original input expression.
# File lib/cascading/expr_stub.rb, line 32 def to_s @input_expression end
Evaluates this ExprStub with default values for each actual argument. Values may be overridden with the optional actual_args argument, which accepts a hash like #eval. Throws an CascadingException upon failure.
# File lib/cascading/expr_stub.rb, line 84 def validate(actual_args = {}) self.eval(test_values.merge(actual_args)) end
Throws an exception if any arguments required by this ExprStub are missing from fields. Returns those fields which are unused. Throws an ExprArgException upon failure.
# File lib/cascading/expr_stub.rb, line 98 def validate_fields(fields) names = @types.keys.sort missing = names - fields raise ExprArgException.new("Expression '#{@expression}' is missing these fields: #{missing.inspect}\nRequires: #{names.inspect}, found: #{fields.inspect}") unless missing.empty? fields - names end
Given a scope, validates that the fields required by this ExprStub are available in the values fields of the scope. Returns those values fields which are unused in the expression.
# File lib/cascading/expr_stub.rb, line 91 def validate_scope(scope) validate_fields(scope.values_fields.to_a) end
Convenience constructor for an ExprStub that optionally performs validation. Takes a string to use as a Janino expression and an optional options hash.
The named options are:
A boolean indicating whether expression validation using default actual argument values should be performed. Defaults to true.
A hash mapping field names (or symbols) to the value that should be used for validation. Strings default to nil, so if you have previously filtered nulls you might use a marker value like ‘nulls_filtered’. Defaults to {}.
Example:
insert 'x_eq_y' => expr('x:string.equals(y:string)', :validate_with => { :x => 'nulls_filtered' })
# File lib/cascading/expr_stub.rb, line 51 def self.expr(expression, options = {}) options = { :validate => true, :validate_with => {} }.merge(options) expr_stub = expression.kind_of?(ExprStub) ? expression : ExprStub.new(expression).compile expr_stub.validate(options[:validate_with]) if options[:validate] puts "Expression validation is disabled for '#{expression}'" unless options[:validate] expr_stub end
ExprStub requires a Janino expression decorated with field types. For example:
expr('"Found: " + (x:int + y:int) + " " + z:string')
Type names are defined in Cascading::JAVA_TYPE_MAP.
# File lib/cascading/expr_stub.rb, line 9 def initialize(expression) @input_expression = expression @expression = expression.dup @types = {} # Simple regexp based parser for types JAVA_TYPE_MAP.each do |sym, klass| @expression.gsub!(/[A-Za-z0-9_]+:#{sym.to_s}/) do |match| name = match.split(/:/).first.gsub(/\s+/, "") @types[name] = klass match.gsub(/:#{sym.to_s}/, "") end end end