rgeoserver 0.5.5 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,104 +1,99 @@
1
1
 
2
2
  module RGeoServer
3
+ # A style describes how a resource (feature type or coverage) should be symbolized or rendered by a Web Map Service. In GeoServer styles are specified with {SLD}[http://docr.geoserver.org/stable/en/user/styling/index.html#styling]
4
+ class Style < ResourceInfo
3
5
 
4
- class Style < ResourceInfo
6
+ OBJ_ATTRIBUTES = {:catalog => 'catalog', :name => 'name', :sld_version => 'sldVersion', :filename => 'filename', :sld_doc => 'sld_doc' }
7
+ OBJ_DEFAULT_ATTRIBUTES = {:catalog => nil, :name => nil, :sld_version => nil, :filename => '', :sld_doc => nil }
5
8
 
6
- OBJ_ATTRIBUTES = {:catalog => 'catalog', :name => 'name', :sld_version => 'sldVersion', :filename => 'filename', :sld_doc => 'sld_doc' }
7
- OBJ_DEFAULT_ATTRIBUTES = {:catalog => nil, :name => nil, :sld_version => nil, :filename => '', :sld_doc => nil }
9
+ define_attribute_methods OBJ_ATTRIBUTES.keys
10
+ update_attribute_accessors OBJ_ATTRIBUTES
8
11
 
9
- define_attribute_methods OBJ_ATTRIBUTES.keys
10
- update_attribute_accessors OBJ_ATTRIBUTES
12
+ @@route = "styles"
13
+ @@resource_name = "style"
14
+ @@sld_namespace = "http://www.opengis.net/sld"
11
15
 
12
- @@r = Confstruct::Configuration.new(:route => 'styles', :resource_name => 'style', :sld_namespace => 'http://www.opengis.net/sld')
13
-
14
- def self.resource_name
15
- @@r.resource_name
16
- end
16
+ def self.resource_name
17
+ @@resource_name
18
+ end
17
19
 
18
- def self.create_method
19
- :post
20
- end
20
+ def self.root_xpath
21
+ "//#{@@route}/#{@@resource_name}"
22
+ end
21
23
 
22
- def self.update_method
23
- :put
24
- end
25
-
26
- def self.root_xpath
27
- "//#{@@r.route}/#{@@r.resource_name}"
28
- end
24
+ def self.member_xpath
25
+ "//#{resource_name}"
26
+ end
29
27
 
30
- def self.member_xpath
31
- "//#{resource_name}"
32
- end
28
+ def route
29
+ @@route
30
+ end
31
+
32
+ def sld_namespace
33
+ @@sld_namespace
34
+ end
33
35
 
34
- def route
35
- @@r.route
36
- end
37
-
38
- def create_options
39
- {
40
- :headers => {
41
- :accept => :xml,
42
- :content_type=> "application/vnd.ogc.sld+xml"
43
- },
44
- :format => :xml,
45
- :name => @name
46
- }
47
- end
48
-
49
- def update_options
50
- {
51
- :headers => {
52
- :accept => :xml,
53
- :content_type=> "application/vnd.ogc.sld+xml"
54
- },
55
- :format => :sld
56
- }
57
- end
58
36
 
59
- def sld_namespace
60
- @@r.sld_namespace
61
- end
37
+ def create_options
38
+ {
39
+ :headers => {
40
+ :accept => :xml,
41
+ :content_type=> "application/vnd.ogc.sld+xml"
42
+ },
43
+ :format => :xml,
44
+ :name => @name
45
+ }
46
+ end
47
+
48
+ def update_options
49
+ {
50
+ :headers => {
51
+ :accept => :xml,
52
+ :content_type=> "application/vnd.ogc.sld+xml"
53
+ },
54
+ :format => :sld
55
+ }
56
+ end
62
57
 
63
- def message
64
- @sld_doc
65
- end
58
+ def message
59
+ @sld_doc
60
+ end
66
61
 
67
- # @param [RGeoServer::Catalog] catalog
68
- # @param [Hash] options
69
- def initialize catalog, options
70
- super({})
71
- _run_initialize_callbacks do
72
- @catalog = catalog
73
- @name = options[:name].strip
74
- end
75
- @route = route
76
- end
77
-
78
- # Obtain all layers that use this style.
79
- # WARNING: This will be slow and inneficient when the list of all layers is too long.
80
- def layers &block
81
- return to_enum(:layers).to_a unless block_given?
82
- @catalog.get_layers do |l|
83
- lyrs = [l.profile['default_style']]+l.profile['alternate_styles']
84
- yield l if lyrs.include? @name
85
- end
86
- end
62
+ # @param [RGeoServer::Catalog] catalog
63
+ # @param [Hash] options
64
+ def initialize catalog, options
65
+ super({})
66
+ _run_initialize_callbacks do
67
+ @catalog = catalog
68
+ @name = options[:name].strip
69
+ end
70
+ @route = route
71
+ end
87
72
 
88
- def profile_xml_to_hash profile_xml
89
- doc = profile_xml_to_ng profile_xml
90
- h = {
91
- 'name' => doc.at_xpath('//name').text.strip,
92
- 'sld_version' => doc.at_xpath('//sldVersion/version/text()').to_s,
93
- 'filename' => doc.at_xpath('//filename/text()').to_s,
94
- 'sld_doc' => begin
95
- Nokogiri::XML(@catalog.search({:styles => @name}, options={:format => 'sld'})).to_xml
96
- rescue RestClient::ResourceNotFound
97
- nil
98
- end
99
- }.freeze
100
- h
101
- end
102
-
73
+ # Obtain all layers that use this style.
74
+ # WARNING: This will be slow and inneficient when the list of all layers is too long.
75
+ def layers &block
76
+ return to_enum(:layers).to_a unless block_given?
77
+ @catalog.get_layers do |l|
78
+ lyrs = [l.profile['default_style']]+l.profile['alternate_styles']
79
+ yield l if lyrs.include? @name
80
+ end
103
81
  end
82
+
83
+ def profile_xml_to_hash profile_xml
84
+ doc = profile_xml_to_ng profile_xml
85
+ h = {
86
+ 'name' => doc.at_xpath('//name').text.strip,
87
+ 'sld_version' => doc.at_xpath('//sldVersion/version/text()').to_s,
88
+ 'filename' => doc.at_xpath('//filename/text()').to_s,
89
+ 'sld_doc' => begin
90
+ Nokogiri::XML(@catalog.search({:styles => @name}, options={:format => 'sld'})).to_xml
91
+ rescue RestClient::ResourceNotFound
92
+ nil
93
+ end
94
+ }.freeze
95
+ h
96
+ end
97
+
98
+ end
104
99
  end
@@ -5,26 +5,16 @@ module RGeoServer
5
5
 
6
6
  define_attribute_methods [:catalog, :workspace, :name]
7
7
 
8
- @@r = Confstruct::Configuration.new(
9
- :route => "workspaces/%s/wmsstores",
10
- :root => "wmsStores",
11
- :resource_name => "wmsStore"
12
- )
8
+ @@route = "workspaces/%s/wmsstores"
9
+ @@root = "wmsStores"
10
+ @@resource_name = "wmsStore"
13
11
 
14
12
  def self.root
15
- @@r.root
16
- end
17
-
18
- def self.create_method
19
- :put
20
- end
21
-
22
- def self.update_method
23
- :put
13
+ @@root
24
14
  end
25
15
 
26
16
  def self.resource_name
27
- @@r.resource_name
17
+ @@resource_name
28
18
  end
29
19
 
30
20
  def self.root_xpath
@@ -36,7 +26,7 @@ module RGeoServer
36
26
  end
37
27
 
38
28
  def route
39
- @@r.route % @workspace.name
29
+ @@route % @workspace.name
40
30
  end
41
31
 
42
32
  def xml options = nil
@@ -1,95 +1,88 @@
1
1
 
2
2
  module RGeoServer
3
+ # A workspace is a grouping of data stores. More commonly known as a namespace, it is commonly used to group data that is related in some way.
4
+ class Workspace < ResourceInfo
3
5
 
4
- class Workspace < ResourceInfo
6
+ OBJ_ATTRIBUTES = {:enabled => 'enabled', :catalog => 'catalog', :name => 'name' }
7
+ OBJ_DEFAULT_ATTRIBUTES = {:enabled => 'true', :catalog => nil, :name => nil }
5
8
 
6
- OBJ_ATTRIBUTES = {:enabled => 'enabled', :catalog => 'catalog', :name => 'name' }
7
- OBJ_DEFAULT_ATTRIBUTES = {:enabled => 'true', :catalog => nil, :name => nil }
9
+ define_attribute_methods OBJ_ATTRIBUTES.keys
10
+ update_attribute_accessors OBJ_ATTRIBUTES
8
11
 
9
- define_attribute_methods OBJ_ATTRIBUTES.keys
10
- update_attribute_accessors OBJ_ATTRIBUTES
12
+ @@route = "workspaces"
13
+ @@resource_name = "workspace"
11
14
 
12
- @@r = Confstruct::Configuration.new(:route => 'workspaces', :resource_name => 'workspace')
13
-
14
- def self.resource_name
15
- @@r.resource_name
16
- end
15
+ def self.resource_name
16
+ @@resource_name
17
+ end
17
18
 
18
- def self.create_method
19
- :post
20
- end
19
+ def self.root_xpath
20
+ "//#{@@route}/#{@@resource_name}"
21
+ end
21
22
 
22
- def self.update_method
23
- :put
24
- end
25
-
26
- def self.root_xpath
27
- "//#{@@r.route}/#{@@r.resource_name}"
28
- end
23
+ def self.member_xpath
24
+ "//#{resource_name}"
25
+ end
29
26
 
30
- def self.member_xpath
31
- "//#{resource_name}"
32
- end
27
+ def route
28
+ @@route
29
+ end
33
30
 
34
- def route
35
- @@r.route
31
+ def message
32
+ builder = Nokogiri::XML::Builder.new do |xml|
33
+ xml.workspace {
34
+ xml.enabled @enabled if enabled_changed?
35
+ xml.name @name
36
+ }
36
37
  end
38
+ return builder.doc.to_xml
39
+ end
37
40
 
38
- def message
39
- builder = Nokogiri::XML::Builder.new do |xml|
40
- xml.workspace {
41
- xml.enabled @enabled if enabled_changed?
42
- xml.name @name
43
- }
44
- end
45
- return builder.doc.to_xml
46
- end
41
+ # @param [RGeoServer::Catalog] catalog
42
+ # @param [Hash] options
43
+ def initialize catalog, options
44
+ super({})
45
+ _run_initialize_callbacks do
46
+ @catalog = catalog
47
+ @name = options[:name].strip
48
+ end
49
+ @route = route
50
+ end
47
51
 
48
- # @param [RGeoServer::Catalog] catalog
49
- # @param [Hash] options
50
- def initialize catalog, options
51
- super({})
52
- _run_initialize_callbacks do
53
- @catalog = catalog
54
- @name = options[:name].strip
55
- end
56
- @route = route
57
- end
52
+ def data_stores &block
53
+ self.class.list DataStore, @catalog, profile['dataStores'], {:workspace => self}, check_remote = true, &block
54
+ end
55
+
56
+ def coverage_stores &block
57
+ self.class.list CoverageStore, @catalog, profile['coverageStores'], {:workspace => self}, check_remote = true, &block
58
+ end
58
59
 
59
- def data_stores &block
60
- self.class.list DataStore, @catalog, profile['dataStores'], {:workspace => self}, check_remote = true, &block
61
- end
62
-
63
- def coverage_stores &block
64
- self.class.list CoverageStore, @catalog, profile['coverageStores'], {:workspace => self}, check_remote = true, &block
65
- end
60
+ def wms_stores &block
61
+ self.class.list WmsStore, @catalog, profile['wmsStores'], {:workspace => self}, check_remote = true, &block
62
+ end
66
63
 
67
- def wms_stores &block
68
- self.class.list WmsStore, @catalog, profile['wmsStores'], {:workspace => self}, check_remote = true, &block
69
- end
70
-
71
- def profile_xml_to_hash profile_xml
72
- doc = profile_xml_to_ng profile_xml
73
- h = {'name' => doc.at_xpath('//name').text.strip, 'enabled' => @enabled }
74
- doc.xpath('//atom:link/@href', "xmlns:atom"=>"http://www.w3.org/2005/Atom").each{ |l|
75
- target = l.text.match(/([a-zA-Z]+)\.xml$/)[1]
76
- if !target.nil? && target != l.parent.parent.name.to_s.downcase
77
- begin
78
- h[l.parent.parent.name.to_s] << target
79
- rescue
80
- h[l.parent.parent.name.to_s] = []
81
- end
82
- else
83
- h[l.parent.parent.name.to_s] = begin
84
- response = @catalog.fetch_url l.text
85
- Nokogiri::XML(response).xpath('//name').collect{ |a| a.text.strip }
86
- rescue RestClient::ResourceNotFound
87
- []
88
- end.freeze
64
+ def profile_xml_to_hash profile_xml
65
+ doc = profile_xml_to_ng profile_xml
66
+ h = {'name' => doc.at_xpath('//name').text.strip, 'enabled' => @enabled }
67
+ doc.xpath('//atom:link/@href', "xmlns:atom"=>"http://www.w3.org/2005/Atom").each{ |l|
68
+ target = l.text.match(/([a-zA-Z]+)\.xml$/)[1]
69
+ if !target.nil? && target != l.parent.parent.name.to_s.downcase
70
+ begin
71
+ h[l.parent.parent.name.to_s] << target
72
+ rescue
73
+ h[l.parent.parent.name.to_s] = []
89
74
  end
90
- }
91
- h
92
- end
93
-
75
+ else
76
+ h[l.parent.parent.name.to_s] = begin
77
+ response = @catalog.do_url l.text
78
+ Nokogiri::XML(response).xpath('//name').collect{ |a| a.text.strip }
79
+ rescue RestClient::ResourceNotFound
80
+ []
81
+ end.freeze
82
+ end
83
+ }
84
+ h
94
85
  end
86
+
87
+ end
95
88
  end
data/lib/rgeoserver.rb CHANGED
@@ -16,6 +16,7 @@ module RGeoServer
16
16
  autoload :WmsStore, "rgeoserver/wmsstore"
17
17
  autoload :Style, "rgeoserver/style"
18
18
  autoload :Layer, "rgeoserver/layer"
19
+ autoload :LayerGroup, "rgeoserver/layergroup"
19
20
 
20
21
  require 'restclient'
21
22
  require 'nokogiri'
@@ -5,6 +5,7 @@ describe "Integration test against a GeoServer instance", :integration => true d
5
5
 
6
6
  before(:all) do
7
7
  @catalog = RGeoServer.catalog
8
+ @fixtures_dir = File.join(File.dirname(__FILE__), "/../fixtures/")
8
9
  end
9
10
 
10
11
 
@@ -86,7 +87,8 @@ describe "Integration test against a GeoServer instance", :integration => true d
86
87
  lyr.default_style = 'rain'
87
88
  lyr.alternate_styles = ['raster']
88
89
  lyr.enabled = 'true'
89
- expect{ lyr.save }.to raise_error
90
+ lyr.resource = @catalog.get_coverage 'sf','sfdem', 'sfdem'
91
+ expect{ lyr.save }.to raise_error
90
92
  end
91
93
 
92
94
  it "should list layers" do
@@ -96,9 +98,33 @@ describe "Integration test against a GeoServer instance", :integration => true d
96
98
  end
97
99
  end
98
100
 
101
+ context "LayerGroups" do
102
+ it "should instantiate a new group layer" do
103
+ lyrs = ['a','b','c'].collect{|l| RGeoServer::Layer.new @catalog, :name => l}
104
+ stys = ['s1','s2','s3','s4'].collect{|s| RGeoServer::Style.new @catalog, :name => s}
105
+ g = RGeoServer::LayerGroup.new @catalog, :name => 'test_group_layer'
106
+ g.layers = lyrs
107
+ g.styles = stys
108
+ g.new?.should == true
109
+ end
110
+
111
+ it "should create a new group layer from existing layers and styles and delete it right after" do
112
+ g = RGeoServer::LayerGroup.new @catalog, :name => 'test_group_layer'
113
+ g.layers = @catalog.get_layers[1,2]
114
+ g.styles = @catalog.get_styles[1,2]
115
+ g.new?.should == true
116
+ g.save
117
+ # Bounds metadata should come back aggregated from the server
118
+ g.bounds['maxx'].should_not == ''
119
+ g.delete
120
+ g.new?.should == true
121
+ end
122
+
123
+ end
124
+
99
125
  context "Styles" do
100
126
  before :all do
101
- sld_dir = File.join(File.dirname(__FILE__), '/../fixtures/styles/')
127
+ sld_dir = File.join(@fixtures_dir, 'styles')
102
128
  @test_sld = Nokogiri::XML(File.new(File.join(sld_dir, 'test_style.sld')))
103
129
  @pop_sld = Nokogiri::XML(File.new(File.join(sld_dir, 'poptest.sld')))
104
130
  end
@@ -137,6 +163,8 @@ describe "Integration test against a GeoServer instance", :integration => true d
137
163
  before :all do
138
164
  @ws = RGeoServer::Workspace.new @catalog, :name => 'test_workspace_for_stores'
139
165
  @ws.save
166
+ @shapefile = File.join(@fixtures_dir, 'datasets/vector/granules.shp')
167
+ @raster = File.join(@fixtures_dir, 'datasets/raster/test.tif')
140
168
  end
141
169
 
142
170
  after :all do
@@ -164,7 +192,7 @@ describe "Integration test against a GeoServer instance", :integration => true d
164
192
  end
165
193
 
166
194
  it "should create a datastore under existing workspace, update and delete it right after" do
167
- ds = RGeoServer::DataStore.new @catalog, :workspace => @ws, :name => 'test', :connection_parameters => {"namespace"=>"http://test_workspace_for_stores", "url" => "file://tmp/geo.tif"}
195
+ ds = RGeoServer::DataStore.new @catalog, :workspace => @ws, :name => 'test', :connection_parameters => {"namespace"=>"http://test_workspace_for_stores", "url" => "file:#{@shapefile}"}
168
196
  ds.new?.should == true
169
197
  ds.save
170
198
  ds.new?.should == false
@@ -179,6 +207,15 @@ describe "Integration test against a GeoServer instance", :integration => true d
179
207
  ds.profile['connectionParameters'].should == new_connection_parameters
180
208
  ds.delete
181
209
  end
210
+
211
+ it "should create a datastore under existing workspace and add a feature type that will also create a layer" do
212
+ ds = RGeoServer::DataStore.new @catalog, :workspace => @ws, :name => 'test', :connection_parameters => {"namespace"=>"http://test_workspace_for_stores", "url" => "file:#{@shapefile}"}
213
+ ds.new?.should == true
214
+ ds.save
215
+ ft = RGeoServer::FeatureType.new @catalog, :workspace => @ws, :data_store => ds, :name => 'granules'
216
+ ft.save
217
+
218
+ end
182
219
  end
183
220
 
184
221
  context "CoverageStores" do
@@ -189,7 +226,7 @@ describe "Integration test against a GeoServer instance", :integration => true d
189
226
  end
190
227
  it "should create a coverage store under existing workspace, update and delete it right after" do
191
228
  cs = RGeoServer::CoverageStore.new @catalog, :workspace => @ws, :name => 'test_coverage_store'
192
- cs.url = "file:data_dir/sf/raster.tif"
229
+ cs.url = "file://#{@raster}"
193
230
  cs.description = 'description'
194
231
  cs.enabled = 'true'
195
232
  cs.data_type = 'GeoTIFF'
@@ -202,6 +239,28 @@ describe "Integration test against a GeoServer instance", :integration => true d
202
239
  cs.description.should == 'new description'
203
240
  cs.new?.should == false
204
241
  end
242
+ it "should create a coverage store under existing workspace and add a coverage to it. A layer must be created as a result of this operation" do
243
+ cs = RGeoServer::CoverageStore.new @catalog, :workspace => @ws, :name => 'raster'
244
+ cs.url = "file://#{@raster}"
245
+ cs.description = 'description'
246
+ cs.enabled = 'true'
247
+ cs.data_type = 'GeoTIFF'
248
+ cs.save
249
+ c = RGeoServer::Coverage.new @catalog, :workspace => @ws, :coverage_store => cs, :name => 'raster'
250
+ c.title = 'Test Raster Layer'
251
+ #c.save
252
+ end
253
+ end
254
+
255
+ context "Catalog operations" do
256
+ it "should reload the catalog" do
257
+ @catalog.reload
258
+ end
259
+
260
+ it "should reset the catalog" do
261
+ @catalog.reset
262
+ end
263
+
205
264
  end
206
265
  end
207
266
  end