rgeoserver 0.5.8.2 → 0.5.9
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.
- 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
|