rcap 0.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 +2 -0
- data/README +151 -0
- data/lib/rcap.rb +21 -0
- data/lib/rcap/alert.rb +186 -0
- data/lib/rcap/area.rb +82 -0
- data/lib/rcap/circle.rb +62 -0
- data/lib/rcap/event_code.rb +20 -0
- data/lib/rcap/geocode.rb +20 -0
- data/lib/rcap/info.rb +239 -0
- data/lib/rcap/parameter.rb +54 -0
- data/lib/rcap/point.rb +39 -0
- data/lib/rcap/polygon.rb +50 -0
- data/lib/rcap/resource.rb +81 -0
- data/lib/rcap/utilities.rb +50 -0
- data/lib/rcap/validations.rb +116 -0
- data/spec/alert_spec.rb +132 -0
- data/spec/area_spec.rb +120 -0
- data/spec/circle_spec.rb +59 -0
- data/spec/geocode_spec.rb +26 -0
- data/spec/info_spec.rb +119 -0
- data/spec/point_spec.rb +34 -0
- data/spec/polygon_spec.rb +45 -0
- data/spec/resource_spec.rb +74 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/utilities_spec.rb +57 -0
- data/spec/validations_spec.rb +95 -0
- metadata +99 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
module RCAP
|
2
|
+
class EventCode < Parameter
|
3
|
+
|
4
|
+
XML_ELEMENT_NAME = 'eventCode' # :nodoc:
|
5
|
+
|
6
|
+
XPATH = "cap:#{ XML_ELEMENT_NAME }" # :nodoc:
|
7
|
+
|
8
|
+
def to_xml_element # :nodoc:
|
9
|
+
xml_element = REXML::Element.new( XML_ELEMENT_NAME )
|
10
|
+
xml_element.add_element( NAME_ELEMENT_NAME ).add_text( self.name )
|
11
|
+
xml_element.add_element( VALUE_ELEMENT_NAME ).add_text( self.value )
|
12
|
+
xml_element
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.from_xml_element( event_code_xml_element ) # :nodoc:
|
16
|
+
EventCode.new( :name => RCAP.xpath_text( event_code_xml_element, NAME_XPATH ),
|
17
|
+
:value => RCAP.xpath_text( event_code_xml_element, VALUE_XPATH ))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/rcap/geocode.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module RCAP
|
2
|
+
class Geocode < Parameter
|
3
|
+
|
4
|
+
XML_ELEMENT_NAME = 'geocode' # :nodoc:
|
5
|
+
|
6
|
+
XPATH = "cap:#{ XML_ELEMENT_NAME }" # :nodoc:
|
7
|
+
|
8
|
+
def to_xml_element # :nodoc:
|
9
|
+
xml_element = REXML::Element.new( XML_ELEMENT_NAME )
|
10
|
+
xml_element.add_element( NAME_ELEMENT_NAME ).add_text( @name )
|
11
|
+
xml_element.add_element( VALUE_ELEMENT_NAME ).add_text( @value )
|
12
|
+
xml_element
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.from_xml_element( geocode_xml_element ) # :nodoc:
|
16
|
+
self.new( :name => RCAP.xpath_text( geocode_xml_element, NAME_XPATH ),
|
17
|
+
:value => RCAP.xpath_text( geocode_xml_element, VALUE_XPATH ))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/rcap/info.rb
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
module RCAP
|
2
|
+
# In Info object is valid if
|
3
|
+
# * it has an event
|
4
|
+
# * it has an urgency with a valid value
|
5
|
+
# * it has a severity with a valid value
|
6
|
+
# * it has a certainty with a valid value
|
7
|
+
# * all categories are valid and categories has at minimum 1 entry
|
8
|
+
# * all Resource objects in the resources collection are valid
|
9
|
+
# * all Area objects in the areas collection are valid
|
10
|
+
#
|
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
|
+
ALL_CATEGORIES = [ CATEGORY_GEO, CATEGORY_MET, CATEGORY_SAFETY,
|
27
|
+
CATEGORY_SECURITY, CATEGORY_RESCUE, CATEGORY_FIRE, CATEGORY_HEALTH,
|
28
|
+
CATEGORY_ENV, CATEGORY_TRANSPORT, CATEGORY_INFRA, CATEGORY_CBRNE,
|
29
|
+
CATEGORY_OTHER ] # :nodoc:
|
30
|
+
|
31
|
+
RESPONSE_TYPE_SHELTER = "Shelter"
|
32
|
+
RESPONSE_TYPE_EVACUATE = "Evacuate"
|
33
|
+
RESPONSE_TYPE_PREPARE = "Prepare"
|
34
|
+
RESPONSE_TYPE_EXECUTE = "Execute"
|
35
|
+
RESPONSE_TYPE_MONITOR = "Monitor"
|
36
|
+
RESPONSE_TYPE_ASSESS = "Assess"
|
37
|
+
RESPONSE_TYPE_NONE = "None"
|
38
|
+
ALL_RESPONSE_TYPES = [ RESPONSE_TYPE_SHELTER, RESPONSE_TYPE_EVACUATE,
|
39
|
+
RESPONSE_TYPE_PREPARE, RESPONSE_TYPE_EXECUTE, RESPONSE_TYPE_MONITOR,
|
40
|
+
RESPONSE_TYPE_ASSESS, RESPONSE_TYPE_NONE ] # :nodoc:
|
41
|
+
|
42
|
+
URGENCY_IMMEDIATE = "Immediate"
|
43
|
+
URGENCY_EXPECTED = "Expected"
|
44
|
+
URGENCY_FUTURE = "Future"
|
45
|
+
URGENCY_PAST = "Past"
|
46
|
+
URGENCY_UNKNOWN = "Unknown"
|
47
|
+
ALL_URGENCIES = [ URGENCY_IMMEDIATE, URGENCY_EXPECTED, URGENCY_FUTURE,
|
48
|
+
URGENCY_PAST, URGENCY_UNKNOWN ] # :nodoc:
|
49
|
+
|
50
|
+
SEVERITY_EXTREME = "Extreme"
|
51
|
+
SEVERITY_SEVERE = "Severe"
|
52
|
+
SEVERITY_MODERATE = "Moderate"
|
53
|
+
SEVERITY_MINOR = "Minor"
|
54
|
+
SEVERITY_UNKNOWN = "Unknown"
|
55
|
+
ALL_SEVERITIES = [ SEVERITY_EXTREME, SEVERITY_SEVERE, SEVERITY_MODERATE,
|
56
|
+
SEVERITY_MINOR, SEVERITY_UNKNOWN ] # :nodoc:
|
57
|
+
|
58
|
+
CERTAINTY_OBSERVED = "Observed"
|
59
|
+
CERTAINTY_LIKELY = "Likely"
|
60
|
+
CERTAINTY_POSSIBLE = "Possible"
|
61
|
+
CERTAINTY_UNLIKELY = "Unlikely"
|
62
|
+
CERTAINTY_UNKNOWN = "Unknown"
|
63
|
+
ALL_CERTAINTIES = [ CERTAINTY_OBSERVED, CERTAINTY_LIKELY,
|
64
|
+
CERTAINTY_POSSIBLE, CERTAINTY_UNLIKELY, CERTAINTY_UNKNOWN ] # :nodoc:
|
65
|
+
|
66
|
+
XML_ELEMENT_NAME = 'info' # :nodoc:
|
67
|
+
LANGUAGE_ELEMENT_NAME = 'language' # :nodoc:
|
68
|
+
CATEGORY_ELEMENT_NAME = 'category' # :nodoc:
|
69
|
+
EVENT_ELEMENT_NAME = 'event' # :nodoc:
|
70
|
+
RESPONSE_TYPE_ELEMENT_NAME = 'responseType' # :nodoc:
|
71
|
+
URGENCY_ELEMENT_NAME = 'urgency' # :nodoc:
|
72
|
+
SEVERITY_ELEMENT_NAME = 'severity' # :nodoc:
|
73
|
+
CERTAINTY_ELEMENT_NAME = 'certainty' # :nodoc:
|
74
|
+
AUDIENCE_ELEMENT_NAME = 'audience' # :nodoc:
|
75
|
+
EVENT_CODE_ELEMENT_NAME = 'eventCode' # :nodoc:
|
76
|
+
EFFECTIVE_ELEMENT_NAME = 'effective' # :nodoc:
|
77
|
+
ONSET_ELEMENT_NAME = 'onset' # :nodoc:
|
78
|
+
EXPIRES_ELEMENT_NAME = 'expires' # :nodoc:
|
79
|
+
SENDER_NAME_ELEMENT_NAME = 'sernderName' # :nodoc:
|
80
|
+
HEADLINE_ELEMENT_NAME = 'headline' # :nodoc:
|
81
|
+
DESCRIPTION_ELEMENT_NAME = 'description' # :nodoc:
|
82
|
+
INSTRUCTION_ELEMENT_NAME = 'instruction' # :nodoc:
|
83
|
+
WEB_ELEMENT_NAME = 'web' # :nodoc:
|
84
|
+
CONTACT_ELEMENT_NAME = 'contact' # :nodoc:
|
85
|
+
|
86
|
+
XPATH = "cap:#{ XML_ELEMENT_NAME }" # :nodoc:
|
87
|
+
LANGUAGE_XPATH = "cap:#{ LANGUAGE_ELEMENT_NAME }" # :nodoc:
|
88
|
+
EVENT_XPATH = "cap:#{ EVENT_ELEMENT_NAME }" # :nodoc:
|
89
|
+
URGENCY_XPATH = "cap:#{ URGENCY_ELEMENT_NAME }" # :nodoc:
|
90
|
+
RESPONSE_TYPE_XPATH = "cap:#{ RESPONSE_TYPE_ELEMENT_NAME }" # :nodoc:
|
91
|
+
CATEGORY_XPATH = "cap:#{ CATEGORY_ELEMENT_NAME }" # :nodoc:
|
92
|
+
SEVERITY_XPATH = "cap:#{ SEVERITY_ELEMENT_NAME }" # :nodoc:
|
93
|
+
CERTAINTY_XPATH = "cap:#{ CERTAINTY_ELEMENT_NAME }" # :nodoc:
|
94
|
+
AUDIENCE_XPATH = "cap:#{ AUDIENCE_ELEMENT_NAME }" # :nodoc:
|
95
|
+
EVENT_CODE_XPATH = "cap:#{ EVENT_CODE_ELEMENT_NAME }" # :nodoc:
|
96
|
+
EFFECTIVE_XPATH = "cap:#{ EFFECTIVE_ELEMENT_NAME }" # :nodoc:
|
97
|
+
ONSET_XPATH = "cap:#{ ONSET_ELEMENT_NAME }" # :nodoc:
|
98
|
+
EXPIRES_XPATH = "cap:#{ EXPIRES_ELEMENT_NAME }" # :nodoc:
|
99
|
+
SENDER_NAME_XPATH = "cap:#{ SENDER_NAME_ELEMENT_NAME }" # :nodoc:
|
100
|
+
HEADLINE_XPATH = "cap:#{ HEADLINE_ELEMENT_NAME }" # :nodoc:
|
101
|
+
DESCRIPTION_XPATH = "cap:#{ DESCRIPTION_ELEMENT_NAME }" # :nodoc:
|
102
|
+
INSTRUCTION_XPATH = "cap:#{ INSTRUCTION_ELEMENT_NAME }" # :nodoc:
|
103
|
+
WEB_XPATH = "cap:#{ WEB_ELEMENT_NAME }" # :nodoc:
|
104
|
+
CONTACT_XPATH = "cap:#{ CONTACT_ELEMENT_NAME }" # :nodoc:
|
105
|
+
|
106
|
+
DEFAULT_LANGUAGE = 'en-US'
|
107
|
+
|
108
|
+
validates_presence_of( :event, :urgency, :severity, :certainty )
|
109
|
+
validates_length_of( :categories, :minimum => 1 )
|
110
|
+
validates_inclusion_of( :certainty, :allow_nil => true, :in => ALL_CERTAINTIES, :message => "can only be assigned the following values: #{ ALL_CERTAINTIES.join(', ') }")
|
111
|
+
validates_inclusion_of( :severity, :allow_nil => true, :in => ALL_SEVERITIES, :message => "can only be assigned the following values: #{ ALL_SEVERITIES.join(', ') }" )
|
112
|
+
validates_inclusion_of( :urgency, :allow_nil => true, :in => ALL_URGENCIES, :message => "can only be assigned the following values: #{ ALL_URGENCIES.join(', ') }" )
|
113
|
+
validates_inclusion_of_members_of( :response_types, :in => ALL_RESPONSE_TYPES, :allow_blank => true )
|
114
|
+
validates_inclusion_of_members_of( :categories, :in => ALL_CATEGORIES, :allow_blank => true )
|
115
|
+
validates_collection_of( :resources, :areas )
|
116
|
+
|
117
|
+
attr_accessor( :event )
|
118
|
+
attr_accessor( :urgency )
|
119
|
+
attr_accessor( :severity )
|
120
|
+
attr_accessor( :certainty )
|
121
|
+
attr_accessor( :language )
|
122
|
+
attr_accessor( :audience )
|
123
|
+
# Effective start time of information
|
124
|
+
attr_accessor( :effective )
|
125
|
+
# Expected start of event
|
126
|
+
attr_accessor( :onset )
|
127
|
+
# Effected expiry time of information
|
128
|
+
attr_accessor( :expires )
|
129
|
+
attr_accessor( :sender_name )
|
130
|
+
attr_accessor( :headline )
|
131
|
+
attr_accessor( :description )
|
132
|
+
attr_accessor( :instruction )
|
133
|
+
attr_accessor( :web )
|
134
|
+
attr_accessor( :contact )
|
135
|
+
|
136
|
+
# Collection of textual categories
|
137
|
+
attr_reader( :categories )
|
138
|
+
# Collection of textual response types
|
139
|
+
attr_reader( :response_types )
|
140
|
+
# Collectoin of EventCode objects
|
141
|
+
attr_reader( :event_codes )
|
142
|
+
# Collection of Parameter objects
|
143
|
+
attr_reader( :parameters )
|
144
|
+
# Collection of Resource objects
|
145
|
+
attr_reader( :resources )
|
146
|
+
# Collection of Area objects
|
147
|
+
attr_reader( :areas )
|
148
|
+
|
149
|
+
def initialize( attributes = {} )
|
150
|
+
@language = attributes[ :language ] || DEFAULT_LANGUAGE
|
151
|
+
@categories = Array( attributes[ :categories ])
|
152
|
+
@event = attributes [ :event ]
|
153
|
+
@response_types = Array( attributes[ :response_types ])
|
154
|
+
@urgency = attributes[ :urgency ]
|
155
|
+
@severity = attributes[ :severity ]
|
156
|
+
@certainty = attributes[ :certainty ]
|
157
|
+
@effective = attributes[ :effective ]
|
158
|
+
@onset = attributes[ :onset ]
|
159
|
+
@expires = attributes[ :expires ]
|
160
|
+
@event_codes = Array( attributes[ :event_codes ])
|
161
|
+
@sender_name = attributes[ :sender_name ]
|
162
|
+
@headline = attributes[ :headline ]
|
163
|
+
@description = attributes[ :description ]
|
164
|
+
@instruction = attributes[ :instruction ]
|
165
|
+
@web = attributes[ :web ]
|
166
|
+
@contact = attributes[ :contact ]
|
167
|
+
@parameters = Array( attributes[ :parameters ])
|
168
|
+
@resources = Array( attributes[ :resources ])
|
169
|
+
@areas = Array( attributes[ :areas ])
|
170
|
+
end
|
171
|
+
|
172
|
+
def to_xml_element # :nodoc:
|
173
|
+
xml_element = REXML::Element.new( XML_ELEMENT_NAME )
|
174
|
+
xml_element.add_element( LANGUAGE_ELEMENT_NAME ).add_text( self.language ) if self.language
|
175
|
+
@categories.each do |category|
|
176
|
+
xml_element.add_element( CATEGORY_ELEMENT_NAME ).add_text( category )
|
177
|
+
end
|
178
|
+
xml_element.add_element( EVENT_ELEMENT_NAME ).add_text( self.event )
|
179
|
+
@response_types.each do |response_type|
|
180
|
+
xml_element.add_element( RESPONSE_TYPE_ELEMENT_NAME ).add_text( response_type )
|
181
|
+
end
|
182
|
+
xml_element.add_element( URGENCY_ELEMENT_NAME ).add_text( self.urgency )
|
183
|
+
xml_element.add_element( SEVERITY_ELEMENT_NAME ).add_text( self.severity )
|
184
|
+
xml_element.add_element( CERTAINTY_ELEMENT_NAME ).add_text( self.certainty )
|
185
|
+
xml_element.add_element( AUDIENCE_ELEMENT_NAME ).add_text( self.audience ) if self.audience
|
186
|
+
@event_codes.each do |event_code|
|
187
|
+
xml_element.add_element( event_code.to_xml_element )
|
188
|
+
end
|
189
|
+
xml_element.add_element( EFFECTIVE_ELEMENT_NAME ).add_text( self.effective.to_s ) if self.effective
|
190
|
+
xml_element.add_element( ONSET_ELEMENT_NAME ).add_text( self.onset.to_s ) if self.onset
|
191
|
+
xml_element.add_element( EXPIRES_ELEMENT_NAME ).add_text( self.expires.to_s ) if self.expires
|
192
|
+
xml_element.add_element( SENDER_NAME_ELEMENT_NAME ).add_text( self.sender_name ) if self.sender_name
|
193
|
+
xml_element.add_element( HEADLINE_ELEMENT_NAME ).add_text( self.headline ) if self.headline
|
194
|
+
xml_element.add_element( DESCRIPTION_ELEMENT_NAME ).add_text( self.description ) if self.description
|
195
|
+
xml_element.add_element( INSTRUCTION_ELEMENT_NAME ).add_text( self.instruction ) if self.instruction
|
196
|
+
xml_element.add_element( WEB_ELEMENT_NAME ).add_text( self.web ) if self.web
|
197
|
+
xml_element.add_element( CONTACT_ELEMENT_NAME ).add_text( self.contact ) if self.contact
|
198
|
+
@parameters.each do |parameter|
|
199
|
+
xml_element.add_element( parameter.to_xml_element )
|
200
|
+
end
|
201
|
+
@resources.each do |resource|
|
202
|
+
xml_element.add_element( resource.to_xml_element )
|
203
|
+
end
|
204
|
+
@areas.each do |area|
|
205
|
+
xml_element.add_element( area.to_xml_element )
|
206
|
+
end
|
207
|
+
xml_element
|
208
|
+
end
|
209
|
+
|
210
|
+
def to_xml # :nodoc:
|
211
|
+
self.to_xml_element.to_s
|
212
|
+
end
|
213
|
+
|
214
|
+
def self.from_xml_element( info_xml_element ) # :nodoc:
|
215
|
+
self.new(
|
216
|
+
:language => RCAP.xpath_text( info_xml_element, LANGUAGE_XPATH ) || DEFAULT_LANGUAGE,
|
217
|
+
:categories => RCAP.xpath_match( info_xml_element, CATEGORY_XPATH ).map{ |element| element.text },
|
218
|
+
:event => RCAP.xpath_text( info_xml_element, EVENT_XPATH ),
|
219
|
+
:response_types => RCAP.xpath_match( info_xml_element, RESPONSE_TYPE_XPATH ).map{ |element| element.text },
|
220
|
+
:urgency => RCAP.xpath_text( info_xml_element, URGENCY_XPATH ),
|
221
|
+
:severity => RCAP.xpath_text( info_xml_element, SEVERITY_XPATH ),
|
222
|
+
:certainty => RCAP.xpath_text( info_xml_element, CERTAINTY_XPATH ),
|
223
|
+
:audience => RCAP.xpath_text( info_xml_element, AUDIENCE_XPATH ),
|
224
|
+
:effective => (( effective = RCAP.xpath_first( info_xml_element, EFFECTIVE_XPATH )) ? DateTime.parse( effective.text ) : nil ),
|
225
|
+
:onset => (( onset = RCAP.xpath_first( info_xml_element, ONSET_XPATH )) ? DateTime.parse( onset.text ) : nil ),
|
226
|
+
:expires => (( expires = RCAP.xpath_first( info_xml_element, EXPIRES_XPATH )) ? DateTime.parse( expires.text ) : nil ),
|
227
|
+
:sender_name => RCAP.xpath_text( info_xml_element, SENDER_NAME_XPATH ),
|
228
|
+
:headline => RCAP.xpath_text( info_xml_element, HEADLINE_XPATH ),
|
229
|
+
:description => RCAP.xpath_text( info_xml_element, DESCRIPTION_XPATH ),
|
230
|
+
:instruction => RCAP.xpath_text( info_xml_element, INSTRUCTION_XPATH ),
|
231
|
+
:web => RCAP.xpath_text( info_xml_element, WEB_XPATH ),
|
232
|
+
:contact => RCAP.xpath_text( info_xml_element, CONTACT_XPATH ),
|
233
|
+
:event_codes => RCAP.xpath_match( info_xml_element, RCAP::EventCode::XPATH ).map{ |element| RCAP::EventCode.from_xml_element( element )},
|
234
|
+
:parameters => RCAP.xpath_match( info_xml_element, RCAP::Parameter::XPATH ).map{ |element| RCAP::Parameter.from_xml_element( element )},
|
235
|
+
:areas => RCAP.xpath_match( info_xml_element, RCAP::Area::XPATH ).map{ |element| RCAP::Area.from_xml_element( element )}
|
236
|
+
)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module RCAP
|
2
|
+
# A Parameter object is valid if
|
3
|
+
# * it has a name
|
4
|
+
# * it has a value
|
5
|
+
class Parameter
|
6
|
+
include Validation
|
7
|
+
|
8
|
+
validates_presence_of( :name, :value )
|
9
|
+
|
10
|
+
attr_accessor( :name, :value )
|
11
|
+
|
12
|
+
XML_ELEMENT_NAME = "parameter" # :nodoc:
|
13
|
+
NAME_ELEMENT_NAME = "valueName" # :nodoc:
|
14
|
+
VALUE_ELEMENT_NAME = "value" # :nodoc:
|
15
|
+
|
16
|
+
XPATH = "cap:#{ XML_ELEMENT_NAME }" # :nodoc:
|
17
|
+
NAME_XPATH = "cap:#{ NAME_ELEMENT_NAME }" # :nodoc:
|
18
|
+
VALUE_XPATH = "cap:#{ VALUE_ELEMENT_NAME }" # :nodoc:
|
19
|
+
|
20
|
+
def initialize( attributes = {} )
|
21
|
+
@name = attributes[ :name ]
|
22
|
+
@value = attributes[ :value ]
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_xml_element # :nodoc:
|
26
|
+
xml_element = REXML::Element.new( XML_ELEMENT_NAME )
|
27
|
+
xml_element.add_element( NAME_ELEMENT_NAME ).add_text( self.name )
|
28
|
+
xml_element.add_element( VALUE_ELEMENT_NAME ).add_text( self.value )
|
29
|
+
xml_element
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_xml # :nodoc:
|
33
|
+
self.to_xml_element.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
def inspect # :nodoc:
|
37
|
+
"#{ self.name }: #{ self.value }"
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s # :nodoc:
|
41
|
+
self.inspect
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.from_xml_element( parameter_xml_element ) # :nodoc:
|
45
|
+
Parameter.new( :name => RCAP.xpath_text( parameter_xml_element, NAME_XPATH ),
|
46
|
+
:value => RCAP.xpath_text( parameter_xml_element, VALUE_XPATH ))
|
47
|
+
end
|
48
|
+
|
49
|
+
# Two parameters are equivalent if they have the same name and value.
|
50
|
+
def ==( other )
|
51
|
+
[ self.name, self.value ] == [ other.name, other.value ]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/rcap/point.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module RCAP
|
2
|
+
# A Point object is valid if
|
3
|
+
# * it has a lattitude within the minimum and maximum lattitude values
|
4
|
+
# * it has a longitude within the minimum and maximum longitude values
|
5
|
+
class Point
|
6
|
+
include Validation
|
7
|
+
|
8
|
+
MAX_LONGITUDE = 180
|
9
|
+
MIN_LONGITUDE = -180
|
10
|
+
MAX_LATTITUDE = 90
|
11
|
+
MIN_LATTITUDE= -90
|
12
|
+
|
13
|
+
attr_accessor( :lattitude )
|
14
|
+
attr_accessor( :longitude )
|
15
|
+
|
16
|
+
validates_numericality_of( :lattitude, :longitude )
|
17
|
+
validates_inclusion_of( :lattitude, :in => MIN_LATTITUDE..MAX_LATTITUDE )
|
18
|
+
validates_inclusion_of( :longitude, :in => MIN_LONGITUDE..MAX_LONGITUDE)
|
19
|
+
|
20
|
+
def initialize( attributes = {} )
|
21
|
+
@lattitude = attributes[ :lattitude ]
|
22
|
+
@longitude = attributes[ :longitude ]
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s # :nodoc:
|
26
|
+
"#{ self.lattitude },#{ self.longitude }"
|
27
|
+
end
|
28
|
+
|
29
|
+
def inspect # :nodoc:
|
30
|
+
'('+self.to_s+')'
|
31
|
+
end
|
32
|
+
|
33
|
+
# Two points are equivalent if they have the same lattitude and longitude
|
34
|
+
def ==( other )
|
35
|
+
self.lattitude == other.lattitude &&
|
36
|
+
self.longitude == other.longitude
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/rcap/polygon.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module RCAP
|
2
|
+
# A Polygon object is valid if
|
3
|
+
# * it has a minimum of three points
|
4
|
+
# * each Point object in the points collection is valid
|
5
|
+
class Polygon
|
6
|
+
include Validation
|
7
|
+
|
8
|
+
# Collection of Point objects.
|
9
|
+
attr_reader( :points )
|
10
|
+
|
11
|
+
validates_length_of( :points, :minimum => 3 )
|
12
|
+
validates_collection_of( :points )
|
13
|
+
|
14
|
+
XML_ELEMENT_NAME = 'polygon' # :nodoc:
|
15
|
+
XPATH = "cap:#{ XML_ELEMENT_NAME }" # :nodoc:
|
16
|
+
|
17
|
+
def initialize( attributes = {})
|
18
|
+
@points = Array( attributes[ :points ])
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s # :nodoc:
|
22
|
+
(@points.map{ |point| point.to_s } + [ @points.first ]).join( ' ' )
|
23
|
+
end
|
24
|
+
|
25
|
+
def inspect # :nodoc:
|
26
|
+
"(#{ @points.map{|point| point.inspect}.join(', ')})"
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_xml_element # :nodoc:
|
30
|
+
xml_element = REXML::Element.new( XML_ELEMENT_NAME )
|
31
|
+
xml_element.add_text( self.to_s )
|
32
|
+
xml_element
|
33
|
+
end
|
34
|
+
|
35
|
+
# Two polygons are equivalent if their collection of points is equivalent.
|
36
|
+
def ==( other )
|
37
|
+
self.points == other.points
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.parse_polygon_string( polygon_string ) # :nodoc:
|
41
|
+
polygon_string.split( ' ' ).map{ |coordinate_string| coordinate_string.split( ',' ).map{|coordinate| coordinate.to_f }}
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.from_xml_element( polygon_xml_element ) # :nodoc:
|
45
|
+
coordinates = self.parse_polygon_string( polygon_xml_element.text )
|
46
|
+
points = coordinates.map{ |lattitude, longitude| RCAP::Point.new( :lattitude => lattitude, :longitude => longitude )}[0..-2]
|
47
|
+
polygon = self.new( :points => points )
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module RCAP
|
2
|
+
# A Resourse object is valid if
|
3
|
+
# * it has a resource description
|
4
|
+
class Resource
|
5
|
+
include Validation
|
6
|
+
|
7
|
+
# Resource Description
|
8
|
+
attr_accessor( :resource_desc )
|
9
|
+
attr_accessor( :mime_type )
|
10
|
+
# Expressed in bytes
|
11
|
+
attr_accessor( :size )
|
12
|
+
# Resource location
|
13
|
+
attr_accessor( :uri )
|
14
|
+
# Dereferenced URI - contents of URI Base64 encoded
|
15
|
+
attr_accessor( :deref_uri )
|
16
|
+
# SHA-1 hash of contents of resource
|
17
|
+
attr_accessor( :digest )
|
18
|
+
|
19
|
+
validates_presence_of( :resource_desc )
|
20
|
+
|
21
|
+
XML_ELEMENT_NAME = 'resource' # :nodoc:
|
22
|
+
MIME_TYPE_ELEMENT_NAME = 'mimeType' # :nodoc:
|
23
|
+
SIZE_ELEMENT_NAME = 'size' # :nodoc:
|
24
|
+
URI_ELEMENT_NAME = 'uri' # :nodoc:
|
25
|
+
DEREF_URI_ELEMENT_NAME = 'derefUri' # :nodoc:
|
26
|
+
DIGEST_ELEMENT_NAME = 'digest' # :nodoc:
|
27
|
+
RESOURCE_DESC_ELEMENT_NAME = 'resourceDesc' # :nodoc:
|
28
|
+
|
29
|
+
XPATH = "cap:#{ XML_ELEMENT_NAME }" # :nodoc:
|
30
|
+
MIME_TYPE_XPATH = "cap:#{ MIME_TYPE_ELEMENT_NAME }" # :nodoc:
|
31
|
+
SIZE_XPATH = "cap:#{ SIZE_ELEMENT_NAME }" # :nodoc:
|
32
|
+
URI_XPATH = "cap:#{ URI_ELEMENT_NAME }" # :nodoc:
|
33
|
+
DEREF_URI_XPATH = "cap:#{ DEREF_URI_ELEMENT_NAME }" # :nodoc:
|
34
|
+
DIGEST_XPATH = "cap:#{ DIGEST_ELEMENT_NAME }" # :nodoc:
|
35
|
+
RESOURCE_DESC_XPATH = "cap:#{ RESOURCE_DESC_ELEMENT_NAME }" # :nodoc:
|
36
|
+
|
37
|
+
def initialize( attributes = {} )
|
38
|
+
@mime_type = attributes[ :mime_type ]
|
39
|
+
@size = attributes[ :size ]
|
40
|
+
@uri = attributes[ :uri ]
|
41
|
+
@deref_uri = attributes[ :deref_uri ]
|
42
|
+
@digest = attributes[ :digest ]
|
43
|
+
@resource_desc = attributes[ :resource_desc ]
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_xml_element # :nodoc:
|
47
|
+
xml_element = REXML::Element.new( XML_ELEMENT_NAME )
|
48
|
+
xml_element.add_element( RESOURCE_DESC_ELEMENT_NAME ).add_text( self.resource_desc )
|
49
|
+
xml_element.add_element( MIME_TYPE_ELEMENT_NAME ).add_text( self.mime_type ) if self.mime_type
|
50
|
+
xml_element.add_element( SIZE_ELEMENT_NAME ).add_text( self.size ) if self.size
|
51
|
+
xml_element.add_element( URI_ELEMENT_NAME ).add_text( self.uri ) if self.uri
|
52
|
+
xml_element.add_element( DEREF_URI_ELEMENT_NAME ).add_text( self.deref_uri ) if self.deref_uri
|
53
|
+
xml_element.add_element( DIGEST_ELEMENT_NAME ).add_text( self.digest ) if self.digest
|
54
|
+
xml_element
|
55
|
+
end
|
56
|
+
|
57
|
+
# If size is defined returns the size in kilobytes
|
58
|
+
def size_in_kb
|
59
|
+
if self.size
|
60
|
+
self.size.to_f/1024
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_xml # :nodoc:
|
65
|
+
self.to_xml_element.to_s
|
66
|
+
end
|
67
|
+
|
68
|
+
def inspect # :nodoc:
|
69
|
+
[ self.resource_desc, self.uri, self.mime_type, self.size ? format( "%.1fKB", self.size_in_kb ) : nil ].compact.join(' - ')
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.from_xml_element( resource_xml_element ) # :nodoc:
|
73
|
+
resource = self.new( :resource_desc => RCAP.xpath_text( resource_xml_element, RESOURCE_DESC_XPATH ),
|
74
|
+
:uri => RCAP.xpath_text( resource_xml_element, URI_XPATH ),
|
75
|
+
:mime_type => RCAP.xpath_text( resource_xml_element, MIME_TYPE_XPATH ),
|
76
|
+
:deref_uri => RCAP.xpath_text( resource_xml_element, DEREF_URI_XPATH ),
|
77
|
+
:size => RCAP.xpath_text( resource_xml_element, SIZE_XPATH ),
|
78
|
+
:digest => RCAP.xpath_text( resource_xml_element, DIGEST_XPATH ))
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|