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,92 +1,86 @@
1
1
 
2
2
  module RGeoServer
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
+ class FeatureType < ResourceInfo
5
+ OBJ_ATTRIBUTES = {:catalog => "catalog", :name => "name", :workspace => "workspace", :enabled => "enabled" }
6
+ OBJ_DEFAULT_ATTRIBUTES = {:catalog => nil, :workspace => nil, :coverage_store => nil, :name => nil, :enabled => "false" }
7
+
8
+ define_attribute_methods OBJ_ATTRIBUTES.keys
9
+ update_attribute_accessors OBJ_ATTRIBUTES
10
+
11
+ @@route = "workspaces/%s/datastores/%s/featuretypes"
12
+ @@root = "featureTypes"
13
+ @@resource_name = "featureType"
14
+
15
+ def self.root
16
+ @@root
17
+ end
3
18
 
4
- class FeatureType < ResourceInfo
5
- OBJ_ATTRIBUTES = {:catalog => "catalog", :name => "name", :workspace => "workspace", :enabled => "enabled" }
6
- OBJ_DEFAULT_ATTRIBUTES = {:catalog => nil, :workspace => nil, :coverage_store => nil, :name => nil, :enabled => "false" }
7
-
8
- define_attribute_methods OBJ_ATTRIBUTES.keys
9
- update_attribute_accessors OBJ_ATTRIBUTES
10
-
11
- @@r = Confstruct::Configuration.new(
12
- :route => "workspaces/%s/datastores/%s/featuretypes",
13
- :root => "featureTypes",
14
- :resource_name => "featureType"
15
- )
16
-
17
- def self.root
18
- @@r.root
19
- end
20
-
21
- def self.create_method
22
- :put
23
- end
24
-
25
- def self.update_method
26
- :put
27
- end
28
-
19
+ def self.resource_name
20
+ @@resource_name
21
+ end
29
22
 
30
- def self.resource_name
31
- @@r.resource_name
32
- end
33
-
34
- def self.root_xpath
35
- "//#{root}/#{resource_name}"
36
- end
23
+ def self.root_xpath
24
+ "//#{root}/#{resource_name}"
25
+ end
37
26
 
38
- def self.member_xpath
39
- "//#{resource_name}"
40
- end
27
+ def self.member_xpath
28
+ "//#{resource_name}"
29
+ end
41
30
 
42
- def route
43
- @@r.route % [@workspace.name , @data_store.name ]
44
- end
31
+ def route
32
+ @@route % [@workspace.name , @data_store.name ]
33
+ end
45
34
 
46
- def message
47
- "<featureType/>"
35
+ def message
36
+ builder = Nokogiri::XML::Builder.new do |xml|
37
+ xml.featureType {
38
+ xml.name @name
39
+ }
48
40
  end
41
+ @message = builder.doc.to_xml
42
+ end
49
43
 
50
44
 
51
- # @param [RGeoServer::Catalog] catalog
52
- # @param [Hash] options
53
- def initialize catalog, options
54
- super({})
55
- _run_initialize_callbacks do
56
- @catalog = catalog
57
- workspace = options[:workspace] || 'default'
58
- if workspace.instance_of? String
59
- @workspace = @catalog.get_workspace(workspace)
60
- elsif workspace.instance_of? Workspace
61
- @workspace = workspace
62
- else
63
- raise "Not a valid workspace"
64
- end
65
- data_store = options[:data_store]
66
- if data_store.instance_of? String
67
- @data_store = DataStore.new @catalog, :workspace => @workspace, :name => data_store
68
- elsif data_store.instance_of? DataStore
69
- @data_store = data_store
70
- else
71
- raise "Not a valid data store"
72
- end
73
-
74
- @name = options[:name].strip
75
- @route = route
76
- end
77
- end
45
+ # @param [RGeoServer::Catalog] catalog
46
+ # @param [Hash] options
47
+ def initialize catalog, options
48
+ super({})
49
+ _run_initialize_callbacks do
50
+ @catalog = catalog
51
+ workspace = options[:workspace] || 'default'
52
+ if workspace.instance_of? String
53
+ @workspace = @catalog.get_workspace(workspace)
54
+ elsif workspace.instance_of? Workspace
55
+ @workspace = workspace
56
+ else
57
+ raise "Not a valid workspace"
58
+ end
59
+ data_store = options[:data_store]
60
+ if data_store.instance_of? String
61
+ @data_store = DataStore.new @catalog, :workspace => @workspace, :name => data_store
62
+ elsif data_store.instance_of? DataStore
63
+ @data_store = data_store
64
+ else
65
+ raise "Not a valid data store"
66
+ end
67
+
68
+ @name = options[:name].strip
69
+ @route = route
70
+ end
71
+ end
78
72
 
79
73
 
80
- def profile_xml_to_hash profile_xml
81
- doc = profile_xml_to_ng profile_xml
82
- h = {
83
- "name" => doc.at_xpath('//name').text.strip,
84
- "workspace" => @workspace.name,
85
- "nativeName" => doc.at_xpath('//nativeName').to_s
86
- }.freeze
87
- h
88
- end
74
+ def profile_xml_to_hash profile_xml
75
+ doc = profile_xml_to_ng profile_xml
76
+ h = {
77
+ "name" => doc.at_xpath('//name').text.strip,
78
+ "workspace" => @workspace.name,
79
+ "nativeName" => doc.at_xpath('//nativeName').to_s
80
+ }.freeze
81
+ h
82
+ end
89
83
 
90
84
 
91
- end
85
+ end
92
86
  end
@@ -1,159 +1,152 @@
1
1
 
2
2
  module RGeoServer
3
+ # A layer is a published resource (feature type or coverage).
4
+ class Layer < ResourceInfo
3
5
 
4
- class Layer < ResourceInfo
6
+ OBJ_ATTRIBUTES = {:enabled => 'enabled', :catalog => 'catalog', :name => 'name', :default_style => 'default_style', :alternate_styles => 'alternate_styles', :metadata => 'metadata', :attribution => 'attribution', :layer_type => 'type' }
7
+ OBJ_DEFAULT_ATTRIBUTES = {:enabled => 'true', :catalog => nil, :name => nil, :default_style => nil, :alternate_styles => [], :metadata => {}, :attribution => {:logo_height => '0', :logo_width => '0', 'title' => ''}, :layer_type => nil }
5
8
 
6
- OBJ_ATTRIBUTES = {:enabled => 'enabled', :catalog => 'catalog', :name => 'name', :default_style => 'default_style', :alternate_styles => 'alternate_styles', :metadata => 'metadata', :attribution => 'attribution', :layer_type => 'type' }
7
- OBJ_DEFAULT_ATTRIBUTES = {:enabled => 'true', :catalog => nil, :name => nil, :default_style => nil, :alternate_styles => [], :metadata => {}, :attribution => {:logo_height => '0', :logo_width => '0', 'title' => ''}, :layer_type => 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 = "layers"
13
+ @@resource_name = "layer"
11
14
 
12
- @@r = Confstruct::Configuration.new(:route => 'layers', :resource_name => 'layer')
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
36
- end
37
-
38
- # No direct layer creation
39
- def create_route
40
- nil
41
- end
31
+ # No direct layer creation
32
+ def create_route
33
+ nil
34
+ end
42
35
 
43
- def message
44
- builder = Nokogiri::XML::Builder.new do |xml|
45
- xml.layer {
46
- #xml.name @name
47
- xml.type_ layer_type
48
- xml.enabled enabled
49
- xml.defaultStyle {
50
- xml.name default_style
51
- }
52
- xml.styles {
53
- alternate_styles.each { |s|
54
- xml.style {
55
- xml.name s
56
- }
36
+ def message
37
+ builder = Nokogiri::XML::Builder.new do |xml|
38
+ xml.layer {
39
+ #xml.name @name
40
+ xml.type_ layer_type
41
+ xml.enabled enabled
42
+ xml.defaultStyle {
43
+ xml.name default_style
44
+ }
45
+ xml.styles {
46
+ alternate_styles.each { |s|
47
+ xml.style {
48
+ xml.name s
57
49
  }
58
- } unless alternate_styles.empty?
59
- xml.resource(:class => resource.class.resource_name){
60
- xml.name resource.name
61
- } unless resource.nil?
62
- xml.attribution {
63
- xml.title attribution['title'] unless attribution['title'].empty?
64
- xml.logoWidth attribution['logo_width']
65
- xml.logoHeight attribution['logo_height']
66
- } if !attribution['logo_width'].nil? && !attribution['logo_height'].nil?
67
- }
68
- end
69
- return builder.doc.to_xml
50
+ }
51
+ } unless alternate_styles.empty?
52
+ xml.resource(:class => resource.class.resource_name){
53
+ xml.name resource.name
54
+ } unless resource.nil?
55
+ xml.attribution {
56
+ xml.title attribution['title'] unless attribution['title'].empty?
57
+ xml.logoWidth attribution['logo_width']
58
+ xml.logoHeight attribution['logo_height']
59
+ } if !attribution['logo_width'].nil? && !attribution['logo_height'].nil?
60
+ }
70
61
  end
62
+ return builder.doc.to_xml
63
+ end
71
64
 
72
- # @param [RGeoServer::Catalog] catalog
73
- # @param [Hash] options
74
- # @option options [String] :name
75
- # @option options [String] :default_style
76
- # @option options [Array<String>] :alternate_styles
77
- def initialize catalog, options
78
- super({})
79
- _run_initialize_callbacks do
80
- @catalog = catalog
81
- @name = options[:name].strip
82
- #@default_style = options[:default_style] || ''
83
- #@alternate_styles = options[:alternate_styles] || []
84
- end
85
- @route = route
86
- end
65
+ # @param [RGeoServer::Catalog] catalog
66
+ # @param [Hash] options
67
+ # @option options [String] :name
68
+ # @option options [String] :default_style
69
+ # @option options [Array<String>] :alternate_styles
70
+ def initialize catalog, options
71
+ super({})
72
+ _run_initialize_callbacks do
73
+ @catalog = catalog
74
+ @name = options[:name].strip
75
+ #@default_style = options[:default_style] || ''
76
+ #@alternate_styles = options[:alternate_styles] || []
77
+ end
78
+ @route = route
79
+ end
87
80
 
88
- def resource= r
89
- if r.is_a?(RGeoServer::Coverage) || r.is_a?(RGeoServer::FeatureType)
90
- @resource = r
91
- else
92
- raise 'Unknown resource type'
93
- end
94
- end
81
+ def resource= r
82
+ if r.is_a?(RGeoServer::Coverage) || r.is_a?(RGeoServer::FeatureType)
83
+ @resource = r
84
+ else
85
+ raise 'Unknown resource type'
86
+ end
87
+ end
95
88
 
96
- def resource
97
- @resource ||= begin
98
- unless profile['resource'].empty?
99
- data_type = profile['resource']['type']
100
- workspace = profile['resource']['workspace']
101
- name = profile['resource']['name']
102
- store = profile['resource']['store']
103
-
104
- case data_type
105
- when 'coverage'
106
- return RGeoServer::Coverage.new @catalog, :workspace => workspace, :coverage_store => store, :name => name
107
- when 'featureType'
108
- return RGeoServer::FeatureType.new @catalog, :workspace => workspace, :data_store => store, :name => name
109
- else
110
- raise 'Unknown resource type'
111
- end
89
+ def resource
90
+ @resource ||= begin
91
+ unless profile['resource'].empty?
92
+ data_type = profile['resource']['type']
93
+ workspace = profile['resource']['workspace']
94
+ name = profile['resource']['name']
95
+ store = profile['resource']['store']
96
+
97
+ case data_type
98
+ when 'coverage'
99
+ return RGeoServer::Coverage.new @catalog, :workspace => workspace, :coverage_store => store, :name => name
100
+ when 'featureType'
101
+ return RGeoServer::FeatureType.new @catalog, :workspace => workspace, :data_store => store, :name => name
112
102
  else
113
- nil
103
+ raise 'Unknown resource type'
114
104
  end
115
- rescue Exception => e
105
+ else
116
106
  nil
117
107
  end
108
+ rescue Exception => e
109
+ nil
118
110
  end
119
-
120
- # TODO: Simplify if necessary with "/layers/<l>/styles[.<format>]", as speficied in the API
121
- def get_default_style &block
122
- self.class.list Style, @catalog, @default_style, {:layer => self}, check_remote = false, &block
123
- end
124
-
125
- def get_alternate_styles &block
126
- self.class.list Style, @catalog, @alternate_styles, {:layer => self}, check_remote = false, &block
127
- end
111
+ end
128
112
 
129
- def profile_xml_to_hash profile_xml
130
- doc = profile_xml_to_ng profile_xml
131
- name = doc.at_xpath('//name/text()').text.strip
132
- link = doc.at_xpath('//resource//atom:link/@href', "xmlns:atom"=>"http://www.w3.org/2005/Atom").text.strip
133
- workspace, _, store = link.match(/workspaces\/(.*?)\/(.*?)\/(.*?)\/(.*?)\/#{name}.xml$/).to_a[1,3]
134
-
135
- h = {
136
- "name" => name,
137
- "path" => doc.at_xpath('//path/text()').to_s,
138
- "default_style" => doc.at_xpath('//defaultStyle/name/text()').to_s,
139
- "alternate_styles" => doc.xpath('//styles/style/name/text()').collect{ |s| s.to_s},
140
- "type" => doc.at_xpath('//type/text()').to_s,
141
- "enabled" => doc.at_xpath('//enabled/text()').to_s,
142
- "attribution" => {
143
- "title" => doc.at_xpath('//attribution/title/text()').to_s,
144
- "logo_width" => doc.at_xpath('//attribution/logoWidth/text()').to_s,
145
- "logo_height" => doc.at_xpath('//attribution/logoHeight/text()').to_s
146
- },
147
- "resource" => {
148
- "type" => doc.at_xpath('//resource/@class').to_s,
149
- "name" => doc.at_xpath('//resource/name/text()').to_s,
150
- "store" => store,
151
- "workspace" => workspace
152
- },
153
- "metadata" => doc.xpath('//metadata/entry').inject({}){ |h, e| h.merge(e['key']=> e.text.to_s) }
154
- }.freeze
155
- h
156
- end
157
-
113
+ # TODO: Simplify if necessary with "/layers/<l>/styles[.<format>]", as specified in the API
114
+ def get_default_style &block
115
+ self.class.list Style, @catalog, @default_style, {:layer => self}, check_remote = false, &block
116
+ end
117
+
118
+ def get_alternate_styles &block
119
+ self.class.list Style, @catalog, @alternate_styles, {:layer => self}, check_remote = false, &block
158
120
  end
121
+
122
+ def profile_xml_to_hash profile_xml
123
+ doc = profile_xml_to_ng profile_xml
124
+ name = doc.at_xpath('//name/text()').text.strip
125
+ link = doc.at_xpath('//resource//atom:link/@href', "xmlns:atom"=>"http://www.w3.org/2005/Atom").text.strip
126
+ workspace, _, store = link.match(/workspaces\/(.*?)\/(.*?)\/(.*?)\/(.*?)\/#{name}.xml$/).to_a[1,3]
127
+
128
+ h = {
129
+ "name" => name,
130
+ "path" => doc.at_xpath('//path/text()').to_s,
131
+ "default_style" => doc.at_xpath('//defaultStyle/name/text()').to_s,
132
+ "alternate_styles" => doc.xpath('//styles/style/name/text()').collect{ |s| s.to_s},
133
+ "type" => doc.at_xpath('//type/text()').to_s,
134
+ "enabled" => doc.at_xpath('//enabled/text()').to_s,
135
+ "attribution" => {
136
+ "title" => doc.at_xpath('//attribution/title/text()').to_s,
137
+ "logo_width" => doc.at_xpath('//attribution/logoWidth/text()').to_s,
138
+ "logo_height" => doc.at_xpath('//attribution/logoHeight/text()').to_s
139
+ },
140
+ "resource" => {
141
+ "type" => doc.at_xpath('//resource/@class').to_s,
142
+ "name" => doc.at_xpath('//resource/name/text()').to_s,
143
+ "store" => store,
144
+ "workspace" => workspace
145
+ },
146
+ "metadata" => doc.xpath('//metadata/entry').inject({}){ |h, e| h.merge(e['key']=> e.text.to_s) }
147
+ }.freeze
148
+ h
149
+ end
150
+
151
+ end
159
152
  end
@@ -0,0 +1,138 @@
1
+
2
+ module RGeoServer
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
+ class LayerGroup < ResourceInfo
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'=>'', 'miny' =>'', 'maxx'=>'', 'maxy'=>'', 'crs' =>''}, :metadata => {} }
8
+
9
+ define_attribute_methods OBJ_ATTRIBUTES.keys
10
+ update_attribute_accessors OBJ_ATTRIBUTES
11
+
12
+ @@route = "layergroups"
13
+ @@resource_name = "layerGroup"
14
+
15
+ def self.resource_name
16
+ @@resource_name
17
+ end
18
+
19
+ def self.root_xpath
20
+ "//#{@@route}/#{@@resource_name}"
21
+ end
22
+
23
+ def self.member_xpath
24
+ "//#{resource_name}"
25
+ end
26
+
27
+ def route
28
+ @@route
29
+ end
30
+
31
+ def message
32
+ builder = Nokogiri::XML::Builder.new do |xml|
33
+ xml.layerGroup {
34
+ xml.name @name
35
+ xml.layers {
36
+ layers.each { |l|
37
+ xml.layer {
38
+ xml.name l.name
39
+ }
40
+ }
41
+ } unless layers.nil?
42
+ xml.styles {
43
+ styles.each { |s|
44
+ xml.style {
45
+ xml.name s.name
46
+ }
47
+ }
48
+ } unless styles.nil?
49
+ 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 @bounds
56
+ }
57
+ end
58
+ return builder.doc.to_xml
59
+ end
60
+
61
+ # @param [RGeoServer::Catalog] catalog
62
+ # @param [Hash] options
63
+ # @option options [String] :name
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
72
+
73
+ # @param [Array<RGeoServer::Style>] sl list of styles
74
+ def styles= sl
75
+ if sl.inject(true){|t,s| t && s.is_a?(RGeoServer::Style)}
76
+ styles_will_change! unless sl == styles
77
+ @styles = sl
78
+ else
79
+ raise 'Unknown list of styles'
80
+ end
81
+ end
82
+
83
+ def styles
84
+ @styles ||= begin
85
+ unless profile['styles'].empty?
86
+ return profile['styles'].each{ |s| RGeoServer::Style.new @catalog, :name => s.name }
87
+ else
88
+ nil
89
+ end
90
+ rescue Exception => e
91
+ nil
92
+ end
93
+ end
94
+
95
+ # @param [Array<RGeoServer::Layer>] ll list of layers
96
+ def layers= ll
97
+ if ll.inject(true){ |t,l| t && l.is_a?(RGeoServer::Layer) }
98
+ layers_will_change! unless ll == layers
99
+ @layers = ll
100
+ else
101
+ raise 'Unknown list of layers'
102
+ end
103
+ end
104
+
105
+ def layers
106
+ @layers ||= begin
107
+ unless profile['layers'].empty?
108
+ return profile['layers'].each{ |s| RGeoServer::Layer.new @catalog, :name => s.name }
109
+ else
110
+ nil
111
+ end
112
+ rescue Exception => e
113
+ nil
114
+ end
115
+ end
116
+
117
+ def profile_xml_to_hash profile_xml
118
+ doc = profile_xml_to_ng profile_xml
119
+ name = doc.at_xpath('//name/text()').text.strip
120
+
121
+ h = {
122
+ "name" => name,
123
+ "layers" => doc.xpath('//layers/layer/name/text()').collect{|l| l.to_s},
124
+ "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()')
131
+ },
132
+ "metadata" => doc.xpath('//metadata/entry').inject({}){ |h, e| h.merge(e['key']=> e.text.to_s) }
133
+ }.freeze
134
+ h
135
+ end
136
+
137
+ end
138
+ end
@@ -57,14 +57,13 @@ module RGeoServer
57
57
  end
58
58
 
59
59
  def create_method
60
- self.class.create_method
60
+ :post
61
61
  end
62
62
 
63
63
  def update_method
64
- self.class.update_method
64
+ :put
65
65
  end
66
66
 
67
-
68
67
  # Modify or save the resource
69
68
  # @param [Hash] options / query parameters
70
69
  # @return [RGeoServer::ResourceInfo]
@@ -36,20 +36,22 @@ module RGeoServer
36
36
  end
37
37
  end
38
38
 
39
- # Fetch an arbitrary URL within the catalog
39
+ # Do an action on an arbitrary URL within the catalog passing no data
40
+ # Default method is GET
40
41
  # @param [String] url
41
- def fetch_url url
42
+ # @param [String] method
43
+ def do_url url, method = :get
42
44
  url.slice! client.url
43
45
  fetcher = client[url]
44
46
  fetcher.options[:headers] ||= headers(:xml)
45
- begin
46
- return fetcher.get
47
+ begin
48
+ return fetcher.get if method == :get
49
+ fetcher.send method, nil
47
50
  rescue RestClient::InternalServerError => e
48
51
  $logger.error e.response
49
52
  $logger.flush if $logger.respond_to? :flush
50
53
  raise GeoServerInvalidRequest, "Error fetching URL: #{url}. See $logger for details"
51
54
  end
52
-
53
55
  end
54
56
 
55
57
  # Add resource to the catalog