rcap 2.4.1 → 2.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.ruby-version +1 -0
- data/CHANGELOG.md +18 -0
- data/README.md +1 -0
- data/lib/rcap.rb +3 -1
- data/lib/rcap/alert.rb +30 -29
- data/lib/rcap/base/alert.rb +208 -205
- data/lib/rcap/base/area.rb +95 -91
- data/lib/rcap/base/circle.rb +45 -34
- data/lib/rcap/base/event_code.rb +2 -0
- data/lib/rcap/base/geocode.rb +2 -0
- data/lib/rcap/base/info.rb +273 -272
- data/lib/rcap/base/parameter.rb +29 -28
- data/lib/rcap/base/point.rb +26 -24
- data/lib/rcap/base/polygon.rb +43 -35
- data/lib/rcap/base/resource.rb +65 -65
- data/lib/rcap/cap_1_0/alert.rb +85 -86
- data/lib/rcap/cap_1_0/area.rb +2 -2
- data/lib/rcap/cap_1_0/circle.rb +2 -1
- data/lib/rcap/cap_1_0/event_code.rb +3 -1
- data/lib/rcap/cap_1_0/geocode.rb +3 -1
- data/lib/rcap/cap_1_0/info.rb +3 -3
- data/lib/rcap/cap_1_0/parameter.rb +13 -13
- data/lib/rcap/cap_1_0/point.rb +2 -1
- data/lib/rcap/cap_1_0/polygon.rb +3 -3
- data/lib/rcap/cap_1_0/resource.rb +2 -3
- data/lib/rcap/cap_1_1/alert.rb +6 -6
- data/lib/rcap/cap_1_1/area.rb +2 -2
- data/lib/rcap/cap_1_1/circle.rb +2 -1
- data/lib/rcap/cap_1_1/event_code.rb +3 -1
- data/lib/rcap/cap_1_1/geocode.rb +3 -1
- data/lib/rcap/cap_1_1/info.rb +125 -132
- data/lib/rcap/cap_1_1/parameter.rb +2 -3
- data/lib/rcap/cap_1_1/point.rb +2 -1
- data/lib/rcap/cap_1_1/polygon.rb +3 -3
- data/lib/rcap/cap_1_1/resource.rb +37 -38
- data/lib/rcap/cap_1_2/alert.rb +6 -6
- data/lib/rcap/cap_1_2/area.rb +2 -2
- data/lib/rcap/cap_1_2/circle.rb +2 -1
- data/lib/rcap/cap_1_2/event_code.rb +3 -1
- data/lib/rcap/cap_1_2/geocode.rb +3 -1
- data/lib/rcap/cap_1_2/info.rb +120 -123
- data/lib/rcap/cap_1_2/parameter.rb +2 -3
- data/lib/rcap/cap_1_2/point.rb +2 -1
- data/lib/rcap/cap_1_2/polygon.rb +4 -4
- data/lib/rcap/cap_1_2/resource.rb +38 -38
- data/lib/rcap/config.rb +5 -3
- data/lib/rcap/custom_validators.rb +75 -78
- data/lib/rcap/extensions/array.rb +3 -1
- data/lib/rcap/extensions/date.rb +3 -1
- data/lib/rcap/extensions/date_time.rb +5 -2
- data/lib/rcap/extensions/float.rb +2 -0
- data/lib/rcap/extensions/integer.rb +7 -0
- data/lib/rcap/extensions/nil_class.rb +2 -0
- data/lib/rcap/extensions/string.rb +6 -4
- data/lib/rcap/extensions/time.rb +5 -3
- data/lib/rcap/formatters/yaml.rb +5 -0
- data/lib/rcap/info.rb +6 -5
- data/lib/rcap/utilities.rb +27 -30
- data/lib/rcap/validation.rb +22 -21
- data/lib/rcap/version.rb +3 -1
- data/rcap.gemspec +5 -5
- data/spec/alert_spec.rb +141 -141
- data/spec/cap_1_0/alert_spec.rb +92 -94
- data/spec/cap_1_0/area_spec.rb +86 -86
- data/spec/cap_1_0/circle_spec.rb +48 -39
- data/spec/cap_1_0/event_code_spec.rb +15 -15
- data/spec/cap_1_0/geocode_spec.rb +16 -16
- data/spec/cap_1_0/info_spec.rb +175 -177
- data/spec/cap_1_0/parameter_spec.rb +27 -27
- data/spec/cap_1_0/point_spec.rb +18 -18
- data/spec/cap_1_0/polygon_spec.rb +43 -41
- data/spec/cap_1_0/resource_spec.rb +63 -64
- data/spec/cap_1_1/alert_spec.rb +107 -109
- data/spec/cap_1_1/area_spec.rb +90 -90
- data/spec/cap_1_1/circle_spec.rb +43 -34
- data/spec/cap_1_1/event_code_spec.rb +15 -16
- data/spec/cap_1_1/geocode_spec.rb +16 -16
- data/spec/cap_1_1/info_spec.rb +194 -196
- data/spec/cap_1_1/parameter_spec.rb +17 -17
- data/spec/cap_1_1/point_spec.rb +18 -18
- data/spec/cap_1_1/polygon_spec.rb +43 -41
- data/spec/cap_1_1/resource_spec.rb +106 -107
- data/spec/cap_1_2/alert_spec.rb +98 -99
- data/spec/cap_1_2/area_spec.rb +90 -90
- data/spec/cap_1_2/circle_spec.rb +52 -43
- data/spec/cap_1_2/event_code_spec.rb +19 -20
- data/spec/cap_1_2/geocode_spec.rb +20 -20
- data/spec/cap_1_2/info_spec.rb +196 -198
- data/spec/cap_1_2/parameter_spec.rb +19 -19
- data/spec/cap_1_2/point_spec.rb +21 -21
- data/spec/cap_1_2/polygon_spec.rb +55 -47
- data/spec/cap_1_2/resource_spec.rb +96 -97
- data/spec/extensions_spec.rb +29 -29
- data/spec/info_spec.rb +15 -15
- data/spec/spec_helper.rb +3 -3
- data/spec/validations_spec.rb +73 -73
- metadata +12 -11
- data/lib/rcap/extensions/fixnum.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f9d35572f21978f5fff7370828a4c146daf2c2abe960e1c508bcbee6f5713319
|
4
|
+
data.tar.gz: b998e0210707386d1d0de2d1157e7296900be5b79c1191e02741524f3ac3fe20
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33705a6c22c94be4b61d469f1f5a7c727cd92e968ef639dd947d51a65ba012d70eda684af771960c10816dace76804fb341696709fb039a1b16c1b71be98c09c
|
7
|
+
data.tar.gz: a332b8e3b2f155545afbd53bf319d862f1b2e51c692bebf728646b759d5fc97ef2f0b293df81e65987ae0a999662a436a4298172b4a368d743aab0ca7a956911
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.0
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,24 @@
|
|
1
1
|
Change Log
|
2
2
|
==========
|
3
3
|
|
4
|
+
## 2.7.0 - 22 March 2017
|
5
|
+
|
6
|
+
* Coordinates of a polygon should be an array of coordinate arrays rather than a single coordinate array. (Seth Deckard)
|
7
|
+
* Moved Fixnum extenions to Integer
|
8
|
+
* Ruby 2.4.0 tested
|
9
|
+
|
10
|
+
## 2.6.0 - 30 October 2016
|
11
|
+
|
12
|
+
* Adds GeoJSON export to Polygon and Circle
|
13
|
+
|
14
|
+
## 2.5.1 - 3 November 2014
|
15
|
+
|
16
|
+
* Allow the polygons to be empty.
|
17
|
+
|
18
|
+
## 2.5.0 - 3 November 2014
|
19
|
+
|
20
|
+
* Allow the values of parameters, area codes and event codes to be empty.
|
21
|
+
|
4
22
|
## 2.4.1 - 7 August 2013
|
5
23
|
|
6
24
|
* Further integration of validations.
|
data/README.md
CHANGED
data/lib/rcap.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# System and require libs
|
2
4
|
require 'date'
|
3
5
|
require 'uuidtools'
|
@@ -11,7 +13,7 @@ require 'digest/sha1'
|
|
11
13
|
|
12
14
|
# Extensions
|
13
15
|
require 'rcap/extensions/nil_class'
|
14
|
-
require 'rcap/extensions/
|
16
|
+
require 'rcap/extensions/integer'
|
15
17
|
require 'rcap/extensions/float'
|
16
18
|
require 'rcap/extensions/array'
|
17
19
|
require 'rcap/extensions/string'
|
data/lib/rcap/alert.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RCAP
|
2
4
|
module Alert
|
5
|
+
XMLNS_KEY = 'xmlns'
|
6
|
+
YAML_CAP_VERSION_KEY = 'CAP Version'
|
7
|
+
JSON_CAP_VERSION_KEY = 'cap_version'
|
3
8
|
|
4
|
-
|
5
|
-
YAML_CAP_VERSION_KEY = "CAP Version"
|
6
|
-
JSON_CAP_VERSION_KEY = "cap_version"
|
7
|
-
|
8
|
-
CAP_NAMESPACES = [ RCAP::CAP_1_0::Alert::XMLNS, RCAP::CAP_1_1::Alert::XMLNS, RCAP::CAP_1_2::Alert::XMLNS ]
|
9
|
+
CAP_NAMESPACES = [RCAP::CAP_1_0::Alert::XMLNS, RCAP::CAP_1_1::Alert::XMLNS, RCAP::CAP_1_2::Alert::XMLNS].freeze
|
9
10
|
|
10
11
|
# Initialise a RCAP Alert from a XML document.
|
11
12
|
#
|
@@ -14,19 +15,19 @@ module RCAP
|
|
14
15
|
# the namespace of the document is inspected and a CAP_1_0::Alert, CAP_1_1::Alert
|
15
16
|
# or CAP_1_2::Alert is instantiated accordingly. If no namespace can be detected
|
16
17
|
# a CAP 1.2 message will be assumed.
|
17
|
-
# @return [
|
18
|
-
def self.from_xml(
|
19
|
-
xml_document = REXML::Document.new(
|
18
|
+
# @return [RCAP::CAP_1_0::Alert, RCAP::CAP_1_1::Alert, RCAP::CAP_1_2::Alert ]
|
19
|
+
def self.from_xml(xml, namespace_key = nil)
|
20
|
+
xml_document = REXML::Document.new(xml)
|
20
21
|
document_namespaces = xml_document.root.namespaces.invert
|
21
|
-
namespace = namespace_key || CAP_NAMESPACES.find{ |namepsace| document_namespaces[
|
22
|
+
namespace = namespace_key || CAP_NAMESPACES.find { |namepsace| document_namespaces[namepsace] }
|
22
23
|
|
23
24
|
case namespace
|
24
25
|
when CAP_1_0::Alert::XMLNS
|
25
|
-
CAP_1_0::Alert.from_xml_document(
|
26
|
+
CAP_1_0::Alert.from_xml_document(xml_document)
|
26
27
|
when CAP_1_1::Alert::XMLNS
|
27
|
-
CAP_1_1::Alert.from_xml_document(
|
28
|
+
CAP_1_1::Alert.from_xml_document(xml_document)
|
28
29
|
else
|
29
|
-
CAP_1_2::Alert.from_xml_document(
|
30
|
+
CAP_1_2::Alert.from_xml_document(xml_document)
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
@@ -35,17 +36,17 @@ module RCAP
|
|
35
36
|
# CAP 1.0, 1.1 or 1.2 Alert is instantiated accordingly.
|
36
37
|
#
|
37
38
|
# @param [IO, String] yaml CAP Alert in YAML format. Can be a String or any IO object.
|
38
|
-
# @return [
|
39
|
-
def self.from_yaml(
|
40
|
-
yaml_data = YAML.
|
39
|
+
# @return [RCAP::CAP_1_0::Alert, RCAP::CAP_1_1::Alert, RCAP::CAP_1_2::Alert ]
|
40
|
+
def self.from_yaml(yaml)
|
41
|
+
yaml_data = YAML.safe_load(yaml, [Time, DateTime])
|
41
42
|
|
42
|
-
case yaml_data[
|
43
|
+
case yaml_data[YAML_CAP_VERSION_KEY]
|
43
44
|
when CAP_1_0::Alert::CAP_VERSION
|
44
|
-
CAP_1_0::Alert.from_yaml_data(
|
45
|
+
CAP_1_0::Alert.from_yaml_data(yaml_data)
|
45
46
|
when CAP_1_1::Alert::CAP_VERSION
|
46
|
-
CAP_1_1::Alert.from_yaml_data(
|
47
|
+
CAP_1_1::Alert.from_yaml_data(yaml_data)
|
47
48
|
else
|
48
|
-
CAP_1_2::Alert.from_yaml_data(
|
49
|
+
CAP_1_2::Alert.from_yaml_data(yaml_data)
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
@@ -54,10 +55,10 @@ module RCAP
|
|
54
55
|
# CAP 1.0, 1.1 or 1.2 Alert is instantiated accordingly.
|
55
56
|
#
|
56
57
|
# @param [#to_s] json Alert in JSON format
|
57
|
-
# @return [
|
58
|
-
def self.from_json(
|
59
|
-
json_hash = JSON.parse(
|
60
|
-
|
58
|
+
# @return [RCAP::CAP_1_0::Alert, RCAP::CAP_1_1::Alert, RCAP::CAP_1_2::Alert ]
|
59
|
+
def self.from_json(json)
|
60
|
+
json_hash = JSON.parse(json.to_s)
|
61
|
+
from_h(json_hash)
|
61
62
|
end
|
62
63
|
|
63
64
|
# Initialise a RCAP Alert from a Ruby hash produced by
|
@@ -65,15 +66,15 @@ module RCAP
|
|
65
66
|
# CAP 1.0, 1.1 or 1.2 Alert is instantiated accordingly.
|
66
67
|
#
|
67
68
|
# @param [Hash] hash Alert as a Ruby hash.
|
68
|
-
# @return [
|
69
|
-
def self.from_h(
|
70
|
-
case hash[
|
69
|
+
# @return [RCAP::CAP_1_0::Alert, RCAP::CAP_1_1::Alert, RCAP::CAP_1_2::Alert ]
|
70
|
+
def self.from_h(hash)
|
71
|
+
case hash[JSON_CAP_VERSION_KEY]
|
71
72
|
when CAP_1_0::Alert::CAP_VERSION
|
72
|
-
CAP_1_0::Alert.from_h(
|
73
|
+
CAP_1_0::Alert.from_h(hash)
|
73
74
|
when CAP_1_1::Alert::CAP_VERSION
|
74
|
-
CAP_1_1::Alert.from_h(
|
75
|
+
CAP_1_1::Alert.from_h(hash)
|
75
76
|
else
|
76
|
-
CAP_1_2::Alert.from_h(
|
77
|
+
CAP_1_2::Alert.from_h(hash)
|
77
78
|
end
|
78
79
|
end
|
79
80
|
end
|
data/lib/rcap/base/alert.rb
CHANGED
@@ -1,73 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RCAP
|
2
4
|
module Base
|
3
5
|
class Alert
|
4
6
|
include Validation
|
5
7
|
|
6
|
-
STATUS_ACTUAL =
|
7
|
-
STATUS_EXERCISE =
|
8
|
-
STATUS_SYSTEM =
|
9
|
-
STATUS_TEST =
|
8
|
+
STATUS_ACTUAL = 'Actual'
|
9
|
+
STATUS_EXERCISE = 'Exercise'
|
10
|
+
STATUS_SYSTEM = 'System'
|
11
|
+
STATUS_TEST = 'Test'
|
10
12
|
# Valid values for status
|
11
|
-
VALID_STATUSES = [
|
13
|
+
VALID_STATUSES = [STATUS_ACTUAL, STATUS_EXERCISE, STATUS_SYSTEM, STATUS_TEST].freeze
|
12
14
|
|
13
|
-
MSG_TYPE_ALERT =
|
14
|
-
MSG_TYPE_UPDATE =
|
15
|
-
MSG_TYPE_CANCEL =
|
16
|
-
MSG_TYPE_ACK =
|
17
|
-
MSG_TYPE_ERROR =
|
15
|
+
MSG_TYPE_ALERT = 'Alert'
|
16
|
+
MSG_TYPE_UPDATE = 'Update'
|
17
|
+
MSG_TYPE_CANCEL = 'Cancel'
|
18
|
+
MSG_TYPE_ACK = 'Ack'
|
19
|
+
MSG_TYPE_ERROR = 'Error'
|
18
20
|
# Valid values for msg_type
|
19
|
-
VALID_MSG_TYPES = [
|
21
|
+
VALID_MSG_TYPES = [MSG_TYPE_ALERT, MSG_TYPE_UPDATE, MSG_TYPE_CANCEL, MSG_TYPE_ACK, MSG_TYPE_ERROR].freeze
|
20
22
|
|
21
|
-
SCOPE_PUBLIC =
|
22
|
-
SCOPE_RESTRICTED =
|
23
|
-
SCOPE_PRIVATE =
|
23
|
+
SCOPE_PUBLIC = 'Public'
|
24
|
+
SCOPE_RESTRICTED = 'Restricted'
|
25
|
+
SCOPE_PRIVATE = 'Private'
|
24
26
|
# Valid values for scope
|
25
|
-
VALID_SCOPES = [
|
27
|
+
VALID_SCOPES = [SCOPE_PUBLIC, SCOPE_PRIVATE, SCOPE_RESTRICTED].freeze
|
26
28
|
|
27
29
|
# @return [String] If not set a UUID will be set by default on object initialisation
|
28
|
-
attr_accessor(
|
30
|
+
attr_accessor(:identifier)
|
29
31
|
# @return [String]
|
30
|
-
attr_accessor(
|
32
|
+
attr_accessor(:sender)
|
31
33
|
# @return [DateTime] If not set will be time of creation.
|
32
|
-
attr_accessor(
|
34
|
+
attr_accessor(:sent)
|
33
35
|
# @return [String] Can only be one of {VALID_STATUSES}
|
34
|
-
attr_accessor(
|
36
|
+
attr_accessor(:status)
|
35
37
|
# @return [String] Can only be one of {VALID_MSG_TYPES}
|
36
|
-
attr_accessor(
|
38
|
+
attr_accessor(:msg_type)
|
37
39
|
# @return [String] Can only be one of {VALID_SCOPES}
|
38
|
-
attr_accessor(
|
40
|
+
attr_accessor(:scope)
|
39
41
|
# @return [String]
|
40
|
-
attr_accessor(
|
42
|
+
attr_accessor(:source)
|
41
43
|
# @return [String ] Required if scope is {SCOPE_RESTRICTED}
|
42
|
-
attr_accessor(
|
44
|
+
attr_accessor(:restriction)
|
43
45
|
# @return [String]
|
44
|
-
attr_accessor(
|
46
|
+
attr_accessor(:note)
|
45
47
|
|
46
48
|
# @return [Array<String>] Collection of address strings. Depends on scope being {SCOPE_PRIVATE}
|
47
|
-
attr_reader(
|
49
|
+
attr_reader(:addresses)
|
48
50
|
# @return [Array<String>]
|
49
|
-
attr_reader(
|
51
|
+
attr_reader(:codes)
|
50
52
|
# @return [Array<String>] Collection of references to previous alerts
|
51
53
|
# @see #to_reference
|
52
|
-
attr_reader(
|
54
|
+
attr_reader(:references)
|
53
55
|
# @return [Array<String>] Collection of incident strings
|
54
|
-
attr_reader(
|
56
|
+
attr_reader(:incidents)
|
55
57
|
# @return [Array<Info>]
|
56
|
-
attr_reader(
|
58
|
+
attr_reader(:infos)
|
57
59
|
|
58
|
-
validates_presence_of(
|
60
|
+
validates_presence_of(:identifier, :sender, :sent, :status, :msg_type, :scope)
|
59
61
|
|
60
|
-
validates_inclusion_of(
|
61
|
-
validates_inclusion_of(
|
62
|
-
validates_inclusion_of(
|
62
|
+
validates_inclusion_of(:status, in: VALID_STATUSES)
|
63
|
+
validates_inclusion_of(:msg_type, in: VALID_MSG_TYPES)
|
64
|
+
validates_inclusion_of(:scope, in: VALID_SCOPES)
|
63
65
|
|
64
|
-
validates_format_of(
|
65
|
-
validates_format_of(
|
66
|
+
validates_format_of(:identifier, with: ALLOWED_CHARACTERS)
|
67
|
+
validates_format_of(:sender, with: ALLOWED_CHARACTERS)
|
66
68
|
|
67
|
-
validates_conditional_presence_of(
|
68
|
-
validates_conditional_presence_of(
|
69
|
+
validates_conditional_presence_of(:addresses, when: :scope, is: SCOPE_PRIVATE)
|
70
|
+
validates_conditional_presence_of(:restriction, when: :scope, is: SCOPE_RESTRICTED)
|
69
71
|
|
70
|
-
validates_collection_of(
|
72
|
+
validates_collection_of(:infos)
|
71
73
|
|
72
74
|
# Initialises a new Alert object. Yields the initialised alert to a block.
|
73
75
|
#
|
@@ -87,7 +89,7 @@ module RCAP
|
|
87
89
|
@references = []
|
88
90
|
@incidents = []
|
89
91
|
@infos = []
|
90
|
-
yield(
|
92
|
+
yield(self) if block_given?
|
91
93
|
end
|
92
94
|
|
93
95
|
# Creates a new {Info} object and adds it to the {#infos} array.
|
@@ -96,8 +98,8 @@ module RCAP
|
|
96
98
|
# @yield [Info] The newly initialised Info object.
|
97
99
|
# @return [Info] The initialised Info object after being yielded to the block
|
98
100
|
def add_info
|
99
|
-
|
100
|
-
yield(
|
101
|
+
info_class.new.tap do |info|
|
102
|
+
yield(info) if block_given?
|
101
103
|
@infos << info
|
102
104
|
end
|
103
105
|
end
|
@@ -119,31 +121,31 @@ module RCAP
|
|
119
121
|
|
120
122
|
# @return [REXML::Element]
|
121
123
|
def to_xml_element
|
122
|
-
xml_element = REXML::Element.new(
|
123
|
-
xml_element.add_namespace(
|
124
|
-
xml_element.add_element(
|
125
|
-
xml_element.add_element(
|
126
|
-
xml_element.add_element(
|
127
|
-
xml_element.add_element(
|
128
|
-
xml_element.add_element(
|
129
|
-
xml_element.add_element(
|
130
|
-
xml_element.add_element(
|
131
|
-
xml_element.add_element(
|
124
|
+
xml_element = REXML::Element.new(XML_ELEMENT_NAME)
|
125
|
+
xml_element.add_namespace(self.class::XMLNS)
|
126
|
+
xml_element.add_element(IDENTIFIER_ELEMENT_NAME).add_text(@identifier) if @identifier
|
127
|
+
xml_element.add_element(SENDER_ELEMENT_NAME).add_text(@sender) if @sender
|
128
|
+
xml_element.add_element(SENT_ELEMENT_NAME).add_text(@sent.to_s_for_cap) if @sent
|
129
|
+
xml_element.add_element(STATUS_ELEMENT_NAME).add_text(@status) if @status
|
130
|
+
xml_element.add_element(MSG_TYPE_ELEMENT_NAME).add_text(@msg_type) if @msg_type
|
131
|
+
xml_element.add_element(SOURCE_ELEMENT_NAME).add_text(@source) if @source
|
132
|
+
xml_element.add_element(SCOPE_ELEMENT_NAME).add_text(@scope) if @scope
|
133
|
+
xml_element.add_element(RESTRICTION_ELEMENT_NAME).add_text(@restriction) if @restriction
|
132
134
|
if @addresses.any?
|
133
|
-
xml_element.add_element(
|
135
|
+
xml_element.add_element(ADDRESSES_ELEMENT_NAME).add_text(@addresses.to_s_for_cap)
|
134
136
|
end
|
135
137
|
@codes.each do |code|
|
136
|
-
xml_element.add_element(
|
138
|
+
xml_element.add_element(CODE_ELEMENT_NAME).add_text(code)
|
137
139
|
end
|
138
|
-
xml_element.add_element(
|
140
|
+
xml_element.add_element(NOTE_ELEMENT_NAME).add_text(@note) if @note
|
139
141
|
if @references.any?
|
140
|
-
xml_element.add_element(
|
142
|
+
xml_element.add_element(REFERENCES_ELEMENT_NAME).add_text(@references.join(' '))
|
141
143
|
end
|
142
144
|
if @incidents.any?
|
143
|
-
xml_element.add_element(
|
145
|
+
xml_element.add_element(INCIDENTS_ELEMENT_NAME).add_text(@incidents.join(' '))
|
144
146
|
end
|
145
147
|
@infos.each do |info|
|
146
|
-
xml_element.add_element(
|
148
|
+
xml_element.add_element(info.to_xml_element)
|
147
149
|
end
|
148
150
|
xml_element
|
149
151
|
end
|
@@ -151,8 +153,8 @@ module RCAP
|
|
151
153
|
# @return [REXML::Document]
|
152
154
|
def to_xml_document
|
153
155
|
xml_document = REXML::Document.new
|
154
|
-
xml_document.add(
|
155
|
-
xml_document.add(
|
156
|
+
xml_document.add(REXML::XMLDecl.new)
|
157
|
+
xml_document.add(to_xml_element)
|
156
158
|
xml_document
|
157
159
|
end
|
158
160
|
|
@@ -160,13 +162,13 @@ module RCAP
|
|
160
162
|
#
|
161
163
|
# @param [true,false] pretty_print Pretty print output
|
162
164
|
# @return [String]
|
163
|
-
def to_xml(
|
165
|
+
def to_xml(pretty_print = false)
|
164
166
|
if pretty_print
|
165
|
-
xml_document =
|
166
|
-
RCAP::XML_PRETTY_PRINTER.write(
|
167
|
+
xml_document = +''
|
168
|
+
RCAP::XML_PRETTY_PRINTER.write(to_xml_document, xml_document)
|
167
169
|
xml_document
|
168
170
|
else
|
169
|
-
|
171
|
+
to_xml_document.to_s
|
170
172
|
end
|
171
173
|
end
|
172
174
|
|
@@ -175,29 +177,30 @@ module RCAP
|
|
175
177
|
#
|
176
178
|
# @return [String]
|
177
179
|
def to_reference
|
178
|
-
"#{
|
180
|
+
"#{@sender},#{@identifier},#{RCAP.to_s_for_cap(@sent)}"
|
179
181
|
end
|
180
182
|
|
181
183
|
# @return [String]
|
182
184
|
def inspect
|
183
|
-
alert_inspect = [
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
185
|
+
alert_inspect = ["CAP Version: #{self.class::CAP_VERSION}",
|
186
|
+
"Identifier: #{@identifier}",
|
187
|
+
"Sender: #{@sender}",
|
188
|
+
"Sent: #{@sent}",
|
189
|
+
"Status: #{@status}",
|
190
|
+
"Message Type: #{@msg_type}",
|
191
|
+
"Source: #{@source}",
|
192
|
+
"Scope: #{@scope}",
|
193
|
+
"Restriction: #{@restriction}",
|
194
|
+
"Addresses: #{@addresses.to_s_for_cap}",
|
195
|
+
'Codes:',
|
196
|
+
@codes.map { |code| ' ' + code }.join("\n") + '',
|
197
|
+
"Note: #{@note}",
|
198
|
+
'References:',
|
199
|
+
@references.join("\n "),
|
200
|
+
"Incidents: #{@incidents.join(' ')}",
|
201
|
+
'Information:',
|
202
|
+
@infos.map { |info| ' ' + info.to_s }.join("\n")].join("\n")
|
203
|
+
RCAP.format_lines_for_inspect('ALERT', alert_inspect)
|
201
204
|
end
|
202
205
|
|
203
206
|
# Returns a string representation of the alert of the form
|
@@ -206,149 +209,149 @@ module RCAP
|
|
206
209
|
#
|
207
210
|
# @return [String]
|
208
211
|
def to_s
|
209
|
-
"#{
|
212
|
+
"#{@sender}/#{@identifier}/#{RCAP.to_s_for_cap(@sent)}"
|
210
213
|
end
|
211
214
|
|
212
215
|
XPATH = 'cap:alert'
|
213
|
-
IDENTIFIER_XPATH = "cap:#{
|
214
|
-
SENDER_XPATH = "cap:#{
|
215
|
-
SENT_XPATH = "cap:#{
|
216
|
-
STATUS_XPATH = "cap:#{
|
217
|
-
MSG_TYPE_XPATH = "cap:#{
|
218
|
-
SOURCE_XPATH = "cap:#{
|
219
|
-
SCOPE_XPATH = "cap:#{
|
220
|
-
RESTRICTION_XPATH = "cap:#{
|
221
|
-
ADDRESSES_XPATH = "cap:#{
|
222
|
-
CODE_XPATH = "cap:#{
|
223
|
-
NOTE_XPATH = "cap:#{
|
224
|
-
REFERENCES_XPATH = "cap:#{
|
225
|
-
INCIDENTS_XPATH = "cap:#{
|
216
|
+
IDENTIFIER_XPATH = "cap:#{IDENTIFIER_ELEMENT_NAME}"
|
217
|
+
SENDER_XPATH = "cap:#{SENDER_ELEMENT_NAME}"
|
218
|
+
SENT_XPATH = "cap:#{SENT_ELEMENT_NAME}"
|
219
|
+
STATUS_XPATH = "cap:#{STATUS_ELEMENT_NAME}"
|
220
|
+
MSG_TYPE_XPATH = "cap:#{MSG_TYPE_ELEMENT_NAME}"
|
221
|
+
SOURCE_XPATH = "cap:#{SOURCE_ELEMENT_NAME}"
|
222
|
+
SCOPE_XPATH = "cap:#{SCOPE_ELEMENT_NAME}"
|
223
|
+
RESTRICTION_XPATH = "cap:#{RESTRICTION_ELEMENT_NAME}"
|
224
|
+
ADDRESSES_XPATH = "cap:#{ADDRESSES_ELEMENT_NAME}"
|
225
|
+
CODE_XPATH = "cap:#{CODE_ELEMENT_NAME}"
|
226
|
+
NOTE_XPATH = "cap:#{NOTE_ELEMENT_NAME}"
|
227
|
+
REFERENCES_XPATH = "cap:#{REFERENCES_ELEMENT_NAME}"
|
228
|
+
INCIDENTS_XPATH = "cap:#{INCIDENTS_ELEMENT_NAME}"
|
226
229
|
|
227
230
|
# @param [REXML::Element] alert_xml_element
|
228
231
|
# @return [RCAP::CAP_1_0::Alert]
|
229
|
-
def self.from_xml_element(
|
230
|
-
|
231
|
-
alert.identifier = RCAP.xpath_text(
|
232
|
-
alert.sender = RCAP.xpath_text(
|
233
|
-
alert.sent = RCAP.parse_datetime(
|
234
|
-
alert.status = RCAP.xpath_text(
|
235
|
-
alert.msg_type = RCAP.xpath_text(
|
236
|
-
alert.source = RCAP.xpath_text(
|
237
|
-
alert.scope = RCAP.xpath_text(
|
238
|
-
alert.restriction = RCAP.xpath_text(
|
239
|
-
|
240
|
-
RCAP.unpack_if_given(
|
232
|
+
def self.from_xml_element(alert_xml_element)
|
233
|
+
new do |alert|
|
234
|
+
alert.identifier = RCAP.xpath_text(alert_xml_element, IDENTIFIER_XPATH, alert.xmlns)
|
235
|
+
alert.sender = RCAP.xpath_text(alert_xml_element, SENDER_XPATH, alert.xmlns)
|
236
|
+
alert.sent = RCAP.parse_datetime(RCAP.xpath_text(alert_xml_element, SENT_XPATH, alert.xmlns))
|
237
|
+
alert.status = RCAP.xpath_text(alert_xml_element, STATUS_XPATH, alert.xmlns)
|
238
|
+
alert.msg_type = RCAP.xpath_text(alert_xml_element, MSG_TYPE_XPATH, alert.xmlns)
|
239
|
+
alert.source = RCAP.xpath_text(alert_xml_element, SOURCE_XPATH, alert.xmlns)
|
240
|
+
alert.scope = RCAP.xpath_text(alert_xml_element, SCOPE_XPATH, alert.xmlns)
|
241
|
+
alert.restriction = RCAP.xpath_text(alert_xml_element, RESTRICTION_XPATH, alert.xmlns)
|
242
|
+
|
243
|
+
RCAP.unpack_if_given(RCAP.xpath_text(alert_xml_element, ADDRESSES_XPATH, alert.xmlns)).each do |address|
|
241
244
|
alert.addresses << address.strip
|
242
245
|
end
|
243
246
|
|
244
|
-
RCAP.xpath_match(
|
247
|
+
RCAP.xpath_match(alert_xml_element, CODE_XPATH, alert.xmlns).each do |element|
|
245
248
|
alert.codes << element.text.strip
|
246
249
|
end
|
247
250
|
|
248
|
-
alert.note = RCAP.xpath_text(
|
251
|
+
alert.note = RCAP.xpath_text(alert_xml_element, NOTE_XPATH, alert.xmlns)
|
249
252
|
|
250
|
-
RCAP.unpack_if_given(
|
253
|
+
RCAP.unpack_if_given(RCAP.xpath_text(alert_xml_element, REFERENCES_XPATH, alert.xmlns)).each do |reference|
|
251
254
|
alert.references << reference.strip
|
252
255
|
end
|
253
256
|
|
254
|
-
RCAP.unpack_if_given(
|
257
|
+
RCAP.unpack_if_given(RCAP.xpath_text(alert_xml_element, INCIDENTS_XPATH, alert.xmlns)).each do |incident|
|
255
258
|
alert.incidents << incident.strip
|
256
259
|
end
|
257
260
|
|
258
|
-
RCAP.xpath_match(
|
259
|
-
alert.infos << alert.info_class.from_xml_element(
|
261
|
+
RCAP.xpath_match(alert_xml_element, Info::XPATH, alert.xmlns).each do |element|
|
262
|
+
alert.infos << alert.info_class.from_xml_element(element)
|
260
263
|
end
|
261
264
|
end
|
262
265
|
end
|
263
266
|
|
264
267
|
# @param [REXML::Document] xml_document
|
265
268
|
# @return [Alert]
|
266
|
-
def self.from_xml_document(
|
267
|
-
|
269
|
+
def self.from_xml_document(xml_document)
|
270
|
+
from_xml_element(xml_document.root)
|
268
271
|
end
|
269
272
|
|
270
273
|
# Initialise an Alert object from an XML string. Any object that is a subclass of IO (e.g. File) can be passed in.
|
271
274
|
#
|
272
275
|
# @param [String] xml
|
273
276
|
# @return [Alert]
|
274
|
-
def self.from_xml(
|
275
|
-
|
277
|
+
def self.from_xml(xml)
|
278
|
+
from_xml_document(REXML::Document.new(xml))
|
276
279
|
end
|
277
280
|
|
278
|
-
CAP_VERSION_YAML =
|
279
|
-
IDENTIFIER_YAML =
|
280
|
-
SENDER_YAML =
|
281
|
-
SENT_YAML =
|
282
|
-
STATUS_YAML =
|
283
|
-
MSG_TYPE_YAML =
|
284
|
-
SOURCE_YAML =
|
285
|
-
SCOPE_YAML =
|
286
|
-
RESTRICTION_YAML =
|
287
|
-
ADDRESSES_YAML =
|
288
|
-
CODES_YAML =
|
289
|
-
NOTE_YAML =
|
290
|
-
REFERENCES_YAML =
|
291
|
-
INCIDENTS_YAML =
|
292
|
-
INFOS_YAML =
|
281
|
+
CAP_VERSION_YAML = 'CAP Version'
|
282
|
+
IDENTIFIER_YAML = 'Identifier'
|
283
|
+
SENDER_YAML = 'Sender'
|
284
|
+
SENT_YAML = 'Sent'
|
285
|
+
STATUS_YAML = 'Status'
|
286
|
+
MSG_TYPE_YAML = 'Message Type'
|
287
|
+
SOURCE_YAML = 'Source'
|
288
|
+
SCOPE_YAML = 'Scope'
|
289
|
+
RESTRICTION_YAML = 'Restriction'
|
290
|
+
ADDRESSES_YAML = 'Addresses'
|
291
|
+
CODES_YAML = 'Codes'
|
292
|
+
NOTE_YAML = 'Note'
|
293
|
+
REFERENCES_YAML = 'References'
|
294
|
+
INCIDENTS_YAML = 'Incidents'
|
295
|
+
INFOS_YAML = 'Information'
|
293
296
|
|
294
297
|
# Returns a string containing the YAML representation of the alert.
|
295
298
|
#
|
296
299
|
# @return [String]
|
297
|
-
def to_yaml(
|
298
|
-
RCAP.attribute_values_to_hash(
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
300
|
+
def to_yaml(options = {})
|
301
|
+
RCAP.attribute_values_to_hash([CAP_VERSION_YAML, self.class::CAP_VERSION],
|
302
|
+
[IDENTIFIER_YAML, @identifier],
|
303
|
+
[SENDER_YAML, @sender],
|
304
|
+
[SENT_YAML, @sent],
|
305
|
+
[STATUS_YAML, @status],
|
306
|
+
[MSG_TYPE_YAML, @msg_type],
|
307
|
+
[SOURCE_YAML, @source],
|
308
|
+
[SCOPE_YAML, @scope],
|
309
|
+
[RESTRICTION_YAML, @restriction],
|
310
|
+
[ADDRESSES_YAML, @addresses],
|
311
|
+
[CODES_YAML, @codes],
|
312
|
+
[NOTE_YAML, @note],
|
313
|
+
[REFERENCES_YAML, @references],
|
314
|
+
[INCIDENTS_YAML, @incidents],
|
315
|
+
[INFOS_YAML, @infos.map(&:to_yaml_data)]).to_yaml(options)
|
313
316
|
end
|
314
317
|
|
315
318
|
# Initialise an Alert object from a YAML string. Any object that is a subclass of IO (e.g. File) can be passed in.
|
316
319
|
#
|
317
320
|
# @param [String] yaml
|
318
321
|
# @return [Alert]
|
319
|
-
def self.from_yaml(
|
320
|
-
|
322
|
+
def self.from_yaml(yaml)
|
323
|
+
from_yaml_data(YAML.safe_load(yaml, [Time, DateTime]))
|
321
324
|
end
|
322
325
|
|
323
326
|
# Initialise an Alert object from a hash reutrned from YAML.load.
|
324
327
|
#
|
325
328
|
# @param [hash] alert_yaml_data
|
326
329
|
# @return [Alert]
|
327
|
-
def self.from_yaml_data(
|
328
|
-
|
329
|
-
alert.identifier = RCAP.strip_if_given(
|
330
|
-
alert.sender = RCAP.strip_if_given(
|
331
|
-
alert.sent = RCAP.parse_datetime(
|
332
|
-
alert.status = RCAP.strip_if_given(
|
333
|
-
alert.msg_type = RCAP.strip_if_given(
|
334
|
-
alert.source = RCAP.strip_if_given(
|
335
|
-
alert.scope = RCAP.strip_if_given(
|
336
|
-
alert.restriction = RCAP.strip_if_given(
|
337
|
-
Array(
|
330
|
+
def self.from_yaml_data(alert_yaml_data)
|
331
|
+
new do |alert|
|
332
|
+
alert.identifier = RCAP.strip_if_given(alert_yaml_data[IDENTIFIER_YAML])
|
333
|
+
alert.sender = RCAP.strip_if_given(alert_yaml_data[SENDER_YAML])
|
334
|
+
alert.sent = RCAP.parse_datetime(alert_yaml_data[SENT_YAML])
|
335
|
+
alert.status = RCAP.strip_if_given(alert_yaml_data[STATUS_YAML])
|
336
|
+
alert.msg_type = RCAP.strip_if_given(alert_yaml_data[MSG_TYPE_YAML])
|
337
|
+
alert.source = RCAP.strip_if_given(alert_yaml_data[SOURCE_YAML])
|
338
|
+
alert.scope = RCAP.strip_if_given(alert_yaml_data[SCOPE_YAML])
|
339
|
+
alert.restriction = RCAP.strip_if_given(alert_yaml_data[RESTRICTION_YAML])
|
340
|
+
Array(alert_yaml_data[ADDRESSES_YAML]).each do |address|
|
338
341
|
alert.addresses << address.strip
|
339
342
|
end
|
340
|
-
Array(
|
343
|
+
Array(alert_yaml_data[CODES_YAML]).each do |code|
|
341
344
|
alert.codes << code.strip
|
342
345
|
end
|
343
|
-
alert.note
|
344
|
-
Array(
|
346
|
+
alert.note = alert_yaml_data[NOTE_YAML]
|
347
|
+
Array(alert_yaml_data[REFERENCES_YAML]).each do |reference|
|
345
348
|
alert.references << reference.strip
|
346
349
|
end
|
347
|
-
Array(
|
350
|
+
Array(alert_yaml_data[INCIDENTS_YAML]).each do |incident|
|
348
351
|
alert.incidents << incident.strip
|
349
352
|
end
|
350
|
-
Array(
|
351
|
-
alert.infos << alert.info_class.from_yaml_data(
|
353
|
+
Array(alert_yaml_data[INFOS_YAML]).each do |info_yaml_data|
|
354
|
+
alert.infos << alert.info_class.from_yaml_data(info_yaml_data)
|
352
355
|
end
|
353
356
|
end
|
354
357
|
end
|
@@ -373,54 +376,54 @@ module RCAP
|
|
373
376
|
#
|
374
377
|
# @return [Hash]
|
375
378
|
def to_h
|
376
|
-
RCAP.attribute_values_to_hash(
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
379
|
+
RCAP.attribute_values_to_hash([CAP_VERSION_KEY, self.class::CAP_VERSION],
|
380
|
+
[IDENTIFIER_KEY, @identifier],
|
381
|
+
[SENDER_KEY, @sender],
|
382
|
+
[SENT_KEY, RCAP.to_s_for_cap(@sent)],
|
383
|
+
[STATUS_KEY, @status],
|
384
|
+
[MSG_TYPE_KEY, @msg_type],
|
385
|
+
[SOURCE_KEY, @source],
|
386
|
+
[SCOPE_KEY, @scope],
|
387
|
+
[RESTRICTION_KEY, @restriction],
|
388
|
+
[ADDRESSES_KEY, @addresses],
|
389
|
+
[CODES_KEY, @codes],
|
390
|
+
[NOTE_KEY, @note],
|
391
|
+
[REFERENCES_KEY, @references],
|
392
|
+
[INCIDENTS_KEY, @incidents],
|
393
|
+
[INFOS_KEY, @infos.map(&:to_h)])
|
391
394
|
end
|
392
395
|
|
393
396
|
# Initialises an Alert object from a Hash produced by Alert#to_h
|
394
397
|
#
|
395
398
|
# @param [Hash] alert_hash
|
396
399
|
# @return [RCAP::CAP_1_0::Alert]
|
397
|
-
def self.from_h(
|
398
|
-
|
399
|
-
alert.identifier = RCAP.strip_if_given(
|
400
|
-
alert.sender = RCAP.strip_if_given(
|
401
|
-
alert.sent = RCAP.parse_datetime(
|
402
|
-
alert.status = RCAP.strip_if_given(
|
403
|
-
alert.msg_type = RCAP.strip_if_given(
|
404
|
-
alert.source = RCAP.strip_if_given(
|
405
|
-
alert.scope = RCAP.strip_if_given(
|
406
|
-
alert.restriction = RCAP.strip_if_given(
|
407
|
-
Array(
|
400
|
+
def self.from_h(alert_hash)
|
401
|
+
new do |alert|
|
402
|
+
alert.identifier = RCAP.strip_if_given(alert_hash[IDENTIFIER_KEY])
|
403
|
+
alert.sender = RCAP.strip_if_given(alert_hash[SENDER_KEY])
|
404
|
+
alert.sent = RCAP.parse_datetime(alert_hash[SENT_KEY])
|
405
|
+
alert.status = RCAP.strip_if_given(alert_hash[STATUS_KEY])
|
406
|
+
alert.msg_type = RCAP.strip_if_given(alert_hash[MSG_TYPE_KEY])
|
407
|
+
alert.source = RCAP.strip_if_given(alert_hash[SOURCE_KEY])
|
408
|
+
alert.scope = RCAP.strip_if_given(alert_hash[SCOPE_KEY])
|
409
|
+
alert.restriction = RCAP.strip_if_given(alert_hash[RESTRICTION_KEY])
|
410
|
+
Array(alert_hash[ADDRESSES_KEY]).each do |address|
|
408
411
|
alert.addresses << address.strip
|
409
412
|
end
|
410
|
-
Array(
|
413
|
+
Array(alert_hash[CODES_KEY]).each do |code|
|
411
414
|
alert.codes << code.strip
|
412
415
|
end
|
413
|
-
alert.note = alert_hash[
|
414
|
-
Array(
|
416
|
+
alert.note = alert_hash[NOTE_KEY]
|
417
|
+
Array(alert_hash[REFERENCES_KEY]).each do |reference|
|
415
418
|
alert.references << reference.strip
|
416
419
|
end
|
417
420
|
|
418
|
-
Array(
|
421
|
+
Array(alert_hash[INCIDENTS_KEY]).each do |incident|
|
419
422
|
alert.incidents << incident.strip
|
420
423
|
end
|
421
424
|
|
422
|
-
Array(
|
423
|
-
alert.infos << alert.info_class.from_h(
|
425
|
+
Array(alert_hash[INFOS_KEY]).each do |info_hash|
|
426
|
+
alert.infos << alert.info_class.from_h(info_hash)
|
424
427
|
end
|
425
428
|
end
|
426
429
|
end
|
@@ -429,11 +432,11 @@ module RCAP
|
|
429
432
|
#
|
430
433
|
# @param [true,false] pretty_print
|
431
434
|
# @return [String]
|
432
|
-
def to_json(
|
435
|
+
def to_json(pretty_print = false)
|
433
436
|
if pretty_print
|
434
|
-
JSON.pretty_generate(
|
437
|
+
JSON.pretty_generate(to_h)
|
435
438
|
else
|
436
|
-
|
439
|
+
to_h.to_json
|
437
440
|
end
|
438
441
|
end
|
439
442
|
|
@@ -441,8 +444,8 @@ module RCAP
|
|
441
444
|
#
|
442
445
|
# @param [String] json_string
|
443
446
|
# @return [Alert]
|
444
|
-
def self.from_json(
|
445
|
-
|
447
|
+
def self.from_json(json_string)
|
448
|
+
from_h(JSON.parse(json_string))
|
446
449
|
end
|
447
450
|
end
|
448
451
|
end
|