rcap 1.3.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/README.md +78 -151
  3. data/Rakefile +1 -1
  4. data/lib/rcap/alert.rb +2 -2
  5. data/lib/rcap/base/alert.rb +446 -0
  6. data/lib/rcap/base/area.rb +228 -0
  7. data/lib/rcap/base/circle.rb +121 -0
  8. data/lib/rcap/base/event_code.rb +6 -0
  9. data/lib/rcap/base/geocode.rb +6 -0
  10. data/lib/rcap/base/info.rb +498 -0
  11. data/lib/rcap/base/parameter.rb +88 -0
  12. data/lib/rcap/base/point.rb +87 -0
  13. data/lib/rcap/base/polygon.rb +120 -0
  14. data/lib/rcap/base/resource.rb +168 -0
  15. data/lib/rcap/cap_1_0/alert.rb +59 -342
  16. data/lib/rcap/cap_1_0/area.rb +13 -188
  17. data/lib/rcap/cap_1_0/circle.rb +2 -100
  18. data/lib/rcap/cap_1_0/event_code.rb +8 -3
  19. data/lib/rcap/cap_1_0/geocode.rb +8 -3
  20. data/lib/rcap/cap_1_0/info.rb +16 -468
  21. data/lib/rcap/cap_1_0/parameter.rb +9 -67
  22. data/lib/rcap/cap_1_0/point.rb +2 -61
  23. data/lib/rcap/cap_1_0/polygon.rb +5 -95
  24. data/lib/rcap/cap_1_0/resource.rb +4 -144
  25. data/lib/rcap/cap_1_1/alert.rb +7 -412
  26. data/lib/rcap/cap_1_1/area.rb +13 -188
  27. data/lib/rcap/cap_1_1/circle.rb +2 -100
  28. data/lib/rcap/cap_1_1/event_code.rb +8 -3
  29. data/lib/rcap/cap_1_1/geocode.rb +7 -3
  30. data/lib/rcap/cap_1_1/info.rb +127 -386
  31. data/lib/rcap/cap_1_1/parameter.rb +4 -76
  32. data/lib/rcap/cap_1_1/point.rb +2 -61
  33. data/lib/rcap/cap_1_1/polygon.rb +5 -95
  34. data/lib/rcap/cap_1_1/resource.rb +37 -143
  35. data/lib/rcap/cap_1_2/alert.rb +8 -413
  36. data/lib/rcap/cap_1_2/area.rb +13 -188
  37. data/lib/rcap/cap_1_2/circle.rb +2 -100
  38. data/lib/rcap/cap_1_2/event_code.rb +8 -3
  39. data/lib/rcap/cap_1_2/geocode.rb +8 -3
  40. data/lib/rcap/cap_1_2/info.rb +132 -419
  41. data/lib/rcap/cap_1_2/parameter.rb +4 -76
  42. data/lib/rcap/cap_1_2/point.rb +2 -61
  43. data/lib/rcap/cap_1_2/polygon.rb +5 -92
  44. data/lib/rcap/cap_1_2/resource.rb +31 -134
  45. data/lib/rcap/config.rb +3 -0
  46. data/lib/{extensions → rcap/extensions}/array.rb +1 -1
  47. data/lib/rcap/extensions/date.rb +11 -0
  48. data/lib/{extensions → rcap/extensions}/date_time.rb +2 -5
  49. data/lib/{extensions → rcap/extensions}/string.rb +1 -1
  50. data/lib/{extensions → rcap/extensions}/time.rb +2 -4
  51. data/lib/rcap/utilities.rb +11 -11
  52. data/lib/rcap/validations.rb +7 -2
  53. data/lib/rcap/version.rb +1 -1
  54. data/lib/rcap.rb +21 -4
  55. data/spec/alert_spec.rb +69 -37
  56. data/spec/cap_1_0/alert_spec.rb +46 -61
  57. data/spec/cap_1_0/area_spec.rb +77 -37
  58. data/spec/cap_1_0/circle_spec.rb +26 -6
  59. data/spec/cap_1_0/event_code_spec.rb +10 -3
  60. data/spec/cap_1_0/geocode_spec.rb +11 -4
  61. data/spec/cap_1_0/info_spec.rb +74 -77
  62. data/spec/cap_1_0/parameter_spec.rb +18 -5
  63. data/spec/cap_1_0/point_spec.rb +9 -2
  64. data/spec/cap_1_0/polygon_spec.rb +52 -9
  65. data/spec/cap_1_0/resource_spec.rb +28 -21
  66. data/spec/cap_1_1/alert_spec.rb +47 -60
  67. data/spec/cap_1_1/area_spec.rb +66 -43
  68. data/spec/cap_1_1/circle_spec.rb +29 -6
  69. data/spec/cap_1_1/event_code_spec.rb +11 -3
  70. data/spec/cap_1_1/geocode_spec.rb +11 -3
  71. data/spec/cap_1_1/info_spec.rb +262 -118
  72. data/spec/cap_1_1/parameter_spec.rb +12 -3
  73. data/spec/cap_1_1/point_spec.rb +8 -2
  74. data/spec/cap_1_1/polygon_spec.rb +57 -18
  75. data/spec/cap_1_1/resource_spec.rb +70 -20
  76. data/spec/cap_1_2/alert_spec.rb +97 -110
  77. data/spec/cap_1_2/area_spec.rb +59 -41
  78. data/spec/cap_1_2/circle_spec.rb +15 -8
  79. data/spec/cap_1_2/event_code_spec.rb +11 -3
  80. data/spec/cap_1_2/geocode_spec.rb +11 -3
  81. data/spec/cap_1_2/info_spec.rb +266 -119
  82. data/spec/cap_1_2/parameter_spec.rb +11 -3
  83. data/spec/cap_1_2/point_spec.rb +10 -3
  84. data/spec/cap_1_2/polygon_spec.rb +25 -10
  85. data/spec/cap_1_2/resource_spec.rb +33 -28
  86. data/spec/{utilities_spec.rb → extensions_spec.rb} +0 -0
  87. data/spec/validations_spec.rb +18 -2
  88. metadata +20 -46
@@ -1,5 +1,6 @@
1
1
  module RCAP
2
2
  module CAP_1_1
3
+
3
4
  # In Info object is valid if
4
5
  # * it has an event
5
6
  # * it has an urgency with a valid value
@@ -8,151 +9,32 @@ module RCAP
8
9
  # * all categories are valid and categories has at minimum 1 entry
9
10
  # * all Resource objects in the resources collection are valid
10
11
  # * all Area objects in the areas collection are valid
11
- class Info
12
- include Validation
13
-
14
- CATEGORY_GEO = "Geo"
15
- CATEGORY_MET = "Met"
16
- CATEGORY_SAFETY = "Safety"
17
- CATEGORY_SECURITY = "Security"
18
- CATEGORY_RESCUE = "Rescue"
19
- CATEGORY_FIRE = "Fire"
20
- CATEGORY_HEALTH = "Health"
21
- CATEGORY_ENV = "Env"
22
- CATEGORY_TRANSPORT = "Transport"
23
- CATEGORY_INFRA = "Infra"
24
- CATEGORY_CBRNE = "CBRNE"
25
- CATEGORY_OTHER = "Other"
26
- # Valid values for categories
27
- VALID_CATEGORIES = [ CATEGORY_GEO, CATEGORY_MET, CATEGORY_SAFETY,
28
- CATEGORY_SECURITY, CATEGORY_RESCUE, CATEGORY_FIRE, CATEGORY_HEALTH,
29
- CATEGORY_ENV, CATEGORY_TRANSPORT, CATEGORY_INFRA, CATEGORY_CBRNE,
30
- CATEGORY_OTHER ]
12
+ class Info < RCAP::Base::Info
31
13
 
32
- RESPONSE_TYPE_SHELTER = "Shelter"
33
- RESPONSE_TYPE_EVACUATE = "Evacuate"
34
- RESPONSE_TYPE_PREPARE = "Prepare"
35
- RESPONSE_TYPE_EXECUTE = "Execute"
36
- RESPONSE_TYPE_MONITOR = "Monitor"
37
- RESPONSE_TYPE_ASSESS = "Assess"
38
- RESPONSE_TYPE_NONE = "None"
14
+ RESPONSE_TYPE_SHELTER = "Shelter"
15
+ RESPONSE_TYPE_EVACUATE = "Evacuate"
16
+ RESPONSE_TYPE_PREPARE = "Prepare"
17
+ RESPONSE_TYPE_EXECUTE = "Execute"
18
+ RESPONSE_TYPE_MONITOR = "Monitor"
19
+ RESPONSE_TYPE_ASSESS = "Assess"
20
+ RESPONSE_TYPE_NONE = "None"
39
21
  # Valid values for response_type
40
22
  VALID_RESPONSE_TYPES = [ RESPONSE_TYPE_SHELTER, RESPONSE_TYPE_EVACUATE,
41
23
  RESPONSE_TYPE_PREPARE, RESPONSE_TYPE_EXECUTE, RESPONSE_TYPE_MONITOR,
42
24
  RESPONSE_TYPE_ASSESS, RESPONSE_TYPE_NONE ]
43
25
 
44
- URGENCY_IMMEDIATE = "Immediate"
45
- URGENCY_EXPECTED = "Expected"
46
- URGENCY_FUTURE = "Future"
47
- URGENCY_PAST = "Past"
48
- URGENCY_UNKNOWN = "Unknown"
49
- # Valid values for urgency
50
- VALID_URGENCIES = [ URGENCY_IMMEDIATE, URGENCY_EXPECTED, URGENCY_FUTURE,
51
- URGENCY_PAST, URGENCY_UNKNOWN ]
52
-
53
- SEVERITY_EXTREME = "Extreme"
54
- SEVERITY_SEVERE = "Severe"
55
- SEVERITY_MODERATE = "Moderate"
56
- SEVERITY_MINOR = "Minor"
57
- SEVERITY_UNKNOWN = "Unknown"
58
- # Valid values for severity
59
- VALID_SEVERITIES = [ SEVERITY_EXTREME, SEVERITY_SEVERE, SEVERITY_MODERATE,
60
- SEVERITY_MINOR, SEVERITY_UNKNOWN ]
61
26
 
62
- CERTAINTY_OBSERVED = "Observed"
63
- CERTAINTY_LIKELY = "Likely"
64
- CERTAINTY_POSSIBLE = "Possible"
65
- CERTAINTY_UNLIKELY = "Unlikely"
66
- CERTAINTY_UNKNOWN = "Unknown"
27
+ CERTAINTY_OBSERVED = "Observed"
67
28
  # Valid valies for certainty
68
29
  VALID_CERTAINTIES = [ CERTAINTY_OBSERVED, CERTAINTY_LIKELY,
69
30
  CERTAINTY_POSSIBLE, CERTAINTY_UNLIKELY, CERTAINTY_UNKNOWN ]
70
31
 
71
- XML_ELEMENT_NAME = 'info'
72
- LANGUAGE_ELEMENT_NAME = 'language'
73
- CATEGORY_ELEMENT_NAME = 'category'
74
- EVENT_ELEMENT_NAME = 'event'
75
- RESPONSE_TYPE_ELEMENT_NAME = 'responseType'
76
- URGENCY_ELEMENT_NAME = 'urgency'
77
- SEVERITY_ELEMENT_NAME = 'severity'
78
- CERTAINTY_ELEMENT_NAME = 'certainty'
79
- AUDIENCE_ELEMENT_NAME = 'audience'
80
- EVENT_CODE_ELEMENT_NAME = 'eventCode'
81
- EFFECTIVE_ELEMENT_NAME = 'effective'
82
- ONSET_ELEMENT_NAME = 'onset'
83
- EXPIRES_ELEMENT_NAME = 'expires'
84
- SENDER_NAME_ELEMENT_NAME = 'senderName'
85
- HEADLINE_ELEMENT_NAME = 'headline'
86
- DESCRIPTION_ELEMENT_NAME = 'description'
87
- INSTRUCTION_ELEMENT_NAME = 'instruction'
88
- WEB_ELEMENT_NAME = 'web'
89
- CONTACT_ELEMENT_NAME = 'contact'
90
-
91
- XPATH = "cap:#{ XML_ELEMENT_NAME }"
92
- LANGUAGE_XPATH = "cap:#{ LANGUAGE_ELEMENT_NAME }"
93
- EVENT_XPATH = "cap:#{ EVENT_ELEMENT_NAME }"
94
- URGENCY_XPATH = "cap:#{ URGENCY_ELEMENT_NAME }"
95
- RESPONSE_TYPE_XPATH = "cap:#{ RESPONSE_TYPE_ELEMENT_NAME }"
96
- CATEGORY_XPATH = "cap:#{ CATEGORY_ELEMENT_NAME }"
97
- SEVERITY_XPATH = "cap:#{ SEVERITY_ELEMENT_NAME }"
98
- CERTAINTY_XPATH = "cap:#{ CERTAINTY_ELEMENT_NAME }"
99
- AUDIENCE_XPATH = "cap:#{ AUDIENCE_ELEMENT_NAME }"
100
- EVENT_CODE_XPATH = "cap:#{ EVENT_CODE_ELEMENT_NAME }"
101
- EFFECTIVE_XPATH = "cap:#{ EFFECTIVE_ELEMENT_NAME }"
102
- ONSET_XPATH = "cap:#{ ONSET_ELEMENT_NAME }"
103
- EXPIRES_XPATH = "cap:#{ EXPIRES_ELEMENT_NAME }"
104
- SENDER_NAME_XPATH = "cap:#{ SENDER_NAME_ELEMENT_NAME }"
105
- HEADLINE_XPATH = "cap:#{ HEADLINE_ELEMENT_NAME }"
106
- DESCRIPTION_XPATH = "cap:#{ DESCRIPTION_ELEMENT_NAME }"
107
- INSTRUCTION_XPATH = "cap:#{ INSTRUCTION_ELEMENT_NAME }"
108
- WEB_XPATH = "cap:#{ WEB_ELEMENT_NAME }"
109
- CONTACT_XPATH = "cap:#{ CONTACT_ELEMENT_NAME }"
110
-
111
- DEFAULT_LANGUAGE = 'en-US'
112
32
 
113
- validates_presence_of( :event, :urgency, :severity, :certainty )
114
33
  validates_length_of( :categories, :minimum => 1 )
115
- validates_inclusion_of( :certainty, :allow_nil => true, :in => VALID_CERTAINTIES, :message => "can only be assigned the following values: #{ VALID_CERTAINTIES.join(', ') }")
116
- validates_inclusion_of( :severity, :allow_nil => true, :in => VALID_SEVERITIES, :message => "can only be assigned the following values: #{ VALID_SEVERITIES.join(', ') }" )
117
- validates_inclusion_of( :urgency, :allow_nil => true, :in => VALID_URGENCIES, :message => "can only be assigned the following values: #{ VALID_URGENCIES.join(', ') }" )
118
34
  validates_inclusion_of_members_of( :response_types, :in => VALID_RESPONSE_TYPES, :allow_blank => true )
119
- validates_inclusion_of_members_of( :categories, :in => VALID_CATEGORIES, :allow_blank => true )
120
- validates_collection_of( :resources, :areas, :event_codes, :parameters )
121
-
122
- # @return [String]
123
- attr_accessor( :event )
124
- # @return [String] Value can only be one of {VALID_URGENCIES}
125
- attr_accessor( :urgency )
126
- # @return [String] Value can only be one of {VALID_SEVERITIES}
127
- attr_accessor( :severity )
128
- # @return [String] Value can only be one of {VALID_CERTAINTIES}
129
- attr_accessor( :certainty )
130
- # @return [String]
131
- attr_accessor( :language )
132
- # @return [String]
133
- attr_accessor( :audience )
134
- # @return [DateTime] Effective start time of information
135
- attr_accessor( :effective )
136
- # @return [DateTime] Expected start of event
137
- attr_accessor( :onset )
138
- # @return [DateTime] Effective expiry time of information
139
- attr_accessor( :expires )
140
- # @return [String]
141
- attr_accessor( :sender_name )
142
- # @return [String]
143
- attr_accessor( :headline )
144
- # @return [String]
145
- attr_accessor( :description )
146
- # @return [String]
147
- attr_accessor( :instruction )
148
- # @return [String]
149
- attr_accessor( :web )
150
- # @return [String]
151
- attr_accessor( :contact )
35
+ validates_inclusion_of( :certainty, :allow_nil => true, :in => VALID_CERTAINTIES, :message => "can only be assigned the following values: #{ VALID_CERTAINTIES.join(', ') }")
152
36
 
153
- # @return [Array<String>] Collection of textual categories; elements can be one of {VALID_CATEGORIES}
154
- attr_reader( :categories )
155
- # @return [Array<String>] Collection of textual response types; elements must be from {VALID_RESPONSE_TYPES}
37
+ # @return [Array<String>] Collection of textual response types; elements must be from {VALID_RESPONSE_TYPES}
156
38
  attr_reader( :response_types )
157
39
  # @return [Array<EventCode>] Collection of {EventCode} objects
158
40
  attr_reader( :event_codes )
@@ -172,7 +54,7 @@ module RCAP
172
54
  # @option attributes [String] :urgency A member of {VALID_URGENCIES}
173
55
  # @option attributes [String] :severity A member of {VALID_SEVERITIES}
174
56
  # @option attributes [String] :certainty A member of {VALID_CERTAINTIES}
175
- # @option attributes [DateTime] :effective
57
+ # @option attributes [DateTime] :effective
176
58
  # @option attributes [DateTime] :onset
177
59
  # @option attributes [DateTime] :expires
178
60
  # @option attributes [Array<EventCode>] :event_codes Collection of {EventCode} objects
@@ -183,86 +65,38 @@ module RCAP
183
65
  # @option attributes [String] :web URL
184
66
  # @option attributes [String] :contact
185
67
  # @option attributes [Array<Parameter>] :parameters Collection of {Parameter} objects
186
- # @option attributes [Array<Resource>] :resources Collection of {Resource} objects
68
+ # @option attributes [Array<Resource>] :resources Collection of {Resource} objects
187
69
  # @option attributes [Array<Area>] :areas Collection of {Area} objects
188
- def initialize( attributes = {} )
189
- @language = attributes[ :language ] || DEFAULT_LANGUAGE
190
- @categories = Array( attributes[ :categories ])
191
- @audience = attributes [ :audience ]
192
- @event = attributes [ :event ]
193
- @response_types = Array( attributes[ :response_types ])
194
- @urgency = attributes[ :urgency ]
195
- @severity = attributes[ :severity ]
196
- @certainty = attributes[ :certainty ]
197
- @effective = attributes[ :effective ]
198
- @onset = attributes[ :onset ]
199
- @expires = attributes[ :expires ]
200
- @event_codes = Array( attributes[ :event_codes ])
201
- @sender_name = attributes[ :sender_name ]
202
- @headline = attributes[ :headline ]
203
- @description = attributes[ :description ]
204
- @instruction = attributes[ :instruction ]
205
- @web = attributes[ :web ]
206
- @contact = attributes[ :contact ]
207
- @parameters = Array( attributes[ :parameters ])
208
- @resources = Array( attributes[ :resources ])
209
- @areas = Array( attributes[ :areas ])
70
+ def initialize
71
+ @response_types = []
72
+ super
210
73
  end
211
74
 
212
- # Creates a new EventCode object and adds it to the event_codes array. The
213
- # event_code_attributes are passed as a parameter to EventCode.new.
214
- #
215
- # @see EventCode#initialize
216
- #
217
- # @param [Hash] event_code_attributes (see EventCode#initialize)
218
- # @return [EventCode]
219
- def add_event_code( event_code_attributes = {})
220
- event_code = EventCode.new( event_code_attributes )
221
- @event_codes << event_code
222
- event_code
75
+ def event_code_class
76
+ EventCode
223
77
  end
224
78
 
225
- # Creates a new Parameter object and adds it to the parameters array. The
226
- # parameter_attributes are passed as a parameter to Parameter.new.
227
- #
228
- # @see Parameter#initialize
229
- #
230
- # @param [Hash] parameter_attributes (see Parameter#initialize)
231
- # @return [Parameter]
232
- def add_parameter( parameter_attributes = {})
233
- parameter = Parameter.new( parameter_attributes )
234
- @parameters << parameter
235
- parameter
79
+ def parameter_class
80
+ Parameter
236
81
  end
237
82
 
238
- # Creates a new Resource object and adds it to the resources array. The
239
- # resource_attributes are passed as a parameter to Resource.new.
240
- #
241
- # @see Resource#initialize
242
- #
243
- # @param [Hash] resource_attributes (See Resource#initialize)
244
- # @return [Resource]
245
- def add_resource( resource_attributes = {})
246
- resource = Resource.new( resource_attributes )
247
- @resources << resource
248
- resource
83
+ def resource_class
84
+ Resource
249
85
  end
250
86
 
251
- # Creates a new Area object and adds it to the areas array. The
252
- # area_attributes are passed as a parameter to Area.new.
253
- #
254
- # @see Area#initialize
255
- #
256
- # @param [Hash] area_attributes (see Area#initialize)
257
- # @return [Area]
258
- def add_area( area_attributes = {})
259
- area = Area.new( area_attributes )
260
- @areas << area
261
- area
87
+ def area_class
88
+ Area
89
+ end
90
+
91
+ def xmlns
92
+ Alert::XMLNS
262
93
  end
263
94
 
95
+ RESPONSE_TYPE_ELEMENT_NAME = 'responseType'
96
+ RESPONSE_TYPE_XPATH = "cap:#{ RESPONSE_TYPE_ELEMENT_NAME }"
97
+
264
98
  # @return [REXML::Element]
265
- def to_xml_element
99
+ def to_xml_element
266
100
  xml_element = REXML::Element.new( XML_ELEMENT_NAME )
267
101
  xml_element.add_element( LANGUAGE_ELEMENT_NAME ).add_text( @language ) if @language
268
102
  @categories.each do |category|
@@ -301,37 +135,47 @@ module RCAP
301
135
  end
302
136
 
303
137
  # @return [String]
304
- def to_xml
138
+ def to_xml
305
139
  self.to_xml_element.to_s
306
140
  end
307
141
 
142
+ # @param [REXML::Element] info_xml_element
143
+ # @return [Info]
144
+ def self.from_xml_element( info_xml_element )
145
+ super.tap do |info|
146
+ RCAP.xpath_match( info_xml_element, RESPONSE_TYPE_XPATH, info.xmlns ).each do |element|
147
+ info.response_types << element.text
148
+ end
149
+ end
150
+ end
151
+
308
152
  # @return [String]
309
- def inspect
153
+ def inspect
310
154
  info_inspect = "Language: #{ @language }\n"+
311
- "Categories: #{ @categories.to_s_for_cap }\n"+
312
- "Event: #{ @event }\n"+
313
- "Response Types: #{ @response_types.to_s_for_cap }\n"+
314
- "Urgency: #{ @urgency }\n"+
315
- "Severity: #{ @severity }\n"+
316
- "Certainty: #{ @certainty }\n"+
317
- "Audience: #{ @audience }\n"+
318
- "Event Codes: #{ @event_codes.inspect }\n"+
319
- "Effective: #{ @effective }\n"+
320
- "Onset: #{ @onset }\n"+
321
- "Expires: #{ @expires }\n"+
322
- "Sender Name: #{ @sender_name }\n"+
323
- "Headline: #{ @headline }\n"+
324
- "Description:\n"+
325
- @description.to_s.lines.map{ |line| " " + line }.join( "\n")+"\n"+
326
- "Instruction: #{ @instruction }\n"+
327
- "Web: #{ @web }\n"+
328
- "Contact: #{ @contact }\n"+
329
- "Parameters:\n"+
330
- @parameters.map{ |parameter| parameter.inspect }.join( "\n" )+"\n"+
331
- "Resources:\n"+
332
- @resources.map{ |resource| " " + resource.inspect }.join( "\n" )+"\n"+
333
- "Area:\n"+
334
- @areas.map{ |area| " #{ area }" }.join( "\n" )+"\n"
155
+ "Categories: #{ @categories.to_s_for_cap }\n"+
156
+ "Event: #{ @event }\n"+
157
+ "Response Types: #{ @response_types.to_s_for_cap }\n"+
158
+ "Urgency: #{ @urgency }\n"+
159
+ "Severity: #{ @severity }\n"+
160
+ "Certainty: #{ @certainty }\n"+
161
+ "Audience: #{ @audience }\n"+
162
+ "Event Codes: #{ @event_codes.inspect }\n"+
163
+ "Effective: #{ @effective }\n"+
164
+ "Onset: #{ @onset }\n"+
165
+ "Expires: #{ @expires }\n"+
166
+ "Sender Name: #{ @sender_name }\n"+
167
+ "Headline: #{ @headline }\n"+
168
+ "Description:\n"+
169
+ @description.to_s.lines.map{ |line| " " + line }.join( "\n")+"\n"+
170
+ "Instruction: #{ @instruction }\n"+
171
+ "Web: #{ @web }\n"+
172
+ "Contact: #{ @contact }\n"+
173
+ "Parameters:\n"+
174
+ @parameters.map{ |parameter| " " + parameter.inspect }.join( "\n" )+"\n"+
175
+ "Resources:\n"+
176
+ @resources.map{ |resource| " " + resource.inspect }.join( "\n" )+"\n"+
177
+ "Area:\n"+
178
+ @areas.map{ |area| " #{ area }" }.join( "\n" )+"\n"
335
179
  RCAP.format_lines_for_inspect( 'INFO', info_inspect )
336
180
  end
337
181
 
@@ -343,184 +187,81 @@ module RCAP
343
187
  "#{ @event }(#{ @urgency }/#{ @severity }/#{ @certainty })"
344
188
  end
345
189
 
346
- # @param [REXML::Element] info_xml_element
347
- # @return [Info]
348
- def self.from_xml_element( info_xml_element )
349
- self.new(
350
- :language => RCAP.xpath_text( info_xml_element, LANGUAGE_XPATH, Alert::XMLNS ) || DEFAULT_LANGUAGE,
351
- :categories => RCAP.xpath_match( info_xml_element, CATEGORY_XPATH, Alert::XMLNS ).map{ |element| element.text },
352
- :event => RCAP.xpath_text( info_xml_element, EVENT_XPATH, Alert::XMLNS ),
353
- :response_types => RCAP.xpath_match( info_xml_element, RESPONSE_TYPE_XPATH, Alert::XMLNS ).map{ |element| element.text },
354
- :urgency => RCAP.xpath_text( info_xml_element, URGENCY_XPATH, Alert::XMLNS ),
355
- :severity => RCAP.xpath_text( info_xml_element, SEVERITY_XPATH, Alert::XMLNS ),
356
- :certainty => RCAP.xpath_text( info_xml_element, CERTAINTY_XPATH, Alert::XMLNS ),
357
- :audience => RCAP.xpath_text( info_xml_element, AUDIENCE_XPATH, Alert::XMLNS ),
358
- :effective => (( effective = RCAP.xpath_first( info_xml_element, EFFECTIVE_XPATH, Alert::XMLNS )) ? DateTime.parse( effective.text ) : nil ),
359
- :onset => (( onset = RCAP.xpath_first( info_xml_element, ONSET_XPATH, Alert::XMLNS )) ? DateTime.parse( onset.text ) : nil ),
360
- :expires => (( expires = RCAP.xpath_first( info_xml_element, EXPIRES_XPATH, Alert::XMLNS )) ? DateTime.parse( expires.text ) : nil ),
361
- :sender_name => RCAP.xpath_text( info_xml_element, SENDER_NAME_XPATH, Alert::XMLNS ),
362
- :headline => RCAP.xpath_text( info_xml_element, HEADLINE_XPATH, Alert::XMLNS ),
363
- :description => RCAP.xpath_text( info_xml_element, DESCRIPTION_XPATH, Alert::XMLNS ),
364
- :instruction => RCAP.xpath_text( info_xml_element, INSTRUCTION_XPATH, Alert::XMLNS ),
365
- :web => RCAP.xpath_text( info_xml_element, WEB_XPATH, Alert::XMLNS ),
366
- :contact => RCAP.xpath_text( info_xml_element, CONTACT_XPATH, Alert::XMLNS ),
367
- :event_codes => RCAP.xpath_match( info_xml_element, EventCode::XPATH, Alert::XMLNS ).map{ |element| EventCode.from_xml_element( element )},
368
- :parameters => RCAP.xpath_match( info_xml_element, Parameter::XPATH, Alert::XMLNS ).map{ |element| Parameter.from_xml_element( element )},
369
- :resources => RCAP.xpath_match( info_xml_element, Resource::XPATH, Alert::XMLNS ).map{ |element| Resource.from_xml_element( element )},
370
- :areas => RCAP.xpath_match( info_xml_element, Area::XPATH, Alert::XMLNS ).map{ |element| Area.from_xml_element( element )}
371
- )
372
- end
373
190
 
374
- LANGUAGE_YAML = 'Language'
375
- CATEGORIES_YAML = 'Categories'
376
- EVENT_YAML = 'Event'
377
- RESPONSE_TYPES_YAML = 'Response Types'
378
- URGENCY_YAML = 'Urgency'
379
- SEVERITY_YAML = 'Severity'
380
- CERTAINTY_YAML = 'Certainty'
381
- AUDIENCE_YAML = 'Audience'
382
- EFFECTIVE_YAML = 'Effective'
383
- ONSET_YAML = 'Onset'
384
- EXPIRES_YAML = 'Expires'
385
- SENDER_NAME_YAML = 'Sender Name'
386
- HEADLINE_YAML = 'Headline'
387
- DESCRIPTION_YAML = 'Description'
388
- INSTRUCTION_YAML = 'Instruction'
389
- WEB_YAML = 'Web'
390
- CONTACT_YAML = 'Contact'
391
- EVENT_CODES_YAML = 'Event Codes'
392
- PARAMETERS_YAML = 'Parameters'
393
- RESOURCES_YAML = 'Resources'
394
- AREAS_YAML = 'Areas'
191
+ RESPONSE_TYPES_YAML = 'Response Types'
395
192
 
396
193
  # @return [String]
397
- def to_yaml( options = {} )
194
+ def to_yaml( options = {} )
398
195
  parameter_to_hash = lambda{ |hash, parameter| hash.merge( parameter.name => parameter.value )}
399
196
 
400
- RCAP.attribute_values_to_hash(
401
- [ LANGUAGE_YAML, @language ],
402
- [ CATEGORIES_YAML, @categories ],
403
- [ EVENT_YAML, @event ],
404
- [ RESPONSE_TYPES_YAML, @response_types ],
405
- [ URGENCY_YAML, @urgency ],
406
- [ SEVERITY_YAML, @severity ],
407
- [ CERTAINTY_YAML, @certainty ],
408
- [ AUDIENCE_YAML, @audience ],
409
- [ EFFECTIVE_YAML, @effective ],
410
- [ ONSET_YAML, @onset ],
411
- [ EXPIRES_YAML, @expires ],
412
- [ SENDER_NAME_YAML, @sender_name ],
413
- [ HEADLINE_YAML, @headline ],
414
- [ DESCRIPTION_YAML, @description ],
415
- [ INSTRUCTION_YAML, @instruction ],
416
- [ WEB_YAML, @web ],
417
- [ CONTACT_YAML, @contact ],
418
- [ EVENT_CODES_YAML, @event_codes.inject({}, &parameter_to_hash )],
419
- [ PARAMETERS_YAML, @parameters.inject({}, &parameter_to_hash )],
420
- [ RESOURCES_YAML, @resources ],
421
- [ AREAS_YAML, @areas ]).to_yaml( options )
197
+ RCAP.attribute_values_to_hash( [ LANGUAGE_YAML, @language ],
198
+ [ CATEGORIES_YAML, @categories ],
199
+ [ EVENT_YAML, @event ],
200
+ [ RESPONSE_TYPES_YAML, @response_types ],
201
+ [ URGENCY_YAML, @urgency ],
202
+ [ SEVERITY_YAML, @severity ],
203
+ [ CERTAINTY_YAML, @certainty ],
204
+ [ AUDIENCE_YAML, @audience ],
205
+ [ EFFECTIVE_YAML, @effective ],
206
+ [ ONSET_YAML, @onset ],
207
+ [ EXPIRES_YAML, @expires ],
208
+ [ SENDER_NAME_YAML, @sender_name ],
209
+ [ HEADLINE_YAML, @headline ],
210
+ [ DESCRIPTION_YAML, @description ],
211
+ [ INSTRUCTION_YAML, @instruction ],
212
+ [ WEB_YAML, @web ],
213
+ [ CONTACT_YAML, @contact ],
214
+ [ EVENT_CODES_YAML, @event_codes.inject({}, &parameter_to_hash )],
215
+ [ PARAMETERS_YAML, @parameters.inject({}, &parameter_to_hash )],
216
+ [ RESOURCES_YAML, @resources ],
217
+ [ AREAS_YAML, @areas ]).to_yaml( options )
422
218
  end
423
219
 
424
220
  # @param [Hash] info_yaml_data
425
221
  # @return [Info]
426
- def self.from_yaml_data( info_yaml_data )
427
- self.new(
428
- :language => info_yaml_data [ LANGUAGE_YAML ],
429
- :categories => info_yaml_data [ CATEGORIES_YAML ],
430
- :event => info_yaml_data [ EVENT_YAML ],
431
- :response_types => info_yaml_data [ RESPONSE_TYPES_YAML ],
432
- :urgency => info_yaml_data [ URGENCY_YAML ],
433
- :severity => info_yaml_data [ SEVERITY_YAML ],
434
- :certainty => info_yaml_data [ CERTAINTY_YAML ],
435
- :audience => info_yaml_data [ AUDIENCE_YAML ],
436
- :effective => ( effective = info_yaml_data[ EFFECTIVE_YAML ]).blank? ? nil : DateTime.parse( effective.to_s ),
437
- :onset => ( onset = info_yaml_data[ ONSET_YAML ]).blank? ? nil : DateTime.parse( onset.to_s ),
438
- :expires => ( expires = info_yaml_data[ EXPIRES_YAML ]).blank? ? nil : DateTime.parse( expires.to_s ),
439
- :sender_name => info_yaml_data [ SENDER_NAME_YAML ],
440
- :headline => info_yaml_data [ HEADLINE_YAML ],
441
- :description => info_yaml_data [ DESCRIPTION_YAML ],
442
- :instruction => info_yaml_data [ INSTRUCTION_YAML ],
443
- :web => info_yaml_data [ WEB_YAML ],
444
- :contact => info_yaml_data [ CONTACT_YAML ],
445
- :event_codes => Array( info_yaml_data [ EVENT_CODES_YAML ]).map{ |name,value| EventCode.new( :name => name, :value => value )},
446
- :parameters => Array( info_yaml_data [ PARAMETERS_YAML ]).map{ |parameter_yaml_data| Parameter.new( :name => name, :value => value )},
447
- :resources => Array( info_yaml_data [ RESOURCES_YAML ]).map{ |resource_yaml_data| Resource.from_yaml_data( resource_yaml_data )},
448
- :areas => Array( info_yaml_data [ AREAS_YAML ]).map{ |area_yaml_data| Area.from_yaml_data( area_yaml_data )}
449
- )
222
+ def self.from_yaml_data( info_yaml_data )
223
+ super.tap do |info|
224
+ Array( info_yaml_data [ RESPONSE_TYPES_YAML ] ).each do |response_type|
225
+ info.response_types << response_type
226
+ end
227
+ end
450
228
  end
451
229
 
452
- LANGUAGE_KEY = 'language'
453
- CATEGORIES_KEY = 'categories'
454
- EVENT_KEY = 'event'
455
- RESPONSE_TYPES_KEY = 'response_types'
456
- URGENCY_KEY = 'urgency'
457
- SEVERITY_KEY = 'severity'
458
- CERTAINTY_KEY = 'certainty'
459
- AUDIENCE_KEY = 'audience'
460
- EFFECTIVE_KEY = 'effective'
461
- ONSET_KEY = 'onset'
462
- EXPIRES_KEY = 'expires'
463
- SENDER_NAME_KEY = 'sender_name'
464
- HEADLINE_KEY = 'headline'
465
- DESCRIPTION_KEY = 'description'
466
- INSTRUCTION_KEY = 'instruction'
467
- WEB_KEY = 'web'
468
- CONTACT_KEY = 'contact'
469
- RESOURCES_KEY = 'resources'
470
- EVENT_CODES_KEY = 'event_codes'
471
- PARAMETERS_KEY = 'parameters'
472
- AREAS_KEY = 'areas'
230
+ RESPONSE_TYPES_KEY = 'response_types'
473
231
 
474
232
  # @return [Hash]
475
- def to_h
476
- RCAP.attribute_values_to_hash(
477
- [ LANGUAGE_KEY, @language ],
478
- [ CATEGORIES_KEY, @categories ],
479
- [ EVENT_KEY, @event ],
480
- [ RESPONSE_TYPES_KEY, @response_types ],
481
- [ URGENCY_KEY, @urgency ],
482
- [ SEVERITY_KEY, @severity ],
483
- [ CERTAINTY_KEY, @certainty ],
484
- [ AUDIENCE_KEY, @audience ],
485
- [ EFFECTIVE_KEY, RCAP.to_s_for_cap( @effective )],
486
- [ ONSET_KEY, RCAP.to_s_for_cap( @onset )],
487
- [ EXPIRES_KEY, RCAP.to_s_for_cap( @expires )],
488
- [ SENDER_NAME_KEY, @sender_name ],
489
- [ HEADLINE_KEY, @headline ],
490
- [ DESCRIPTION_KEY, @description ],
491
- [ INSTRUCTION_KEY, @instruction ],
492
- [ WEB_KEY, @web ],
493
- [ CONTACT_KEY, @contact ],
494
- [ RESOURCES_KEY, @resources.map{ |resource| resource.to_h } ],
495
- [ EVENT_CODES_KEY, @event_codes.map{ |event_code| event_code.to_h } ],
496
- [ PARAMETERS_KEY, @parameters.map{ |parameter| parameter.to_h } ],
497
- [ AREAS_KEY, @areas.map{ |area| area.to_h }])
233
+ def to_h
234
+ RCAP.attribute_values_to_hash( [ LANGUAGE_KEY, @language ],
235
+ [ CATEGORIES_KEY, @categories ],
236
+ [ EVENT_KEY, @event ],
237
+ [ RESPONSE_TYPES_KEY, @response_types ],
238
+ [ URGENCY_KEY, @urgency ],
239
+ [ SEVERITY_KEY, @severity ],
240
+ [ CERTAINTY_KEY, @certainty ],
241
+ [ AUDIENCE_KEY, @audience ],
242
+ [ EFFECTIVE_KEY, RCAP.to_s_for_cap( @effective )],
243
+ [ ONSET_KEY, RCAP.to_s_for_cap( @onset )],
244
+ [ EXPIRES_KEY, RCAP.to_s_for_cap( @expires )],
245
+ [ SENDER_NAME_KEY, @sender_name ],
246
+ [ HEADLINE_KEY, @headline ],
247
+ [ DESCRIPTION_KEY, @description ],
248
+ [ INSTRUCTION_KEY, @instruction ],
249
+ [ WEB_KEY, @web ],
250
+ [ CONTACT_KEY, @contact ],
251
+ [ RESOURCES_KEY, @resources.map{ |resource| resource.to_h } ],
252
+ [ EVENT_CODES_KEY, @event_codes.map{ |event_code| event_code.to_h } ],
253
+ [ PARAMETERS_KEY, @parameters.map{ |parameter| parameter.to_h } ],
254
+ [ AREAS_KEY, @areas.map{ |area| area.to_h }])
498
255
  end
499
256
 
500
257
  # @param [Hash] info_hash
501
258
  # @return [Info]
502
- def self.from_h( info_hash )
503
- self.new( :language => info_hash[ LANGUAGE_KEY ],
504
- :categories => info_hash[ CATEGORIES_KEY ],
505
- :event => info_hash[ EVENT_KEY ],
506
- :response_types => info_hash[ RESPONSE_TYPES_KEY ],
507
- :urgency => info_hash[ URGENCY_KEY ],
508
- :severity => info_hash[ SEVERITY_KEY ],
509
- :certainty => info_hash[ CERTAINTY_KEY ],
510
- :audience => info_hash[ AUDIENCE_KEY ],
511
- :effective => RCAP.parse_datetime( info_hash[ EFFECTIVE_KEY ]),
512
- :onset => RCAP.parse_datetime( info_hash[ ONSET_KEY ]),
513
- :expires => RCAP.parse_datetime( info_hash[ EXPIRES_KEY ]),
514
- :sender_name => info_hash[ SENDER_NAME_KEY ],
515
- :headline => info_hash[ HEADLINE_KEY ],
516
- :description => info_hash[ DESCRIPTION_KEY ],
517
- :instruction => info_hash[ INSTRUCTION_KEY ],
518
- :web => info_hash[ WEB_KEY ],
519
- :contact => info_hash[ CONTACT_KEY ],
520
- :resources => Array( info_hash[ RESOURCES_KEY ]).map{ |resource_hash| Resource.from_h( resource_hash ) },
521
- :event_codes => Array( info_hash[ EVENT_CODES_KEY ]).map{ |event_code_hash| EventCode.from_h( event_code_hash )},
522
- :parameters => Array( info_hash[ PARAMETERS_KEY ]).map{ |parameter_hash| Parameter.from_h( parameter_hash )},
523
- :areas => Array( info_hash[ AREAS_KEY ]).map{ |area_hash| Area.from_h( area_hash )})
259
+ def self.from_h( info_hash )
260
+ super.tap do |info|
261
+ Array( info_hash[ RESPONSE_TYPES_KEY ]).each do |response_type|
262
+ info.response_types << response_type
263
+ end
264
+ end
524
265
  end
525
266
  end
526
267
  end