fiksu-af 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.travis.yml +14 -0
- data/Gemfile +22 -0
- data/LICENSE +30 -0
- data/README.md +175 -0
- data/Rakefile +42 -0
- data/examples/af_script_with_options.rb +73 -0
- data/examples/af_side_component.rb +16 -0
- data/examples/my_application.rb +8 -0
- data/fiksu-af.gemspec +27 -0
- data/lib/fiksu-af/application/component.rb +95 -0
- data/lib/fiksu-af/application.rb +361 -0
- data/lib/fiksu-af/deprecated.rb +15 -0
- data/lib/fiksu-af/get_options.rb +68 -0
- data/lib/fiksu-af/logging/configurator.rb +152 -0
- data/lib/fiksu-af/logging.rb +13 -0
- data/lib/fiksu-af/option_parser/columnizer.rb +36 -0
- data/lib/fiksu-af/option_parser/dsl.rb +290 -0
- data/lib/fiksu-af/option_parser/get_options.rb +65 -0
- data/lib/fiksu-af/option_parser/helper.rb +80 -0
- data/lib/fiksu-af/option_parser/instance_variable_setter.rb +117 -0
- data/lib/fiksu-af/option_parser/interface.rb +63 -0
- data/lib/fiksu-af/option_parser/option.rb +40 -0
- data/lib/fiksu-af/option_parser/option_check.rb +66 -0
- data/lib/fiksu-af/option_parser/option_finder.rb +82 -0
- data/lib/fiksu-af/option_parser/option_group.rb +37 -0
- data/lib/fiksu-af/option_parser/option_select.rb +68 -0
- data/lib/fiksu-af/option_parser/option_store.rb +89 -0
- data/lib/fiksu-af/option_parser/option_type.rb +59 -0
- data/lib/fiksu-af/option_parser.rb +145 -0
- data/lib/fiksu-af/q_thread/base.rb +20 -0
- data/lib/fiksu-af/q_thread/interface.rb +23 -0
- data/lib/fiksu-af/q_thread/message.rb +14 -0
- data/lib/fiksu-af/q_thread/message_handler.rb +30 -0
- data/lib/fiksu-af/tcp_command/client.rb +49 -0
- data/lib/fiksu-af/tcp_command/server.rb +119 -0
- data/lib/fiksu-af/thread_pool.rb +102 -0
- data/lib/fiksu-af/version.rb +4 -0
- data/lib/fiksu-af.rb +12 -0
- data/logging/af.yml +32 -0
- data/spec/dummy/.rspec +1 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +59 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database-sample.yml +32 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +31 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +35 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/spec/spec_helper.rb +32 -0
- data/spec/lib/af/application_spec.rb +60 -0
- data/spec/lib/af/get_options_spec.rb +24 -0
- data/spec/lib/af/option_parser/option_check_spec.rb +50 -0
- data/spec/lib/af/option_parser/option_select_spec.rb +51 -0
- data/spec/spec_helper.rb +33 -0
- metadata +288 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
module ::Af::OptionParser
|
2
|
+
class OptionCheck < InstanceVariableSetter
|
3
|
+
FACTORY_SETTABLES = [
|
4
|
+
:action,
|
5
|
+
:targets,
|
6
|
+
:error_message,
|
7
|
+
:block
|
8
|
+
]
|
9
|
+
|
10
|
+
attr_accessor *FACTORY_SETTABLES
|
11
|
+
attr_accessor :var_name
|
12
|
+
|
13
|
+
def initialize(var_name, parameters = {})
|
14
|
+
super(parameters)
|
15
|
+
@var_name = var_name
|
16
|
+
end
|
17
|
+
|
18
|
+
#-------------------------
|
19
|
+
# *** Instance Methods ***
|
20
|
+
#+++++++++++++++++++++++++
|
21
|
+
|
22
|
+
def set_instance_variables(parameters = {})
|
23
|
+
super(parameters, FACTORY_SETTABLES)
|
24
|
+
end
|
25
|
+
|
26
|
+
def merge(that_option)
|
27
|
+
super(that_option, FACTORY_SETTABLES)
|
28
|
+
end
|
29
|
+
|
30
|
+
# This methods validates the selected options based
|
31
|
+
# on the chosen action.
|
32
|
+
#
|
33
|
+
# Available actions: requires, excludes
|
34
|
+
#
|
35
|
+
# If an invalidation occurs, an OptionCheckError is raised
|
36
|
+
# with a specific message.
|
37
|
+
def validate
|
38
|
+
# If an option_check is used, the target_variable must be instantiated
|
39
|
+
if target_container.try(target_variable.to_sym).blank?
|
40
|
+
raise OptionCheckError.new("Option --#{target_variable} must be specified")
|
41
|
+
end
|
42
|
+
|
43
|
+
# If an option_check is used, an array of options must be given
|
44
|
+
if targets.empty?
|
45
|
+
raise OptionCheckError.new("An array of #{action.to_s[0..-2]}d options must be specified")
|
46
|
+
end
|
47
|
+
|
48
|
+
if action == :requires
|
49
|
+
# Each target option must be specified
|
50
|
+
targets.each do |target|
|
51
|
+
if target_container.try(target.to_sym).blank?
|
52
|
+
raise OptionCheckError.new("You must specify these options: --#{targets.join(', --')}")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
elsif action == :excludes
|
56
|
+
# None of the target options can be specified
|
57
|
+
targets.each do |target|
|
58
|
+
if target_container.try(target.to_sym).present?
|
59
|
+
raise OptionCheckError.new("You cannot specify these options: --#{targets.join(', --')}")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module ::Af::OptionParser
|
2
|
+
class OptionFinder
|
3
|
+
|
4
|
+
def initialize(class_path)
|
5
|
+
@class_path = class_path
|
6
|
+
@all_options = {}
|
7
|
+
@all_option_groups = {}
|
8
|
+
@all_option_checks = {}
|
9
|
+
@all_option_selects = {}
|
10
|
+
|
11
|
+
# class_path:
|
12
|
+
# Class: include class and all its ancestors options
|
13
|
+
@class_path.each do |klass|
|
14
|
+
klass.ancestors.reverse.each do |ancestor|
|
15
|
+
option_store = OptionStore.find(ancestor)
|
16
|
+
if option_store
|
17
|
+
options = option_store.options
|
18
|
+
if options.present?
|
19
|
+
options.each do |long_name, option|
|
20
|
+
merged_option = @all_options[long_name] ||= Option.new(long_name)
|
21
|
+
merged_option.set_instance_variables(option)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
option_groups = option_store.option_groups
|
26
|
+
if option_groups.present?
|
27
|
+
option_groups.each do |name, option_group|
|
28
|
+
merged_option_group = @all_option_groups[name] ||= OptionGroup.new(name)
|
29
|
+
merged_option_group.set_instance_variables(option_group)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
option_checks = option_store.option_checks
|
34
|
+
if option_checks.present?
|
35
|
+
option_checks.each do |name, option_check|
|
36
|
+
merged_option_check = @all_option_checks[name] ||= OptionCheck.new(name)
|
37
|
+
merged_option_check.set_instance_variables(option_check)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
option_selects = option_store.option_selects
|
42
|
+
if option_selects.present?
|
43
|
+
option_selects.each do |name, option_select|
|
44
|
+
merged_option_select = @all_option_selects[name] ||= OptionSelect.new(name)
|
45
|
+
merged_option_select.set_instance_variables(option_select)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#-------------------------
|
54
|
+
# *** Instance Methods ***
|
55
|
+
#+++++++++++++++++++++++++
|
56
|
+
|
57
|
+
def all_options
|
58
|
+
return @all_options.values
|
59
|
+
end
|
60
|
+
|
61
|
+
def all_option_groups
|
62
|
+
return @all_option_groups.values
|
63
|
+
end
|
64
|
+
|
65
|
+
def all_option_checks
|
66
|
+
return @all_option_checks.values
|
67
|
+
end
|
68
|
+
|
69
|
+
def all_option_selects
|
70
|
+
return @all_option_selects.values
|
71
|
+
end
|
72
|
+
|
73
|
+
def all_options_by_long_name
|
74
|
+
return @all_options
|
75
|
+
end
|
76
|
+
|
77
|
+
def find_option(long_name)
|
78
|
+
return all_options_by_long_name[long_name]
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ::Af::OptionParser
|
2
|
+
class OptionGroup
|
3
|
+
FACTORY_SETTABLES = [:title,
|
4
|
+
:priority,
|
5
|
+
:description,
|
6
|
+
:hidden,
|
7
|
+
:disabled]
|
8
|
+
attr_accessor *FACTORY_SETTABLES
|
9
|
+
attr_accessor :group_name
|
10
|
+
|
11
|
+
def initialize(group_name, parameters = {})
|
12
|
+
@group_name = group_name
|
13
|
+
set_instance_variables(parameters)
|
14
|
+
end
|
15
|
+
|
16
|
+
#-------------------------
|
17
|
+
# *** Instance Methods ***
|
18
|
+
#+++++++++++++++++++++++++
|
19
|
+
|
20
|
+
def set_instance_variables(parameters = {})
|
21
|
+
parameters.select do |name,value|
|
22
|
+
FACTORY_SETTABLES.include? name
|
23
|
+
end.each do |name,value|
|
24
|
+
instance_variable_set("@#{name}", value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def merge(that_option_group)
|
29
|
+
FACTORY_SETTABLES.each do |name|
|
30
|
+
if that_option_group.instance_variable_defined?("@#{name}")
|
31
|
+
self.send("#{name}=", that_option_group.send(name))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module ::Af::OptionParser
|
2
|
+
class OptionSelect < InstanceVariableSetter
|
3
|
+
FACTORY_SETTABLES = [
|
4
|
+
:action,
|
5
|
+
:targets,
|
6
|
+
:error_message
|
7
|
+
]
|
8
|
+
|
9
|
+
attr_accessor *FACTORY_SETTABLES
|
10
|
+
attr_accessor :var_name
|
11
|
+
|
12
|
+
def initialize(var_name, parameters = {})
|
13
|
+
super(parameters)
|
14
|
+
@var_name = var_name
|
15
|
+
end
|
16
|
+
|
17
|
+
#-------------------------
|
18
|
+
# *** Instance Methods ***
|
19
|
+
#+++++++++++++++++++++++++
|
20
|
+
|
21
|
+
def set_instance_variables(parameters = {})
|
22
|
+
super(parameters, FACTORY_SETTABLES)
|
23
|
+
end
|
24
|
+
|
25
|
+
def merge(that_option)
|
26
|
+
super(that_option, FACTORY_SETTABLES)
|
27
|
+
end
|
28
|
+
|
29
|
+
# This methods validates the selected options based
|
30
|
+
# on the chosen action.
|
31
|
+
#
|
32
|
+
# Available actions: one_of, none_or_one_of, one_or_more_of
|
33
|
+
#
|
34
|
+
# If an invalidation occurs, an OptionSelectError is raised
|
35
|
+
# with a specific message.
|
36
|
+
def validate
|
37
|
+
# If an option_select is used, an array of options must be given
|
38
|
+
if targets.blank?
|
39
|
+
raise OptionSelectError.new("An array of options must be specified")
|
40
|
+
end
|
41
|
+
|
42
|
+
# Populate the options_set array with all instantiated class/instance variables
|
43
|
+
options_set = []
|
44
|
+
targets.each do |target|
|
45
|
+
if target_container.try(target.to_sym).present?
|
46
|
+
options_set << target
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Assign instantiated options to an instance variable
|
51
|
+
if options_set.size == 1
|
52
|
+
value = options_set.first
|
53
|
+
else
|
54
|
+
value = options_set
|
55
|
+
end
|
56
|
+
target_container.instance_variable_set("@#{target_variable}", value)
|
57
|
+
|
58
|
+
if action == :one_of && options_set.size != 1
|
59
|
+
raise OptionSelectError.new("You must specify only one of these options: --#{targets.join(', --')}")
|
60
|
+
elsif action == :none_or_one_of && options_set.size > 1
|
61
|
+
raise OptionSelectError.new("You must specify no more than one of these options: --#{targets.join(', --')}")
|
62
|
+
elsif action == :one_or_more_of && options_set.size < 1
|
63
|
+
raise OptionSelectError.new("You must specify at least one of these options: --#{targets.join(', --')}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module ::Af::OptionParser
|
2
|
+
class OptionStore
|
3
|
+
attr_reader :options,
|
4
|
+
:option_groups,
|
5
|
+
:containing_class,
|
6
|
+
:option_checks,
|
7
|
+
:option_selects
|
8
|
+
|
9
|
+
@@option_stores = {}
|
10
|
+
|
11
|
+
def initialize(containing_class)
|
12
|
+
@containing_class = containing_class
|
13
|
+
@options = {}
|
14
|
+
@option_groups = {}
|
15
|
+
@option_checks = {}
|
16
|
+
@option_selects = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
#----------------------
|
20
|
+
# *** Class Methods ***
|
21
|
+
#++++++++++++++++++++++
|
22
|
+
|
23
|
+
def self.find(containing_class)
|
24
|
+
return @@option_stores[containing_class]
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.factory(containing_class)
|
28
|
+
@@option_stores[containing_class] ||= new(containing_class)
|
29
|
+
return @@option_stores[containing_class]
|
30
|
+
end
|
31
|
+
|
32
|
+
#-------------------------
|
33
|
+
# *** Instance Methods ***
|
34
|
+
#+++++++++++++++++++++++++
|
35
|
+
|
36
|
+
def find_option(long_name)
|
37
|
+
return options[long_name]
|
38
|
+
end
|
39
|
+
|
40
|
+
def construct_option(long_name)
|
41
|
+
@options[long_name] ||= {}
|
42
|
+
return @options[long_name]
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_option(long_name)
|
46
|
+
return find_option(long_name) || construct_option(long_name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_option_group(long_name)
|
50
|
+
return option_groups[long_name]
|
51
|
+
end
|
52
|
+
|
53
|
+
def construct_option_group(name)
|
54
|
+
@option_groups[name] ||= {}
|
55
|
+
return @option_groups[name]
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_option_group(long_name)
|
59
|
+
return find_option_group(long_name) || construct_option_group(long_name)
|
60
|
+
end
|
61
|
+
|
62
|
+
def find_option_check(var_name)
|
63
|
+
return option_checks[var_name]
|
64
|
+
end
|
65
|
+
|
66
|
+
def construct_option_check(var_name)
|
67
|
+
@option_checks[var_name] ||= {}
|
68
|
+
return @option_checks[var_name]
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_option_check(var_name)
|
72
|
+
return find_option_check(var_name) || construct_option_check(var_name)
|
73
|
+
end
|
74
|
+
|
75
|
+
def find_option_select(var_name)
|
76
|
+
return option_selects[var_name]
|
77
|
+
end
|
78
|
+
|
79
|
+
def construct_option_select(var_name)
|
80
|
+
@option_selects[var_name] ||= {}
|
81
|
+
return @option_selects[var_name]
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_option_select(var_name)
|
85
|
+
return find_option_select(var_name) || construct_option_select(var_name)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module ::Af::OptionParser
|
2
|
+
class OptionType
|
3
|
+
attr_reader :name,
|
4
|
+
:short_name,
|
5
|
+
:argument_note,
|
6
|
+
:evaluate_method,
|
7
|
+
:handler_method
|
8
|
+
|
9
|
+
@@types = []
|
10
|
+
|
11
|
+
def initialize(name, short_name, argument_note, evaluate_method, handler_method)
|
12
|
+
@name = name
|
13
|
+
@short_name = short_name
|
14
|
+
@argument_note = argument_note
|
15
|
+
@evaluate_method = evaluate_method
|
16
|
+
@handler_method = handler_method
|
17
|
+
@@types << self
|
18
|
+
end
|
19
|
+
|
20
|
+
#----------------------
|
21
|
+
# *** Class Methods ***
|
22
|
+
#++++++++++++++++++++++
|
23
|
+
|
24
|
+
def self.types
|
25
|
+
return @@types
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.valid_option_type_names
|
29
|
+
return types.map(&:short_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.find_by_value(value)
|
33
|
+
return types.find{ |t| t.handle?(value) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.find_by_short_name(short_name)
|
37
|
+
return types.find{ |t| t.short_name == short_name }
|
38
|
+
end
|
39
|
+
|
40
|
+
#-------------------------
|
41
|
+
# *** Instance Methods ***
|
42
|
+
#+++++++++++++++++++++++++
|
43
|
+
|
44
|
+
def evaluate_argument(argument, option)
|
45
|
+
if @evaluate_method.is_a? Symbol
|
46
|
+
return argument.send(@evaluate_method)
|
47
|
+
end
|
48
|
+
return @evaluate_method.call(argument, option)
|
49
|
+
end
|
50
|
+
|
51
|
+
def handle?(value)
|
52
|
+
if @handler_method.is_a? Class
|
53
|
+
return value.is_a? @handler_method
|
54
|
+
end
|
55
|
+
return @handler_method.call(value)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'fiksu-af/option_parser/columnizer.rb'
|
2
|
+
require 'fiksu-af/option_parser/dsl.rb'
|
3
|
+
require 'fiksu-af/option_parser/get_options.rb'
|
4
|
+
require 'fiksu-af/option_parser/helper.rb'
|
5
|
+
require 'fiksu-af/option_parser/interface.rb'
|
6
|
+
require 'fiksu-af/option_parser/instance_variable_setter.rb'
|
7
|
+
require 'fiksu-af/option_parser/option.rb'
|
8
|
+
require 'fiksu-af/option_parser/option_check.rb'
|
9
|
+
require 'fiksu-af/option_parser/option_select.rb'
|
10
|
+
require 'fiksu-af/option_parser/option_group.rb'
|
11
|
+
require 'fiksu-af/option_parser/option_type.rb'
|
12
|
+
require 'fiksu-af/option_parser/option_store.rb'
|
13
|
+
require 'fiksu-af/option_parser/option_finder.rb'
|
14
|
+
|
15
|
+
module Af::OptionParser
|
16
|
+
include Interface
|
17
|
+
|
18
|
+
class Error < ArgumentError; end
|
19
|
+
class MisconfiguredOptionError < Error; end
|
20
|
+
class BadChoiceError < Error; end
|
21
|
+
class UndeterminedArgumentTypeError < Error; end
|
22
|
+
class OptionCheckError < Error; end
|
23
|
+
class OptionSelectError < Error; end
|
24
|
+
|
25
|
+
def self.included(base)
|
26
|
+
add_option_types
|
27
|
+
base.extend(Dsl)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.add_option_types
|
31
|
+
OptionType.new(:Switch, :switch, "", lambda {|argument,option|
|
32
|
+
if ["t", "true", "yes", "on"].include?(argument.to_s.downcase)
|
33
|
+
return true
|
34
|
+
elsif ["f", "false", "no", "off"].include?(argument.to_s.downcase)
|
35
|
+
return false
|
36
|
+
else
|
37
|
+
if option.default_value == nil
|
38
|
+
return true
|
39
|
+
else
|
40
|
+
return !option.default_value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
}, lambda{ |value| return (value.is_a?(TrueClass) || value.is_a?(FalseClass)) })
|
44
|
+
OptionType.new(:Boolean, :boolean, "", lambda {|argument,option|
|
45
|
+
if ["t", "true", "yes", "on"].include?(argument.to_s.downcase)
|
46
|
+
return true
|
47
|
+
elsif ["f", "false", "no", "off"].include?(argument.to_s.downcase)
|
48
|
+
return false
|
49
|
+
else
|
50
|
+
if option.default_value == nil
|
51
|
+
return true
|
52
|
+
else
|
53
|
+
return !option.default_value
|
54
|
+
end
|
55
|
+
end
|
56
|
+
}, lambda{ |value| return (value.is_a?(TrueClass) || value.is_a?(FalseClass)) })
|
57
|
+
OptionType.new(:Int, :int, "INTEGER", :to_i, Fixnum)
|
58
|
+
OptionType.new(:Integer, :integer, "INTEGER", :to_i, Fixnum)
|
59
|
+
OptionType.new(:Float, :float, "NUMBER", :to_f, Float)
|
60
|
+
OptionType.new(:Number, :number, "NUMBER", :to_f, Float)
|
61
|
+
OptionType.new(:String, :string, "STRING", :to_s, String)
|
62
|
+
OptionType.new(:Uri, :uri, "URI", lambda {|argument, option_parser| return URI.parse(argument) }, URI::HTTP)
|
63
|
+
OptionType.new(:Date, :date, "DATE", lambda {|argument, option_parser| return Time.zone.parse(argument).to_date }, Date)
|
64
|
+
OptionType.new(:Time, :time, "TIME", lambda {|argument, option_parser| return Time.zone.parse(argument) }, Time)
|
65
|
+
OptionType.new(:DateTime, :datetime, "DATETIME", lambda {|argument, option_parser| return Time.zone.parse(argument) }, DateTime)
|
66
|
+
OptionType.new(:Choice,
|
67
|
+
:choice,
|
68
|
+
"CHOICE",
|
69
|
+
lambda { |argument, option_parser|
|
70
|
+
choice = argument.to_sym
|
71
|
+
choices = option_parser.choices
|
72
|
+
unless choices.blank?
|
73
|
+
unless choices.include? choice
|
74
|
+
raise BadChoiceError.new("invalid choice '#{choice}' not in list of choices: #{choices.map(&:to_s).join(', ')}")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
return choice
|
78
|
+
}, Symbol)
|
79
|
+
OptionType.new(:Hash,
|
80
|
+
:hash,
|
81
|
+
"K1=V1,K2=V2,K3=V3...",
|
82
|
+
lambda { |argument, option_parser| return Hash[argument.split(',').map{ |ai| ai.split('=') }] },
|
83
|
+
Hash)
|
84
|
+
OptionType.new(:Ints,
|
85
|
+
:ints,
|
86
|
+
"INT1,INT2,INT3...",
|
87
|
+
lambda { |argument, option_parser| return argument.split(',').map(&:to_i) },
|
88
|
+
lambda { |value| return value.class == Array && value.first.class == Fixnum })
|
89
|
+
OptionType.new(:Integers,
|
90
|
+
:integers,
|
91
|
+
"INT1,INT2,INT3...",
|
92
|
+
lambda { |argument, option_parser| return argument.split(',').map(&:to_i) },
|
93
|
+
lambda { |value| return value.class == Array && value.first.class == Fixnum })
|
94
|
+
OptionType.new(:Floats,
|
95
|
+
:floats,
|
96
|
+
"NUM1,NUM2,NUM3...",
|
97
|
+
lambda { |argument, option_parser| return argument.split(',').map(&:to_f) },
|
98
|
+
lambda { |value| return value.class == Array && value.first.class == Float })
|
99
|
+
OptionType.new(:Numbers,
|
100
|
+
:numbers,
|
101
|
+
"NUM1,NUM2,NUM3...",
|
102
|
+
lambda { |argument, option_parser| return argument.split(',').map(&:to_f) },
|
103
|
+
lambda { |value| return value.class == Array && value.first.class == Float })
|
104
|
+
OptionType.new(:Strings,
|
105
|
+
:strings,
|
106
|
+
"STR1,STR2,STR3...",
|
107
|
+
lambda { |argument, option_parser| return argument.split(',').map(&:to_s) },
|
108
|
+
lambda { |value| return value.class == Array && value.first.class == String })
|
109
|
+
OptionType.new(:Uris,
|
110
|
+
:uris,
|
111
|
+
"URL1,URL2,URL3...",
|
112
|
+
lambda { |argument, option_parser| return argument.split(',').map{ |a| URI.parse(a)} },
|
113
|
+
lambda { |value| return value.class == Array && value.first.class == URI::HTTP })
|
114
|
+
OptionType.new(:Dates,
|
115
|
+
:dates,
|
116
|
+
"DATE1,DATE2,DATE3...",
|
117
|
+
lambda { |argument, option_parser| return argument.split(',').map{ |a| Time.zone.parse(a).to_date} },
|
118
|
+
lambda { |value| return value.class == Array && value.first.class == Date })
|
119
|
+
OptionType.new(:Times,
|
120
|
+
:times,
|
121
|
+
"TIME1,TIME2,TIME3...",
|
122
|
+
lambda { |argument, option_parser| return argument.split(',').map{ |a| Time.zone.parse(a) } },
|
123
|
+
lambda { |value| return value.class == Array && value.first.class == Time })
|
124
|
+
OptionType.new(:DateTimes,
|
125
|
+
:datetimes,
|
126
|
+
"TIME1,TIME2,TIME3...",
|
127
|
+
lambda { |argument, option_parser| return argument.split(',').map{ |a| Time.zone.parse(a) } },
|
128
|
+
lambda { |value| return value.class == Array && value.first.class == DateTime })
|
129
|
+
OptionType.new(:Choices,
|
130
|
+
:choices,
|
131
|
+
"CHOICE1,CHOICE2,CHOICE3...",
|
132
|
+
lambda { |argument, option_parser|
|
133
|
+
choice_list = argument.split(',').map(&:to_sym)
|
134
|
+
choices = option_parser.choices
|
135
|
+
unless choices.blank?
|
136
|
+
choice_list.each do |choice|
|
137
|
+
unless choices.include? choice
|
138
|
+
raise BadChoiceError.new("invalid choice '#{choice}' not in list of choices: #{choices.map(&:to_s).join(', ')}")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
return choice_list
|
143
|
+
}, lambda {|value| return value.class == Array && value.first.class == Symbol })
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Af::QThread
|
2
|
+
class Base < Thread
|
3
|
+
attr_reader :queue
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@queue = Queue.new
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
include ::Af::QThread::Interface
|
11
|
+
|
12
|
+
def request_termination(from = Thread.current)
|
13
|
+
post_data_message(:terminate, from)
|
14
|
+
end
|
15
|
+
|
16
|
+
def kick_start(from = Thread.current)
|
17
|
+
post_data_message(:kick_start, from)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Af::QThread
|
2
|
+
module Interface
|
3
|
+
def has_message?
|
4
|
+
return !queue.empty?
|
5
|
+
end
|
6
|
+
|
7
|
+
def read_message
|
8
|
+
return queue.pop
|
9
|
+
end
|
10
|
+
|
11
|
+
def post_message(message)
|
12
|
+
queue << message
|
13
|
+
end
|
14
|
+
|
15
|
+
def requeue(message)
|
16
|
+
post_message(message)
|
17
|
+
end
|
18
|
+
|
19
|
+
def post_data_message(data, from = Thread.current)
|
20
|
+
post_message(::Af::QThread::Message.new(data, from))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Af::QThread
|
2
|
+
class Message
|
3
|
+
attr_accessor :from, :data, :msg_id
|
4
|
+
def initialize(data, from = Thread.current)
|
5
|
+
@from = from
|
6
|
+
@data = data
|
7
|
+
@msg_id = self.class.new_msg_id
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.new_msg_id
|
11
|
+
return UUID.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Af::QThread
|
2
|
+
class MessageHandler
|
3
|
+
attr_reader :thread
|
4
|
+
|
5
|
+
def initialize(thread)
|
6
|
+
@thread = thread
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.run(thread = Thread.current)
|
10
|
+
return new(thread).run
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
process_messages
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_messages
|
18
|
+
while true
|
19
|
+
message = thread.read_message
|
20
|
+
break if message.data == :terminate
|
21
|
+
response = process_message(message)
|
22
|
+
message.from.post_data_message(response, thread)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def process_message(message)
|
27
|
+
return nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Af::TCPCommand
|
2
|
+
class Client
|
3
|
+
include ::Af::Application::Proxy
|
4
|
+
|
5
|
+
attr_reader :client, :server_hostname, :server_port
|
6
|
+
|
7
|
+
def initialize(server_hostname, server_port)
|
8
|
+
@server_hostname = server_hostname
|
9
|
+
@server_port = server_port
|
10
|
+
@client = TCPSocket.new(server_hostname, server_port)
|
11
|
+
end
|
12
|
+
|
13
|
+
def logger
|
14
|
+
return af_logger(self.class.name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def command_reader
|
18
|
+
return client.readline.chomp
|
19
|
+
end
|
20
|
+
|
21
|
+
def command_dispatcher(line)
|
22
|
+
logger.debug_fine "process command: #{line}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def reply_to_server(line)
|
26
|
+
client.write("#{line}\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def ready
|
30
|
+
reply_to_server("ready")
|
31
|
+
end
|
32
|
+
|
33
|
+
def serve
|
34
|
+
while true
|
35
|
+
logger.debug_medium "READY!"
|
36
|
+
ready
|
37
|
+
begin
|
38
|
+
line = command_reader
|
39
|
+
logger.debug_fine "working on: #{line}"
|
40
|
+
command_dispatcher(line)
|
41
|
+
rescue EOFError
|
42
|
+
logger.warn "master closed connection: #{client.inspect}"
|
43
|
+
client.close
|
44
|
+
break
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|