openagent 0.7.1

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.
Files changed (221) hide show
  1. data/README.md +64 -0
  2. data/lib/openagent.rb +4 -0
  3. data/lib/openagent/agent.rb +24 -0
  4. data/lib/openagent/client.rb +170 -0
  5. data/lib/openagent/errors.rb +30 -0
  6. data/lib/openagent/message_builder.rb +171 -0
  7. data/lib/openagent/ssl_config.rb +26 -0
  8. data/lib/openagent/version.rb +3 -0
  9. data/lib/openagent/xml_helpers.rb +24 -0
  10. data/lib/openagent/zone.rb +58 -0
  11. data/lib/sif/infra/common/application.rb +13 -0
  12. data/lib/sif/infra/common/condition.rb +13 -0
  13. data/lib/sif/infra/common/condition_group.rb +14 -0
  14. data/lib/sif/infra/common/data.rb +11 -0
  15. data/lib/sif/infra/common/error.rb +14 -0
  16. data/lib/sif/infra/common/event.rb +0 -0
  17. data/lib/sif/infra/common/event_object.rb +12 -0
  18. data/lib/sif/infra/common/extended_query.rb +15 -0
  19. data/lib/sif/infra/common/extended_query_results.rb +12 -0
  20. data/lib/sif/infra/common/header.rb +27 -0
  21. data/lib/sif/infra/common/message.rb +49 -0
  22. data/lib/sif/infra/common/object.rb +11 -0
  23. data/lib/sif/infra/common/object_data.rb +46 -0
  24. data/lib/sif/infra/common/other_id.rb +12 -0
  25. data/lib/sif/infra/common/property.rb +12 -0
  26. data/lib/sif/infra/common/protocol.rb +16 -0
  27. data/lib/sif/infra/common/provision.rb +17 -0
  28. data/lib/sif/infra/common/query.rb +16 -0
  29. data/lib/sif/infra/common/query_object.rb +12 -0
  30. data/lib/sif/infra/common/secure_channel.rb +12 -0
  31. data/lib/sif/infra/common/security.rb +13 -0
  32. data/lib/sif/infra/common/status.rb +16 -0
  33. data/lib/sif/infra/common/unprovision.rb +9 -0
  34. data/lib/sif/infra/common/vendor.rb +13 -0
  35. data/lib/sif/infra/messages/ack.rb +16 -0
  36. data/lib/sif/infra/messages/event.rb +12 -0
  37. data/lib/sif/infra/messages/get_agent_acl.rb +11 -0
  38. data/lib/sif/infra/messages/get_message.rb +11 -0
  39. data/lib/sif/infra/messages/get_zone_status.rb +10 -0
  40. data/lib/sif/infra/messages/ping.rb +10 -0
  41. data/lib/sif/infra/messages/provide.rb +16 -0
  42. data/lib/sif/infra/messages/provision.rb +18 -0
  43. data/lib/sif/infra/messages/register.rb +21 -0
  44. data/lib/sif/infra/messages/request.rb +16 -0
  45. data/lib/sif/infra/messages/responder.rb +9 -0
  46. data/lib/sif/infra/messages/response.rb +18 -0
  47. data/lib/sif/infra/messages/sleep.rb +11 -0
  48. data/lib/sif/infra/messages/subscribe.rb +12 -0
  49. data/lib/sif/infra/messages/system_control.rb +15 -0
  50. data/lib/sif/infra/messages/system_control_data.rb +39 -0
  51. data/lib/sif/infra/messages/unprovide.rb +12 -0
  52. data/lib/sif/infra/messages/unregister.rb +11 -0
  53. data/lib/sif/infra/messages/unsubscribe.rb +12 -0
  54. data/lib/sif/infra/messages/wakeup.rb +11 -0
  55. data/lib/sif/infra/messages/zone_status_role.rb +12 -0
  56. data/lib/sif/infra/objects/agent_acl.rb +19 -0
  57. data/lib/sif/infra/objects/zone_status.rb +30 -0
  58. data/lib/sif/models/common/address.rb +21 -0
  59. data/lib/sif/models/common/alert_message.rb +12 -0
  60. data/lib/sif/models/common/base_name.rb +12 -0
  61. data/lib/sif/models/common/calendar_summary.rb +28 -0
  62. data/lib/sif/models/common/code.rb +12 -0
  63. data/lib/sif/models/common/contact_info.rb +21 -0
  64. data/lib/sif/models/common/credits_attempted.rb +12 -0
  65. data/lib/sif/models/common/demographics.rb +31 -0
  66. data/lib/sif/models/common/dwelling_arrangement.rb +14 -0
  67. data/lib/sif/models/common/earned_status.rb +15 -0
  68. data/lib/sif/models/common/electronic_id.rb +12 -0
  69. data/lib/sif/models/common/email.rb +13 -0
  70. data/lib/sif/models/common/english_proficiency.rb +14 -0
  71. data/lib/sif/models/common/exceptionality_category.rb +13 -0
  72. data/lib/sif/models/common/grade_level.rb +12 -0
  73. data/lib/sif/models/common/grid_location.rb +12 -0
  74. data/lib/sif/models/common/identification_info.rb +12 -0
  75. data/lib/sif/models/common/language.rb +14 -0
  76. data/lib/sif/models/common/meal_status.rb +16 -0
  77. data/lib/sif/models/common/medical_alert_message.rb +12 -0
  78. data/lib/sif/models/common/meeting_time.rb +12 -0
  79. data/lib/sif/models/common/name.rb +19 -0
  80. data/lib/sif/models/common/other_code.rb +12 -0
  81. data/lib/sif/models/common/other_id.rb +12 -0
  82. data/lib/sif/models/common/phone_number.rb +15 -0
  83. data/lib/sif/models/common/principal_info.rb +12 -0
  84. data/lib/sif/models/common/race.rb +15 -0
  85. data/lib/sif/models/common/sced_code.rb +15 -0
  86. data/lib/sif/models/common/schedule_info.rb +14 -0
  87. data/lib/sif/models/common/schedule_info_override.rb +13 -0
  88. data/lib/sif/models/common/school_contact.rb +13 -0
  89. data/lib/sif/models/common/school_course_info_override.rb +18 -0
  90. data/lib/sif/models/common/street.rb +22 -0
  91. data/lib/sif/models/common/subject_area.rb +13 -0
  92. data/lib/sif/models/groups/data_model/term_span.rb +14 -0
  93. data/lib/sif/models/groups/sis/attendance_code_info.rb +23 -0
  94. data/lib/sif/models/groups/sis/calendar_date.rb +25 -0
  95. data/lib/sif/models/groups/sis/discipline_incident.rb +31 -0
  96. data/lib/sif/models/groups/sis/lea_info.rb +28 -0
  97. data/lib/sif/models/groups/sis/personal_representer.rb +22 -0
  98. data/lib/sif/models/groups/sis/school_course_info.rb +30 -0
  99. data/lib/sif/models/groups/sis/school_info.rb +32 -0
  100. data/lib/sif/models/groups/sis/section_info.rb +26 -0
  101. data/lib/sif/models/groups/sis/sis_representer.rb +15 -0
  102. data/lib/sif/models/groups/sis/staff_personal.rb +20 -0
  103. data/lib/sif/models/groups/sis/student_personal.rb +37 -0
  104. data/lib/sif/models/groups/sis/student_section_enrollment.rb +21 -0
  105. data/lib/sif/models/groups/sis/term_info.rb +29 -0
  106. data/lib/sif/representations/infra/common/application.rb +16 -0
  107. data/lib/sif/representations/infra/common/condition.rb +16 -0
  108. data/lib/sif/representations/infra/common/condition_group.rb +18 -0
  109. data/lib/sif/representations/infra/common/data.rb +17 -0
  110. data/lib/sif/representations/infra/common/error.rb +17 -0
  111. data/lib/sif/representations/infra/common/event.rb +0 -0
  112. data/lib/sif/representations/infra/common/event_object.rb +15 -0
  113. data/lib/sif/representations/infra/common/extended_query.rb +18 -0
  114. data/lib/sif/representations/infra/common/extended_query_results.rb +15 -0
  115. data/lib/sif/representations/infra/common/header.rb +23 -0
  116. data/lib/sif/representations/infra/common/message.rb +54 -0
  117. data/lib/sif/representations/infra/common/object.rb +14 -0
  118. data/lib/sif/representations/infra/common/object_data.rb +43 -0
  119. data/lib/sif/representations/infra/common/other_id.rb +15 -0
  120. data/lib/sif/representations/infra/common/property.rb +15 -0
  121. data/lib/sif/representations/infra/common/protocol.rb +22 -0
  122. data/lib/sif/representations/infra/common/provision.rb +38 -0
  123. data/lib/sif/representations/infra/common/query.rb +24 -0
  124. data/lib/sif/representations/infra/common/query_object.rb +15 -0
  125. data/lib/sif/representations/infra/common/secure_channel.rb +15 -0
  126. data/lib/sif/representations/infra/common/security.rb +18 -0
  127. data/lib/sif/representations/infra/common/status.rb +18 -0
  128. data/lib/sif/representations/infra/messages/ack.rb +25 -0
  129. data/lib/sif/representations/infra/messages/event.rb +19 -0
  130. data/lib/sif/representations/infra/messages/get_message.rb +12 -0
  131. data/lib/sif/representations/infra/messages/ping.rb +13 -0
  132. data/lib/sif/representations/infra/messages/provide.rb +19 -0
  133. data/lib/sif/representations/infra/messages/provision.rb +37 -0
  134. data/lib/sif/representations/infra/messages/register.rb +30 -0
  135. data/lib/sif/representations/infra/messages/request.rb +24 -0
  136. data/lib/sif/representations/infra/messages/response.rb +29 -0
  137. data/lib/sif/representations/infra/messages/sleep.rb +14 -0
  138. data/lib/sif/representations/infra/messages/subscribe.rb +19 -0
  139. data/lib/sif/representations/infra/messages/system_control.rb +23 -0
  140. data/lib/sif/representations/infra/messages/system_control_data.rb +31 -0
  141. data/lib/sif/representations/infra/messages/wakeup.rb +14 -0
  142. data/lib/sif/representations/models/common/address.rb +24 -0
  143. data/lib/sif/representations/models/common/alert_message.rb +16 -0
  144. data/lib/sif/representations/models/common/contact_info.rb +28 -0
  145. data/lib/sif/representations/models/common/credits_attempted.rb +15 -0
  146. data/lib/sif/representations/models/common/demographics.rb +43 -0
  147. data/lib/sif/representations/models/common/dwelling_arrangement.rb +18 -0
  148. data/lib/sif/representations/models/common/electronic_id.rb +16 -0
  149. data/lib/sif/representations/models/common/email.rb +16 -0
  150. data/lib/sif/representations/models/common/english_proficiency.rb +17 -0
  151. data/lib/sif/representations/models/common/identification_info.rb +16 -0
  152. data/lib/sif/representations/models/common/language.rb +19 -0
  153. data/lib/sif/representations/models/common/medical_alert_message.rb +15 -0
  154. data/lib/sif/representations/models/common/meeting_time.rb +16 -0
  155. data/lib/sif/representations/models/common/name.rb +22 -0
  156. data/lib/sif/representations/models/common/other_code.rb +15 -0
  157. data/lib/sif/representations/models/common/other_id.rb +15 -0
  158. data/lib/sif/representations/models/common/phone_number.rb +18 -0
  159. data/lib/sif/representations/models/common/principal_info.rb +15 -0
  160. data/lib/sif/representations/models/common/race.rb +18 -0
  161. data/lib/sif/representations/models/common/sced_code.rb +18 -0
  162. data/lib/sif/representations/models/common/schedule_info.rb +19 -0
  163. data/lib/sif/representations/models/common/schedule_info_override.rb +18 -0
  164. data/lib/sif/representations/models/common/school_contact.rb +17 -0
  165. data/lib/sif/representations/models/common/school_course_info_override.rb +21 -0
  166. data/lib/sif/representations/models/common/street.rb +26 -0
  167. data/lib/sif/representations/models/common/subject_area.rb +17 -0
  168. data/lib/sif/representations/models/groups/data_model/term_span.rb +20 -0
  169. data/lib/sif/representations/models/groups/sis/personal_representer.rb +38 -0
  170. data/lib/sif/representations/models/groups/sis/school_course_info.rb +36 -0
  171. data/lib/sif/representations/models/groups/sis/school_info.rb +47 -0
  172. data/lib/sif/representations/models/groups/sis/section_info.rb +29 -0
  173. data/lib/sif/representations/models/groups/sis/sis_representer.rb +17 -0
  174. data/lib/sif/representations/models/groups/sis/staff_personal.rb +19 -0
  175. data/lib/sif/representations/models/groups/sis/student_personal.rb +37 -0
  176. data/lib/sif/representations/models/groups/sis/student_section_enrollment.rb +26 -0
  177. data/lib/sif/representations/models/groups/sis/term_info.rb +30 -0
  178. data/lib/sif/sif.rb +249 -0
  179. data/openagent.gemspec +33 -0
  180. data/spec/agent_spec.rb +32 -0
  181. data/spec/client_spec.rb +96 -0
  182. data/spec/fixtures/agent.yaml +31 -0
  183. data/spec/fixtures/messages/event.xml +72 -0
  184. data/spec/fixtures/messages/response.xml +107 -0
  185. data/spec/fixtures/sif/attendance_code_info.xml +9 -0
  186. data/spec/fixtures/sif/calendar_date.xml +22 -0
  187. data/spec/fixtures/sif/calendar_summary.xml +21 -0
  188. data/spec/fixtures/sif/demographics.xml +33 -0
  189. data/spec/fixtures/sif/discipline_incident.xml +70 -0
  190. data/spec/fixtures/sif/lea_info.xml +55 -0
  191. data/spec/fixtures/sif/section_info.xml +1536 -0
  192. data/spec/fixtures/sif/sif_header.xml +12 -0
  193. data/spec/fixtures/sif/sif_message__response.xml +107 -0
  194. data/spec/fixtures/sif/sif_object_data.xml +5 -0
  195. data/spec/fixtures/sif/sif_protocol.xml +3 -0
  196. data/spec/fixtures/sif/sif_protocol__properties.xml +10 -0
  197. data/spec/fixtures/sif/sif_provide.xml +9 -0
  198. data/spec/fixtures/sif/sif_provision.xml +33 -0
  199. data/spec/fixtures/sif/sif_register.xml +20 -0
  200. data/spec/fixtures/sif/sif_request.xml +21 -0
  201. data/spec/fixtures/sif/sif_response.xml +19 -0
  202. data/spec/fixtures/sif/sif_system_control.xml +10 -0
  203. data/spec/fixtures/sif/stu_pers_resp.xml +2 -0
  204. data/spec/fixtures/sif/student_personal.xml +42 -0
  205. data/spec/fixtures/zone.yaml +6 -0
  206. data/spec/message_builder_spec.rb +81 -0
  207. data/spec/response_spec.rb +35 -0
  208. data/spec/sif/representations/xml/header_spec.rb +30 -0
  209. data/spec/sif/representations/xml/message_spec.rb +20 -0
  210. data/spec/sif/representations/xml/object_data_spec.rb +19 -0
  211. data/spec/sif/representations/xml/protocol_spec.rb +34 -0
  212. data/spec/sif/representations/xml/provide_spec.rb +19 -0
  213. data/spec/sif/representations/xml/provision_spec.rb +56 -0
  214. data/spec/sif/representations/xml/register_spec.rb +17 -0
  215. data/spec/sif/representations/xml/request_spec.rb +17 -0
  216. data/spec/sif/representations/xml/response_spec.rb +16 -0
  217. data/spec/sif/representations/xml/spec_helper.rb +7 -0
  218. data/spec/sif/representations/xml/student_personal_spec.rb +69 -0
  219. data/spec/spec_helper.rb +7 -0
  220. data/spec/zone_spec.rb +26 -0
  221. metadata +455 -0
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ OpenAgent
2
+ =========
3
+
4
+ OpenAgent is a Ruby library for educational institutions that makes it easy to communicate with a ZIS (Zone Information Server). It implements most of the SIF 2.0r1 (School Interoperability Framework) specification.
5
+
6
+ Getting Started
7
+ --------------------
8
+
9
+ ```ruby
10
+ client = OpenAgent::Client.connect(:name => "myagent", :url => "http://zis.institution.com/zis/myzone")
11
+
12
+ # Send an initial request for all StudentPersonal objects
13
+ client.request('StudentPersonal')
14
+
15
+ # Set a callback so we can do something when we receive replies
16
+ client.callback(:receive_message) do |message, http_response|
17
+ File.open("#{message.timestamp}.xml", "w") do |file|
18
+ file.write(http_response.body)
19
+ end
20
+ end
21
+
22
+ # Enter a polling loop
23
+ client.run
24
+ ```
25
+
26
+ Blog
27
+ ----
28
+ http://blog.openzis.org/2010/08/23/creating-the-start-of-a-sif-agent-in-ruby/
29
+
30
+
31
+ SIF 2.0 Spec
32
+ ------------
33
+ http://specification.sifinfo.org/Implementation/2.0r1/
34
+
35
+ History
36
+ -------
37
+ OpenAgent started as a Billboard.Net implementation of SIF in Ruby. Some features were later added by Instructure.
38
+
39
+ TODO
40
+ ----
41
+
42
+ - Convert old conditiongroup code to a DSL or something:
43
+ ```ruby
44
+ def create_conditiongroup(refobject, refid, operator="EQ")
45
+ cond1 = OpenAgent::Message::SIF_Request::SIF_Condition.new
46
+ cond1.element = "@SIF_RefObject"
47
+ cond1.operator = "EQ"
48
+ cond1.value = refobject
49
+
50
+ cond2 = OpenAgent::Message::SIF_Request::SIF_Condition.new
51
+ cond2.element = "@SIF_RefId"
52
+ cond2.operator = operator
53
+ cond2.value = refid
54
+
55
+ conditions = OpenAgent::Message::SIF_Request::SIF_Conditions.new
56
+ conditions.condition = [cond1, cond2]
57
+ conditions.type = 'And'
58
+
59
+ OpenAgent::Message::SIF_Request::SIF_ConditionGroup.new.tap do |cg|
60
+ cg.conditions = [conditions]
61
+ cg.type = 'None'
62
+ end
63
+ end
64
+ ```
data/lib/openagent.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'openagent/message_builder'
2
+ require 'openagent/zone'
3
+ require 'openagent/agent'
4
+ require 'openagent/client'
@@ -0,0 +1,24 @@
1
+ require 'virtus'
2
+
3
+ module OpenAgent
4
+ class Agent
5
+ include Virtus.model
6
+
7
+ attribute :name, String
8
+ attribute :source_id, String, :default => :name
9
+ attribute :version, String, :default => "2.0r1"
10
+ attribute :max_buffer_size, Integer, :default => 128_000
11
+ attribute :mode, String, :default => "Pull"
12
+ attribute :msg_version, String, :default => :version
13
+ attribute :msg_xmlns, String, :default => "http://www.sifinfo.org/infrastructure/2.x"
14
+
15
+ attribute :provide, Array[String]
16
+ attribute :subscribe, Array[String]
17
+ attribute :publish_add, Array[String]
18
+ attribute :publish_change, Array[String]
19
+ attribute :publish_delete, Array[String]
20
+ attribute :request, Array[String]
21
+ attribute :respond, Array[String]
22
+
23
+ end
24
+ end
@@ -0,0 +1,170 @@
1
+ require "sif/sif"
2
+ require "openagent/agent"
3
+ require "openagent/zone"
4
+ require "openagent/xml_helpers"
5
+ require "openagent/errors"
6
+ require "openagent/message_builder"
7
+ require "logger"
8
+
9
+ module OpenAgent
10
+ class Client
11
+ include XMLHelpers
12
+
13
+ attr_reader :name, :url
14
+ attr_reader :agent, :zone, :builder
15
+
16
+ ZIS_SUCCESS = 0
17
+ ZIS_NO_MESSAGES = 9
18
+
19
+ Message = SIF::Infra::Common::Message
20
+ MessageRepresenter = ::SIF::Representation::Infra::Common::Message
21
+
22
+ def self.connect(opts={})
23
+ Client.new(opts).tap do |client|
24
+ client.register
25
+ client.provision
26
+ end
27
+ end
28
+
29
+ def initialize(opts={})
30
+ @callbacks = {
31
+ :receive_message => [],
32
+ :each_loop => []
33
+ }
34
+
35
+ @name = opts.delete(:name)
36
+ @url = opts.delete(:url)
37
+ @pretty_print = opts.has_key?(:pretty_print) ? opts.delete(:pretty_print) : true
38
+
39
+ @agent_opts = opts['agent_opts'] || {}
40
+ @agent_opts[:name] = @name if @name
41
+
42
+ @zone_opts = opts['zone_opts'] || {}
43
+ @zone_opts[:uri] = @url if @url
44
+
45
+ @log = Logger.new(opts["log"] || STDOUT, 'daily')
46
+ @agent = opts['agent'] || OpenAgent::Agent.new(@agent_opts)
47
+ @zone = opts['zone'] || OpenAgent::Zone.new(@zone_opts)
48
+
49
+ @builder = OpenAgent::MessageBuilder.new(@agent, @zone)
50
+ end
51
+
52
+ def log(name, body)
53
+ @log.info "#{name}\n#{body}\n"
54
+ end
55
+
56
+ # Proxy to OpenAgent::Messaging
57
+ def method_missing(method, *args, &block)
58
+ if @builder.respond_to?(method)
59
+ message = @builder.send(method, *args)
60
+ send_message(message, &block)
61
+ else
62
+ super
63
+ end
64
+ end
65
+
66
+ def callback(name, &block)
67
+ if cbs = @callbacks[name.to_sym]
68
+ cbs << block
69
+ else
70
+ raise "Can't register callback #{name}. " +
71
+ "Available callbacks: #{@callbacks.keys.inspect}"
72
+ end
73
+ end
74
+
75
+ def trigger(name, *args)
76
+ if cbs = @callbacks[name.to_sym]
77
+ cbs.each { |cb| cb.call(*args) }
78
+ else
79
+ raise "Can't trigger callback #{name}. " +
80
+ "Available callbacks: #{@callbacks.keys.inspect}"
81
+ end
82
+ end
83
+
84
+ def run
85
+ wait_short = 10
86
+ wait_long = 30
87
+ loop do
88
+ begin
89
+ trigger(:each_loop)
90
+
91
+ wait_period = wait_long
92
+ messages_in_queue = true
93
+ while messages_in_queue
94
+ get_message do |http_response, doc, status_code|
95
+ wrap_msg = Message.new
96
+ MessageRepresenter.new(wrap_msg).from_xml(http_response.body)
97
+
98
+ if message = wrap_msg.inner_message
99
+
100
+ trigger(:receive_message, wrap_msg, http_response)
101
+
102
+ if message.response
103
+ case status_code
104
+ when ZIS_SUCCESS then
105
+ if message.response.morepackets?
106
+ wait_period = wait_short
107
+ else
108
+ wait_period = wait_long
109
+ end
110
+ when ZIS_NO_MESSAGES then
111
+ if not message.morepackets?
112
+ wait_period = wait_long
113
+ end
114
+ end
115
+ end
116
+
117
+ # We send an Ack for both an Event and a Response
118
+ if status_code == ZIS_SUCCESS
119
+ ack(message.sourceid, message.msgid)
120
+ end
121
+ else
122
+ if status_code == ZIS_NO_MESSAGES
123
+ messages_in_queue = false
124
+ end
125
+ end
126
+ end
127
+ end
128
+ sleep wait_period
129
+ rescue ResponseError => e
130
+ @log.error e
131
+ end
132
+ end
133
+ end
134
+
135
+ protected
136
+
137
+ def check_for_errors(msg)
138
+ # First check for a SIF_Error tag
139
+ raise SIFError, msg.ack.error if msg.ack.error
140
+
141
+ # Next check for a SIF_Code != 0
142
+ status_code = msg.ack.status.code
143
+ raise SIFCodeError, status_code unless [0, 9].include? status_code
144
+
145
+ status_code
146
+ end
147
+
148
+ def send_message(outgoing, &block)
149
+ representer = MessageRepresenter.new(outgoing)
150
+ req = @zone.create_request(representer.to_xml)
151
+
152
+ log "Request", req.body
153
+ @zone.send_request(req).tap do |response|
154
+ log "Response", formatted_xml(response.body, @pretty_print)
155
+
156
+ if response.body.empty?
157
+ raise ResponseError, "Response is empty"
158
+ else
159
+ incoming = Message.new
160
+ MessageRepresenter.new(incoming).from_xml(response.body)
161
+
162
+ check_for_errors(incoming)
163
+
164
+ yield incoming if block_given?
165
+ end
166
+ end
167
+ end
168
+
169
+ end
170
+ end
@@ -0,0 +1,30 @@
1
+ module OpenAgent
2
+ class ResponseError < StandardError
3
+ attr_reader :error_object
4
+ def initialize(msg, error_object=nil)
5
+ @error_object = error_object
6
+ super(msg)
7
+ end
8
+ end
9
+
10
+ class SIFError < ResponseError
11
+ def initialize(error_object)
12
+ @error_object = error_object
13
+ super(@error_object.desc, @error_object)
14
+ end
15
+ end
16
+
17
+ class SIFCodeError < ResponseError
18
+ CODES = {
19
+ 0 => "Success. SIF_Status/SIF_Data may contain additional data.",
20
+ 7 => "Already have a message with this SIF_MsgId from you.",
21
+ 8 => "Receiver is sleeping.",
22
+ 9 => "No messages available. This is returned when an agent is trying to pull messages from a ZIS and there are no messages available."
23
+ }
24
+ def initialize(status_code)
25
+ code = CODES[status_code]
26
+ raise "Unknown SIF_Status Code: #{status_code.inspect} (Known Codes: #{CODES.keys.inspect})" if code.nil?
27
+ super("Code #{status_code}: " + code)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,171 @@
1
+ require "uuid"
2
+ require "sif/sif"
3
+
4
+ module OpenAgent
5
+ class MessageBuilder
6
+ attr_writer :timestamp, :guuid
7
+
8
+ def initialize(agent, zone)
9
+ @agent = agent
10
+ @zone = zone
11
+ end
12
+
13
+ def ack(original_source_id, original_msg_id, code=1)
14
+ SIF::Infra::Common::Message.new(
15
+ :version => @agent.msg_version,
16
+ :xmlns => @agent.msg_xmlns,
17
+ :ack => SIF::Infra::Message::Ack.new(
18
+ :header => create_header,
19
+ :original_source_id => original_source_id,
20
+ :original_msg_id => original_msg_id,
21
+ :status => SIF::Infra::Common::Status.new(
22
+ :code => code
23
+ )
24
+ )
25
+ )
26
+ end
27
+
28
+ def request(object_name, condition_group=nil)
29
+ SIF::Infra::Common::Message.new(
30
+ :version => @agent.msg_version,
31
+ :xmlns => @agent.msg_xmlns,
32
+ :request => SIF::Infra::Message::Request.new(
33
+ :version => @agent.version,
34
+ :max_buffer_size => @agent.max_buffer_size,
35
+ :header => create_header,
36
+ :query => SIF::Infra::Common::Query.new(
37
+ :query_object => SIF::Infra::Common::QueryObject.new(
38
+ :object_name => object_name
39
+ ),
40
+ :condition_group => condition_group
41
+ )
42
+ )
43
+ )
44
+ end
45
+
46
+ def event(object_name, action='Change', object=nil)
47
+ SIF::Infra::Common::Message.new(
48
+ :version => @agent.msg_version,
49
+ :xmlns => @agent.msg_xmlns,
50
+ :event => SIF::Infra::Common::Event.new(
51
+ :header => create_header,
52
+ :object_data => SIF::Infra::Common::ObjectData.new(
53
+ :event_object => SIF::Infra::Common::EventObject.new(
54
+ :object_name => object_name,
55
+ :action => action,
56
+ :objects => [
57
+ SIF::Infra::Common::Object.new(
58
+ :object_name => object_name
59
+ )
60
+ ]
61
+ )
62
+ )
63
+ )
64
+ )
65
+ end
66
+
67
+ def provision
68
+ object = SIF::Infra::Common::Object
69
+ SIF::Infra::Common::Message.new(
70
+ :version => @agent.msg_version,
71
+ :xmlns => @agent.msg_xmlns,
72
+ :provision => SIF::Infra::Common::Provision.new(
73
+ :header => create_header,
74
+ :subscribe_objects =>
75
+ (@agent.subscribe || []).map { |o| object.new(:object_name => o) },
76
+ :provide_objects =>
77
+ (@agent.provide || []).map { |o| object.new(:object_name => o) },
78
+ :request_objects =>
79
+ (@agent.request || []).map { |o| object.new(:object_name => o) },
80
+ :respond_objects =>
81
+ (@agent.respond || []).map { |o| object.new(:object_name => o) },
82
+ :publish_add_objects =>
83
+ (@agent.publish_add || []).map { |o| object.new(:object_name => o) },
84
+ :publish_change_objects =>
85
+ (@agent.publish_change || []).map { |o| object.new(:object_name => o) },
86
+ :publish_delete_objects =>
87
+ (@agent.publish_delete || []).map { |o| object.new(:object_name => o) },
88
+ )
89
+ )
90
+ end
91
+
92
+ def register
93
+ SIF::Infra::Common::Message.new(
94
+ :version => @agent.msg_version,
95
+ :xmlns => @agent.msg_xmlns,
96
+ :register => SIF::Infra::Message::Register.new(
97
+ :name => @agent.name,
98
+ :version => @agent.version,
99
+ :max_buffer_size => @agent.max_buffer_size,
100
+ :mode => @agent.mode,
101
+ :header => create_header
102
+ )
103
+ )
104
+ end
105
+
106
+ def unregister
107
+ SIF::Infra::Common::Message.new(
108
+ :version => @agent.msg_version,
109
+ :xmlns => @agent.msg_xmlns,
110
+ :unregister => SIF::Infra::Message::Unregister.new(
111
+ :header => create_header
112
+ )
113
+ )
114
+ end
115
+
116
+ def ping
117
+ system_control(SIF::Infra::Message::Ping.new)
118
+ end
119
+
120
+ def sleep
121
+ system_control(SIF::Infra::Message::Sleep.new)
122
+ end
123
+
124
+ def wakeup
125
+ system_control(SIF::Infra::Message::Wakeup.new)
126
+ end
127
+
128
+ def get_message
129
+ system_control(SIF::Infra::Message::GetMessage.new)
130
+ end
131
+
132
+ def get_zone_status
133
+ system_control(SIF::Infra::Message::GetZoneStatus.new)
134
+ end
135
+
136
+ def get_agent_acl
137
+ system_control(SIF::Infra::Message::GetAgentACL.new)
138
+ end
139
+
140
+ protected
141
+
142
+ def timestamp
143
+ @timestamp || Time.now.strftime('%Y-%m-%dT%H:%M:%S')
144
+ end
145
+
146
+ def guuid
147
+ @guuid || UUID.generate(:compact).upcase
148
+ end
149
+
150
+ def create_header
151
+ SIF::Infra::Common::Header.new(
152
+ :msg_id => guuid(),
153
+ :source_id => @agent.source_id,
154
+ :timestamp => timestamp()
155
+ )
156
+ end
157
+
158
+ def system_control(message_instance)
159
+ SIF::Infra::Common::Message.new(
160
+ :version => @agent.msg_version,
161
+ :xmlns => @agent.msg_xmlns,
162
+ :system_control => SIF::Infra::Message::SystemControl.new(
163
+ :header => create_header,
164
+ :system_control_data => SIF::Infra::Message::SystemControlData.new(
165
+ :data => message_instance
166
+ )
167
+ )
168
+ )
169
+ end
170
+ end
171
+ end