geoloader 0.1.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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +13 -0
  3. data/.gitignore +17 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +2 -0
  7. data/README.md +212 -0
  8. data/Rakefile +10 -0
  9. data/bin/geoloader +4 -0
  10. data/config.yaml +18 -0
  11. data/geoloader.gemspec +37 -0
  12. data/iso19139.xsl +445 -0
  13. data/lib/geoloader.rb +48 -0
  14. data/lib/geoloader/assets/asset.rb +63 -0
  15. data/lib/geoloader/assets/description.rb +55 -0
  16. data/lib/geoloader/assets/geonetwork.rb +58 -0
  17. data/lib/geoloader/assets/geotiff.rb +41 -0
  18. data/lib/geoloader/assets/shapefile.rb +28 -0
  19. data/lib/geoloader/assets/solr.rb +23 -0
  20. data/lib/geoloader/cli/app.rb +26 -0
  21. data/lib/geoloader/cli/geonetwork.rb +36 -0
  22. data/lib/geoloader/cli/geoserver.rb +36 -0
  23. data/lib/geoloader/cli/solr.rb +36 -0
  24. data/lib/geoloader/loaders/geonetwork.rb +40 -0
  25. data/lib/geoloader/loaders/geotiff_geoserver.rb +47 -0
  26. data/lib/geoloader/loaders/geotiff_solr.rb +40 -0
  27. data/lib/geoloader/loaders/loader.rb +53 -0
  28. data/lib/geoloader/loaders/shapefile_geoserver.rb +40 -0
  29. data/lib/geoloader/loaders/shapefile_solr.rb +40 -0
  30. data/lib/geoloader/services/geonetwork.rb +201 -0
  31. data/lib/geoloader/services/geoserver.rb +104 -0
  32. data/lib/geoloader/services/solr.rb +62 -0
  33. data/lib/geoloader/tasks/geonetwork.rb +28 -0
  34. data/lib/geoloader/tasks/geoserver.rb +19 -0
  35. data/lib/geoloader/tasks/solr.rb +19 -0
  36. data/lib/geoloader/version.rb +4 -0
  37. data/metadata.md +13 -0
  38. data/spec/fixtures/geotiff.tfw +6 -0
  39. data/spec/fixtures/geotiff.tif +0 -0
  40. data/spec/fixtures/geotiff.tif.aux.xml +1315 -0
  41. data/spec/fixtures/geotiff.tif.ovr +0 -0
  42. data/spec/fixtures/geotiff.tif.vat.dbf +0 -0
  43. data/spec/fixtures/geotiff.tif.xml +2 -0
  44. data/spec/fixtures/shapefile.dbf +0 -0
  45. data/spec/fixtures/shapefile.prj +1 -0
  46. data/spec/fixtures/shapefile.sbn +0 -0
  47. data/spec/fixtures/shapefile.sbx +0 -0
  48. data/spec/fixtures/shapefile.shp +0 -0
  49. data/spec/fixtures/shapefile.shp.xml +51 -0
  50. data/spec/fixtures/shapefile.shx +0 -0
  51. data/spec/helpers/fixture.rb +13 -0
  52. data/spec/loaders/geonetwork.rb +38 -0
  53. data/spec/loaders/geotiff_geoserver.rb +49 -0
  54. data/spec/loaders/geotiff_solr.rb +34 -0
  55. data/spec/loaders/shapefile_geoserver.rb +49 -0
  56. data/spec/loaders/shapefile_solr.rb +34 -0
  57. data/spec/spec_helper.rb +6 -0
  58. metadata +362 -0
@@ -0,0 +1,40 @@
1
+
2
+ module Geoloader
3
+ module Loaders
4
+
5
+ class Geonetwork < Loader
6
+
7
+ attr_reader :asset, :geonetwork
8
+
9
+ @queue = :geoloader
10
+
11
+ #
12
+ # Configure the asset, connect to Geonetwork.
13
+ #
14
+ def initialize(*args)
15
+
16
+ super
17
+
18
+ # Create and configure the asset.
19
+ @asset = Geoloader::Assets::Asset.new(@file_path, @workspace, @desc_path)
20
+ @asset.extend(Geoloader::Assets::Geonetwork)
21
+
22
+ # Connect to Geonetwork, create the group.
23
+ @geonetwork = Geoloader::Services::Geonetwork.new
24
+ @geonetwork.ensure_group(@workspace)
25
+
26
+ end
27
+
28
+ #
29
+ # Push an asset to Geonetwork.
30
+ #
31
+ def load
32
+ @asset.stage do
33
+ @geonetwork.create_record(@asset)
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,47 @@
1
+
2
+ module Geoloader
3
+ module Loaders
4
+
5
+ class GeotiffGeoserver < Loader
6
+
7
+ attr_reader :geotiff, :geoserver
8
+
9
+ @queue = :geoloader
10
+
11
+ #
12
+ # Configure the asset, connect to Geoserver.
13
+ #
14
+ def initialize(*args)
15
+
16
+ super
17
+
18
+ # Create and configure the asset.
19
+ @geotiff = Geoloader::Assets::Asset.new(@file_path, @workspace, @desc_path)
20
+ @geotiff.extend(Geoloader::Assets::Geotiff)
21
+
22
+ # Connect to Geoserver, create the workspace.
23
+ @geoserver = Geoloader::Services::Geoserver.new
24
+ @geoserver.ensure_workspace(@workspace)
25
+
26
+ end
27
+
28
+ #
29
+ # Push a GeoTIFF to Geoserver.
30
+ #
31
+ def load
32
+ @geotiff.stage do
33
+
34
+ # Prepare the file.
35
+ @geotiff.make_borders_transparent
36
+ @geotiff.reproject
37
+
38
+ # Push to Geoserver.
39
+ @geoserver.create_coveragestore(@geotiff)
40
+
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+
2
+ module Geoloader
3
+ module Loaders
4
+
5
+ class GeotiffSolr < Loader
6
+
7
+ attr_reader :geotiff, :solr
8
+
9
+ @queue = :geoloader
10
+
11
+ #
12
+ # Configure the asset, connect to Solr.
13
+ #
14
+ def initialize(*args)
15
+
16
+ super
17
+
18
+ # Create and configure the asset.
19
+ @geotiff = Geoloader::Assets::Asset.new(@file_path, @workspace, @desc_path)
20
+ @geotiff.extend(Geoloader::Assets::Geotiff)
21
+ @geotiff.extend(Geoloader::Assets::Solr)
22
+
23
+ # Connect to Solr.
24
+ @solr = Geoloader::Services::Solr.new
25
+
26
+ end
27
+
28
+ #
29
+ # Push a GeoTIFF to Solr.
30
+ #
31
+ def load
32
+ @geotiff.stage do
33
+ @solr.create_document(@geotiff)
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,53 @@
1
+
2
+ module Geoloader
3
+ module Loaders
4
+
5
+ class Loader
6
+
7
+ #
8
+ # Perform or enqueue an upload.
9
+ #
10
+ # @param [String] file_path
11
+ # @param [Hash] options
12
+ #
13
+ def self.load_or_enqueue(file_path, options)
14
+ if options[:queue]
15
+ Resque.enqueue(self, file_path, options[:workspace], options[:description])
16
+ else
17
+ self.perform(file_path, options[:workspace], options[:description])
18
+ end
19
+ end
20
+
21
+ #
22
+ # Perform an upload (used by Resque).
23
+ #
24
+ # @param [String] file_path
25
+ # @param [String] workspace
26
+ # @param [String] desc_path
27
+ #
28
+ def self.perform(file_path, workspace, desc_path = nil)
29
+ new(file_path, workspace, desc_path).load
30
+ puts "Loaded #{File.basename(file_path)}."
31
+ end
32
+
33
+ #
34
+ # Set the file path and workspace.
35
+ #
36
+ # @param [String] file_path
37
+ # @param [String] workspace
38
+ # @param [String] desc_path
39
+ #
40
+ def initialize(file_path, workspace, desc_path = nil)
41
+
42
+ @file_path = file_path
43
+ @desc_path = desc_path
44
+
45
+ # If no workspace is provided, revert to the default.
46
+ @workspace = (workspace or Geoloader.config.workspaces.production)
47
+
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,40 @@
1
+
2
+ module Geoloader
3
+ module Loaders
4
+
5
+ class ShapefileGeoserver < Loader
6
+
7
+ attr_reader :shapefile, :geoserver
8
+
9
+ @queue = :geoloader
10
+
11
+ #
12
+ # Configure the asset, connect to Geoserver.
13
+ #
14
+ def initialize(*args)
15
+
16
+ super
17
+
18
+ # Create and configure the asset.
19
+ @shapefile = Geoloader::Assets::Asset.new(@file_path, @workspace, @desc_path)
20
+ @shapefile.extend(Geoloader::Assets::Shapefile)
21
+
22
+ # Connect to Geoserver, create the workspace.
23
+ @geoserver = Geoloader::Services::Geoserver.new
24
+ @geoserver.ensure_workspace(@workspace)
25
+
26
+ end
27
+
28
+ #
29
+ # Push a Shapefile to Geoserver.
30
+ #
31
+ def load
32
+ @shapefile.stage do
33
+ @geoserver.create_datastore(@shapefile)
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+
2
+ module Geoloader
3
+ module Loaders
4
+
5
+ class ShapefileSolr < Loader
6
+
7
+ attr_reader :shapefile, :solr
8
+
9
+ @queue = :geoloader
10
+
11
+ #
12
+ # Configure the shapefile, connect to Solr.
13
+ #
14
+ def initialize(*args)
15
+
16
+ super
17
+
18
+ # Create and configure the asset.
19
+ @shapefile = Geoloader::Assets::Asset.new(@file_path, @workspace, @desc_path)
20
+ @shapefile.extend(Geoloader::Assets::Shapefile)
21
+ @shapefile.extend(Geoloader::Assets::Solr)
22
+
23
+ # Connect to Solr.
24
+ @solr = Geoloader::Services::Solr.new
25
+
26
+ end
27
+
28
+ #
29
+ # Push a Shapefile to Solr.
30
+ #
31
+ def load
32
+ @shapefile.stage do
33
+ @solr.create_document(@shapefile)
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,201 @@
1
+
2
+ require "rest_client"
3
+ require "builder"
4
+ require "nokogiri"
5
+
6
+ module Geoloader
7
+ module Services
8
+
9
+ class Geonetwork
10
+
11
+ attr_reader :resource
12
+
13
+ #
14
+ # Initialize the API wrapper.
15
+ #
16
+ def initialize
17
+ @resource = RestClient::Resource.new(Geoloader.config.geonetwork.url, {
18
+ :user => Geoloader.config.geonetwork.username,
19
+ :password => Geoloader.config.geonetwork.password,
20
+ :headers => { :content_type => :xml }
21
+ })
22
+ end
23
+
24
+ #
25
+ # List all groups on the node.
26
+ #
27
+ def get_groups
28
+ @resource["xml.group.list"].get
29
+ end
30
+
31
+ #
32
+ # Get a group with a given name.
33
+ #
34
+ # @param [String] group
35
+ #
36
+ def get_group(group)
37
+ Nokogiri::XML(get_groups).at_xpath("//record[name[text()='#{group}']]")
38
+ end
39
+
40
+ #
41
+ # Does a group with a given name exist?
42
+ #
43
+ # @param [String] group
44
+ #
45
+ def group_exists?(group)
46
+ !!get_group(group)
47
+ end
48
+
49
+ #
50
+ # Get the id of a group with a given name.
51
+ #
52
+ # @param [String] group
53
+ #
54
+ def get_group_id(group)
55
+ get_group(group).at_xpath("id").content.to_i
56
+ end
57
+
58
+ #
59
+ # Create a new group with a given name.
60
+ #
61
+ # @param [String] group
62
+ #
63
+ def create_group(group)
64
+ post("group.update", self.class.xml_doc.request { |r|
65
+ r.name group
66
+ })
67
+ end
68
+
69
+ #
70
+ # Check to see if a group exists, and if not, create it.
71
+ #
72
+ # @param [String] group
73
+ #
74
+ def ensure_group(group)
75
+ create_group(group) unless group_exists?(group)
76
+ end
77
+
78
+ #
79
+ # Get a list of the ids of all records in a group.
80
+ #
81
+ # @param [String] group
82
+ #
83
+ def get_ids_in_group(group)
84
+ Nokogiri::XML(search_records_by_group(group)).xpath("//metadata//id").map do |m|
85
+ m.content.to_i
86
+ end
87
+ end
88
+
89
+ #
90
+ # Delete group with a given name.
91
+ #
92
+ # @param [String] group
93
+ #
94
+ def delete_group(group)
95
+ delete_records_by_group(group)
96
+ post("group.remove", self.class.xml_doc.request { |r|
97
+ r.id get_group_id(group)
98
+ })
99
+ end
100
+
101
+ #
102
+ # Insert a new record.
103
+ #
104
+ # @param [Geoloader::Asset] asset
105
+ # @param [String] style_sheet
106
+ # @param [String] category
107
+ #
108
+ def create_record(asset, style_sheet = "_none_", category = "_none_")
109
+ delete_record(asset)
110
+ post("metadata.insert", self.class.xml_doc.request { |r|
111
+ r.group get_group_id(asset.workspace)
112
+ r.data { |d| d.cdata! asset.iso19139_xml }
113
+ r.category category
114
+ r.styleSheet style_sheet
115
+ })
116
+ end
117
+
118
+ #
119
+ # Get the metadata record for an asset.
120
+ #
121
+ # @param [Geoloader::Asset] asset
122
+ #
123
+ def get_record(asset)
124
+ post("xml.metadata.get", self.class.xml_doc.request { |r|
125
+ r.uuid asset.uuid
126
+ })
127
+ end
128
+
129
+ #
130
+ # Get all records in a given group.
131
+ #
132
+ # @param [String] group
133
+ #
134
+ def search_records_by_group(group)
135
+ post("xml.search", self.class.xml_doc.request { |r|
136
+ r.group get_group_id(group)
137
+ })
138
+ end
139
+
140
+ #
141
+ # Delete the metadata record for an asset.
142
+ #
143
+ # @param [Geoloader::Asset] asset
144
+ #
145
+ def delete_record(asset)
146
+ post("metadata.delete", self.class.xml_doc.request { |r|
147
+ r.uuid asset.uuid
148
+ }) rescue nil # Geonetwork 500's if the record doesn't exist...
149
+ end
150
+
151
+ #
152
+ # Delete a record by id.
153
+ #
154
+ # @param [Integer] id
155
+ #
156
+ def delete_record_by_id(id)
157
+ post("metadata.delete", self.class.xml_doc.request { |r|
158
+ r.id id
159
+ })
160
+ end
161
+
162
+ #
163
+ # Delete all records in a group with a given name.
164
+ #
165
+ # @param [Integer] group
166
+ #
167
+ def delete_records_by_group(group)
168
+ get_ids_in_group(group).each do |id|
169
+ delete_record_by_id(id)
170
+ end
171
+ end
172
+
173
+ #
174
+ # POST to an XML service.
175
+ #
176
+ # @param [String] service
177
+ # @param [String] payload
178
+ #
179
+ def post(service, payload)
180
+ @resource[service].post(payload) { |response, request, result, &block|
181
+ if [301, 302, 307].include?(response.code)
182
+ response.follow_redirection(request, result, &block)
183
+ else
184
+ response.return!(request, result, &block)
185
+ end
186
+ }
187
+ end
188
+
189
+ #
190
+ # Get an XML builder instance.
191
+ #
192
+ def self.xml_doc
193
+ xml = Builder::XmlMarkup.new
194
+ xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
195
+ xml
196
+ end
197
+
198
+ end
199
+
200
+ end
201
+ end