rcap 0.1

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