rcap 0.1

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