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