openagent 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
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