odata4 0.7.0
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.
- checksums.yaml +7 -0
- data/.autotest +2 -0
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +75 -0
- data/CHANGELOG.md +120 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +287 -0
- data/Rakefile +7 -0
- data/TODO.md +55 -0
- data/lib/odata4.rb +37 -0
- data/lib/odata4/complex_type.rb +76 -0
- data/lib/odata4/complex_type/property.rb +114 -0
- data/lib/odata4/entity.rb +319 -0
- data/lib/odata4/entity_set.rb +162 -0
- data/lib/odata4/enum_type.rb +95 -0
- data/lib/odata4/enum_type/property.rb +62 -0
- data/lib/odata4/navigation_property.rb +29 -0
- data/lib/odata4/navigation_property/proxy.rb +76 -0
- data/lib/odata4/properties.rb +25 -0
- data/lib/odata4/properties/binary.rb +50 -0
- data/lib/odata4/properties/boolean.rb +37 -0
- data/lib/odata4/properties/date.rb +27 -0
- data/lib/odata4/properties/date_time.rb +83 -0
- data/lib/odata4/properties/date_time_offset.rb +17 -0
- data/lib/odata4/properties/decimal.rb +50 -0
- data/lib/odata4/properties/float.rb +67 -0
- data/lib/odata4/properties/geography.rb +13 -0
- data/lib/odata4/properties/geography/base.rb +162 -0
- data/lib/odata4/properties/geography/line_string.rb +33 -0
- data/lib/odata4/properties/geography/point.rb +31 -0
- data/lib/odata4/properties/geography/polygon.rb +38 -0
- data/lib/odata4/properties/guid.rb +17 -0
- data/lib/odata4/properties/integer.rb +107 -0
- data/lib/odata4/properties/number.rb +14 -0
- data/lib/odata4/properties/string.rb +72 -0
- data/lib/odata4/properties/time.rb +40 -0
- data/lib/odata4/properties/time_of_day.rb +27 -0
- data/lib/odata4/property.rb +118 -0
- data/lib/odata4/property_registry.rb +41 -0
- data/lib/odata4/query.rb +231 -0
- data/lib/odata4/query/criteria.rb +92 -0
- data/lib/odata4/query/criteria/comparison_operators.rb +49 -0
- data/lib/odata4/query/criteria/date_functions.rb +61 -0
- data/lib/odata4/query/criteria/geography_functions.rb +21 -0
- data/lib/odata4/query/criteria/lambda_operators.rb +27 -0
- data/lib/odata4/query/criteria/string_functions.rb +40 -0
- data/lib/odata4/query/in_batches.rb +58 -0
- data/lib/odata4/query/result.rb +84 -0
- data/lib/odata4/query/result/atom.rb +41 -0
- data/lib/odata4/query/result/json.rb +42 -0
- data/lib/odata4/railtie.rb +19 -0
- data/lib/odata4/service.rb +344 -0
- data/lib/odata4/service_registry.rb +52 -0
- data/lib/odata4/version.rb +3 -0
- data/odata4.gemspec +34 -0
- data/spec/fixtures/files/entity_to_xml.xml +17 -0
- data/spec/fixtures/files/metadata.xml +150 -0
- data/spec/fixtures/files/product_0.json +10 -0
- data/spec/fixtures/files/product_0.xml +28 -0
- data/spec/fixtures/files/products.json +106 -0
- data/spec/fixtures/files/products.xml +308 -0
- data/spec/fixtures/files/supplier_0.json +26 -0
- data/spec/fixtures/files/supplier_0.xml +32 -0
- data/spec/fixtures/vcr_cassettes/complex_type_specs.yml +127 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs.yml +1348 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/bad_entry.yml +183 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/existing_entry.yml +256 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/new_entry.yml +185 -0
- data/spec/fixtures/vcr_cassettes/entity_specs.yml +285 -0
- data/spec/fixtures/vcr_cassettes/navigation_property_proxy_specs.yml +346 -0
- data/spec/fixtures/vcr_cassettes/query/result_specs.yml +189 -0
- data/spec/fixtures/vcr_cassettes/query_specs.yml +663 -0
- data/spec/fixtures/vcr_cassettes/service_registry_specs.yml +129 -0
- data/spec/fixtures/vcr_cassettes/service_specs.yml +127 -0
- data/spec/fixtures/vcr_cassettes/usage_example_specs.yml +749 -0
- data/spec/odata4/complex_type_spec.rb +116 -0
- data/spec/odata4/entity/shared_examples.rb +82 -0
- data/spec/odata4/entity_set_spec.rb +168 -0
- data/spec/odata4/entity_spec.rb +151 -0
- data/spec/odata4/enum_type_spec.rb +134 -0
- data/spec/odata4/navigation_property/proxy_spec.rb +44 -0
- data/spec/odata4/navigation_property_spec.rb +55 -0
- data/spec/odata4/properties/binary_spec.rb +50 -0
- data/spec/odata4/properties/boolean_spec.rb +72 -0
- data/spec/odata4/properties/date_spec.rb +23 -0
- data/spec/odata4/properties/date_time_offset_spec.rb +30 -0
- data/spec/odata4/properties/date_time_spec.rb +23 -0
- data/spec/odata4/properties/decimal_spec.rb +24 -0
- data/spec/odata4/properties/float_spec.rb +45 -0
- data/spec/odata4/properties/geography/line_string_spec.rb +33 -0
- data/spec/odata4/properties/geography/point_spec.rb +29 -0
- data/spec/odata4/properties/geography/polygon_spec.rb +55 -0
- data/spec/odata4/properties/geography/shared_examples.rb +72 -0
- data/spec/odata4/properties/guid_spec.rb +17 -0
- data/spec/odata4/properties/integer_spec.rb +58 -0
- data/spec/odata4/properties/string_spec.rb +46 -0
- data/spec/odata4/properties/time_of_day_spec.rb +23 -0
- data/spec/odata4/properties/time_spec.rb +15 -0
- data/spec/odata4/property_registry_spec.rb +16 -0
- data/spec/odata4/property_spec.rb +32 -0
- data/spec/odata4/query/criteria_spec.rb +229 -0
- data/spec/odata4/query/result_spec.rb +53 -0
- data/spec/odata4/query_spec.rb +196 -0
- data/spec/odata4/service_registry_spec.rb +18 -0
- data/spec/odata4/service_spec.rb +80 -0
- data/spec/odata4/usage_example_spec.rb +176 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/coverage.rb +2 -0
- data/spec/support/vcr.rb +9 -0
- metadata +380 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module OData4
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the Binary OData4 type.
|
|
4
|
+
class Binary < OData4::Property
|
|
5
|
+
# Returns the property value, properly typecast
|
|
6
|
+
# @return [Integer,nil]
|
|
7
|
+
def value
|
|
8
|
+
if (@value.nil? || @value.empty?) && allows_nil?
|
|
9
|
+
nil
|
|
10
|
+
else
|
|
11
|
+
@value.to_i
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Sets the property value
|
|
16
|
+
# @params new_value [0,1,Boolean]
|
|
17
|
+
def value=(new_value)
|
|
18
|
+
validate(new_value)
|
|
19
|
+
@value = parse_value(new_value)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# The OData4 type name
|
|
23
|
+
def type
|
|
24
|
+
'Edm.Binary'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Value to be used in URLs.
|
|
28
|
+
# @return [String]
|
|
29
|
+
def url_value
|
|
30
|
+
"binary'#{value}'"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def parse_value(value)
|
|
36
|
+
if value == 0 || value == '0' || value == false
|
|
37
|
+
'0'
|
|
38
|
+
else
|
|
39
|
+
'1'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def validate(value)
|
|
44
|
+
unless [0,1,'0','1',true,false].include?(value)
|
|
45
|
+
raise ArgumentError, 'Value is outside accepted range: 0 or 1'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module OData4
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the Boolean OData4 type.
|
|
4
|
+
class Boolean < OData4::Property
|
|
5
|
+
# Returns the property value, properly typecast
|
|
6
|
+
# @return [Boolean, nil]
|
|
7
|
+
def value
|
|
8
|
+
if (@value.nil? || @value.empty?) && allows_nil?
|
|
9
|
+
nil
|
|
10
|
+
else
|
|
11
|
+
(@value == 'true' || @value == '1')
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Sets the property value
|
|
16
|
+
# @params new_value [Boolean]
|
|
17
|
+
def value=(new_value)
|
|
18
|
+
validate(new_value)
|
|
19
|
+
@value = new_value.to_s
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# The OData4 type name
|
|
23
|
+
def type
|
|
24
|
+
'Edm.Boolean'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def validate(value)
|
|
30
|
+
return if value.nil? && allows_nil?
|
|
31
|
+
unless [0,1,'0','1','true','false',true,false].include?(value)
|
|
32
|
+
raise ArgumentError, 'Value is outside accepted range: true or false'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'odata4/properties/date_time'
|
|
2
|
+
|
|
3
|
+
module OData4
|
|
4
|
+
module Properties
|
|
5
|
+
# Defines the Date OData4 type.
|
|
6
|
+
class Date < OData4::Properties::DateTime
|
|
7
|
+
# The OData4 type name
|
|
8
|
+
def type
|
|
9
|
+
'Edm.Date'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def url_value
|
|
13
|
+
@value
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
protected
|
|
17
|
+
|
|
18
|
+
def date_class
|
|
19
|
+
::Date
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def strptime_format
|
|
23
|
+
'%Y-%m-%d'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module OData4
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the DateTime OData4 type.
|
|
4
|
+
class DateTime < OData4::Property
|
|
5
|
+
# Returns the property value, properly typecast
|
|
6
|
+
# @return [DateTime, nil]
|
|
7
|
+
def value
|
|
8
|
+
if (@value.nil? || @value.empty?) && allows_nil?
|
|
9
|
+
nil
|
|
10
|
+
else
|
|
11
|
+
begin
|
|
12
|
+
date_class.strptime(@value, strptime_format)
|
|
13
|
+
rescue ArgumentError
|
|
14
|
+
date_class.parse(@value)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Sets the property value
|
|
20
|
+
# @params new_value [DateTime]
|
|
21
|
+
def value=(new_value)
|
|
22
|
+
validate(new_value)
|
|
23
|
+
@value = parse_value(new_value)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The OData4 type name
|
|
27
|
+
def type
|
|
28
|
+
'Edm.DateTime'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Value to be used in JSON.
|
|
32
|
+
# @return [String]
|
|
33
|
+
def xml_value
|
|
34
|
+
@value.andand.sub(/[\+\-]00:00$/, 'Z')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Value to be used in JSON.
|
|
38
|
+
# @return [String]
|
|
39
|
+
def json_value
|
|
40
|
+
xml_value
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Value to be used in URLs.
|
|
44
|
+
# @return [String]
|
|
45
|
+
def url_value
|
|
46
|
+
xml_value
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
protected
|
|
50
|
+
|
|
51
|
+
# Specifies date/time implementation to use
|
|
52
|
+
def date_class
|
|
53
|
+
::DateTime
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Specifies the date/time format string used for `strptime`
|
|
57
|
+
def strptime_format
|
|
58
|
+
#'%Y-%m-%dT%H:%M:%S.%L'
|
|
59
|
+
"%Y-%m-%dT%H:%M:%SZ"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def validate(value)
|
|
63
|
+
begin
|
|
64
|
+
return if value.nil? && allows_nil?
|
|
65
|
+
return if value.is_a?(date_class)
|
|
66
|
+
date_class.parse(value)
|
|
67
|
+
rescue
|
|
68
|
+
raise ArgumentError, "Value '#{value}' is not a date time format that can be parsed"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def parse_value(value)
|
|
73
|
+
return value if value.nil? && allows_nil?
|
|
74
|
+
if value.is_a?(date_class)
|
|
75
|
+
parsed_value = value
|
|
76
|
+
else
|
|
77
|
+
parsed_value = date_class.parse(value)
|
|
78
|
+
end
|
|
79
|
+
parsed_value.strftime(strptime_format)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module OData4
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the DateTimeOffset OData4 type.
|
|
4
|
+
class DateTimeOffset < OData4::Properties::DateTime
|
|
5
|
+
# The OData4 type name
|
|
6
|
+
def type
|
|
7
|
+
'Edm.DateTimeOffset'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
protected
|
|
11
|
+
|
|
12
|
+
def strptime_format
|
|
13
|
+
'%Y-%m-%dT%H:%M:%S%:z'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module OData4
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the Decimal OData4 type.
|
|
4
|
+
class Decimal < OData4::Property
|
|
5
|
+
# Returns the property value, properly typecast
|
|
6
|
+
# @return [BigDecimal,nil]
|
|
7
|
+
def value
|
|
8
|
+
if (@value.nil? || @value.empty?) && (strict? && allows_nil?)
|
|
9
|
+
nil
|
|
10
|
+
else
|
|
11
|
+
BigDecimal(@value)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Sets the property value
|
|
16
|
+
# @params new_value something BigDecimal() can parse
|
|
17
|
+
def value=(new_value)
|
|
18
|
+
validate(BigDecimal(new_value.to_s))
|
|
19
|
+
@value = new_value.to_s
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# The OData4 type name
|
|
23
|
+
def type
|
|
24
|
+
'Edm.Decimal'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Value to be used in URLs.
|
|
28
|
+
# @return [String]
|
|
29
|
+
def url_value
|
|
30
|
+
"#{value.to_f}M"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def validate(value)
|
|
36
|
+
if value > max_value || value < min_value || value.precs.first > 29
|
|
37
|
+
raise ArgumentError, "Value is outside accepted range: #{min_value} to #{max_value}, or has more than 29 significant digits"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def min_value
|
|
42
|
+
@min ||= BigDecimal(-7.9 * (10**28), 2)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def max_value
|
|
46
|
+
@max ||= BigDecimal(7.9 * (10**28), 2)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module OData4
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the Float OData4 type.
|
|
4
|
+
class Float < OData4::Property
|
|
5
|
+
include OData4::Properties::Number
|
|
6
|
+
|
|
7
|
+
# Returns the property value, properly typecast
|
|
8
|
+
# @return [Float,nil]
|
|
9
|
+
def value
|
|
10
|
+
if (@value.nil? || @value.empty?) && allows_nil?
|
|
11
|
+
nil
|
|
12
|
+
else
|
|
13
|
+
@value.to_f
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Sets the property value
|
|
18
|
+
# @params new_value [to_f]
|
|
19
|
+
def value=(new_value)
|
|
20
|
+
validate(new_value.to_f)
|
|
21
|
+
@value = new_value.to_f.to_s
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# The OData4 type name
|
|
25
|
+
def type
|
|
26
|
+
'Edm.Double'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def min_value
|
|
32
|
+
@min ||= -(1.7 * (10**308))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def max_value
|
|
36
|
+
@max ||= (1.7 * (10**308))
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Defines the Double (Float) OData4 type.
|
|
41
|
+
class Double < OData4::Properties::Float; end
|
|
42
|
+
|
|
43
|
+
# Defines the Single (Float) OData4 type.
|
|
44
|
+
class Single < OData4::Properties::Float
|
|
45
|
+
# The OData4 type name
|
|
46
|
+
def type
|
|
47
|
+
'Edm.Single'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Value to be used in URLs.
|
|
51
|
+
# @return [String]
|
|
52
|
+
def url_value
|
|
53
|
+
"#{value}F"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def min_value
|
|
59
|
+
@min ||= -(3.4 * (10**38))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def max_value
|
|
63
|
+
@max ||= (3.4 * (10**38))
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'odata4/properties/geography/base'
|
|
2
|
+
require 'odata4/properties/geography/point'
|
|
3
|
+
require 'odata4/properties/geography/line_string'
|
|
4
|
+
require 'odata4/properties/geography/polygon'
|
|
5
|
+
|
|
6
|
+
OData4::Properties::Geography.constants.each do |property_name|
|
|
7
|
+
next if property_name =~ /Base$/
|
|
8
|
+
klass = OData4::Properties::Geography.const_get(property_name)
|
|
9
|
+
if klass.is_a?(Class)
|
|
10
|
+
property = klass.new('test', nil)
|
|
11
|
+
OData4::PropertyRegistry.add(property.type, property.class)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
module OData4
|
|
2
|
+
module Properties
|
|
3
|
+
module Geography
|
|
4
|
+
class Base < OData4::Property
|
|
5
|
+
# The SRID (Spatial Reference ID) of this property.
|
|
6
|
+
attr_accessor :srid
|
|
7
|
+
|
|
8
|
+
# The default SRID (same as used by GPS)
|
|
9
|
+
DEFAULT_SRID = 4326
|
|
10
|
+
|
|
11
|
+
# Initializes a geography property.
|
|
12
|
+
#
|
|
13
|
+
# Special options available for geographic types:
|
|
14
|
+
#
|
|
15
|
+
# +srid+: the SRID (spatial reference ID) of the
|
|
16
|
+
# coordinate system being used.
|
|
17
|
+
# Defaults to 4326 (same as GPS).
|
|
18
|
+
#
|
|
19
|
+
# @param name [to_s]
|
|
20
|
+
# @param value [Hash|Array|to_s|nil]
|
|
21
|
+
# @param options [Hash]
|
|
22
|
+
def initialize(name, value, options = {})
|
|
23
|
+
super(name, value, options)
|
|
24
|
+
self.value = value
|
|
25
|
+
self.srid = srid || options[:srid] || DEFAULT_SRID
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Sets the value of the property.
|
|
29
|
+
# @param value [Hash|Array|to_s|nil]
|
|
30
|
+
def value=(value)
|
|
31
|
+
if value.nil? && allows_nil?
|
|
32
|
+
@value = nil
|
|
33
|
+
elsif value.is_a?(Hash)
|
|
34
|
+
@value = value['coordinates']
|
|
35
|
+
elsif value.is_a?(Array)
|
|
36
|
+
@value = value
|
|
37
|
+
else
|
|
38
|
+
@value = parse_wkt(value.to_s)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Value to be used in URLs.
|
|
43
|
+
# @return [String]
|
|
44
|
+
def url_value
|
|
45
|
+
"geography'SRID=#{srid};#{type_name}(#{coords_to_s})'"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Value to be used in JSON.
|
|
49
|
+
# @return [Hash]
|
|
50
|
+
def json_value
|
|
51
|
+
{
|
|
52
|
+
type: type_name,
|
|
53
|
+
coordinates: value,
|
|
54
|
+
crs: crs
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# The name of the SRS (Spatial Reference System) used.
|
|
59
|
+
# Basically, the SRID in URI/URL form.
|
|
60
|
+
# @return [String]
|
|
61
|
+
def srs_name
|
|
62
|
+
if srid == DEFAULT_SRID
|
|
63
|
+
"http://www.opengis.net/def/crs/EPSG/0/#{srid}"
|
|
64
|
+
else
|
|
65
|
+
raise NotImplementedError, "Unsupported SRID #{srid}"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# The name of the CRS (Coordinate Reference System) used.
|
|
70
|
+
# Used in GeoJSON representation
|
|
71
|
+
# @return [String]
|
|
72
|
+
def crs_name
|
|
73
|
+
if srid == DEFAULT_SRID
|
|
74
|
+
"EPSG:#{srid}"
|
|
75
|
+
else
|
|
76
|
+
raise NotImplementedError, "Unsupported SRID #{srid}"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# The full CRS representation as used by GeoJSON
|
|
81
|
+
# @return [Hash]
|
|
82
|
+
def crs
|
|
83
|
+
{
|
|
84
|
+
type: 'name',
|
|
85
|
+
properties: { name: crs_name }
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Returns the XML representation of the property to the supplied XML
|
|
90
|
+
# builder.
|
|
91
|
+
# @param xml_builder [Nokogiri::XML::Builder]
|
|
92
|
+
def to_xml(xml_builder)
|
|
93
|
+
attributes = { 'metadata:type' => type }
|
|
94
|
+
type_attrs = { 'gml:srsName' => srs_name }
|
|
95
|
+
|
|
96
|
+
xml_builder['data'].send(name.to_sym, attributes) do
|
|
97
|
+
xml_builder['gml'].send(type_name, type_attrs) do
|
|
98
|
+
value_to_xml(xml_value, xml_builder)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Creates a new property instance from an XML element
|
|
104
|
+
# @param property_xml [Nokogiri::XML::Element]
|
|
105
|
+
# @param options [Hash]
|
|
106
|
+
# @return [OData4::Properties::Geography]
|
|
107
|
+
def self.from_xml(property_xml, options = {})
|
|
108
|
+
if property_xml.attributes['null'].andand.value == 'true'
|
|
109
|
+
content = nil
|
|
110
|
+
else
|
|
111
|
+
content = parse_xml(property_xml)
|
|
112
|
+
options.merge!(srid: srid_from_xml(property_xml))
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
new(property_xml.name, content, options)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
protected
|
|
119
|
+
|
|
120
|
+
def type_name
|
|
121
|
+
self.class.name.split('::').last
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def parse_wkt(value)
|
|
125
|
+
if value =~ /^geography'(SRID=(\d+);)+(\w+)\((.+)\)'$/
|
|
126
|
+
$3 == type_name or raise ArgumentError, "Invalid geography type '#{$3}'"
|
|
127
|
+
self.srid = $1 ? $2.to_i : DEFAULT_SRID
|
|
128
|
+
coords_from_s($4)
|
|
129
|
+
else
|
|
130
|
+
raise ArgumentError, "Invalid geography value '#{value}'"
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Recursively turn a JSON-like data structure into XML
|
|
135
|
+
def value_to_xml(value, xml_builder)
|
|
136
|
+
if value.is_a?(Hash)
|
|
137
|
+
value.each do |key, val|
|
|
138
|
+
xml_builder['gml'].send(key) do
|
|
139
|
+
value_to_xml(val, xml_builder)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
elsif value.is_a?(Array)
|
|
143
|
+
value.each do |val|
|
|
144
|
+
value_to_xml(val, xml_builder)
|
|
145
|
+
end
|
|
146
|
+
else
|
|
147
|
+
xml_builder.text(value)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Extract the SRID from a GML element's `srsName` attribute
|
|
152
|
+
def self.srid_from_xml(property_xml)
|
|
153
|
+
gml_elem = property_xml.element_children.first
|
|
154
|
+
srs_attr = gml_elem.attributes['srsName']
|
|
155
|
+
if srs_attr
|
|
156
|
+
srs_attr.value.split(/[\/:]/).last.to_i
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|