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.
@@ -0,0 +1,50 @@
1
+ ALLOWED_CHARACTERS = /[^\s&<]+/ # :nodoc:
2
+
3
+ class Array # :nodoc:
4
+ def to_s_for_cap
5
+ self.map{ |element| element.to_s.for_cap_list }.join( ' ' )
6
+ end
7
+ end
8
+
9
+ class String # :nodoc:
10
+ CAP_LIST_REGEX = /"([\w\s]+)"|(\S+)/
11
+ WHITESPACE_REGEX = /^\s+$/
12
+
13
+ def for_cap_list
14
+ if self =~ /\s/
15
+ '"'+self+'"'
16
+ else
17
+ self
18
+ end
19
+ end
20
+
21
+ def unpack_cap_list
22
+ self.split( CAP_LIST_REGEX ).reject{ |match| match == "" || match =~ WHITESPACE_REGEX }
23
+ end
24
+ end
25
+
26
+ class DateTime # :nodoc:
27
+ alias inspect to_s
28
+ alias to_s_for_cap to_s
29
+ end
30
+
31
+ class Time # :nodoc:
32
+ def to_s_for_cap
33
+
34
+ end
35
+ end
36
+
37
+ module RCAP # :nodoc:
38
+ def self.xpath_text( xml_element, xpath )
39
+ element = self.xpath_first( xml_element, xpath )
40
+ element.text if element
41
+ end
42
+
43
+ def self.xpath_first( xml_element, xpath )
44
+ REXML::XPath.first( xml_element, xpath, { 'cap' => RCAP::XMLNS })
45
+ end
46
+
47
+ def self.xpath_match( xml_element, xpath )
48
+ REXML::XPath.match( xml_element, xpath, { 'cap' => RCAP::XMLNS })
49
+ end
50
+ end
@@ -0,0 +1,116 @@
1
+ module Validation # :nodoc:
2
+ module ClassMethods # :nodoc:
3
+
4
+ NUMBER_RE = /^-{0,1}\d*\.{0,1}\d+$/
5
+ INTEGER_RE = /\-{0,1}A[+-]?\d+\Z/
6
+
7
+ def validates_inclusion_of( *attributes )
8
+ options = {
9
+ :message => 'is not in the required range'
10
+ }.merge!( attributes.extract_options! )
11
+
12
+ validates_each( *attributes ) do |object, attribute, value|
13
+ next if ( value.nil? && options[ :allow_nil ]) || ( value.blank? && options[ :allow_blank ])
14
+ unless options[ :in ].include?( value )
15
+ object.errors[ attribute ] << options[ :message ]
16
+ end
17
+ end
18
+ end
19
+
20
+ def validates_inclusion_of_members_of( *attributes )
21
+ options = {
22
+ :message => 'contains members that are not valid'
23
+ }.merge!( attributes.extract_options! )
24
+
25
+ validates_each( *attributes ) do |object, attribute, collection|
26
+ next if ( collection.nil? && options[ :allow_nil ]) || (collection.blank? && options[ :allow_blank ])
27
+ unless collection.all?{ |member| options[ :in ].include?( member )}
28
+ object.errors[ attribute ] << options[ :message ]
29
+ end
30
+ end
31
+ end
32
+
33
+ def validates_length_of_members_of( *attributes )
34
+ options = {
35
+ :message => 'contains members with incorrect length'
36
+ }.merge!( attributes.extract_options! )
37
+
38
+ validates_each( *attributes ) do |object, attribute, collection|
39
+ next if ( collection.nil? && options[ :allow_nil ]) || (collection.blank? && options[ :allow_blank ])
40
+ unless options[ :minimum ] && collection.length >= options[ :minimum ]
41
+ object.errors[ attribute ] << options[ :message ]
42
+ end
43
+ end
44
+ end
45
+
46
+ def validates_validity_of( *attributes )
47
+ options = {
48
+ :message => 'is not valid'
49
+ }.merge!( attributes.extract_options! )
50
+
51
+ validates_each( *attributes ) do |object, attribute, value|
52
+ next if ( value.nil? && options[ :allow_nil ]) || ( value.blank? && options[ :allow_blank ])
53
+ unless value && value.valid?
54
+ object.errors[ attribute ] << options[ :message ]
55
+ end
56
+ end
57
+ end
58
+
59
+ def validates_collection_of( *attributes )
60
+ options = {
61
+ :message => 'contains an invalid element'
62
+ }.merge!( attributes.extract_options! )
63
+
64
+ validates_each( *attributes ) do |object, attribute, collection|
65
+ next if ( collection.nil? && options[ :allow_nil ]) || ( collection.blank? && options[ :allow_blank ])
66
+ unless collection.all?{ |element| element.valid? }
67
+ object.errors[ attribute ] << options[ :message ]
68
+ end
69
+ end
70
+ end
71
+
72
+ def validates_dependency_of( *attributes )
73
+ options = {
74
+ :message => 'is dependent on :attribute being defined'
75
+ }.merge!( attributes.extract_options! )
76
+
77
+ validates_each( *attributes ) do |object, attribute, value|
78
+ contingent_on_value = object.send( options[ :on ])
79
+ next if ( value.nil? && options[ :allow_nil ]) || ( value.blank? && options[ :allow_blank ])
80
+ unless value.blank? || !value.blank? && !contingent_on_value.blank? && ( options[ :with_value ].nil? || contingent_on_value == options[ :with_value ])
81
+ object.errors[ attribute ] << options[ :message ].gsub( /:attribute/, options[ :on ].to_s )
82
+ end
83
+ end
84
+ end
85
+
86
+ def validates_numericality_of( *attributes )
87
+ options = {
88
+ :message => 'is not a number',
89
+ }.merge!(attributes.extract_options!)
90
+
91
+ re = options[:only_integer] ? INTEGER_RE : NUMBER_RE
92
+
93
+ validates_each( *attributes ) do |object, attribute, value|
94
+ next if (value.nil? && options[ :allow_nil ]) || (value.blank? && options[ :allow_blank ])
95
+ unless ( value.to_s =~ re ) &&
96
+ ( options[ :greater_than ].nil? || value && value > options[ :greater_than ])
97
+ object.errors[ attribute ] << options[ :message ]
98
+ end
99
+ end
100
+ end
101
+
102
+
103
+ def validates_responsiveness_of( *attributes )
104
+ options = {
105
+ :message => 'does not respond to the given method'
106
+ }.merge!( attributes.extract_options! )
107
+
108
+ validates_each( *attributes ) do |object, attribute, value|
109
+ next if ( collection.nil? && options[ :allow_nil ]) || ( collection.blank? && options[ :allow_blank ])
110
+ unless options[ :to ].all?{ |method_name| object.respond_to?( method_name )}
111
+ object.errors[ attribute ] << options [ :message ]
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,132 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe( RCAP::Alert ) do
4
+ context( 'on initialisation' ) do
5
+ before( :each ) do
6
+ @alert = RCAP::Alert.new
7
+ end
8
+
9
+ it( 'should have a default identifier' ){ @alert.identifier.should_not( be_nil )}
10
+ it( 'should not have a sender' ){ @alert.sender.should( be_nil )}
11
+ it( 'should have a default sent time' ){ @alert.sent.should_not( be_nil )}
12
+ it( 'should not have a status' ){ @alert.status.should( be_nil )}
13
+ it( 'should not have a scope' ){ @alert.scope.should( be_nil )}
14
+ it( 'should not have a source'){ @alert.source.should( be_nil )}
15
+ it( 'should not have a restriction'){ @alert.restriction.should( be_nil )}
16
+ it( 'should not have any addresses' ){ @alert.addresses.should( be_empty )}
17
+ it( 'should not have a code' ){ @alert.code.should( be_nil )}
18
+ it( 'should not have a note' ){ @alert.note.should( be_nil )}
19
+ it( 'should not have any references' ){ @alert.references.should( be_empty )}
20
+ it( 'should not have any incidents' ){ @alert.incidents.should( be_empty )}
21
+ it( 'should not have any infos' ){ @alert.infos.should( be_empty )}
22
+
23
+ context( 'from XML' ) do
24
+ before( :each ) do
25
+ @original_alert = RCAP::Alert.new( :sender => 'Sender',
26
+ :status => RCAP::Alert::STATUS_TEST,
27
+ :scope => RCAP::Alert::SCOPE_PUBLIC,
28
+ :source => 'Source',
29
+ :restriction => 'No Restriction',
30
+ :addresses => [ 'Address 1', 'Address 2'],
31
+ :code => 'Code',
32
+ :note => 'Note',
33
+ :references => [ RCAP::Alert.new( :sender => 'Sender1' ).to_reference, RCAP::Alert.new( :sender => 'Sender2' ).to_reference ],
34
+ :incidents => [ 'Incident1', 'Incident2' ],
35
+ :infos => [ RCAP::Info.new, RCAP::Info.new ])
36
+ @xml_string = @original_alert.to_xml
37
+ @xml_document = REXML::Document.new( @xml_string )
38
+ @alert_element = @xml_document.root
39
+ @alert = RCAP::Alert.from_xml_element( @alert_element )
40
+ end
41
+
42
+ it( 'should parse identifier correctly' ){ @alert.identifier.should == @original_alert.identifier }
43
+ it( 'should parse sender correctly' ){ @alert.sender.should == @original_alert.sender }
44
+ it( 'should parse sent correctly' ){ @alert.sent.should( be_close( @original_alert.sent, Rational( 1, 86400 )))}
45
+ it( 'should parse status correctly' ){ @alert.status.should == @original_alert.status }
46
+ it( 'should parse msg_type correctly' ){ @alert.msg_type.should == @original_alert.msg_type }
47
+ it( 'should parse source correctly' ){ @alert.source.should == @original_alert.source }
48
+ it( 'should parse scope correctly' ){ @alert.scope.should == @original_alert.scope }
49
+ it( 'should parse restriction correctly' ){ @alert.restriction.should == @original_alert.restriction }
50
+ it( 'should parse addresses correctly' ){ @alert.addresses.should == @original_alert.addresses }
51
+ it( 'should parse code correctly' ){ @alert.code.should == @original_alert.code }
52
+ it( 'should parse note correctly' ){ @alert.note.should == @original_alert.note }
53
+ it( 'should parse references correctly' ){ @alert.references.should == @original_alert.references }
54
+ it( 'should parse incidents correctly' ){ @alert.incidents.should == @original_alert.incidents }
55
+ it( 'should parse infos correctly' ) do
56
+ @alert.infos.size.should == @original_alert.infos.size
57
+ @alert.infos.each{ |info| info.class.should == RCAP::Info }
58
+ end
59
+ end
60
+ end
61
+
62
+ describe( 'is not valid if it' ) do
63
+ before( :each ) do
64
+ @alert = RCAP::Alert.new( :sender => "cap@tempuri.org",
65
+ :status => RCAP::Alert::STATUS_TEST,
66
+ :msg_type => RCAP::Alert::MSG_TYPE_ALERT,
67
+ :scope => RCAP::Alert::SCOPE_PUBLIC )
68
+ @alert.should( be_valid )
69
+ end
70
+
71
+ it( 'does not have a identifier' ) do
72
+ @alert.identifier = nil
73
+ @alert.should_not( be_valid )
74
+ end
75
+
76
+ it( 'does not have a sender' ) do
77
+ @alert.sender = nil
78
+ @alert.should_not( be_valid )
79
+ end
80
+
81
+ it( 'does not have a sent time (sent)' ) do
82
+ @alert.sent = nil
83
+ @alert.should_not( be_valid )
84
+ end
85
+
86
+ it( 'does not have a status' ) do
87
+ @alert.status = nil
88
+ @alert.should_not( be_valid )
89
+ end
90
+
91
+ it( 'does not have a message type (msg_type)' ) do
92
+ @alert.msg_type = nil
93
+ @alert.should_not( be_valid )
94
+ end
95
+
96
+ it( 'does not have a scope' ) do
97
+ @alert.scope = nil
98
+ @alert.should_not( be_valid )
99
+ end
100
+
101
+
102
+ it( 'does not have a valid status' ) do
103
+ @alert.status = 'incorrect value'
104
+ @alert.should_not( be_valid )
105
+ end
106
+
107
+ it( 'does not have a valid message type msg_type' ) do
108
+ @alert.msg_type = 'incorrect value'
109
+ @alert.should_not( be_valid )
110
+ end
111
+
112
+ it( 'does not have a valid scope' ) do
113
+ @alert.scope = 'incorrect value'
114
+ @alert.should_not( be_valid )
115
+ end
116
+
117
+
118
+ context( 'has an info element and it' ) do
119
+ it( 'is not valid' ) do
120
+ @info = RCAP::Info.new( :event => 'Info Event',
121
+ :categories => RCAP::Info::CATEGORY_GEO,
122
+ :urgency => RCAP::Info::URGENCY_IMMEDIATE,
123
+ :severity => RCAP::Info::SEVERITY_EXTREME,
124
+ :certainty => RCAP::Info::CERTAINTY_OBSERVED )
125
+ @info.event = nil
126
+ @alert.infos << @info
127
+ @info.should_not( be_valid )
128
+ @alert.should_not( be_valid )
129
+ end
130
+ end
131
+ end
132
+ end
data/spec/area_spec.rb ADDED
@@ -0,0 +1,120 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe( RCAP::Area ) do
4
+ context( 'on initialisation' ) do
5
+ before( :each ) do
6
+ @area = RCAP::Area.new
7
+ end
8
+
9
+ # Atomic
10
+ it( 'should not have a area_desc' ){ @area.area_desc.should( be_nil )}
11
+ it( 'should not have a altitude' ){ @area.altitude.should( be_nil )}
12
+ it( 'should not have a ceiling' ){ @area.ceiling.should( be_nil )}
13
+
14
+ # Group
15
+ it( 'should have an empty polygons' ){ @area.polygons.should( be_empty )}
16
+ it( 'should have an empty circles' ){ @area.circles.should( be_empty )}
17
+ it( 'should have an empty geocodes' ){ @area.geocodes.should( be_empty )}
18
+
19
+ context( 'from XML' ) do
20
+ before( :each ) do
21
+ @original_area = RCAP::Area.new( :area_desc => 'Area Description',
22
+ :altitude => 100,
23
+ :ceiling => 200,
24
+ :circles => RCAP::Circle.new( :point => RCAP::Point.new( :lattitude => 0, :longitude => 0 ), :radius => 100 ),
25
+ :geocodes => RCAP::Geocode.new( :name => 'name', :value => 'value' ),
26
+ :polygons => RCAP::Polygon.new( :points => RCAP::Point.new( :lattitude =>1, :longitude => 1 )))
27
+
28
+ @alert = RCAP::Alert.new( :infos => RCAP::Info.new( :areas => @original_area ))
29
+ @xml_string = @alert.to_xml
30
+ @xml_document = REXML::Document.new( @xml_string )
31
+ @info_xml_element = RCAP.xpath_first( @xml_document.root, RCAP::Info::XPATH )
32
+ @area_xml_element = RCAP.xpath_first( @info_xml_element, RCAP::Area::XPATH )
33
+ @area = RCAP::Area.from_xml_element( @area_xml_element )
34
+ end
35
+
36
+ it( 'should parse the area_desc correctly' ) do
37
+ @area.area_desc.should == @original_area.area_desc
38
+ end
39
+
40
+ it( 'should parse the altitude correctly' ) do
41
+ @area.altitude.should == @original_area.altitude
42
+ end
43
+
44
+ it( 'should parse the ceiling correctly' ) do
45
+ @area.ceiling.should == @original_area.ceiling
46
+ end
47
+
48
+ it( 'should parse the circles correctly' ) do
49
+ @area.circles.should == @original_area.circles
50
+ end
51
+
52
+ it( 'should parse the geocodes correctly' ) do
53
+ @area.geocodes.should == @original_area.geocodes
54
+ end
55
+
56
+ it( 'should parse the polygons correctly' ) do
57
+ @area.polygons.should == @original_area.polygons
58
+ end
59
+ end
60
+ end
61
+
62
+ context( 'is not valid if' ) do
63
+ before( :each ) do
64
+ @area = RCAP::Area.new( :area_desc => "Cape Town Metropole" )
65
+ @area.should( be_valid )
66
+ end
67
+
68
+ it( 'does not have an area descrtiption (area_desc)') do
69
+ @area.area_desc = nil
70
+ @area.should_not( be_valid )
71
+ end
72
+
73
+ it( 'has a ceiling defined but no altitude' ) do
74
+ @area.ceiling = 1
75
+ @area.altitude = nil
76
+ @area.should_not( be_valid )
77
+ end
78
+
79
+ context( 'it contains circles and it' ) do
80
+ before( :each ) do
81
+ @area.circles << RCAP::Circle.new( :point => RCAP::Point.new( :lattitude => 0, :longitude => 0 ), :radius => 1)
82
+ @area.should( be_valid )
83
+ end
84
+
85
+ it( 'has an invalid circle' ) do
86
+ @area.circles.first.point.lattitude = nil
87
+ @area.should_not( be_valid )
88
+ end
89
+ end
90
+
91
+ context( 'it contains polygons and it' ) do
92
+ before( :each ) do
93
+ @polygon = RCAP::Polygon.new
94
+ @polygon.points.push( RCAP::Point.new( :lattitude => 0, :longitude => 0 ),
95
+ RCAP::Point.new( :lattitude => 0, :longitude => 1 ),
96
+ RCAP::Point.new( :lattitude => 1, :longitude => 0 ))
97
+ @area.polygons << @polygon
98
+ @area.should( be_valid )
99
+ end
100
+
101
+ it( 'has an invalid polygon' ) do
102
+ @polygon.points.first.lattitude = nil
103
+ @area.should_not( be_valid )
104
+ end
105
+ end
106
+
107
+ context( 'it contains geocodes and it' ) do
108
+ before( :each ) do
109
+ @geocode = RCAP::Geocode.new( :name => 'foo', :value => 'bar' )
110
+ @area.geocodes << @geocode
111
+ @area.should( be_valid )
112
+ end
113
+
114
+ it( 'has an invalid geocode' ) do
115
+ @geocode.value = nil
116
+ @area.should_not( be_valid )
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe( RCAP::Circle ) do
4
+ describe( 'should not be valid if' ) do
5
+ before( :each ) do
6
+ @circle = RCAP::Circle.new( :point => RCAP::Point.new( :lattitude => 0, :longitude => 0 ), :radius => 1 )
7
+ @circle.should( be_valid )
8
+ end
9
+
10
+ it( 'does not have a point defined' ) do
11
+ @circle.point = nil
12
+ @circle.should_not( be_valid )
13
+ end
14
+
15
+ it( 'does not have a valid point' ) do
16
+ @circle.point.longitude = nil
17
+ @circle.should_not( be_valid )
18
+ end
19
+ it( 'does not have a radius defined' ) do
20
+ @circle.radius = nil
21
+ @circle.should_not( be_valid )
22
+ end
23
+
24
+ it( 'does not have a numeric radius' ) do
25
+ @circle.radius = "not a number"
26
+ @circle.should_not( be_valid )
27
+ end
28
+
29
+ it( 'does not have a positive radius' ) do
30
+ @circle.radius = -1
31
+ @circle.should_not( be_valid )
32
+ end
33
+ end
34
+
35
+ context( 'on initialisation' ) do
36
+ context( 'from XML' ) do
37
+ before( :each ) do
38
+ @original_circle = RCAP::Circle.new( :radius => 10.5,
39
+ :point => RCAP::Point.new( :lattitude => 30, :longitude => 60 ))
40
+ @alert = RCAP::Alert.new( :infos => RCAP::Info.new( :areas => RCAP::Area.new( :circles => @original_circle )))
41
+ @xml_string = @alert.to_xml
42
+ @xml_document = REXML::Document.new( @xml_string )
43
+ @info_element = RCAP.xpath_first( @xml_document.root, RCAP::Info::XPATH )
44
+ @area_element = RCAP.xpath_first( @info_element, RCAP::Area::XPATH )
45
+ @circle_element = RCAP.xpath_first( @area_element, RCAP::Circle::XPATH )
46
+ @circle = RCAP::Circle.from_xml_element( @circle_element )
47
+ end
48
+
49
+ it( 'should parse the radius correctly' ) do
50
+ @circle.radius.should == @original_circle.radius
51
+ end
52
+
53
+ it( 'should parse the point correctly' ) do
54
+ @circle.point.lattitude.should == @original_circle.point.lattitude
55
+ @circle.point.longitude.should == @original_circle.point.longitude
56
+ end
57
+ end
58
+ end
59
+ end