rgeoserver 0.5.8.2 → 0.5.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/Gemfile +4 -2
- data/README.rdoc +7 -3
- data/VERSION +1 -1
- data/lib/rgeoserver.rb +4 -1
- data/lib/rgeoserver/catalog.rb +84 -57
- data/lib/rgeoserver/datastore.rb +92 -18
- data/lib/rgeoserver/featuretype.rb +107 -35
- data/lib/rgeoserver/layer.rb +43 -43
- data/lib/rgeoserver/layergroup.rb +110 -35
- data/lib/rgeoserver/resource.rb +27 -27
- data/lib/rgeoserver/utils/boundingbox.rb +88 -0
- data/lib/rgeoserver/utils/shapefile_info.rb +89 -0
- data/rgeoserver.gemspec +5 -1
- data/spec/fixtures/datasets/vector/granules.zip +0 -0
- data/spec/integration/geoserver_spec.rb +170 -55
- data/spec/utils/boundingbox_spec.rb +77 -0
- data/spec/utils/shapefile_info_spec.rb +22 -0
- metadata +183 -29
@@ -2,9 +2,22 @@
|
|
2
2
|
module RGeoServer
|
3
3
|
# A feature type is a vector based spatial resource or data set that originates from a data store. In some cases, like Shapefile, a feature type has a one-to-one relationship with its data store. In other cases, like PostGIS, the relationship of feature type to data store is many-to-one, with each feature type corresponding to a table in the database.
|
4
4
|
class FeatureType < ResourceInfo
|
5
|
-
OBJ_ATTRIBUTES = {:catalog => "catalog", :name => "name", :workspace => "workspace", :data_store => "data_store", :enabled => "enabled", :metadata_links => "metadataLinks", :title => "title", :abstract => "abstract" }
|
6
|
-
OBJ_DEFAULT_ATTRIBUTES =
|
7
|
-
|
5
|
+
OBJ_ATTRIBUTES = {:catalog => "catalog", :name => "name", :workspace => "workspace", :data_store => "data_store", :enabled => "enabled", :metadata_links => "metadataLinks", :title => "title", :abstract => "abstract", :native_bounds => 'native_bounds', :latlon_bounds => "latlon_bounds", :projection_policy => 'projection_policy'}
|
6
|
+
OBJ_DEFAULT_ATTRIBUTES =
|
7
|
+
{
|
8
|
+
:catalog => nil,
|
9
|
+
:workspace => nil,
|
10
|
+
:data_store => nil,
|
11
|
+
:name => nil,
|
12
|
+
:enabled => "false",
|
13
|
+
:metadata_links => [],
|
14
|
+
:title => nil,
|
15
|
+
:abstract => nil,
|
16
|
+
:native_bounds => {'minx'=>nil, 'miny' =>nil, 'maxx'=>nil, 'maxy'=>nil, 'crs' =>nil},
|
17
|
+
:latlon_bounds => {'minx'=>nil, 'miny' =>nil, 'maxx'=>nil, 'maxy'=>nil, 'crs' =>nil},
|
18
|
+
:projection_policy => :force
|
19
|
+
}
|
20
|
+
|
8
21
|
define_attribute_methods OBJ_ATTRIBUTES.keys
|
9
22
|
update_attribute_accessors OBJ_ATTRIBUTES
|
10
23
|
|
@@ -29,7 +42,7 @@ module RGeoServer
|
|
29
42
|
end
|
30
43
|
|
31
44
|
def route
|
32
|
-
@@route % [@workspace.name , @data_store.name
|
45
|
+
@@route % [@workspace.name , @data_store.name]
|
33
46
|
end
|
34
47
|
|
35
48
|
def message
|
@@ -37,12 +50,42 @@ module RGeoServer
|
|
37
50
|
xml.featureType {
|
38
51
|
xml.name @name if new?
|
39
52
|
xml.enabled @enabled if (enabled_changed? || new?)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
53
|
+
xml.title title
|
54
|
+
xml.abstract abstract
|
55
|
+
|
56
|
+
xml.store(:class => 'dataStore') {
|
57
|
+
xml.name @data_store.name
|
58
|
+
} if new? || data_store_changed?
|
59
|
+
|
60
|
+
xml.nativeBoundingBox {
|
61
|
+
xml.minx native_bounds['minx'] if native_bounds['minx']
|
62
|
+
xml.miny native_bounds['miny'] if native_bounds['miny']
|
63
|
+
xml.maxx native_bounds['maxx'] if native_bounds['maxx']
|
64
|
+
xml.maxy native_bounds['maxy'] if native_bounds['maxy']
|
65
|
+
xml.crs native_bounds['crs'] if native_bounds['crs']
|
66
|
+
} if valid_native_bounds?
|
67
|
+
|
68
|
+
xml.latLonBoundingBox {
|
69
|
+
xml.minx latlon_bounds['minx'] if latlon_bounds['minx']
|
70
|
+
xml.miny latlon_bounds['miny'] if latlon_bounds['miny']
|
71
|
+
xml.maxx latlon_bounds['maxx'] if latlon_bounds['maxx']
|
72
|
+
xml.maxy latlon_bounds['maxy'] if latlon_bounds['maxy']
|
73
|
+
xml.crs latlon_bounds['crs'] if latlon_bounds['crs']
|
74
|
+
} if valid_latlon_bounds?
|
75
|
+
|
76
|
+
xml.projectionPolicy get_projection_policy_message(projection_policy) if projection_policy
|
77
|
+
|
78
|
+
if new?
|
79
|
+
xml.attributes {
|
80
|
+
xml.attribute {
|
81
|
+
xml.name 'the_geom'
|
82
|
+
xml.minOccurs 0
|
83
|
+
xml.maxOccurs 1
|
84
|
+
xml.nillable true
|
85
|
+
xml.binding 'com.vividsolutions.jts.geom.Point'
|
86
|
+
}
|
87
|
+
}
|
88
|
+
else
|
46
89
|
xml.metadataLinks {
|
47
90
|
@metadata_links.each{ |m|
|
48
91
|
xml.metadataLink {
|
@@ -55,13 +98,13 @@ module RGeoServer
|
|
55
98
|
end
|
56
99
|
}
|
57
100
|
end
|
58
|
-
@message = builder.doc.to_xml
|
101
|
+
@message = builder.doc.to_xml
|
59
102
|
end
|
60
103
|
|
61
104
|
|
62
105
|
# @param [RGeoServer::Catalog] catalog
|
63
106
|
# @param [Hash] options
|
64
|
-
def initialize catalog, options
|
107
|
+
def initialize catalog, options
|
65
108
|
super({})
|
66
109
|
_run_initialize_callbacks do
|
67
110
|
@catalog = catalog
|
@@ -84,42 +127,42 @@ module RGeoServer
|
|
84
127
|
|
85
128
|
@name = options[:name].strip
|
86
129
|
@route = route
|
87
|
-
end
|
130
|
+
end
|
88
131
|
end
|
89
132
|
|
90
|
-
|
91
133
|
def profile_xml_to_hash profile_xml
|
92
134
|
doc = profile_xml_to_ng profile_xml
|
93
135
|
h = {
|
94
|
-
"name" => doc.at_xpath('//name').text.strip,
|
136
|
+
"name" => doc.at_xpath('//name').text.strip,
|
95
137
|
"title" => doc.at_xpath('//title/text()').to_s,
|
96
|
-
"abstract" => doc.at_xpath('//abstract/text()').to_s,
|
97
|
-
"workspace" => @workspace.name,
|
138
|
+
"abstract" => doc.at_xpath('//abstract/text()').to_s,
|
139
|
+
"workspace" => @workspace.name,
|
98
140
|
"data_store" => @data_store.name,
|
99
141
|
"nativeName" => doc.at_xpath('//nativeName/text()').to_s,
|
100
142
|
"srs" => doc.at_xpath('//srs/text()').to_s,
|
101
|
-
"
|
102
|
-
'minx' => doc.at_xpath('//nativeBoundingBox/minx/text()').to_s,
|
103
|
-
'miny' => doc.at_xpath('//nativeBoundingBox/miny/text()').to_s,
|
104
|
-
'maxx' => doc.at_xpath('//nativeBoundingBox/maxx/text()').to_s,
|
105
|
-
'maxy' => doc.at_xpath('//nativeBoundingBox/maxy/text()').to_s,
|
143
|
+
"native_bounds" => {
|
144
|
+
'minx' => doc.at_xpath('//nativeBoundingBox/minx/text()').to_s.to_f,
|
145
|
+
'miny' => doc.at_xpath('//nativeBoundingBox/miny/text()').to_s.to_f,
|
146
|
+
'maxx' => doc.at_xpath('//nativeBoundingBox/maxx/text()').to_s.to_f,
|
147
|
+
'maxy' => doc.at_xpath('//nativeBoundingBox/maxy/text()').to_s.to_f,
|
106
148
|
'crs' => doc.at_xpath('//nativeBoundingBox/crs/text()').to_s
|
107
149
|
},
|
108
|
-
"
|
109
|
-
'minx' => doc.at_xpath('//latLonBoundingBox/minx/text()').to_s,
|
110
|
-
'miny' => doc.at_xpath('//latLonBoundingBox/miny/text()').to_s,
|
111
|
-
'maxx' => doc.at_xpath('//latLonBoundingBox/maxx/text()').to_s,
|
112
|
-
'maxy' => doc.at_xpath('//latLonBoundingBox/maxy/text()').to_s,
|
150
|
+
"latlon_bounds" => {
|
151
|
+
'minx' => doc.at_xpath('//latLonBoundingBox/minx/text()').to_s.to_f,
|
152
|
+
'miny' => doc.at_xpath('//latLonBoundingBox/miny/text()').to_s.to_f,
|
153
|
+
'maxx' => doc.at_xpath('//latLonBoundingBox/maxx/text()').to_s.to_f,
|
154
|
+
'maxy' => doc.at_xpath('//latLonBoundingBox/maxy/text()').to_s.to_f,
|
113
155
|
'crs' => doc.at_xpath('//latLonBoundingBox/crs/text()').to_s
|
114
156
|
},
|
115
|
-
"
|
116
|
-
|
117
|
-
|
157
|
+
"projection_policy" => get_projection_policy_sym(doc.at_xpath('//projectionPolicy').text.strip),
|
158
|
+
"metadataLinks" => doc.xpath('//metadataLinks/metadataLink').collect{ |m|
|
159
|
+
{
|
160
|
+
'type' => m.at_xpath('//type/text()').to_s,
|
118
161
|
'metadataType' => m.at_xpath('//metadataType/text()').to_s,
|
119
162
|
'content' => m.at_xpath('//content/text()').to_s
|
120
|
-
}
|
163
|
+
}
|
121
164
|
},
|
122
|
-
"attributes" => doc.xpath('//attributes/attribute').collect{ |a|
|
165
|
+
"attributes" => doc.xpath('//attributes/attribute').collect{ |a|
|
123
166
|
{
|
124
167
|
'name' => a.at_xpath('//name/text()').to_s,
|
125
168
|
'minOccurs' => a.at_xpath('//minOccurs/text()').to_s,
|
@@ -128,10 +171,39 @@ module RGeoServer
|
|
128
171
|
'binding' => a.at_xpath('//binding/text()').to_s
|
129
172
|
}
|
130
173
|
}
|
131
|
-
}.freeze
|
132
|
-
h
|
174
|
+
}.freeze
|
175
|
+
h
|
133
176
|
end
|
134
177
|
|
178
|
+
def valid_native_bounds?
|
179
|
+
native_bounds &&
|
180
|
+
![native_bounds['minx'], native_bounds['miny'], native_bounds['maxx'], native_bounds['maxy'], native_bounds['crs']].compact.empty?
|
181
|
+
end
|
135
182
|
|
183
|
+
def valid_latlon_bounds?
|
184
|
+
latlon_bounds &&
|
185
|
+
![latlon_bounds['minx'], latlon_bounds['miny'], latlon_bounds['maxx'], latlon_bounds['maxy'], latlon_bounds['crs']].compact.empty?
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
def get_projection_policy_sym value
|
190
|
+
case value.upcase
|
191
|
+
when 'FORCE_DECLARED' then :force
|
192
|
+
when 'REPROJECT_TO_DECLARED' then :reproject
|
193
|
+
when 'NONE' then :keep
|
194
|
+
else
|
195
|
+
raise ArgumentError, "There is not correspondent to '%s'" % value
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def get_projection_policy_message value
|
200
|
+
case value
|
201
|
+
when :force then 'FORCE_DECLARED'
|
202
|
+
when :reproject then 'REPROJECT_TO_DECLARED'
|
203
|
+
when :keep then 'NONE'
|
204
|
+
else
|
205
|
+
raise ArgumentError, "There is not correspondent to '%s'" % value
|
206
|
+
end
|
207
|
+
end
|
136
208
|
end
|
137
|
-
end
|
209
|
+
end
|
data/lib/rgeoserver/layer.rb
CHANGED
@@ -5,32 +5,32 @@ module RGeoServer
|
|
5
5
|
|
6
6
|
OBJ_ATTRIBUTES = {:enabled => 'enabled', :queryable => 'queryable', :path => 'path', :catalog => 'catalog', :name => 'name', :default_style => 'default_style', :alternate_styles => 'alternate_styles', :metadata => 'metadata', :attribution => 'attribution', :layer_type => 'type' }
|
7
7
|
OBJ_DEFAULT_ATTRIBUTES = {
|
8
|
-
:enabled => 'true',
|
9
|
-
:queryable => 'true',
|
10
|
-
:path => '/',
|
11
|
-
:catalog => nil,
|
12
|
-
:name => nil,
|
13
|
-
:default_style => nil,
|
14
|
-
:alternate_styles => [],
|
8
|
+
:enabled => 'true',
|
9
|
+
:queryable => 'true',
|
10
|
+
:path => '/',
|
11
|
+
:catalog => nil,
|
12
|
+
:name => nil,
|
13
|
+
:default_style => nil,
|
14
|
+
:alternate_styles => [],
|
15
15
|
:metadata => {
|
16
16
|
'GWC.autoCacheStyles' => 'true',
|
17
17
|
'GWC.gutter' => '0',
|
18
18
|
'GWC.enabled' => 'true',
|
19
19
|
'GWC.cacheFormats' => 'image/jpeg,image/png',
|
20
20
|
'GWC.gridSets' => 'EPSG:4326,EPSG:900913'
|
21
|
-
},
|
21
|
+
},
|
22
22
|
:attribution => {
|
23
|
-
'logo_height' => '0',
|
24
|
-
'logo_width' => '0',
|
23
|
+
'logo_height' => '0',
|
24
|
+
'logo_width' => '0',
|
25
25
|
'title' => ''
|
26
|
-
},
|
27
|
-
:layer_type => nil
|
26
|
+
},
|
27
|
+
:layer_type => nil
|
28
28
|
}
|
29
29
|
|
30
30
|
define_attribute_methods OBJ_ATTRIBUTES.keys
|
31
31
|
update_attribute_accessors OBJ_ATTRIBUTES
|
32
32
|
|
33
|
-
@@route = "layers"
|
33
|
+
@@route = "layers"
|
34
34
|
@@resource_name = "layer"
|
35
35
|
|
36
36
|
def self.resource_name
|
@@ -46,12 +46,12 @@ module RGeoServer
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def route
|
49
|
-
@@route
|
49
|
+
@@route
|
50
50
|
end
|
51
51
|
|
52
52
|
# No direct layer creation
|
53
|
-
def create_route
|
54
|
-
nil
|
53
|
+
def create_route
|
54
|
+
nil
|
55
55
|
end
|
56
56
|
|
57
57
|
def update_params name_route = @name
|
@@ -60,15 +60,15 @@ module RGeoServer
|
|
60
60
|
|
61
61
|
def message
|
62
62
|
builder = Nokogiri::XML::Builder.new do |xml|
|
63
|
-
xml.layer {
|
64
|
-
xml.name @name
|
65
|
-
xml.path path
|
66
|
-
xml.type_ layer_type
|
67
|
-
xml.enabled @enabled
|
63
|
+
xml.layer {
|
64
|
+
xml.name @name
|
65
|
+
xml.path path
|
66
|
+
xml.type_ layer_type
|
67
|
+
xml.enabled @enabled
|
68
68
|
xml.queryable @queryable
|
69
69
|
xml.defaultStyle {
|
70
70
|
xml.name default_style
|
71
|
-
}
|
71
|
+
}
|
72
72
|
xml.styles {
|
73
73
|
alternate_styles.each { |s|
|
74
74
|
xml.style {
|
@@ -77,23 +77,23 @@ module RGeoServer
|
|
77
77
|
}
|
78
78
|
} unless alternate_styles.empty?
|
79
79
|
xml.resource(:class => resource.class.resource_name){
|
80
|
-
xml.name resource.name
|
80
|
+
xml.name resource.name
|
81
81
|
} unless resource.nil?
|
82
82
|
xml.metadata {
|
83
83
|
metadata.each_pair { |k,v|
|
84
84
|
xml.entry(:key => k) {
|
85
85
|
xml.text v
|
86
86
|
}
|
87
|
-
}
|
87
|
+
}
|
88
88
|
}
|
89
89
|
xml.attribution {
|
90
90
|
xml.title attribution['title'] unless attribution['title'].empty?
|
91
91
|
xml.logoWidth attribution['logo_width']
|
92
|
-
xml.logoHeight attribution['logo_height']
|
92
|
+
xml.logoHeight attribution['logo_height']
|
93
93
|
} if !attribution['logo_width'].nil? && !attribution['logo_height'].nil?
|
94
94
|
}
|
95
95
|
end
|
96
|
-
return builder.doc.to_xml
|
96
|
+
return builder.doc.to_xml
|
97
97
|
end
|
98
98
|
|
99
99
|
# @param [RGeoServer::Catalog] catalog
|
@@ -108,16 +108,16 @@ module RGeoServer
|
|
108
108
|
@name = options[:name].strip
|
109
109
|
#@default_style = options[:default_style] || ''
|
110
110
|
#@alternate_styles = options[:alternate_styles] || []
|
111
|
-
end
|
111
|
+
end
|
112
112
|
@route = route
|
113
113
|
end
|
114
114
|
|
115
115
|
def resource= r
|
116
|
-
if r.is_a?(RGeoServer::Coverage) || r.is_a?(RGeoServer::FeatureType)
|
116
|
+
if r.is_a?(RGeoServer::Coverage) || r.is_a?(RGeoServer::FeatureType)
|
117
117
|
@resource = r
|
118
118
|
else
|
119
|
-
raise 'Unknown resource type'
|
120
|
-
end
|
119
|
+
raise 'Unknown resource type'
|
120
|
+
end
|
121
121
|
end
|
122
122
|
|
123
123
|
def resource
|
@@ -134,7 +134,7 @@ module RGeoServer
|
|
134
134
|
when 'featureType'
|
135
135
|
return RGeoServer::FeatureType.new @catalog, :workspace => workspace, :data_store => store, :name => name
|
136
136
|
else
|
137
|
-
raise 'Unknown resource type'
|
137
|
+
raise 'Unknown resource type'
|
138
138
|
end
|
139
139
|
else
|
140
140
|
nil
|
@@ -160,7 +160,7 @@ module RGeoServer
|
|
160
160
|
workspace, _, store = link.match(/workspaces\/(.*?)\/(.*?)\/(.*?)\/(.*?)\/#{name}.xml$/).to_a[1,3]
|
161
161
|
|
162
162
|
h = {
|
163
|
-
"name" => name,
|
163
|
+
"name" => name,
|
164
164
|
"path" => doc.at_xpath('//path/text()').to_s,
|
165
165
|
"default_style" => doc.at_xpath('//defaultStyle/name/text()').to_s,
|
166
166
|
"alternate_styles" => doc.xpath('//styles/style/name/text()').collect{ |s| s.to_s},
|
@@ -168,7 +168,7 @@ module RGeoServer
|
|
168
168
|
"type" => doc.at_xpath('//type/text()').to_s,
|
169
169
|
"enabled" => doc.at_xpath('//enabled/text()').to_s,
|
170
170
|
"queryable" => doc.at_xpath('//queryable/text()').to_s,
|
171
|
-
"attribution" => {
|
171
|
+
"attribution" => {
|
172
172
|
"title" => doc.at_xpath('//attribution/title/text()').to_s,
|
173
173
|
"logo_width" => doc.at_xpath('//attribution/logoWidth/text()').to_s,
|
174
174
|
"logo_height" => doc.at_xpath('//attribution/logoHeight/text()').to_s
|
@@ -177,14 +177,14 @@ module RGeoServer
|
|
177
177
|
"type" => doc.at_xpath('//resource/@class').to_s,
|
178
178
|
"name" => doc.at_xpath('//resource/name/text()').to_s,
|
179
179
|
"store" => store,
|
180
|
-
"workspace" => workspace
|
180
|
+
"workspace" => workspace
|
181
181
|
},
|
182
|
-
"metadata" => doc.xpath('//metadata/entry').inject({}){ |h, e| h.merge(e['key']=> e.text.to_s) }
|
182
|
+
"metadata" => doc.xpath('//metadata/entry').inject({}){ |h, e| h.merge(e['key']=> e.text.to_s) }
|
183
183
|
}.freeze
|
184
|
-
h
|
184
|
+
h
|
185
185
|
end
|
186
186
|
|
187
|
-
def workspace
|
187
|
+
def workspace
|
188
188
|
resource.workspace
|
189
189
|
end
|
190
190
|
|
@@ -203,7 +203,7 @@ module RGeoServer
|
|
203
203
|
# }
|
204
204
|
# > lyr.seed :issue, options
|
205
205
|
|
206
|
-
# @param[String] operation
|
206
|
+
# @param[String] operation
|
207
207
|
# @option operation[Symbol] :issue seed
|
208
208
|
# @option operation[Symbol] :truncate seed
|
209
209
|
# @option operation[Symbol] :status of the seeding thread
|
@@ -224,7 +224,7 @@ module RGeoServer
|
|
224
224
|
# @param[Hash] options for seed message
|
225
225
|
def build_seed_request operation, options
|
226
226
|
builder = Nokogiri::XML::Builder.new do |xml|
|
227
|
-
xml.seedRequest {
|
227
|
+
xml.seedRequest {
|
228
228
|
xml.name prefixed_name
|
229
229
|
|
230
230
|
xml.srs {
|
@@ -233,9 +233,9 @@ module RGeoServer
|
|
233
233
|
|
234
234
|
xml.bounds {
|
235
235
|
xml.coords {
|
236
|
-
options[:bounds][:coords].each { |dbl|
|
236
|
+
options[:bounds][:coords].each { |dbl|
|
237
237
|
xml.double dbl
|
238
|
-
}
|
238
|
+
}
|
239
239
|
}
|
240
240
|
} unless options[:bounds].nil?
|
241
241
|
|
@@ -246,7 +246,7 @@ module RGeoServer
|
|
246
246
|
}
|
247
247
|
|
248
248
|
xml.parameters {
|
249
|
-
options[:parameters].each_pair { |k,v|
|
249
|
+
options[:parameters].each_pair { |k,v|
|
250
250
|
xml.entry {
|
251
251
|
xml.string k.upcase
|
252
252
|
xml.string v
|
@@ -259,4 +259,4 @@ module RGeoServer
|
|
259
259
|
end
|
260
260
|
end
|
261
261
|
|
262
|
-
end
|
262
|
+
end
|
@@ -3,13 +3,16 @@ module RGeoServer
|
|
3
3
|
# A layer group is a grouping of layers and styles that can be accessed as a single layer in a WMS GetMap request. A Layer group is often referred to as a "base map".
|
4
4
|
class LayerGroup < ResourceInfo
|
5
5
|
|
6
|
-
OBJ_ATTRIBUTES = {:catalog => 'catalog', :name => 'name', :layers => 'layers', :styles => 'styles', :bounds => 'bounds', :metadata => 'metadata' }
|
7
|
-
OBJ_DEFAULT_ATTRIBUTES = {:catalog => nil, :name => nil, :layers => [], :styles => [], :bounds => {'minx'=>
|
6
|
+
OBJ_ATTRIBUTES = {:catalog => 'catalog', :name => 'name', :workspace => 'workspace', :layers => 'layers', :styles => 'styles', :bounds => 'bounds', :metadata => 'metadata' }
|
7
|
+
OBJ_DEFAULT_ATTRIBUTES = {:catalog => nil, :name => nil, :workspace => nil, :layers => [], :styles => [], :bounds => {'minx'=>nil, 'miny' =>nil, 'maxx'=>nil, 'maxy'=>nil, 'crs' =>nil}, :metadata => {} }
|
8
8
|
|
9
9
|
define_attribute_methods OBJ_ATTRIBUTES.keys
|
10
10
|
update_attribute_accessors OBJ_ATTRIBUTES
|
11
11
|
|
12
|
-
@@
|
12
|
+
@@xml_list_node = "layerGroups"
|
13
|
+
@@xml_node = "layerGroup"
|
14
|
+
|
15
|
+
@@route = "layergroups"
|
13
16
|
@@resource_name = "layerGroup"
|
14
17
|
|
15
18
|
def self.resource_name
|
@@ -17,23 +20,26 @@ module RGeoServer
|
|
17
20
|
end
|
18
21
|
|
19
22
|
def self.root_xpath
|
20
|
-
"//#{@@
|
23
|
+
"//#{@@xml_list_node}/#{@@xml_node}"
|
21
24
|
end
|
22
25
|
|
23
26
|
def self.member_xpath
|
24
|
-
"//#{
|
27
|
+
"//#{@@xml_node}"
|
25
28
|
end
|
26
29
|
|
27
30
|
def route
|
28
|
-
@@route
|
31
|
+
@@route
|
29
32
|
end
|
30
33
|
|
31
34
|
def message
|
32
35
|
builder = Nokogiri::XML::Builder.new do |xml|
|
33
|
-
xml.layerGroup {
|
36
|
+
xml.layerGroup {
|
34
37
|
xml.name @name
|
38
|
+
xml.workspace {
|
39
|
+
xml.name workspace.name
|
40
|
+
} unless workspace.nil?
|
35
41
|
xml.layers {
|
36
|
-
layers.each { |l|
|
42
|
+
layers.each { |l|
|
37
43
|
xml.layer {
|
38
44
|
xml.name l.name
|
39
45
|
}
|
@@ -47,15 +53,15 @@ module RGeoServer
|
|
47
53
|
}
|
48
54
|
} unless styles.nil?
|
49
55
|
xml.bounds {
|
50
|
-
xml.minx bounds['minx']
|
51
|
-
xml.maxx bounds['maxx']
|
52
|
-
xml.miny bounds['miny']
|
53
|
-
xml.maxy bounds['maxy']
|
54
|
-
xml.crs bounds['crs']
|
55
|
-
} if
|
56
|
+
xml.minx bounds['minx'] if bounds['minx']
|
57
|
+
xml.maxx bounds['maxx'] if bounds['miny']
|
58
|
+
xml.miny bounds['miny'] if bounds['maxx']
|
59
|
+
xml.maxy bounds['maxy'] if bounds['maxy']
|
60
|
+
xml.crs bounds['crs'] if bounds['crs']
|
61
|
+
} if valid_bounds?
|
56
62
|
}
|
57
63
|
end
|
58
|
-
return builder.doc.to_xml
|
64
|
+
return builder.doc.to_xml
|
59
65
|
end
|
60
66
|
|
61
67
|
# @param [RGeoServer::Catalog] catalog
|
@@ -66,10 +72,11 @@ module RGeoServer
|
|
66
72
|
_run_initialize_callbacks do
|
67
73
|
@catalog = catalog
|
68
74
|
@name = options[:name].strip
|
69
|
-
|
75
|
+
@workspace = options[:workspace]
|
76
|
+
end
|
70
77
|
@route = route
|
71
78
|
end
|
72
|
-
|
79
|
+
|
73
80
|
# @param [Array<RGeoServer::Style>] sl list of styles
|
74
81
|
def styles= sl
|
75
82
|
if sl.inject(true){|t,s| t && s.is_a?(RGeoServer::Style)}
|
@@ -79,7 +86,7 @@ module RGeoServer
|
|
79
86
|
raise 'Unknown list of styles'
|
80
87
|
end
|
81
88
|
end
|
82
|
-
|
89
|
+
|
83
90
|
def styles
|
84
91
|
@styles ||= begin
|
85
92
|
unless profile['styles'].empty?
|
@@ -101,38 +108,106 @@ module RGeoServer
|
|
101
108
|
raise 'Unknown list of layers'
|
102
109
|
end
|
103
110
|
end
|
104
|
-
|
111
|
+
|
105
112
|
def layers
|
106
|
-
@layers
|
107
|
-
unless
|
108
|
-
|
113
|
+
@layers =
|
114
|
+
unless new?
|
115
|
+
begin
|
116
|
+
unless profile['layers'].empty?
|
117
|
+
return profile['layers'].map{ |s| RGeoServer::Layer.new @catalog, :name => s }
|
118
|
+
else
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
rescue Exception => e
|
122
|
+
nil
|
123
|
+
end
|
109
124
|
else
|
110
|
-
|
125
|
+
@layers || []
|
111
126
|
end
|
112
|
-
|
113
|
-
|
127
|
+
end
|
128
|
+
|
129
|
+
def workspace
|
130
|
+
if new?
|
131
|
+
return @workspace
|
132
|
+
else
|
133
|
+
return RGeoServer::Workspace.new @catalog, name: profile['workspace']
|
114
134
|
end
|
115
135
|
end
|
116
136
|
|
137
|
+
def bounds
|
138
|
+
@bounds = valid_bounds? ? @bounds : profile['bounds']
|
139
|
+
end
|
140
|
+
|
141
|
+
def valid_bounds?
|
142
|
+
@bounds &&
|
143
|
+
![@bounds['minx'], @bounds['miny'], @bounds['maxx'], @bounds['maxy'], @bounds['crs']].compact.empty?
|
144
|
+
end
|
145
|
+
|
146
|
+
def recalculate_bounds
|
147
|
+
bbox = BoundingBox.new
|
148
|
+
|
149
|
+
layers.each do |layer|
|
150
|
+
case layer.resource
|
151
|
+
when RGeoServer::FeatureType
|
152
|
+
b = layer.resource.latlon_bounds
|
153
|
+
bbox.add b['minx'], b['miny']
|
154
|
+
bbox.add b['maxx'], b['maxy']
|
155
|
+
else
|
156
|
+
raise NotImplementedError, 'The bounds calculation for coverage resource was not implemented.'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
@bounds =
|
161
|
+
{'minx' => bbox.min[0], 'miny' => bbox.min[1],
|
162
|
+
'maxx' => bbox.max[0], 'maxy' => bbox.max[1],
|
163
|
+
'crs' => @bounds['crs']}
|
164
|
+
|
165
|
+
bounds
|
166
|
+
end
|
167
|
+
|
168
|
+
# Retrieve the resource profile as a hash and cache it
|
169
|
+
# @return [Hash]
|
170
|
+
def profile
|
171
|
+
if @profile && !@profile.empty?
|
172
|
+
return @profile
|
173
|
+
end
|
174
|
+
|
175
|
+
@profile =
|
176
|
+
begin
|
177
|
+
h = unless @workspace
|
178
|
+
profile_xml_to_hash(@catalog.search @route => @name )
|
179
|
+
else
|
180
|
+
profile_xml_to_hash(@catalog.search workspaces: @workspace, @route => @name )
|
181
|
+
end
|
182
|
+
@new = false
|
183
|
+
h
|
184
|
+
rescue RestClient::ResourceNotFound
|
185
|
+
# The resource is new
|
186
|
+
@new = true
|
187
|
+
{}
|
188
|
+
end.freeze
|
189
|
+
end
|
190
|
+
|
117
191
|
def profile_xml_to_hash profile_xml
|
118
192
|
doc = profile_xml_to_ng profile_xml
|
119
193
|
name = doc.at_xpath('//name/text()').to_s
|
120
194
|
|
121
195
|
h = {
|
122
|
-
"name" => name,
|
196
|
+
"name" => name,
|
197
|
+
"workspace" => doc.xpath('//workspace/name/text()').to_s,
|
123
198
|
"layers" => doc.xpath('//layers/layer/name/text()').collect{|l| l.to_s},
|
124
199
|
"styles" => doc.xpath('//styles/style/name/text()').collect{|s| s.to_s},
|
125
|
-
"bounds" => {
|
126
|
-
"minx" => doc.at_xpath('//bounds/minx/text()').to_s,
|
127
|
-
"maxx" => doc.at_xpath('//bounds/maxx/text()').to_s,
|
128
|
-
"miny" => doc.at_xpath('//bounds/miny/text()').to_s,
|
129
|
-
"maxy" => doc.at_xpath('//bounds/maxy/text()').to_s,
|
130
|
-
"crs" => doc.at_xpath('//bounds/crs/text()')
|
200
|
+
"bounds" => {
|
201
|
+
"minx" => doc.at_xpath('//bounds/minx/text()').to_s.to_f,
|
202
|
+
"maxx" => doc.at_xpath('//bounds/maxx/text()').to_s.to_f,
|
203
|
+
"miny" => doc.at_xpath('//bounds/miny/text()').to_s.to_f,
|
204
|
+
"maxy" => doc.at_xpath('//bounds/maxy/text()').to_s.to_f,
|
205
|
+
"crs" => doc.at_xpath('//bounds/crs/text()').to_s
|
131
206
|
},
|
132
|
-
"metadata" => doc.xpath('//metadata/entry').inject({}){ |h, e| h.merge(e['key']=> e.text.to_s) }
|
207
|
+
"metadata" => doc.xpath('//metadata/entry').inject({}){ |h, e| h.merge(e['key']=> e.text.to_s) }
|
133
208
|
}.freeze
|
134
|
-
h
|
209
|
+
h
|
135
210
|
end
|
136
211
|
|
137
212
|
end
|
138
|
-
end
|
213
|
+
end
|