ginjo-rfm 2.1.7 → 3.0.0
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 +15 -0
- data/CHANGELOG.md +45 -16
- data/README.md +251 -274
- data/lib/rfm.rb +42 -20
- data/lib/rfm/VERSION +1 -1
- data/lib/rfm/base.rb +63 -196
- data/lib/rfm/database.rb +15 -16
- data/lib/rfm/layout.rb +244 -271
- data/lib/rfm/metadata/datum.rb +45 -0
- data/lib/rfm/metadata/field.rb +33 -13
- data/lib/rfm/metadata/field_control.rb +57 -25
- data/lib/rfm/metadata/layout_meta.rb +38 -0
- data/lib/rfm/metadata/resultset_meta.rb +66 -0
- data/lib/rfm/metadata/value_list_item.rb +7 -6
- data/lib/rfm/record.rb +54 -74
- data/lib/rfm/resultset.rb +63 -112
- data/lib/rfm/server.rb +6 -172
- data/lib/rfm/utilities/config.rb +100 -55
- data/lib/rfm/utilities/connection.rb +209 -0
- data/lib/rfm/utilities/core_ext.rb +14 -1
- data/lib/rfm/utilities/factory.rb +68 -65
- data/lib/rfm/utilities/sax_parser.rb +1039 -0
- metadata +154 -206
- data/lib/rfm/utilities/fmpxmlresult.rb +0 -167
- data/lib/rfm/utilities/fmresultset.rb +0 -153
- data/lib/rfm/utilities/xml_parser.rb +0 -124
- data/lib/rfm/xml_mini/hpricot.rb +0 -133
- data/lib/rfm/xml_mini/ox_sax.rb +0 -91
- data/lib/rfm/xml_mini/rexml_sax.rb +0 -81
@@ -1,153 +0,0 @@
|
|
1
|
-
module Rfm
|
2
|
-
|
3
|
-
# Methods to help translate xml_mini document into Rfm/Filemaker objects.
|
4
|
-
module Fmresultset
|
5
|
-
def self.extended(obj)
|
6
|
-
obj.instance_variable_set :@root, obj
|
7
|
-
obj.extend Resultset
|
8
|
-
end
|
9
|
-
|
10
|
-
module Resultset
|
11
|
-
|
12
|
-
def error
|
13
|
-
self['fmresultset']['error']['code'].to_i
|
14
|
-
end
|
15
|
-
|
16
|
-
def datasource
|
17
|
-
self['fmresultset']['datasource']
|
18
|
-
end
|
19
|
-
|
20
|
-
def meta
|
21
|
-
self['fmresultset']['metadata']
|
22
|
-
end
|
23
|
-
|
24
|
-
def resultset
|
25
|
-
self['fmresultset']['resultset']
|
26
|
-
end
|
27
|
-
|
28
|
-
def date_format
|
29
|
-
Rfm.convert_date_time_format(datasource['date-format'].to_s)
|
30
|
-
end
|
31
|
-
|
32
|
-
def time_format
|
33
|
-
Rfm.convert_date_time_format(datasource['time-format'].to_s)
|
34
|
-
end
|
35
|
-
|
36
|
-
def timestamp_format
|
37
|
-
Rfm.convert_date_time_format(datasource['timestamp-format'].to_s)
|
38
|
-
end
|
39
|
-
|
40
|
-
def foundset_count
|
41
|
-
resultset['count'].to_s.to_i
|
42
|
-
end
|
43
|
-
|
44
|
-
def total_count
|
45
|
-
datasource['total-count'].to_s.to_i
|
46
|
-
end
|
47
|
-
|
48
|
-
def table
|
49
|
-
datasource['table']
|
50
|
-
end
|
51
|
-
|
52
|
-
def records
|
53
|
-
resultset['record'].rfm_force_array.rfm_extend_members(Record)
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
def fields
|
58
|
-
meta['field-definition'].rfm_force_array.rfm_extend_members(Field)
|
59
|
-
end
|
60
|
-
|
61
|
-
def portals
|
62
|
-
meta['relatedset-definition'].rfm_force_array.rfm_extend_members(RelatedsetDefinition)
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
module Field
|
68
|
-
def name
|
69
|
-
self['name']
|
70
|
-
end
|
71
|
-
|
72
|
-
def result
|
73
|
-
self['result']
|
74
|
-
end
|
75
|
-
|
76
|
-
def type
|
77
|
-
self['type']
|
78
|
-
end
|
79
|
-
|
80
|
-
def max_repeats
|
81
|
-
self['max-repeats']
|
82
|
-
end
|
83
|
-
|
84
|
-
def global
|
85
|
-
self['global']
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
module RelatedsetDefinition
|
90
|
-
def table
|
91
|
-
self['table']
|
92
|
-
end
|
93
|
-
|
94
|
-
def fields
|
95
|
-
self['field-definition'].rfm_force_array.rfm_extend_members(Field)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
module Record
|
100
|
-
def columns
|
101
|
-
self['field'].rfm_force_array.rfm_extend_members(Column)
|
102
|
-
end
|
103
|
-
|
104
|
-
def record_id
|
105
|
-
self['record-id']
|
106
|
-
end
|
107
|
-
|
108
|
-
def mod_id
|
109
|
-
self['mod-id']
|
110
|
-
end
|
111
|
-
|
112
|
-
def portals
|
113
|
-
self['relatedset'].rfm_force_array.rfm_extend_members(Relatedset)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
module Column
|
118
|
-
def name
|
119
|
-
self['name']
|
120
|
-
end
|
121
|
-
|
122
|
-
def data
|
123
|
-
self['data'].rfm_force_array.collect{|d| d['__content__']}
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
module Relatedset
|
128
|
-
def table
|
129
|
-
self['table']
|
130
|
-
end
|
131
|
-
|
132
|
-
def count
|
133
|
-
self['count']
|
134
|
-
end
|
135
|
-
|
136
|
-
def records
|
137
|
-
self['record'].rfm_force_array.rfm_extend_members(Record)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
end
|
142
|
-
|
143
|
-
def convert_date_time_format(fm_format)
|
144
|
-
fm_format.gsub!('MM', '%m')
|
145
|
-
fm_format.gsub!('dd', '%d')
|
146
|
-
fm_format.gsub!('yyyy', '%Y')
|
147
|
-
fm_format.gsub!('HH', '%H')
|
148
|
-
fm_format.gsub!('mm', '%M')
|
149
|
-
fm_format.gsub!('ss', '%S')
|
150
|
-
fm_format
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|
@@ -1,124 +0,0 @@
|
|
1
|
-
module Rfm
|
2
|
-
module XmlParser
|
3
|
-
|
4
|
-
extend Config
|
5
|
-
config :parent=>'Rfm::Config'
|
6
|
-
|
7
|
-
extend self
|
8
|
-
|
9
|
-
# Backend definitions & configurations
|
10
|
-
BACKENDS = ActiveSupport::OrderedHash.new
|
11
|
-
|
12
|
-
BACKENDS[:jdom] = {:require=>'jdom', :class => 'JDOM'}
|
13
|
-
|
14
|
-
BACKENDS[:oxsax] = {:require=>'ox', :class => proc{
|
15
|
-
# Ox module is part of Rfm, not XmlMini,
|
16
|
-
# and needs to be handed manually to XmlMini.
|
17
|
-
require File.join(File.dirname(__FILE__), '../xml_mini/ox_sax.rb')
|
18
|
-
ActiveSupport::XmlMini_OxSAX}}
|
19
|
-
|
20
|
-
BACKENDS[:libxml] = {:require=>'libxml', :class => 'LibXML'}
|
21
|
-
|
22
|
-
BACKENDS[:libxmlsax] = {:require=>'libxml', :class => 'LibXMLSAX'}
|
23
|
-
|
24
|
-
BACKENDS[:nokogirisax] = {:require=>'nokogiri', :class => proc{ActiveSupport::VERSION; 'NokogiriSAX'}}
|
25
|
-
|
26
|
-
BACKENDS[:nokogiri] = {:require=>'nokogiri', :class => 'Nokogiri'}
|
27
|
-
|
28
|
-
BACKENDS[:hpricot] = {:require=>'hpricot', :class => proc{
|
29
|
-
# Hpricot module is part of Rfm, not XmlMini,
|
30
|
-
# and needs to be handed manually to XmlMini.
|
31
|
-
require File.join(File.dirname(__FILE__), '../xml_mini/hpricot.rb')
|
32
|
-
ActiveSupport::XmlMini_Hpricot}}
|
33
|
-
|
34
|
-
BACKENDS[:rexml] = {:require=>'rexml/document', :class=>'REXML'}
|
35
|
-
|
36
|
-
BACKENDS[:rexmlsax] = {:require=>'rexml/parsers/sax2parser', :class => proc{
|
37
|
-
# Rexmlsax module is part of Rfm, not XmlMini,
|
38
|
-
# and needs to be handed manually to XmlMini.
|
39
|
-
require File.join(File.dirname(__FILE__), '../xml_mini/rexml_sax.rb')
|
40
|
-
ActiveSupport::XmlMini_REXMLSAX}}
|
41
|
-
|
42
|
-
|
43
|
-
# Main parsing method.
|
44
|
-
# Options
|
45
|
-
# :namespace => false # strip out namespace (default)
|
46
|
-
# :parser => :libxml, :libxmlsax, :nokogirisax, :nokogiri, :hpricot, :rexml
|
47
|
-
# :parser => CustomParsingModule # see ActiveSupport::XmlMini
|
48
|
-
def new(string_or_file, opts={})
|
49
|
-
string_or_file.gsub!(/xmlns=\"[^\"]*\"/,'') if (string_or_file.class == String and opts[:namespace] == false)
|
50
|
-
unless opts[:parser] and get_backend_from_hash(opts[:parser]).to_s != self.backend.to_s
|
51
|
-
warn "XmlParser default: #{ActiveSupport::XmlMini.backend.to_s}" if get_config[:log_parser] == true
|
52
|
-
ActiveSupport::XmlMini.parse(string_or_file)
|
53
|
-
else
|
54
|
-
warn "XmlParser backend: #{get_backend_from_hash(opts[:parser]).to_s}" if get_config[:log_parser] == true
|
55
|
-
ActiveSupport::XmlMini.with_backend(get_backend_from_hash(opts[:parser])) {ActiveSupport::XmlMini.parse(string_or_file)}
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# Creates new hash with #new, plus extends the hash with result-dependent translation class.
|
60
|
-
def parse(string_or_file, opts={})
|
61
|
-
doc = new(string_or_file, opts)
|
62
|
-
case true
|
63
|
-
when doc.has_key?('fmresultset') ; doc.extend(Fmresultset)
|
64
|
-
when doc.has_key?('FMPXMLRESULT') ; doc.extend(Fmpxmlresult)
|
65
|
-
when doc.has_key?('FMPDSORESULT') ; doc.extend(Fmpdsoresult)
|
66
|
-
when doc.has_key?('FMPXMLLAYOUT') ; doc.extend(Fmpxmllayout)
|
67
|
-
else doc
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# Shortcut to XmlMini config getter.
|
72
|
-
# If a parameter is passed, it will be used to get the local backend description
|
73
|
-
# from the BACKENDS hash, instead of the XmlMini backend.
|
74
|
-
def backend(name=nil)
|
75
|
-
return ActiveSupport::XmlMini.backend unless name
|
76
|
-
get_backend_from_hash(name)
|
77
|
-
end
|
78
|
-
|
79
|
-
# Shortcut to XmlMini config setter.
|
80
|
-
def backend=(name)
|
81
|
-
if name.is_a? Symbol
|
82
|
-
set_backend_via_hash(name)
|
83
|
-
else
|
84
|
-
ActiveSupport::XmlMini.backend = name
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
private
|
89
|
-
|
90
|
-
# Given name, return backend config from BACKENDS, including any preloading.
|
91
|
-
# Will raise LoadError if can't load backend.
|
92
|
-
def get_backend_from_hash(name)
|
93
|
-
backend_hash = BACKENDS[name.to_sym]
|
94
|
-
require backend_hash[:require]
|
95
|
-
backend_hash[:class].is_a?(Proc) ? backend_hash[:class].call : backend_hash[:class]
|
96
|
-
end
|
97
|
-
|
98
|
-
# Set XmlMini backend, given symbol matching one of the BACKENDS.
|
99
|
-
def set_backend_via_hash(name)
|
100
|
-
ActiveSupport::XmlMini.backend = get_backend_from_hash(name)
|
101
|
-
end
|
102
|
-
|
103
|
-
# Select the best backend from BACKENDS, returns backend config.
|
104
|
-
def decide_backend
|
105
|
-
string_or_class = catch(:done) do
|
106
|
-
BACKENDS.keys.each do |name|
|
107
|
-
begin
|
108
|
-
result = get_backend_from_hash name
|
109
|
-
throw(:done, result)
|
110
|
-
rescue LoadError, StandardError
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# Set XmlMini backend when this file loads.
|
117
|
-
begin
|
118
|
-
self.backend = get_backend_from_hash(get_config[:parser])
|
119
|
-
rescue
|
120
|
-
self.backend = decide_backend
|
121
|
-
end
|
122
|
-
|
123
|
-
end # XmlParser
|
124
|
-
end # Rfm
|
data/lib/rfm/xml_mini/hpricot.rb
DELETED
@@ -1,133 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/kernel/reporting'
|
2
|
-
require 'active_support/core_ext/object/blank'
|
3
|
-
require 'stringio'
|
4
|
-
|
5
|
-
module ActiveSupport
|
6
|
-
module XmlMini_Hpricot
|
7
|
-
extend self
|
8
|
-
|
9
|
-
CONTENT_KEY = '__content__'.freeze
|
10
|
-
|
11
|
-
# Parse an XML Document string or IO into a simple hash
|
12
|
-
#
|
13
|
-
# Same as XmlSimple::xml_in but doesn't shoot itself in the foot,
|
14
|
-
# and uses the defaults from Active Support.
|
15
|
-
#
|
16
|
-
# data::
|
17
|
-
# XML Document string or IO to parse
|
18
|
-
def parse(data)
|
19
|
-
if !data.respond_to?(:read)
|
20
|
-
data = StringIO.new(data || '')
|
21
|
-
end
|
22
|
-
|
23
|
-
char = data.getc
|
24
|
-
if char.nil?
|
25
|
-
{}
|
26
|
-
else
|
27
|
-
data.ungetc(char)
|
28
|
-
silence_warnings { require 'hpricot' } unless defined?(Hpricot)
|
29
|
-
doc = Hpricot.XML(data)
|
30
|
-
|
31
|
-
if doc.root
|
32
|
-
merge_element!({}, doc.root)
|
33
|
-
else
|
34
|
-
raise Hpricot::ParseError,
|
35
|
-
"The document #{doc.to_s.inspect} does not have a valid root"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
# Convert an XML element and merge into the hash
|
42
|
-
#
|
43
|
-
# hash::
|
44
|
-
# Hash to merge the converted element into.
|
45
|
-
# element::
|
46
|
-
# XML element to merge into hash
|
47
|
-
def merge_element!(hash, element)
|
48
|
-
merge!(hash, element.name, collapse(element)) if element.respond_to? :name
|
49
|
-
end
|
50
|
-
|
51
|
-
# Actually converts an XML document element into a data structure.
|
52
|
-
#
|
53
|
-
# element::
|
54
|
-
# The document element to be collapsed.
|
55
|
-
def collapse(element)
|
56
|
-
hash = get_attributes(element)
|
57
|
-
|
58
|
-
if element.respond_to? :children
|
59
|
-
element.each_child {|child| merge_element!(hash, child) unless child.text? }
|
60
|
-
merge_texts!(hash, element) unless empty_content?(element)
|
61
|
-
hash
|
62
|
-
else
|
63
|
-
merge_texts!(hash, element)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Merge all the texts of an element into the hash
|
68
|
-
#
|
69
|
-
# hash::
|
70
|
-
# Hash to add the converted element to.
|
71
|
-
# element::
|
72
|
-
# XML element whose texts are to be merged into the hash
|
73
|
-
def merge_texts!(hash, element)
|
74
|
-
unless element.respond_to? :children and element.children[0].text?
|
75
|
-
hash
|
76
|
-
else
|
77
|
-
# must use value to prevent double-escaping
|
78
|
-
texts = ''
|
79
|
-
#element.texts.each { |t| texts << t.value }
|
80
|
-
#texts << element.children[0].to_s
|
81
|
-
element.each_child { |child| texts << child.inner_text }
|
82
|
-
merge!(hash, CONTENT_KEY, texts)
|
83
|
-
texts
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Adds a new key/value pair to an existing Hash. If the key to be added
|
88
|
-
# already exists and the existing value associated with key is not
|
89
|
-
# an Array, it will be wrapped in an Array. Then the new value is
|
90
|
-
# appended to that Array.
|
91
|
-
#
|
92
|
-
# hash::
|
93
|
-
# Hash to add key/value pair to.
|
94
|
-
# key::
|
95
|
-
# Key to be added.
|
96
|
-
# value::
|
97
|
-
# Value to be associated with key.
|
98
|
-
def merge!(hash, key, value)
|
99
|
-
if hash.has_key?(key)
|
100
|
-
if hash[key].instance_of?(Array)
|
101
|
-
hash[key] << value
|
102
|
-
else
|
103
|
-
hash[key] = [hash[key], value]
|
104
|
-
end
|
105
|
-
elsif value.instance_of?(Array)
|
106
|
-
hash[key] = [value]
|
107
|
-
else
|
108
|
-
hash[key] = value
|
109
|
-
end
|
110
|
-
hash
|
111
|
-
end
|
112
|
-
|
113
|
-
# Converts the attributes array of an XML element into a hash.
|
114
|
-
# Returns an empty Hash if node has no attributes.
|
115
|
-
#
|
116
|
-
# element::
|
117
|
-
# XML element to extract attributes from.
|
118
|
-
def get_attributes(element)
|
119
|
-
attributes = {}
|
120
|
-
element.attributes.to_hash.each { |n,v| attributes[n] = v } if element.respond_to? :attributes
|
121
|
-
attributes
|
122
|
-
end
|
123
|
-
|
124
|
-
# Determines if a document element has text content
|
125
|
-
#
|
126
|
-
# element::
|
127
|
-
# XML element to be checked.
|
128
|
-
def empty_content?(element)
|
129
|
-
#element.texts.join.blank?
|
130
|
-
element.children.nil? #or element.children[0].to_s.blank?
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
data/lib/rfm/xml_mini/ox_sax.rb
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'ox'
|
3
|
-
rescue LoadError => e
|
4
|
-
$stderr.puts "You don't have Ox installed in your application. Please add it to your Gemfile and run bundle install"
|
5
|
-
raise e
|
6
|
-
end
|
7
|
-
require 'active_support/core_ext/object/blank'
|
8
|
-
require 'stringio'
|
9
|
-
|
10
|
-
# = XmlMini Ox implementation using a SAX-based parser
|
11
|
-
# This Ox Sax parser was lifted directly from multi_xml gem.
|
12
|
-
module ActiveSupport
|
13
|
-
module XmlMini_OxSAX
|
14
|
-
|
15
|
-
extend self
|
16
|
-
|
17
|
-
def parse_error
|
18
|
-
Exception
|
19
|
-
end
|
20
|
-
|
21
|
-
def parse(io)
|
22
|
-
if !io.respond_to?(:read)
|
23
|
-
io = StringIO.new(io || '')
|
24
|
-
end
|
25
|
-
handler = Handler.new
|
26
|
-
::Ox.sax_parse(handler, io, :convert_special => true)
|
27
|
-
handler.doc
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
class Handler
|
33
|
-
attr_accessor :stack
|
34
|
-
|
35
|
-
def initialize()
|
36
|
-
@stack = []
|
37
|
-
end
|
38
|
-
|
39
|
-
def doc
|
40
|
-
@stack[0]
|
41
|
-
end
|
42
|
-
|
43
|
-
def attr(name, value)
|
44
|
-
unless @stack.empty?
|
45
|
-
append(name, value)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def text(value)
|
50
|
-
append('__content__', value)
|
51
|
-
end
|
52
|
-
|
53
|
-
def cdata(value)
|
54
|
-
append('__content__', value)
|
55
|
-
end
|
56
|
-
|
57
|
-
def start_element(name)
|
58
|
-
if @stack.empty?
|
59
|
-
@stack.push(Hash.new)
|
60
|
-
end
|
61
|
-
h = Hash.new
|
62
|
-
append(name, h)
|
63
|
-
@stack.push(h)
|
64
|
-
end
|
65
|
-
|
66
|
-
def end_element(name)
|
67
|
-
@stack.pop()
|
68
|
-
end
|
69
|
-
|
70
|
-
def error(message, line, column)
|
71
|
-
raise Exception.new("#{message} at #{line}:#{column}")
|
72
|
-
end
|
73
|
-
|
74
|
-
def append(key, value)
|
75
|
-
key = key.to_s
|
76
|
-
h = @stack.last
|
77
|
-
if h.has_key?(key)
|
78
|
-
v = h[key]
|
79
|
-
if v.is_a?(Array)
|
80
|
-
v << value
|
81
|
-
else
|
82
|
-
h[key] = [v, value]
|
83
|
-
end
|
84
|
-
else
|
85
|
-
h[key] = value
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
end # Handler
|
90
|
-
end
|
91
|
-
end
|