ginjo-rfm 3.0.9 → 3.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +13 -5
- data/CHANGELOG.md +61 -40
- data/README.md +8 -8
- data/lib/rfm.rb +66 -67
- data/lib/rfm/VERSION +1 -1
- data/lib/rfm/base.rb +237 -241
- data/lib/rfm/database.rb +38 -24
- data/lib/rfm/error.rb +25 -25
- data/lib/rfm/layout.rb +217 -195
- data/lib/rfm/metadata/datum.rb +37 -37
- data/lib/rfm/metadata/field.rb +42 -39
- data/lib/rfm/metadata/field_control.rb +72 -72
- data/lib/rfm/metadata/layout_meta.rb +32 -32
- data/lib/rfm/metadata/resultset_meta.rb +74 -74
- data/lib/rfm/metadata/script.rb +3 -3
- data/lib/rfm/metadata/value_list_item.rb +30 -30
- data/lib/rfm/record.rb +80 -77
- data/lib/rfm/resultset.rb +63 -65
- data/lib/rfm/server.rb +31 -23
- data/lib/rfm/utilities/case_insensitive_hash.rb +4 -1
- data/lib/rfm/utilities/compound_query.rb +100 -101
- data/lib/rfm/utilities/config.rb +228 -218
- data/lib/rfm/utilities/connection.rb +65 -57
- data/lib/rfm/utilities/core_ext.rb +114 -119
- data/lib/rfm/utilities/factory.rb +122 -126
- data/lib/rfm/utilities/sax_parser.rb +1058 -1046
- data/lib/rfm/utilities/scope.rb +64 -0
- data/lib/rfm/version.rb +23 -7
- metadata +40 -39
@@ -5,30 +5,31 @@
|
|
5
5
|
|
6
6
|
require 'net/https'
|
7
7
|
require 'cgi'
|
8
|
+
|
8
9
|
module Rfm
|
9
|
-
# These have been moved to rfm.rb.
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
10
|
+
# These have been moved to rfm.rb.
|
11
|
+
# SaxParser.default_class = CaseInsensitiveHash
|
12
|
+
# SaxParser.template_prefix = File.join(File.dirname(__FILE__), './sax/')
|
13
|
+
# SaxParser.templates.merge!({
|
14
|
+
# :fmpxmllayout => 'fmpxmllayout.yml',
|
15
|
+
# :fmresultset => 'fmresultset.yml',
|
16
|
+
# :fmpxmlresult => 'fmpxmlresult.yml',
|
17
|
+
# :none => nil
|
18
|
+
# })
|
19
|
+
|
19
20
|
class Connection
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
include Config
|
22
|
+
|
23
|
+
def initialize(action, params, request_options={}, *args)
|
24
|
+
config(*args)
|
25
|
+
|
25
26
|
# Action sent to FMS
|
26
27
|
@action = action
|
27
28
|
# Query params sent to FMS
|
28
29
|
@params = params
|
29
30
|
# Additional options sent to FMS
|
30
31
|
@request_options = request_options
|
31
|
-
|
32
|
+
|
32
33
|
@defaults = {
|
33
34
|
:host => 'localhost',
|
34
35
|
#:port => 80,
|
@@ -49,66 +50,73 @@ module Rfm
|
|
49
50
|
:template => :fmresultset,
|
50
51
|
:grammar => 'fmresultset'
|
51
52
|
} #.merge(options)
|
52
|
-
|
53
53
|
end
|
54
54
|
|
55
55
|
def state(*args)
|
56
|
-
|
56
|
+
@defaults.merge(super(*args))
|
57
|
+
end
|
58
|
+
|
59
|
+
def host_name
|
60
|
+
state[:host]
|
61
|
+
end
|
62
|
+
|
63
|
+
def scheme
|
64
|
+
state[:ssl] ? "https" : "http"
|
65
|
+
end
|
66
|
+
|
67
|
+
def port
|
68
|
+
state[:ssl] && state[:port].nil? ? 443 : state[:port]
|
57
69
|
end
|
58
|
-
|
59
|
-
def host_name; state[:host]; end
|
60
|
-
def scheme; state[:ssl] ? "https" : "http"; end
|
61
|
-
def port; state[:ssl] && state[:port].nil? ? 443 : state[:port]; end
|
62
70
|
|
63
71
|
def connect(action=@action, params=@params, request_options = @request_options, account_name=state[:account_name], password=state[:password])
|
64
|
-
|
72
|
+
grammar_option = request_options.delete(:grammar)
|
65
73
|
post = params.merge(expand_options(request_options)).merge({action => ''})
|
66
74
|
grammar = select_grammar(post, :grammar=>grammar_option)
|
67
75
|
http_fetch(host_name, port, "/fmi/xml/#{grammar}.xml", account_name, password, post)
|
68
76
|
end
|
69
77
|
|
70
78
|
def select_grammar(post, options={})
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
+
grammar = state(options)[:grammar] || 'fmresultset'
|
80
|
+
if grammar.to_s.downcase == 'auto'
|
81
|
+
# TODO: Build grammar parser in new sax engine templates to handle FMPXMLRESULT.
|
82
|
+
return "fmresultset"
|
83
|
+
# post.keys.find(){|k| %w(-find -findall -dbnames -layoutnames -scriptnames).include? k.to_s} ? "FMPXMLRESULT" : "fmresultset"
|
84
|
+
else
|
85
|
+
grammar
|
86
|
+
end
|
79
87
|
end
|
80
|
-
|
88
|
+
|
81
89
|
def parse(template=nil, initial_object=nil, parser=nil, options={})
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
90
|
+
template ||= state[:template]
|
91
|
+
#(template = 'fmresultset.yml') unless template
|
92
|
+
#(template = File.join(File.dirname(__FILE__), '../sax/', template)) if template.is_a? String
|
93
|
+
Rfm::SaxParser.parse(connect.body, template, initial_object, parser, state(*options)).result
|
86
94
|
end
|
87
95
|
|
88
96
|
|
89
97
|
|
90
98
|
|
91
|
-
|
92
|
-
|
99
|
+
private
|
100
|
+
|
93
101
|
def http_fetch(host_name, port, path, account_name, password, post_data, limit=10)
|
94
102
|
raise Rfm::CommunicationError.new("While trying to reach the Web Publishing Engine, RFM was redirected too many times.") if limit == 0
|
95
|
-
|
103
|
+
|
96
104
|
if state[:log_actions] == true
|
97
105
|
#qs = post_data.collect{|key,val| "#{CGI::escape(key.to_s)}=#{CGI::escape(val.to_s)}"}.join("&")
|
98
106
|
qs_unescaped = post_data.collect{|key,val| "#{key.to_s}=#{val.to_s}"}.join("&")
|
99
107
|
#warn "#{@scheme}://#{@host_name}:#{@port}#{path}?#{qs}"
|
100
108
|
log.info "#{scheme}://#{host_name}:#{port}#{path}?#{qs_unescaped}"
|
101
109
|
end
|
102
|
-
|
110
|
+
|
103
111
|
request = Net::HTTP::Post.new(path)
|
104
112
|
request.basic_auth(account_name, password)
|
105
113
|
request.set_form_data(post_data)
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
114
|
+
|
115
|
+
if state[:proxy]
|
116
|
+
connection = Net::HTTP::Proxy(*state[:proxy]).new(host_name, port)
|
117
|
+
else
|
118
|
+
connection = Net::HTTP.new(host_name, port)
|
119
|
+
end
|
112
120
|
#ADDED LONG TIMEOUT TIMOTHY TING 05/12/2011
|
113
121
|
connection.open_timeout = connection.read_timeout = state[:timeout]
|
114
122
|
if state[:ssl]
|
@@ -120,20 +128,20 @@ module Rfm
|
|
120
128
|
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
121
129
|
end
|
122
130
|
end
|
123
|
-
|
131
|
+
|
124
132
|
response = connection.start { |http| http.request(request) }
|
125
133
|
if state[:log_responses] == true
|
126
134
|
response.to_hash.each { |key, value| log.info "#{key}: #{value}" }
|
127
135
|
log.info response.body
|
128
136
|
end
|
129
|
-
|
137
|
+
|
130
138
|
case response
|
131
139
|
when Net::HTTPSuccess
|
132
140
|
response
|
133
141
|
when Net::HTTPRedirection
|
134
142
|
if state[:warn_on_redirect]
|
135
143
|
log.warn "The web server redirected to " + response['location'] +
|
136
|
-
|
144
|
+
". You should revise your connection hostname or fix your server configuration if possible to improve performance."
|
137
145
|
end
|
138
146
|
newloc = URI.parse(response['location'])
|
139
147
|
http_fetch(newloc.host, newloc.port, newloc.request_uri, account_name, password, post_data, limit - 1)
|
@@ -148,18 +156,18 @@ module Rfm
|
|
148
156
|
raise Rfm::CommunicationError.new(msg)
|
149
157
|
end
|
150
158
|
end
|
151
|
-
|
159
|
+
|
152
160
|
def expand_options(options)
|
153
161
|
result = {}
|
154
162
|
field_mapping = options.delete(:field_mapping) || {}
|
155
163
|
options.each do |key,value|
|
156
164
|
case key.to_sym
|
157
165
|
when :max_portal_rows
|
158
|
-
|
159
|
-
|
166
|
+
result['-relatedsets.max'] = value
|
167
|
+
result['-relatedsets.filter'] = 'layout'
|
160
168
|
when :ignore_portals
|
161
|
-
|
162
|
-
|
169
|
+
result['-relatedsets.max'] = 0
|
170
|
+
result['-relatedsets.filter'] = 'layout'
|
163
171
|
when :max_records
|
164
172
|
result['-max'] = value
|
165
173
|
when :skip_records
|
@@ -211,8 +219,8 @@ module Rfm
|
|
211
219
|
end
|
212
220
|
return result
|
213
221
|
end
|
214
|
-
|
222
|
+
|
215
223
|
end # Connection
|
216
224
|
|
217
|
-
|
218
|
-
end # Rfm
|
225
|
+
|
226
|
+
end # Rfm
|
@@ -1,140 +1,140 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
3
|
Module.module_eval do
|
4
|
-
|
5
|
-
|
4
|
+
# Adds ability to forward methods to other objects using 'def_delegator'
|
5
|
+
include Forwardable
|
6
6
|
end
|
7
7
|
|
8
8
|
class Object
|
9
9
|
|
10
|
-
|
10
|
+
#extend Forwardable
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
# Adds methods to put instance variables in rfm_metaclass, plus getter/setters
|
13
|
+
# This is useful to hide instance variables in objects that would otherwise show "too much" information.
|
14
14
|
def self.meta_attr_accessor(*names)
|
15
|
-
|
16
|
-
|
15
|
+
meta_attr_reader(*names)
|
16
|
+
meta_attr_writer(*names)
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def self.meta_attr_reader(*names)
|
20
20
|
names.each do |n|
|
21
21
|
define_method(n.to_s) {rfm_metaclass.instance_variable_get("@#{n}")}
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def self.meta_attr_writer(*names)
|
26
26
|
names.each do |n|
|
27
27
|
define_method(n.to_s + "=") {|val| rfm_metaclass.instance_variable_set("@#{n}", val)}
|
28
28
|
end
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
# Wrap an object in Array, if not already an Array,
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
32
|
+
# since XmlMini doesn't know which will be returnd for any particular element.
|
33
|
+
# See Rfm Layout & Record where this is used.
|
34
|
+
def rfm_force_array
|
35
|
+
return [] if self.nil?
|
36
|
+
self.is_a?(Array) ? self : [self]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Just testing this functionality
|
40
|
+
def rfm_local_methods
|
41
|
+
self.methods - self.class.superclass.methods
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# Like singleton_method or 'metaclass' from ActiveSupport.
|
47
|
+
def rfm_metaclass
|
48
|
+
class << self
|
49
|
+
self
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
53
|
# Get the superclass object of self.
|
54
54
|
def rfm_super
|
55
55
|
SuperProxy.new(self)
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
end # Object
|
59
59
|
|
60
60
|
|
61
61
|
class Array
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
62
|
+
# Taken from ActiveSupport extract_options!.
|
63
|
+
def rfm_extract_options!
|
64
|
+
last.is_a?(::Hash) ? pop : {}
|
65
|
+
end
|
66
|
+
|
67
|
+
# These methods allow dynamic extension of array members with other modules.
|
68
|
+
# These methods also carry the @root object for reference, when you don't have the
|
69
|
+
# root object explicity referenced anywhere.
|
70
|
+
#
|
71
|
+
# These methods might slow down array traversal, as
|
72
|
+
# they add interpreted code to methods that were otherwise pure C.
|
73
73
|
def rfm_extend_members(klass, caller=nil)
|
74
|
-
|
74
|
+
@parent = caller
|
75
75
|
@root = caller.instance_variable_get(:@root)
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
76
|
+
@member_extension = klass
|
77
|
+
self.instance_eval do
|
78
|
+
class << self
|
79
|
+
attr_accessor :parent
|
80
|
+
|
81
|
+
alias_method 'old_reader', '[]'
|
82
|
+
def [](*args)
|
83
|
+
member = old_reader(*args)
|
84
84
|
rfm_extend_member(member, @member_extension, args[0]) if args[0].is_a? Integer
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
end
|
101
|
-
|
85
|
+
member
|
86
|
+
end
|
87
|
+
|
88
|
+
alias_method 'old_each', 'each'
|
89
|
+
def each
|
90
|
+
i = -1
|
91
|
+
old_each do |member|
|
92
|
+
i = i + 1
|
93
|
+
rfm_extend_member(member, @member_extension, i)
|
94
|
+
yield(member)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end unless defined? old_reader
|
99
|
+
self
|
100
|
+
end
|
101
|
+
|
102
102
|
def rfm_extend_member(member, extension, i=nil)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
103
|
+
if member and extension
|
104
|
+
unless member.instance_variable_get(:@root)
|
105
|
+
member.instance_variable_set(:@root, @root)
|
106
|
+
member.instance_variable_set(:@parent, self)
|
107
|
+
member.instance_variable_set(:@index, i)
|
108
|
+
member.instance_eval(){def root; @root; end}
|
109
|
+
member.instance_eval(){def parent; @parent; end}
|
110
|
+
member.instance_eval(){def get_index; @index; end}
|
111
|
+
end
|
112
|
+
member.extend(extension)
|
113
|
+
end
|
114
114
|
end
|
115
115
|
|
116
116
|
end # Array
|
117
117
|
|
118
118
|
class Hash
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
119
|
+
# TODO: Possibly deprecated, delete if not used.
|
120
|
+
def rfm_only(*keepers)
|
121
|
+
self.dup.each_key {|k| self.delete(k) if !keepers.include?(k)}
|
122
|
+
end
|
123
|
+
|
124
|
+
def rfm_filter(*args)
|
125
|
+
options = args.rfm_extract_options!
|
126
|
+
delete = options[:delete]
|
127
|
+
self.dup.each_key do |k|
|
128
|
+
self.delete(k) if (delete ? args.include?(k) : !args.include?(k))
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Convert hash to Rfm::CaseInsensitiveHash
|
133
|
+
def to_cih
|
134
|
+
new = Rfm::CaseInsensitiveHash.new
|
135
|
+
self.each{|k,v| new[k] = v}
|
136
|
+
new
|
137
|
+
end
|
138
138
|
end # Hash
|
139
139
|
|
140
140
|
# Allows access to superclass object
|
@@ -150,27 +150,22 @@ end # SuperProxy
|
|
150
150
|
|
151
151
|
|
152
152
|
class Time
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
153
|
+
# Returns array of [date,time] in format suitable for FMP.
|
154
|
+
def to_fm_components(reset_time_if_before_today=false)
|
155
|
+
d = self.strftime('%m/%d/%Y')
|
156
|
+
t = if (Date.parse(self.to_s) < Date.today) and reset_time_if_before_today==true
|
157
|
+
"00:00:00"
|
158
|
+
else
|
159
|
+
self.strftime('%T')
|
160
|
+
end
|
161
|
+
[d,t]
|
162
|
+
end
|
163
163
|
end # Time
|
164
164
|
|
165
165
|
class String
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
166
|
+
def title_case
|
167
|
+
self.gsub(/\w+/) do |word|
|
168
|
+
word.capitalize
|
169
|
+
end
|
170
|
+
end
|
171
171
|
end # String
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|