rcap 1.3.0 → 1.3.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.
- data/{CHANGELOG.rdoc → CHANGELOG.md} +26 -20
- data/README.md +259 -0
- data/Rakefile +8 -7
- data/lib/extensions/array.rb +7 -1
- data/lib/extensions/date_time.rb +5 -1
- data/lib/extensions/string.rb +14 -1
- data/lib/extensions/time.rb +5 -1
- data/lib/rcap.rb +1 -1
- data/lib/rcap/alert.rb +24 -10
- data/lib/rcap/cap_1_0/alert.rb +232 -166
- data/lib/rcap/cap_1_0/area.rb +100 -67
- data/lib/rcap/cap_1_0/circle.rb +47 -22
- data/lib/rcap/cap_1_0/event_code.rb +3 -2
- data/lib/rcap/cap_1_0/geocode.rb +3 -2
- data/lib/rcap/cap_1_0/info.rb +265 -202
- data/lib/rcap/cap_1_0/parameter.rb +43 -20
- data/lib/rcap/cap_1_0/point.rb +23 -9
- data/lib/rcap/cap_1_0/polygon.rb +37 -19
- data/lib/rcap/cap_1_0/resource.rb +77 -55
- data/lib/rcap/cap_1_1/alert.rb +222 -156
- data/lib/rcap/cap_1_1/area.rb +100 -67
- data/lib/rcap/cap_1_1/circle.rb +49 -22
- data/lib/rcap/cap_1_1/event_code.rb +3 -2
- data/lib/rcap/cap_1_1/geocode.rb +3 -2
- data/lib/rcap/cap_1_1/info.rb +281 -217
- data/lib/rcap/cap_1_1/parameter.rb +35 -16
- data/lib/rcap/cap_1_1/point.rb +23 -9
- data/lib/rcap/cap_1_1/polygon.rb +38 -20
- data/lib/rcap/cap_1_1/resource.rb +106 -65
- data/lib/rcap/cap_1_2/alert.rb +224 -158
- data/lib/rcap/cap_1_2/area.rb +100 -67
- data/lib/rcap/cap_1_2/circle.rb +49 -24
- data/lib/rcap/cap_1_2/event_code.rb +3 -2
- data/lib/rcap/cap_1_2/geocode.rb +3 -2
- data/lib/rcap/cap_1_2/info.rb +285 -219
- data/lib/rcap/cap_1_2/parameter.rb +39 -19
- data/lib/rcap/cap_1_2/point.rb +23 -9
- data/lib/rcap/cap_1_2/polygon.rb +37 -20
- data/lib/rcap/cap_1_2/resource.rb +107 -67
- data/lib/rcap/config.rb +4 -0
- data/lib/rcap/utilities.rb +55 -2
- data/lib/rcap/validations.rb +2 -2
- data/lib/rcap/version.rb +1 -1
- data/rcap.gemspec +2 -2
- data/spec/cap_1_0/parameter_spec.rb +5 -1
- data/spec/cap_1_1/resource_spec.rb +6 -0
- data/spec/cap_1_2/alert_spec.rb +8 -0
- data/spec/cap_1_2/resource_spec.rb +8 -2
- metadata +11 -10
- data/README.rdoc +0 -247
- data/lib/config.rb +0 -2
data/lib/rcap.rb
CHANGED
data/lib/rcap/alert.rb
CHANGED
@@ -7,12 +7,14 @@ module RCAP
|
|
7
7
|
|
8
8
|
CAP_NAMESPACES = [ RCAP::CAP_1_0::Alert::XMLNS, RCAP::CAP_1_1::Alert::XMLNS, RCAP::CAP_1_2::Alert::XMLNS ]
|
9
9
|
|
10
|
-
# Initialise a RCAP Alert from a XML document.
|
11
|
-
# document is inspected and a CAP_1_0::Alert, CAP_1_1::Alert
|
12
|
-
# or CAP_1_2::Alert is instantiated.
|
10
|
+
# Initialise a RCAP Alert from a XML document.
|
13
11
|
#
|
14
|
-
#
|
15
|
-
#
|
12
|
+
# @param [IO,String] xml CAP alert in XML format. Can be a String or any IO object.
|
13
|
+
# @param [String] namespace_key The XML namespace that the CAP alert is in. If omitted
|
14
|
+
# the namespace of the document is inspected and a CAP_1_0::Alert, CAP_1_1::Alert
|
15
|
+
# or CAP_1_2::Alert is instantiated accordingly. If no namespace can be detected
|
16
|
+
# a CAP 1.2 message will be assumed.
|
17
|
+
# @return [ RCAP::CAP_1_0::Alert, RCAP::CAP_1_1::Alert, RCAP::CAP_1_2::Alert ]
|
16
18
|
def self.from_xml( xml, namespace_key = nil )
|
17
19
|
xml_document = REXML::Document.new( xml )
|
18
20
|
document_namespaces = xml_document.root.namespaces.invert
|
@@ -30,7 +32,10 @@ module RCAP
|
|
30
32
|
|
31
33
|
# Initialise a RCAP Alert from a YAML document produced by
|
32
34
|
# CAP_1_2::Alert#to_yaml. The version of the document is inspected and a
|
33
|
-
#
|
35
|
+
# CAP 1.0, 1.1 or 1.2 Alert is instantiated accordingly.
|
36
|
+
#
|
37
|
+
# @param [IO, String] yaml CAP Alert in YAML format. Can be a String or any IO object.
|
38
|
+
# @return [ RCAP::CAP_1_0::Alert, RCAP::CAP_1_1::Alert, RCAP::CAP_1_2::Alert ]
|
34
39
|
def self.from_yaml( yaml )
|
35
40
|
yaml_data = YAML.load( yaml )
|
36
41
|
|
@@ -46,13 +51,22 @@ module RCAP
|
|
46
51
|
|
47
52
|
# Initialise a RCAP Alert from a JSON document produced by
|
48
53
|
# CAP_1_2::Alert#to_json. The version of the document is inspected and a
|
49
|
-
#
|
50
|
-
|
51
|
-
|
54
|
+
# CAP 1.0, 1.1 or 1.2 Alert is instantiated accordingly.
|
55
|
+
#
|
56
|
+
# @param [#to_s] json Alert in JSON format
|
57
|
+
# @return [ RCAP::CAP_1_0::Alert, RCAP::CAP_1_1::Alert, RCAP::CAP_1_2::Alert ]
|
58
|
+
def self.from_json( json )
|
59
|
+
json_hash = JSON.parse( json.to_s )
|
52
60
|
self.from_h( json_hash )
|
53
61
|
end
|
54
62
|
|
55
|
-
|
63
|
+
# Initialise a RCAP Alert from a Ruby hash produced by
|
64
|
+
# CAP_1_2::Alert#to_h. The cap_version key is inspected and a
|
65
|
+
# CAP 1.0, 1.1 or 1.2 Alert is instantiated accordingly.
|
66
|
+
#
|
67
|
+
# @param [Hash] hash Alert as a Ruby hash.
|
68
|
+
# @return [ RCAP::CAP_1_0::Alert, RCAP::CAP_1_1::Alert, RCAP::CAP_1_2::Alert ]
|
69
|
+
def self.from_h( hash )
|
56
70
|
case hash[ JSON_CAP_VERSION_KEY ]
|
57
71
|
when CAP_1_0::Alert::CAP_VERSION
|
58
72
|
CAP_1_0::Alert.from_h( hash )
|
data/lib/rcap/cap_1_0/alert.rb
CHANGED
@@ -14,84 +14,58 @@ module RCAP
|
|
14
14
|
XMLNS = "http://www.incident.com/cap/1.0"
|
15
15
|
CAP_VERSION = "1.0"
|
16
16
|
|
17
|
-
STATUS_ACTUAL = "Actual"
|
18
|
-
STATUS_EXERCISE = "Exercise"
|
19
|
-
STATUS_SYSTEM = "System"
|
20
|
-
STATUS_TEST = "Test"
|
17
|
+
STATUS_ACTUAL = "Actual"
|
18
|
+
STATUS_EXERCISE = "Exercise"
|
19
|
+
STATUS_SYSTEM = "System"
|
20
|
+
STATUS_TEST = "Test"
|
21
21
|
# Valid values for status
|
22
22
|
VALID_STATUSES = [ STATUS_ACTUAL, STATUS_EXERCISE, STATUS_SYSTEM, STATUS_TEST ]
|
23
23
|
|
24
|
-
MSG_TYPE_ALERT = "Alert"
|
25
|
-
MSG_TYPE_UPDATE = "Update"
|
26
|
-
MSG_TYPE_CANCEL = "Cancel"
|
27
|
-
MSG_TYPE_ACK = "Ack"
|
28
|
-
MSG_TYPE_ERROR = "Error"
|
24
|
+
MSG_TYPE_ALERT = "Alert"
|
25
|
+
MSG_TYPE_UPDATE = "Update"
|
26
|
+
MSG_TYPE_CANCEL = "Cancel"
|
27
|
+
MSG_TYPE_ACK = "Ack"
|
28
|
+
MSG_TYPE_ERROR = "Error"
|
29
29
|
# Valid values for msg_type
|
30
30
|
VALID_MSG_TYPES = [ MSG_TYPE_ALERT, MSG_TYPE_UPDATE, MSG_TYPE_CANCEL, MSG_TYPE_ACK, MSG_TYPE_ERROR ]
|
31
31
|
|
32
|
-
SCOPE_PUBLIC = "Public"
|
33
|
-
SCOPE_RESTRICTED = "Restricted"
|
34
|
-
SCOPE_PRIVATE = "Private"
|
32
|
+
SCOPE_PUBLIC = "Public"
|
33
|
+
SCOPE_RESTRICTED = "Restricted"
|
34
|
+
SCOPE_PRIVATE = "Private"
|
35
35
|
# Valid values for scope
|
36
36
|
VALID_SCOPES = [ SCOPE_PUBLIC, SCOPE_PRIVATE, SCOPE_RESTRICTED ]
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
SENDER_ELEMENT_NAME = 'sender' # :nodoc:
|
41
|
-
SENT_ELEMENT_NAME = 'sent' # :nodoc:
|
42
|
-
STATUS_ELEMENT_NAME = 'status' # :nodoc:
|
43
|
-
MSG_TYPE_ELEMENT_NAME = 'msgType' # :nodoc:
|
44
|
-
PASSWORD_ELEMENT_NAME = 'password' # :nodoc:
|
45
|
-
SOURCE_ELEMENT_NAME = 'source' # :nodoc:
|
46
|
-
SCOPE_ELEMENT_NAME = 'scope' # :nodoc:
|
47
|
-
RESTRICTION_ELEMENT_NAME = 'restriction' # :nodoc:
|
48
|
-
ADDRESSES_ELEMENT_NAME = 'addresses' # :nodoc:
|
49
|
-
CODE_ELEMENT_NAME = 'code' # :nodoc:
|
50
|
-
NOTE_ELEMENT_NAME = 'note' # :nodoc:
|
51
|
-
REFERENCES_ELEMENT_NAME = 'references' # :nodoc:
|
52
|
-
INCIDENTS_ELEMENT_NAME = 'incidents' # :nodoc:
|
53
|
-
|
54
|
-
XPATH = 'cap:alert' # :nodoc:
|
55
|
-
IDENTIFIER_XPATH = "cap:#{ IDENTIFIER_ELEMENT_NAME }" # :nodoc:
|
56
|
-
SENDER_XPATH = "cap:#{ SENDER_ELEMENT_NAME }" # :nodoc:
|
57
|
-
SENT_XPATH = "cap:#{ SENT_ELEMENT_NAME }" # :nodoc:
|
58
|
-
STATUS_XPATH = "cap:#{ STATUS_ELEMENT_NAME }" # :nodoc:
|
59
|
-
MSG_TYPE_XPATH = "cap:#{ MSG_TYPE_ELEMENT_NAME }" # :nodoc:
|
60
|
-
PASSWORD_XPATH = "cap:#{ PASSWORD_ELEMENT_NAME }" # :nodoc:
|
61
|
-
SOURCE_XPATH = "cap:#{ SOURCE_ELEMENT_NAME }" # :nodoc:
|
62
|
-
SCOPE_XPATH = "cap:#{ SCOPE_ELEMENT_NAME }" # :nodoc:
|
63
|
-
RESTRICTION_XPATH = "cap:#{ RESTRICTION_ELEMENT_NAME }" # :nodoc:
|
64
|
-
ADDRESSES_XPATH = "cap:#{ ADDRESSES_ELEMENT_NAME }" # :nodoc:
|
65
|
-
CODE_XPATH = "cap:#{ CODE_ELEMENT_NAME }" # :nodoc:
|
66
|
-
NOTE_XPATH = "cap:#{ NOTE_ELEMENT_NAME }" # :nodoc:
|
67
|
-
REFERENCES_XPATH = "cap:#{ REFERENCES_ELEMENT_NAME }" # :nodoc:
|
68
|
-
INCIDENTS_XPATH = "cap:#{ INCIDENTS_ELEMENT_NAME }" # :nodoc:
|
69
|
-
|
70
|
-
# If not set a UUID will be set by default
|
38
|
+
|
39
|
+
# @return [String] If not set a UUID will be set by default
|
71
40
|
attr_accessor( :identifier)
|
41
|
+
# @return [String]
|
72
42
|
attr_accessor( :sender )
|
73
|
-
#
|
43
|
+
# @return [DateTime] If not set will value will be time of creation.
|
74
44
|
attr_accessor( :sent )
|
75
|
-
#
|
45
|
+
# @return [String] Can only be one of {VALID_STATUSES}
|
76
46
|
attr_accessor( :status )
|
77
|
-
#
|
47
|
+
# @return [String] Can only be one of {VALID_MSG_TYPES}
|
78
48
|
attr_accessor( :msg_type )
|
49
|
+
# @return [String]
|
79
50
|
attr_accessor( :password )
|
80
|
-
#
|
51
|
+
# @return [String] Can only be one of {VALID_SCOPES}
|
81
52
|
attr_accessor( :scope )
|
53
|
+
# @return [String]
|
82
54
|
attr_accessor( :source )
|
83
|
-
# Depends on scope being SCOPE_RESTRICTED
|
55
|
+
# @return [String ] Depends on scope being {SCOPE_RESTRICTED}
|
84
56
|
attr_accessor( :restriction )
|
57
|
+
# @return [String]
|
85
58
|
attr_accessor( :note )
|
86
59
|
|
87
|
-
# Collection of address strings. Depends on scope being SCOPE_PRIVATE
|
60
|
+
# @return [Array<String>] Collection of address strings. Depends on scope being {SCOPE_PRIVATE}
|
88
61
|
attr_reader( :addresses )
|
62
|
+
# @return [Array<String>]
|
89
63
|
attr_reader( :codes )
|
90
|
-
#
|
64
|
+
# @return [Array<String>] See {#to_reference}
|
91
65
|
attr_reader( :references)
|
92
|
-
# Collection of incident strings
|
66
|
+
# @return [Array<String>] Collection of incident strings
|
93
67
|
attr_reader( :incidents )
|
94
|
-
#
|
68
|
+
# @return [Array<Info>]
|
95
69
|
attr_reader( :infos )
|
96
70
|
|
97
71
|
validates_presence_of( :identifier, :sender, :sent, :status, :msg_type, :scope )
|
@@ -108,6 +82,28 @@ module RCAP
|
|
108
82
|
|
109
83
|
validates_collection_of( :infos )
|
110
84
|
|
85
|
+
# @example
|
86
|
+
# Alert.new( sender: 'disaster_management@cape_town.municipal.za',
|
87
|
+
# sent: Date.today,
|
88
|
+
# status: Alert::STATUS_ACTUAL,
|
89
|
+
# msg_type: Alert::MSG_TYPE_ALERT,
|
90
|
+
# scope: Alert::SCOPE_PUBLIC )
|
91
|
+
#
|
92
|
+
# @param [Hash] attributes
|
93
|
+
# @option attributes [String] :identifier Unique identifier - autogenerated if not given
|
94
|
+
# @option attributes [String] :sender
|
95
|
+
# @option attributes [DateTime] :sent
|
96
|
+
# @option attributes [String] :status A member of {VALID_STATUSES}
|
97
|
+
# @option attributes [String] :msg_type A member of {VALID_MSG_TYPES}
|
98
|
+
# @option attributes [String] :password
|
99
|
+
# @option attributes [String] :scope A member of {VALID_SCOPES}
|
100
|
+
# @option attributes [String] :source
|
101
|
+
# @option attributes [String] :restriction
|
102
|
+
# @option attributes [Array<String>] :addresses
|
103
|
+
# @option attributes [Array<String>] :codes
|
104
|
+
# @option attributes [Array<String>] :references see {#to_reference}
|
105
|
+
# @option attributes [Array<String>] :incidents
|
106
|
+
# @option attributes [Array<Info>] :infos
|
111
107
|
def initialize( attributes = {})
|
112
108
|
@identifier = attributes[ :identifier ] || RCAP.generate_identifier
|
113
109
|
@sender = attributes[ :sender ]
|
@@ -125,99 +121,146 @@ module RCAP
|
|
125
121
|
@infos = Array( attributes[ :infos ])
|
126
122
|
end
|
127
123
|
|
128
|
-
# Creates a new Info object and adds it to the infos array.
|
129
|
-
#
|
124
|
+
# Creates a new {Info} object and adds it to the {#infos array}.
|
125
|
+
#
|
126
|
+
# @see Info#initialize
|
127
|
+
# @param [Hash] info_attributes Info attributes - see {Info#initialize}
|
128
|
+
# @return [Info]
|
130
129
|
def add_info( info_attributes = {})
|
131
130
|
info = Info.new( info_attributes )
|
132
|
-
|
131
|
+
@infos << info
|
133
132
|
info
|
134
133
|
end
|
135
134
|
|
136
|
-
|
135
|
+
XML_ELEMENT_NAME = 'alert'
|
136
|
+
IDENTIFIER_ELEMENT_NAME = 'identifier'
|
137
|
+
SENDER_ELEMENT_NAME = 'sender'
|
138
|
+
SENT_ELEMENT_NAME = 'sent'
|
139
|
+
STATUS_ELEMENT_NAME = 'status'
|
140
|
+
MSG_TYPE_ELEMENT_NAME = 'msgType'
|
141
|
+
PASSWORD_ELEMENT_NAME = 'password'
|
142
|
+
SOURCE_ELEMENT_NAME = 'source'
|
143
|
+
SCOPE_ELEMENT_NAME = 'scope'
|
144
|
+
RESTRICTION_ELEMENT_NAME = 'restriction'
|
145
|
+
ADDRESSES_ELEMENT_NAME = 'addresses'
|
146
|
+
CODE_ELEMENT_NAME = 'code'
|
147
|
+
NOTE_ELEMENT_NAME = 'note'
|
148
|
+
REFERENCES_ELEMENT_NAME = 'references'
|
149
|
+
INCIDENTS_ELEMENT_NAME = 'incidents'
|
150
|
+
|
151
|
+
# @return [REXML::Element]
|
152
|
+
def to_xml_element
|
137
153
|
xml_element = REXML::Element.new( XML_ELEMENT_NAME )
|
138
154
|
xml_element.add_namespace( XMLNS )
|
139
|
-
xml_element.add_element( IDENTIFIER_ELEMENT_NAME ).add_text(
|
140
|
-
xml_element.add_element( SENDER_ELEMENT_NAME ).add_text(
|
141
|
-
xml_element.add_element( SENT_ELEMENT_NAME ).add_text(
|
142
|
-
xml_element.add_element( STATUS_ELEMENT_NAME ).add_text(
|
143
|
-
xml_element.add_element( MSG_TYPE_ELEMENT_NAME ).add_text(
|
144
|
-
xml_element.add_element( PASSWORD_ELEMENT_NAME ).add_text(
|
145
|
-
xml_element.add_element( SOURCE_ELEMENT_NAME ).add_text(
|
146
|
-
xml_element.add_element( SCOPE_ELEMENT_NAME ).add_text(
|
147
|
-
xml_element.add_element( RESTRICTION_ELEMENT_NAME ).add_text(
|
148
|
-
|
149
|
-
xml_element.add_element( ADDRESSES_ELEMENT_NAME ).add_text(
|
155
|
+
xml_element.add_element( IDENTIFIER_ELEMENT_NAME ).add_text( @identifier ) if @identifier
|
156
|
+
xml_element.add_element( SENDER_ELEMENT_NAME ).add_text( @sender ) if @sender
|
157
|
+
xml_element.add_element( SENT_ELEMENT_NAME ).add_text( @sent.to_s_for_cap ) if @sent
|
158
|
+
xml_element.add_element( STATUS_ELEMENT_NAME ).add_text( @status ) if @status
|
159
|
+
xml_element.add_element( MSG_TYPE_ELEMENT_NAME ).add_text( @msg_type ) if @msg_type
|
160
|
+
xml_element.add_element( PASSWORD_ELEMENT_NAME ).add_text( @password ) if @password
|
161
|
+
xml_element.add_element( SOURCE_ELEMENT_NAME ).add_text( @source ) if @source
|
162
|
+
xml_element.add_element( SCOPE_ELEMENT_NAME ).add_text( @scope ) if @scope
|
163
|
+
xml_element.add_element( RESTRICTION_ELEMENT_NAME ).add_text( @restriction ) if @restriction
|
164
|
+
if @addresses.any?
|
165
|
+
xml_element.add_element( ADDRESSES_ELEMENT_NAME ).add_text( @addresses.to_s_for_cap )
|
150
166
|
end
|
151
|
-
|
167
|
+
@codes.each do |code|
|
152
168
|
xml_element.add_element( CODE_ELEMENT_NAME ).add_text( code )
|
153
169
|
end
|
154
|
-
xml_element.add_element( NOTE_ELEMENT_NAME ).add_text(
|
155
|
-
|
156
|
-
xml_element.add_element( REFERENCES_ELEMENT_NAME ).add_text(
|
170
|
+
xml_element.add_element( NOTE_ELEMENT_NAME ).add_text( @note ) if @note
|
171
|
+
if @references.any?
|
172
|
+
xml_element.add_element( REFERENCES_ELEMENT_NAME ).add_text( @references.join( ' ' ))
|
157
173
|
end
|
158
|
-
|
159
|
-
xml_element.add_element( INCIDENTS_ELEMENT_NAME ).add_text(
|
174
|
+
if @incidents.any?
|
175
|
+
xml_element.add_element( INCIDENTS_ELEMENT_NAME ).add_text( @incidents.join( ' ' ))
|
160
176
|
end
|
161
|
-
|
177
|
+
@infos.each do |info|
|
162
178
|
xml_element.add_element( info.to_xml_element )
|
163
179
|
end
|
164
180
|
xml_element
|
165
181
|
end
|
166
182
|
|
167
|
-
|
183
|
+
# @return [REXML::Document]
|
184
|
+
def to_xml_document
|
168
185
|
xml_document = REXML::Document.new
|
169
186
|
xml_document.add( REXML::XMLDecl.new )
|
170
|
-
xml_document.add(
|
187
|
+
xml_document.add( to_xml_element )
|
171
188
|
xml_document
|
172
189
|
end
|
173
190
|
|
174
191
|
# Returns a string containing the XML representation of the alert.
|
192
|
+
#
|
193
|
+
# @param [true,false] pretty_print Pretty print output
|
194
|
+
# @return [String]
|
175
195
|
def to_xml( pretty_print = false )
|
176
196
|
if pretty_print
|
177
197
|
xml_document = ""
|
178
|
-
XML_PRETTY_PRINTER.write(
|
198
|
+
RCAP::XML_PRETTY_PRINTER.write( to_xml_document, xml_document )
|
179
199
|
xml_document
|
180
200
|
else
|
181
|
-
|
201
|
+
to_xml_document.to_s
|
182
202
|
end
|
183
203
|
end
|
184
204
|
|
185
205
|
# Returns a string representation of the alert suitable for usage as a reference in a CAP message of the form
|
186
206
|
# sender,identifier,sent
|
207
|
+
#
|
208
|
+
# @return [String]
|
187
209
|
def to_reference
|
188
|
-
"#{
|
210
|
+
"#{ @sender },#{ @identifier },#{ @sent }"
|
189
211
|
end
|
190
212
|
|
191
|
-
|
213
|
+
# @return [String]
|
214
|
+
def inspect
|
192
215
|
alert_inspect = [ "CAP Version: #{ CAP_VERSION }",
|
193
|
-
"Identifier: #{
|
194
|
-
"Sender: #{
|
195
|
-
"Sent: #{
|
196
|
-
"Status: #{
|
197
|
-
"Message Type: #{
|
198
|
-
"Password: #{
|
199
|
-
"Source: #{
|
200
|
-
"Scope: #{
|
201
|
-
"Restriction: #{
|
202
|
-
"Addresses: #{
|
216
|
+
"Identifier: #{ @identifier }",
|
217
|
+
"Sender: #{ @sender }",
|
218
|
+
"Sent: #{ @sent }",
|
219
|
+
"Status: #{ @status }",
|
220
|
+
"Message Type: #{ @msg_type }",
|
221
|
+
"Password: #{ @password }",
|
222
|
+
"Source: #{ @source }",
|
223
|
+
"Scope: #{ @scope }",
|
224
|
+
"Restriction: #{ @restriction }",
|
225
|
+
"Addresses: #{ @addresses.to_s_for_cap }",
|
203
226
|
"Codes:",
|
204
|
-
|
205
|
-
"Note: #{
|
206
|
-
"References: #{
|
207
|
-
"Incidents: #{
|
227
|
+
@codes.map{ |code| " " + code }.join("\n")+"",
|
228
|
+
"Note: #{ @note }",
|
229
|
+
"References: #{ @references.join( ' ' )}",
|
230
|
+
"Incidents: #{ @incidents.join( ' ')}",
|
208
231
|
"Information:",
|
209
|
-
|
232
|
+
@infos.map{ |info| " " + info.to_s }.join( "\n" )].join("\n")
|
210
233
|
RCAP.format_lines_for_inspect( 'ALERT', alert_inspect )
|
211
234
|
end
|
212
235
|
|
213
236
|
# Returns a string representation of the alert of the form
|
214
237
|
# sender/identifier/sent
|
215
|
-
# See
|
238
|
+
# See {#to_reference} for another string representation suitable as a CAP reference.
|
239
|
+
#
|
240
|
+
# @return [String]
|
216
241
|
def to_s
|
217
|
-
"#{
|
242
|
+
"#{ @sender }/#{ @identifier }/#{ @sent }"
|
218
243
|
end
|
219
244
|
|
220
|
-
|
245
|
+
XPATH = 'cap:alert'
|
246
|
+
IDENTIFIER_XPATH = "cap:#{ IDENTIFIER_ELEMENT_NAME }"
|
247
|
+
SENDER_XPATH = "cap:#{ SENDER_ELEMENT_NAME }"
|
248
|
+
SENT_XPATH = "cap:#{ SENT_ELEMENT_NAME }"
|
249
|
+
STATUS_XPATH = "cap:#{ STATUS_ELEMENT_NAME }"
|
250
|
+
MSG_TYPE_XPATH = "cap:#{ MSG_TYPE_ELEMENT_NAME }"
|
251
|
+
PASSWORD_XPATH = "cap:#{ PASSWORD_ELEMENT_NAME }"
|
252
|
+
SOURCE_XPATH = "cap:#{ SOURCE_ELEMENT_NAME }"
|
253
|
+
SCOPE_XPATH = "cap:#{ SCOPE_ELEMENT_NAME }"
|
254
|
+
RESTRICTION_XPATH = "cap:#{ RESTRICTION_ELEMENT_NAME }"
|
255
|
+
ADDRESSES_XPATH = "cap:#{ ADDRESSES_ELEMENT_NAME }"
|
256
|
+
CODE_XPATH = "cap:#{ CODE_ELEMENT_NAME }"
|
257
|
+
NOTE_XPATH = "cap:#{ NOTE_ELEMENT_NAME }"
|
258
|
+
REFERENCES_XPATH = "cap:#{ REFERENCES_ELEMENT_NAME }"
|
259
|
+
INCIDENTS_XPATH = "cap:#{ INCIDENTS_ELEMENT_NAME }"
|
260
|
+
|
261
|
+
# @param [REXML::Element] alert_xml_element
|
262
|
+
# @return [RCAP::CAP_1_0::Alert]
|
263
|
+
def self.from_xml_element( alert_xml_element )
|
221
264
|
self.new( :identifier => RCAP.xpath_text( alert_xml_element, IDENTIFIER_XPATH, Alert::XMLNS ),
|
222
265
|
:sender => RCAP.xpath_text( alert_xml_element, SENDER_XPATH, Alert::XMLNS ),
|
223
266
|
:sent => (( sent = RCAP.xpath_first( alert_xml_element, SENT_XPATH, Alert::XMLNS )) ? DateTime.parse( sent.text ) : nil ),
|
@@ -235,60 +278,72 @@ module RCAP
|
|
235
278
|
:infos => RCAP.xpath_match( alert_xml_element, Info::XPATH, Alert::XMLNS ).map{ |element| Info.from_xml_element( element )})
|
236
279
|
end
|
237
280
|
|
238
|
-
|
281
|
+
# @param [REXML::Document] xml_document
|
282
|
+
# @return [RCAP::CAP_1_0::Alert]
|
283
|
+
def self.from_xml_document( xml_document )
|
239
284
|
self.from_xml_element( xml_document.root )
|
240
285
|
end
|
241
286
|
|
242
287
|
# Initialise an Alert object from an XML string. Any object that is a subclass of IO (e.g. File) can be passed in.
|
288
|
+
#
|
289
|
+
# @param [String] xml
|
290
|
+
# @return [RCAP::CAP_1_0::Alert]
|
243
291
|
def self.from_xml( xml )
|
244
292
|
self.from_xml_document( REXML::Document.new( xml ))
|
245
293
|
end
|
246
294
|
|
247
|
-
CAP_VERSION_YAML = "CAP Version"
|
248
|
-
IDENTIFIER_YAML = "Identifier"
|
249
|
-
SENDER_YAML = "Sender"
|
250
|
-
SENT_YAML = "Sent"
|
251
|
-
STATUS_YAML = "Status"
|
252
|
-
MSG_TYPE_YAML = "Message Type"
|
253
|
-
PASSWORD_YAML = "Password"
|
254
|
-
SOURCE_YAML = "Source"
|
255
|
-
SCOPE_YAML = "Scope"
|
256
|
-
RESTRICTION_YAML = "Restriction"
|
257
|
-
ADDRESSES_YAML = "Addresses"
|
258
|
-
CODES_YAML = "Codes"
|
259
|
-
NOTE_YAML = "Note"
|
260
|
-
REFERENCES_YAML = "References"
|
261
|
-
INCIDENTS_YAML = "Incidents"
|
262
|
-
INFOS_YAML = "Information"
|
295
|
+
CAP_VERSION_YAML = "CAP Version"
|
296
|
+
IDENTIFIER_YAML = "Identifier"
|
297
|
+
SENDER_YAML = "Sender"
|
298
|
+
SENT_YAML = "Sent"
|
299
|
+
STATUS_YAML = "Status"
|
300
|
+
MSG_TYPE_YAML = "Message Type"
|
301
|
+
PASSWORD_YAML = "Password"
|
302
|
+
SOURCE_YAML = "Source"
|
303
|
+
SCOPE_YAML = "Scope"
|
304
|
+
RESTRICTION_YAML = "Restriction"
|
305
|
+
ADDRESSES_YAML = "Addresses"
|
306
|
+
CODES_YAML = "Codes"
|
307
|
+
NOTE_YAML = "Note"
|
308
|
+
REFERENCES_YAML = "References"
|
309
|
+
INCIDENTS_YAML = "Incidents"
|
310
|
+
INFOS_YAML = "Information"
|
263
311
|
|
264
312
|
# Returns a string containing the YAML representation of the alert.
|
313
|
+
#
|
314
|
+
# @return [String]
|
265
315
|
def to_yaml( options = {} )
|
266
316
|
RCAP.attribute_values_to_hash(
|
267
|
-
[ CAP_VERSION_YAML,
|
268
|
-
[ IDENTIFIER_YAML,
|
269
|
-
[ SENDER_YAML,
|
270
|
-
[ SENT_YAML,
|
271
|
-
[ STATUS_YAML,
|
272
|
-
[ MSG_TYPE_YAML,
|
273
|
-
[ PASSWORD_YAML,
|
274
|
-
[ SOURCE_YAML,
|
275
|
-
[ SCOPE_YAML,
|
276
|
-
[ RESTRICTION_YAML,
|
277
|
-
[ ADDRESSES_YAML,
|
278
|
-
[ CODES_YAML,
|
279
|
-
[ NOTE_YAML,
|
280
|
-
[ REFERENCES_YAML,
|
281
|
-
[ INCIDENTS_YAML,
|
282
|
-
[ INFOS_YAML,
|
317
|
+
[ CAP_VERSION_YAML, CAP_VERSION ],
|
318
|
+
[ IDENTIFIER_YAML, @identifier ],
|
319
|
+
[ SENDER_YAML, @sender ],
|
320
|
+
[ SENT_YAML, @sent ],
|
321
|
+
[ STATUS_YAML, @status ],
|
322
|
+
[ MSG_TYPE_YAML, @msg_type ],
|
323
|
+
[ PASSWORD_YAML, @password ],
|
324
|
+
[ SOURCE_YAML, @source ],
|
325
|
+
[ SCOPE_YAML, @scope ],
|
326
|
+
[ RESTRICTION_YAML, @restriction ],
|
327
|
+
[ ADDRESSES_YAML, @addresses ],
|
328
|
+
[ CODES_YAML, @codes ],
|
329
|
+
[ NOTE_YAML, @note ],
|
330
|
+
[ REFERENCES_YAML, @references ],
|
331
|
+
[ INCIDENTS_YAML, @incidents ],
|
332
|
+
[ INFOS_YAML, @infos ]
|
283
333
|
).to_yaml( options )
|
284
334
|
end
|
285
335
|
|
286
336
|
# Initialise an Alert object from a YAML string. Any object that is a subclass of IO (e.g. File) can be passed in.
|
337
|
+
#
|
338
|
+
# @param [String] yaml
|
339
|
+
# @return [RCAP::CAP_1_0::Alert]
|
287
340
|
def self.from_yaml( yaml )
|
288
341
|
self.from_yaml_data( YAML.load( yaml ))
|
289
342
|
end
|
290
343
|
|
291
|
-
|
344
|
+
# @param [Hash] yaml_data
|
345
|
+
# @return [RCAP::CAP_1_0::Alert]
|
346
|
+
def self.from_yaml_data( alert_yaml_data )
|
292
347
|
Alert.new(
|
293
348
|
:identifier => alert_yaml_data[ IDENTIFIER_YAML ],
|
294
349
|
:sender => alert_yaml_data[ SENDER_YAML ],
|
@@ -308,44 +363,49 @@ module RCAP
|
|
308
363
|
)
|
309
364
|
end
|
310
365
|
|
311
|
-
CAP_VERSION_KEY = 'cap_version'
|
312
|
-
IDENTIFIER_KEY = 'identifier'
|
313
|
-
SENDER_KEY = 'sender'
|
314
|
-
SENT_KEY = 'sent'
|
315
|
-
STATUS_KEY = 'status'
|
316
|
-
MSG_TYPE_KEY = 'msg_type'
|
317
|
-
PASSWORD_KEY = 'password'
|
318
|
-
SOURCE_KEY = 'source'
|
319
|
-
SCOPE_KEY = 'scope'
|
320
|
-
RESTRICTION_KEY = 'restriction'
|
321
|
-
ADDRESSES_KEY = 'addresses'
|
322
|
-
CODES_KEY = 'codes'
|
323
|
-
NOTE_KEY = 'note'
|
324
|
-
REFERENCES_KEY = 'references'
|
325
|
-
INCIDENTS_KEY = 'incidents'
|
326
|
-
INFOS_KEY = 'infos'
|
366
|
+
CAP_VERSION_KEY = 'cap_version'
|
367
|
+
IDENTIFIER_KEY = 'identifier'
|
368
|
+
SENDER_KEY = 'sender'
|
369
|
+
SENT_KEY = 'sent'
|
370
|
+
STATUS_KEY = 'status'
|
371
|
+
MSG_TYPE_KEY = 'msg_type'
|
372
|
+
PASSWORD_KEY = 'password'
|
373
|
+
SOURCE_KEY = 'source'
|
374
|
+
SCOPE_KEY = 'scope'
|
375
|
+
RESTRICTION_KEY = 'restriction'
|
376
|
+
ADDRESSES_KEY = 'addresses'
|
377
|
+
CODES_KEY = 'codes'
|
378
|
+
NOTE_KEY = 'note'
|
379
|
+
REFERENCES_KEY = 'references'
|
380
|
+
INCIDENTS_KEY = 'incidents'
|
381
|
+
INFOS_KEY = 'infos'
|
327
382
|
|
328
383
|
# Returns a Hash representation of an Alert object
|
384
|
+
#
|
385
|
+
# @return [Hash]
|
329
386
|
def to_h
|
330
387
|
RCAP.attribute_values_to_hash( [ CAP_VERSION_KEY, CAP_VERSION ],
|
331
|
-
[ IDENTIFIER_KEY,
|
332
|
-
[ SENDER_KEY,
|
333
|
-
[ SENT_KEY, RCAP.to_s_for_cap(
|
334
|
-
[ STATUS_KEY,
|
335
|
-
[ MSG_TYPE_KEY,
|
336
|
-
[ PASSWORD_KEY,
|
337
|
-
[ SOURCE_KEY,
|
338
|
-
[ SCOPE_KEY,
|
339
|
-
[ RESTRICTION_KEY,
|
340
|
-
[ ADDRESSES_KEY,
|
341
|
-
[ CODES_KEY,
|
342
|
-
[ NOTE_KEY,
|
343
|
-
[ REFERENCES_KEY,
|
344
|
-
[ INCIDENTS_KEY,
|
345
|
-
[ INFOS_KEY,
|
388
|
+
[ IDENTIFIER_KEY, @identifier ],
|
389
|
+
[ SENDER_KEY, @sender ],
|
390
|
+
[ SENT_KEY, RCAP.to_s_for_cap( @sent )],
|
391
|
+
[ STATUS_KEY, @status ],
|
392
|
+
[ MSG_TYPE_KEY, @msg_type ],
|
393
|
+
[ PASSWORD_KEY, @password ],
|
394
|
+
[ SOURCE_KEY, @source ],
|
395
|
+
[ SCOPE_KEY, @scope ],
|
396
|
+
[ RESTRICTION_KEY, @restriction ],
|
397
|
+
[ ADDRESSES_KEY, @addresses ],
|
398
|
+
[ CODES_KEY, @codes ],
|
399
|
+
[ NOTE_KEY, @note ],
|
400
|
+
[ REFERENCES_KEY, @references ],
|
401
|
+
[ INCIDENTS_KEY, @incidents ],
|
402
|
+
[ INFOS_KEY, @infos.map{ |info| info.to_h }])
|
346
403
|
end
|
347
404
|
|
348
405
|
# Initialises an Alert object from a Hash produced by Alert#to_h
|
406
|
+
#
|
407
|
+
# @param [Hash] alert_hash
|
408
|
+
# @return [RCAP::CAP_1_0::Alert]
|
349
409
|
def self.from_h( alert_hash )
|
350
410
|
self.new(
|
351
411
|
:identifier => alert_hash[ IDENTIFIER_KEY ],
|
@@ -366,6 +426,9 @@ module RCAP
|
|
366
426
|
end
|
367
427
|
|
368
428
|
# Returns a JSON string representation of an Alert object
|
429
|
+
#
|
430
|
+
# @param [true,false] pretty_print
|
431
|
+
# @return [String]
|
369
432
|
def to_json( pretty_print = false )
|
370
433
|
if pretty_print
|
371
434
|
JSON.pretty_generate( self.to_h )
|
@@ -374,7 +437,10 @@ module RCAP
|
|
374
437
|
end
|
375
438
|
end
|
376
439
|
|
377
|
-
#
|
440
|
+
# Initialises an Alert object from a JSON string produced by Alert#to_json
|
441
|
+
#
|
442
|
+
# @param [String] json_string
|
443
|
+
# @return [RCAP::CAP_1_0::Alert]
|
378
444
|
def self.from_json( json_string )
|
379
445
|
self.from_h( JSON.parse( json_string ))
|
380
446
|
end
|