client_for_poslynx 0.1.1 → 0.2.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 +8 -8
- data/CHANGELOG +3 -0
- data/lib/client_for_poslynx/data/abstract_data.rb +61 -99
- data/lib/client_for_poslynx/data/abstract_data/attribute_element_mapping.rb +141 -0
- data/lib/client_for_poslynx/data/abstract_data/defining_property_mapping.rb +22 -0
- data/lib/client_for_poslynx/data/requests/credit_card_sale.rb +1 -1
- data/lib/client_for_poslynx/data/requests/debit_card_sale.rb +1 -1
- data/lib/client_for_poslynx/data/requests/pin_pad_display_message.rb +3 -3
- data/lib/client_for_poslynx/data/requests/pin_pad_display_specified_form.rb +3 -3
- data/lib/client_for_poslynx/data/requests/pin_pad_initialize.rb +1 -1
- data/lib/client_for_poslynx/data/responses/credit_card_sale.rb +1 -1
- data/lib/client_for_poslynx/data/responses/debit_card_sale.rb +1 -1
- data/lib/client_for_poslynx/data/responses/pin_pad_display_message.rb +1 -1
- data/lib/client_for_poslynx/data/responses/pin_pad_display_specified_form.rb +1 -1
- data/lib/client_for_poslynx/data/responses/pin_pad_initialize.rb +1 -1
- data/lib/client_for_poslynx/data/xml_document.rb +48 -11
- data/lib/client_for_poslynx/version.rb +1 -1
- data/spec/client_for_poslynx/data/abstract_data/attribute_element_mapping_spec.rb +52 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NzJjNDczYjYzYzBiMTE1MDI3YTQ4Mjk1M2Y4OGM3ZTM4YTc5NzdhOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MzgxZGMxZGE4MWQ2ZTc5Yjc3Mjg1MzIzNzJkNDRiZjRkN2M5OGQzZA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTMzZTM0OGI5YThhNmI0ODZiNjllN2ZiMjI4OWFlMTM0N2VkYWVlNDRkMTZm
|
10
|
+
NWUzNTMwMjJkNTgyODYxMDBlYzI3YWNmMTk4MjMxYmE4YWM3OTExNzQ5MmI5
|
11
|
+
MTVkZGVlNmYyODZjNjFhOTM3MzAzZDA1ODJhNjZkNWZjNmU0ODE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTQwZDEyZGI0YWM4MjExNjBiOGU5M2MxNzcwNDY0M2ZhYmVkZjAwYmI2NzYw
|
14
|
+
MjBlZDhmMTM3N2M5ZDA5MDkxZmE3YmNmZDFlZjQwZjNhNmUzN2JmZDc2ZTkx
|
15
|
+
ZDI2MmExMDg0ZmVhYTBmNzdkNjlhM2I2ZTlmN2QxZjViYzkxNWY=
|
data/CHANGELOG
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
|
3
|
+
require_relative 'abstract_data/attribute_element_mapping'
|
4
|
+
require_relative 'abstract_data/defining_property_mapping'
|
4
5
|
|
5
6
|
module ClientForPoslynx
|
6
7
|
module Data
|
@@ -16,22 +17,16 @@ module ClientForPoslynx
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def xml_parse(source_xml)
|
19
|
-
doc = XmlDocument.
|
20
|
-
|
21
|
-
|
22
|
-
sort_by{ |d| -d.ancestors.length }
|
23
|
-
data_class = concrete_data_classes.detect{ |dc|
|
24
|
-
dc.root_element_name == doc.root_name &&
|
25
|
-
dc.fits_properties?( doc.property_element_contents )
|
26
|
-
}
|
27
|
-
data_class.xml_deserialize(source_xml)
|
20
|
+
doc = XmlDocument.from_xml( source_xml )
|
21
|
+
data_class = concrete_data_class_for_nokogiri_document( doc )
|
22
|
+
data_class.xml_deserialize( source_xml )
|
28
23
|
end
|
29
24
|
|
30
25
|
def xml_deserialize(xml)
|
31
|
-
doc = XmlDocument.
|
32
|
-
|
26
|
+
doc = XmlDocument.from_xml( xml )
|
27
|
+
doc.verify_root_element_name root_element_name
|
33
28
|
instance = load_from_properties( doc.property_element_contents )
|
34
|
-
instance.source_data =
|
29
|
+
instance.source_data = xml
|
35
30
|
instance
|
36
31
|
end
|
37
32
|
|
@@ -48,22 +43,20 @@ module ClientForPoslynx
|
|
48
43
|
unmatched.empty?
|
49
44
|
end
|
50
45
|
|
51
|
-
def
|
52
|
-
@
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
46
|
+
def defining_property_mappings
|
47
|
+
@defining_property_mappings ||= (
|
48
|
+
self == AbstractData ?
|
49
|
+
[] :
|
50
|
+
superclass.defining_property_mappings + []
|
51
|
+
)
|
58
52
|
end
|
59
53
|
|
60
54
|
def attr_element_mappings
|
61
|
-
@attr_element_mappings ||=
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
55
|
+
@attr_element_mappings ||= (
|
56
|
+
self == AbstractData ?
|
57
|
+
[] :
|
58
|
+
superclass.attr_element_mappings + []
|
59
|
+
)
|
67
60
|
end
|
68
61
|
|
69
62
|
private
|
@@ -76,72 +69,63 @@ module ClientForPoslynx
|
|
76
69
|
@@descendants ||= []
|
77
70
|
end
|
78
71
|
|
79
|
-
def
|
72
|
+
def concrete_data_class_for_nokogiri_document(doc)
|
73
|
+
data_class = concrete_data_classes.detect{ |dc|
|
74
|
+
dc.root_element_name == doc.root_name &&
|
75
|
+
dc.fits_properties?( doc.property_element_contents )
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def concrete_data_classes
|
80
|
+
descendants.
|
81
|
+
reject{ |d| d.name =~ /\bAbstract[A-Z]\w*$/ }.
|
82
|
+
sort_by{ |d| -d.ancestors.length }
|
83
|
+
end
|
84
|
+
|
85
|
+
def defining_property_value(options)
|
80
86
|
attribute = options.fetch( :attribute )
|
81
87
|
element = options.fetch( :element )
|
82
88
|
value = options.fetch( :value )
|
83
|
-
define_singleton_method(attribute) { value }
|
84
|
-
|
89
|
+
define_singleton_method( attribute ) { value }
|
90
|
+
define_method( attribute ) { value }
|
91
|
+
defining_property_mappings << DefiningPropertyMapping.new( attribute: attribute, element: element )
|
85
92
|
end
|
86
93
|
|
87
94
|
def attr_element_mapping(options)
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
raise ArgumentError, "#{type.inspect} is not a valid :type option. Must be :array when given." unless type == :array
|
92
|
-
end
|
93
|
-
attribute = options.fetch( :attribute )
|
94
|
-
element = options.fetch( :element )
|
95
|
-
attr_accessor attribute
|
96
|
-
attr_element_mappings << options
|
95
|
+
mapping = AbstractData::AttributeElementMapping.new( options )
|
96
|
+
attr_element_mappings << mapping
|
97
|
+
attr_accessor mapping.attribute_name
|
97
98
|
end
|
98
99
|
|
99
100
|
def verify_defining_properties(property_contents)
|
100
101
|
unmatched = unmatched_defining_properties( property_contents )
|
101
102
|
return if unmatched.empty?
|
102
|
-
message = unmatched.map{ |
|
103
|
-
|
104
|
-
|
105
|
-
"#{el_name} child element with \"#{defining_value}\" value not found."
|
103
|
+
message = unmatched.map{ |property_mapping|
|
104
|
+
defining_mapping = public_send( property_mapping.attribute_name )
|
105
|
+
"#{property_mapping.element_name} child element with \"#{defining_mapping}\" value not found."
|
106
106
|
}.join( ' ' )
|
107
107
|
raise InvalidXmlContentError, message
|
108
108
|
end
|
109
109
|
|
110
110
|
def unmatched_defining_properties(property_contents)
|
111
111
|
unmatched = []
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
unmatched << mapping unless property_contents[el_name] == defining_value
|
112
|
+
defining_property_mappings.each do |property_mapping|
|
113
|
+
defining_value = public_send( property_mapping.attribute_name )
|
114
|
+
unmatched << property_mapping unless property_contents[property_mapping.element_name] == defining_value
|
116
115
|
end
|
117
116
|
unmatched
|
118
117
|
end
|
119
118
|
|
120
119
|
def select_variable_property_contents(property_contents)
|
121
|
-
defining_element_names =
|
120
|
+
defining_element_names = defining_property_mappings.map(&:element_name)
|
122
121
|
property_contents.reject{ |name, content| defining_element_names.include?(name) }
|
123
122
|
end
|
124
123
|
|
125
124
|
def populate_instance_from_properties instance, variable_property_contents
|
126
125
|
variable_property_contents.each do |name, content|
|
127
|
-
mapping = attr_element_mappings.detect{ |mapping| mapping
|
126
|
+
mapping = attr_element_mappings.detect{ |mapping| mapping.element_name == name }
|
128
127
|
next unless mapping
|
129
|
-
|
130
|
-
template = mapping[:numbered_lines]
|
131
|
-
[].tap{ |lines|
|
132
|
-
line_num = 1
|
133
|
-
while ( content.has_key?(key = template % line_num) )
|
134
|
-
lines << content[key]
|
135
|
-
line_num += 1
|
136
|
-
end
|
137
|
-
}
|
138
|
-
elsif mapping[:type] == :array
|
139
|
-
content.split('|')
|
140
|
-
else
|
141
|
-
content
|
142
|
-
end
|
143
|
-
attribute = mapping[:attribute]
|
144
|
-
instance.public_send "#{attribute}=", value
|
128
|
+
instance.public_send "#{mapping.attribute_name}=", mapping.value_from_element_content( content)
|
145
129
|
end
|
146
130
|
end
|
147
131
|
|
@@ -150,50 +134,28 @@ module ClientForPoslynx
|
|
150
134
|
attr_accessor :source_data
|
151
135
|
|
152
136
|
def xml_serialize
|
153
|
-
doc =
|
154
|
-
|
155
|
-
|
156
|
-
content = self.class.public_send( mapping[:attribute] )
|
157
|
-
next unless content
|
158
|
-
element = doc.create_element( mapping[:element], nil, nil, content )
|
159
|
-
root.add_child element
|
160
|
-
end
|
161
|
-
self.class.attr_element_mappings.each do |mapping|
|
162
|
-
content = public_send( mapping[:attribute] )
|
163
|
-
next unless content
|
164
|
-
element = if mapping[:numbered_lines]
|
165
|
-
build_numbered_lines_xml_node( doc, mapping[:element], mapping[:numbered_lines], content )
|
166
|
-
elsif mapping[:type] == :array
|
167
|
-
build_vertical_bar_separated_list_node( doc, mapping[:element], content )
|
168
|
-
else
|
169
|
-
build_text_element_node( doc, mapping[:element], content )
|
170
|
-
end
|
171
|
-
root.add_child element
|
172
|
-
end
|
173
|
-
doc.root = root
|
174
|
-
doc.serialize(:save_with => Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION)
|
137
|
+
doc = Data::XmlDocument.with_root_element_name( self.class.root_element_name )
|
138
|
+
add_properties_to_xml_document doc
|
139
|
+
doc.serialize
|
175
140
|
end
|
176
141
|
|
177
142
|
private
|
178
143
|
|
179
|
-
def
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
element.add_child line_el
|
144
|
+
def add_properties_to_xml_document(doc)
|
145
|
+
all_mappings.each do |mapping|
|
146
|
+
content = property_attribute_value( mapping )
|
147
|
+
next unless content
|
148
|
+
doc_content = mapping.xml_doc_content_from_client_content( content )
|
149
|
+
doc.add_property_content mapping.element_name, doc_content
|
186
150
|
end
|
187
|
-
element
|
188
151
|
end
|
189
152
|
|
190
|
-
def
|
191
|
-
|
192
|
-
doc.create_element( element_name, nil, nil, text )
|
153
|
+
def all_mappings
|
154
|
+
self.class.defining_property_mappings + self.class.attr_element_mappings
|
193
155
|
end
|
194
156
|
|
195
|
-
def
|
196
|
-
|
157
|
+
def property_attribute_value( property )
|
158
|
+
public_send( property.attribute_name )
|
197
159
|
end
|
198
160
|
|
199
161
|
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module ClientForPoslynx
|
6
|
+
module Data
|
7
|
+
class AbstractData
|
8
|
+
|
9
|
+
module AttributeElementMapping
|
10
|
+
|
11
|
+
class Abstract ; end
|
12
|
+
class Text < AttributeElementMapping::Abstract ; end
|
13
|
+
class MultiText < AttributeElementMapping::Abstract ; end
|
14
|
+
class NumberedLines < AttributeElementMapping::Abstract ; end
|
15
|
+
|
16
|
+
def self.new(options)
|
17
|
+
klass = case
|
18
|
+
when options[:multi_text] ; AttributeElementMapping::MultiText
|
19
|
+
when options[:numbered_lines] ; AttributeElementMapping::NumberedLines
|
20
|
+
else ; AttributeElementMapping::Text
|
21
|
+
end
|
22
|
+
klass.new( options )
|
23
|
+
end
|
24
|
+
|
25
|
+
class Abstract
|
26
|
+
attr_reader :attribute_name, :element_name, :numbered_line_template
|
27
|
+
|
28
|
+
def numbered_lines? ; @numbered_lines ; end
|
29
|
+
def multi_text? ; @multi_text ; end
|
30
|
+
|
31
|
+
def initialize(options)
|
32
|
+
options = options.reject { |k,v| v.nil? }
|
33
|
+
@attribute_name = options.fetch( :attribute ) { raise ArgumentError, ':attribute option value must be provided' }
|
34
|
+
@element_name = options.fetch( :element ) { raise ArgumentError, ':element option value must be provided' }
|
35
|
+
options.delete :attribute ; options.delete :element
|
36
|
+
additional_init options
|
37
|
+
verify_no_unexpected_unused_options options
|
38
|
+
end
|
39
|
+
|
40
|
+
def text_mapping? ; false ; end
|
41
|
+
def multi_text_mapping? ; false ; end
|
42
|
+
def numbered_lines_mapping? ; false ; end
|
43
|
+
|
44
|
+
def value_from_element_content(content)
|
45
|
+
raise NotImplementedError
|
46
|
+
[].tap{ |lines|
|
47
|
+
line_num = 1
|
48
|
+
while ( content.has_key?(key = numbered_line_template % line_num) )
|
49
|
+
lines << content[key]
|
50
|
+
line_num += 1
|
51
|
+
end
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def xml_doc_content_from_client_content(client_content)
|
56
|
+
raise NotImplementedError
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def verify_no_unexpected_unused_options(unused_options)
|
62
|
+
unless unused_options.empty?
|
63
|
+
key_list = unused_options.keys.map(&:inspect)
|
64
|
+
raise ArgumentError, "Unexpected option(s) #{key_list} supplied"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def additional_init(options)
|
69
|
+
# Do nothing by default.
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Text < AttributeElementMapping::Abstract
|
74
|
+
def text_mapping? ; true ; end
|
75
|
+
|
76
|
+
def value_from_element_content(content)
|
77
|
+
content
|
78
|
+
end
|
79
|
+
|
80
|
+
def xml_doc_content_from_client_content(client_content)
|
81
|
+
client_content.to_s
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class MultiText < AttributeElementMapping::Abstract
|
86
|
+
def multi_text_mapping? ; true ; end
|
87
|
+
|
88
|
+
def value_from_element_content(content)
|
89
|
+
content.split('|')
|
90
|
+
end
|
91
|
+
|
92
|
+
def xml_doc_content_from_client_content(client_content)
|
93
|
+
client_content = [client_content].flatten
|
94
|
+
client_content * '|'
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def additional_init(options)
|
100
|
+
@multi_text = !!options.delete( :multi_text )
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class NumberedLines < AttributeElementMapping::Abstract
|
105
|
+
def numbered_lines_mapping? ; true ; end
|
106
|
+
|
107
|
+
def value_from_element_content(content)
|
108
|
+
[].tap{ |lines|
|
109
|
+
line_num = 1
|
110
|
+
while ( content.has_key?(key = numbered_line_template % line_num) )
|
111
|
+
lines << content[key]
|
112
|
+
line_num += 1
|
113
|
+
end
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
def xml_doc_content_from_client_content(client_content)
|
118
|
+
client_content = [client_content].flatten
|
119
|
+
Hash[
|
120
|
+
client_content.each_with_index.map { |line_text, idx|
|
121
|
+
line_num = idx + 1
|
122
|
+
line_element_name = numbered_line_template % line_num
|
123
|
+
[ line_element_name, line_text ]
|
124
|
+
}
|
125
|
+
]
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def additional_init(options)
|
131
|
+
numbered_line_name_template = options.delete( :numbered_lines )
|
132
|
+
@numbered_lines = !!numbered_line_name_template
|
133
|
+
@numbered_line_template = numbered_line_name_template
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ClientForPoslynx
|
4
|
+
module Data
|
5
|
+
class AbstractData
|
6
|
+
|
7
|
+
class DefiningPropertyMapping
|
8
|
+
attr_reader :attribute_name, :element_name
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
@attribute_name = options.fetch(:attribute)
|
12
|
+
@element_name = options.fetch(:element)
|
13
|
+
end
|
14
|
+
|
15
|
+
def xml_doc_content_from_client_content(client_content)
|
16
|
+
client_content
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -8,7 +8,7 @@ module ClientForPoslynx
|
|
8
8
|
|
9
9
|
class CreditCardSale < AbstractRequest
|
10
10
|
|
11
|
-
|
11
|
+
defining_property_value attribute: :command, element: 'Command', value: 'CCSALE'
|
12
12
|
|
13
13
|
attr_element_mapping attribute: :merchant_supplied_id, element: 'Id'
|
14
14
|
attr_element_mapping attribute: :client_id, element: 'ClientId'
|
@@ -8,7 +8,7 @@ module ClientForPoslynx
|
|
8
8
|
|
9
9
|
class DebitCardSale < AbstractRequest
|
10
10
|
|
11
|
-
|
11
|
+
defining_property_value attribute: :command, element: 'Command', value: 'DCSALE'
|
12
12
|
|
13
13
|
attr_element_mapping attribute: :merchant_supplied_id, element: 'Id'
|
14
14
|
attr_element_mapping attribute: :client_id, element: 'ClientId'
|
@@ -8,10 +8,10 @@ module ClientForPoslynx
|
|
8
8
|
|
9
9
|
class PinPadDisplayMessage < AbstractRequest
|
10
10
|
|
11
|
-
|
11
|
+
defining_property_value attribute: :command, element: 'Command', value: 'PPDISPLAY'
|
12
12
|
attr_element_mapping attribute: :line_count, element: 'Lines'
|
13
|
-
attr_element_mapping attribute: :text_lines, element: 'Text',
|
14
|
-
attr_element_mapping attribute: :button_labels, element: 'Buttons',
|
13
|
+
attr_element_mapping attribute: :text_lines, element: 'Text', multi_text: true
|
14
|
+
attr_element_mapping attribute: :button_labels, element: 'Buttons', multi_text: true
|
15
15
|
|
16
16
|
end
|
17
17
|
|
@@ -8,11 +8,11 @@ module ClientForPoslynx
|
|
8
8
|
|
9
9
|
class PinPadDisplaySpecifiedForm < AbstractRequest
|
10
10
|
|
11
|
-
|
11
|
+
defining_property_value attribute: :command, element: 'Command', value: 'PPSPECIFIEDFORM'
|
12
12
|
|
13
13
|
attr_element_mapping attribute: :form_name, element: 'FormName'
|
14
|
-
attr_element_mapping attribute: :text_values, element: 'Text',
|
15
|
-
attr_element_mapping attribute: :button_labels, element: 'Buttons',
|
14
|
+
attr_element_mapping attribute: :text_values, element: 'Text', multi_text: true
|
15
|
+
attr_element_mapping attribute: :button_labels, element: 'Buttons', multi_text: true
|
16
16
|
|
17
17
|
end
|
18
18
|
|
@@ -8,7 +8,7 @@ module ClientForPoslynx
|
|
8
8
|
|
9
9
|
class PinPadInitialize < AbstractRequest
|
10
10
|
|
11
|
-
|
11
|
+
defining_property_value attribute: :command, element: 'Command', value: 'PPINIT'
|
12
12
|
attr_element_mapping attribute: :idle_prompt, element: 'IdlePrompt'
|
13
13
|
|
14
14
|
end
|
@@ -8,7 +8,7 @@ module ClientForPoslynx
|
|
8
8
|
|
9
9
|
class CreditCardSale < AbstractResponse
|
10
10
|
|
11
|
-
|
11
|
+
defining_property_value attribute: :command, element: 'Command', value: 'CCSALE'
|
12
12
|
|
13
13
|
attr_element_mapping attribute: :processor_authorization, element: 'Authorization'
|
14
14
|
attr_element_mapping attribute: :record_number, element: 'RecNum'
|
@@ -8,7 +8,7 @@ module ClientForPoslynx
|
|
8
8
|
|
9
9
|
class DebitCardSale < AbstractResponse
|
10
10
|
|
11
|
-
|
11
|
+
defining_property_value attribute: :command, element: 'Command', value: 'DCSALE'
|
12
12
|
|
13
13
|
attr_element_mapping attribute: :processor_authorization, element: 'Authorization'
|
14
14
|
attr_element_mapping attribute: :record_number, element: 'RecNum'
|
@@ -8,7 +8,7 @@ module ClientForPoslynx
|
|
8
8
|
|
9
9
|
class PinPadDisplayMessage < AbstractResponse
|
10
10
|
|
11
|
-
|
11
|
+
defining_property_value attribute: :command, element: 'Command', value: 'PPDISPLAY'
|
12
12
|
attr_element_mapping attribute: :button_response, element: 'Response'
|
13
13
|
|
14
14
|
end
|
@@ -8,7 +8,7 @@ module ClientForPoslynx
|
|
8
8
|
|
9
9
|
class PinPadDisplaySpecifiedForm < AbstractResponse
|
10
10
|
|
11
|
-
|
11
|
+
defining_property_value attribute: :command, element: 'Command', value: 'PPSPECIFIEDFORM'
|
12
12
|
attr_element_mapping attribute: :button_response, element: 'Response'
|
13
13
|
attr_element_mapping attribute: :signature_data, element: 'Signature'
|
14
14
|
|
@@ -7,18 +7,42 @@ module ClientForPoslynx
|
|
7
7
|
|
8
8
|
class XmlDocument
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
class << self
|
11
|
+
private :new
|
12
|
+
|
13
|
+
def with_root_element_name(name)
|
14
|
+
nokogiri_doc = Nokogiri::XML::Document.new
|
15
|
+
nokogiri_doc.root = nokogiri_doc.create_element( name )
|
16
|
+
new(nokogiri_doc)
|
17
|
+
end
|
18
|
+
|
19
|
+
def from_xml(source_xml)
|
20
|
+
nokogiri_doc = Nokogiri::XML::Document.parse(
|
21
|
+
source_xml,
|
22
|
+
nil, nil,
|
23
|
+
Nokogiri::XML::ParseOptions::DEFAULT_XML & ~Nokogiri::XML::ParseOptions::RECOVER
|
24
|
+
)
|
25
|
+
new(nokogiri_doc)
|
26
|
+
rescue Nokogiri::XML::SyntaxError => e
|
27
|
+
raise InvalidXmlError
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(nokogiri_doc)
|
33
|
+
@nokogiri_doc = nokogiri_doc
|
34
|
+
end
|
35
|
+
|
36
|
+
def verify_root_element_name(expected_name)
|
37
|
+
unless root_name == expected_name
|
38
|
+
raise InvalidXmlContentError, "#{expected_name} root element not found"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def serialize
|
43
|
+
nokogiri_doc.serialize(
|
44
|
+
:save_with => Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
18
45
|
)
|
19
|
-
rescue Nokogiri::XML::SyntaxError => e
|
20
|
-
p e
|
21
|
-
raise InvalidXmlError
|
22
46
|
end
|
23
47
|
|
24
48
|
def root_name
|
@@ -29,6 +53,19 @@ module ClientForPoslynx
|
|
29
53
|
@property_element_contents ||= hash_from_element( root )
|
30
54
|
end
|
31
55
|
|
56
|
+
def add_property_content(element_name, content)
|
57
|
+
element = nokogiri_doc.create_element( element_name )
|
58
|
+
if Hash === content
|
59
|
+
content.each do |element_name, text|
|
60
|
+
child_element = nokogiri_doc.create_element( element_name, nil, nil, text )
|
61
|
+
element.add_child child_element
|
62
|
+
end
|
63
|
+
else
|
64
|
+
element.content = content.to_s
|
65
|
+
end
|
66
|
+
root.add_child element
|
67
|
+
end
|
68
|
+
|
32
69
|
private
|
33
70
|
|
34
71
|
attr_reader :nokogiri_doc
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe ClientForPoslynx::Data::AbstractData::AttributeElementMapping do
|
6
|
+
|
7
|
+
it "Fails creation without :attribute option" do
|
8
|
+
expect{
|
9
|
+
described_class.new element: 'Foo'
|
10
|
+
}.to raise_exception( ArgumentError )
|
11
|
+
end
|
12
|
+
|
13
|
+
it "Fails creation without :element option" do
|
14
|
+
expect{
|
15
|
+
described_class.new attribute: :foo
|
16
|
+
}.to raise_exception( ArgumentError )
|
17
|
+
end
|
18
|
+
|
19
|
+
it "Creates a text mapping instance with minimum attriubtes" do
|
20
|
+
actual = described_class.new(
|
21
|
+
attribute: :foo, element: 'Foo'
|
22
|
+
)
|
23
|
+
expect( actual ).to be_text_mapping
|
24
|
+
end
|
25
|
+
|
26
|
+
it "Creates a multi-text mapping instance with multi_text attribute" do
|
27
|
+
actual = described_class.new(
|
28
|
+
attribute: :foo, element: 'Foo', multi_text: true
|
29
|
+
)
|
30
|
+
expect( actual ).to be_multi_text_mapping
|
31
|
+
end
|
32
|
+
|
33
|
+
it "Creates a numbered_lines mapping instance with numbered_lines attribute" do
|
34
|
+
actual = described_class.new(
|
35
|
+
attribute: :foo, element: 'Foo', numbered_lines: 'the-template'
|
36
|
+
)
|
37
|
+
expect( actual ).to be_numbered_lines_mapping
|
38
|
+
end
|
39
|
+
|
40
|
+
it "Fails creation with unexpected attribute" do
|
41
|
+
expect{
|
42
|
+
described_class.new attribute: :foo, element: 'Foo', bar: true
|
43
|
+
}.to raise_exception( ArgumentError )
|
44
|
+
end
|
45
|
+
|
46
|
+
it "fails creation with both nulti-text and numbered-lines options" do
|
47
|
+
expect{
|
48
|
+
described_class.new attribute: :foo, element: 'Foo', multi_text: true, numbered_lines: 'x'
|
49
|
+
}.to raise_exception( ArgumentError )
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: client_for_poslynx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Jorgensen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -89,6 +89,8 @@ files:
|
|
89
89
|
- lib/client_for_poslynx.rb
|
90
90
|
- lib/client_for_poslynx/data.rb
|
91
91
|
- lib/client_for_poslynx/data/abstract_data.rb
|
92
|
+
- lib/client_for_poslynx/data/abstract_data/attribute_element_mapping.rb
|
93
|
+
- lib/client_for_poslynx/data/abstract_data/defining_property_mapping.rb
|
92
94
|
- lib/client_for_poslynx/data/properties_xml_parser.rb
|
93
95
|
- lib/client_for_poslynx/data/requests.rb
|
94
96
|
- lib/client_for_poslynx/data/requests/abstract_request.rb
|
@@ -127,6 +129,7 @@ files:
|
|
127
129
|
- lib/client_for_poslynx/message_handling/stream_data_writer.rb
|
128
130
|
- lib/client_for_poslynx/message_handling/xml_extractor.rb
|
129
131
|
- lib/client_for_poslynx/version.rb
|
132
|
+
- spec/client_for_poslynx/data/abstract_data/attribute_element_mapping_spec.rb
|
130
133
|
- spec/client_for_poslynx/data/abstract_data_spec.rb
|
131
134
|
- spec/client_for_poslynx/data/requests/abstract_request_spec.rb
|
132
135
|
- spec/client_for_poslynx/data/requests/can_visit_spec.rb
|
@@ -172,6 +175,7 @@ signing_key:
|
|
172
175
|
specification_version: 4
|
173
176
|
summary: A TCP client for Precidia's POSLynx™ devices
|
174
177
|
test_files:
|
178
|
+
- spec/client_for_poslynx/data/abstract_data/attribute_element_mapping_spec.rb
|
175
179
|
- spec/client_for_poslynx/data/abstract_data_spec.rb
|
176
180
|
- spec/client_for_poslynx/data/requests/abstract_request_spec.rb
|
177
181
|
- spec/client_for_poslynx/data/requests/can_visit_spec.rb
|