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,48 @@
1
+
2
+ require "confstruct"
3
+ require "require_all"
4
+ require "yaml"
5
+
6
+ module Geoloader
7
+
8
+ @config = Confstruct::Configuration.new
9
+
10
+ #
11
+ # Set configuration options.
12
+ #
13
+ # @param [Hash] opts
14
+ #
15
+ def self.configure(opts)
16
+ @config.configure(opts)
17
+ end
18
+
19
+ #
20
+ # Set configuration from a YAML file.
21
+ #
22
+ # @param [String] file_path
23
+ #
24
+ def self.configure_from_yaml(file_path)
25
+ @config.configure(YAML::load(File.read(File.expand_path(file_path))))
26
+ end
27
+
28
+ #
29
+ # Get the root gem directory.
30
+ #
31
+ def self.gem_dir
32
+ File.expand_path("../../", __FILE__)
33
+ end
34
+
35
+ #
36
+ # Get the configuration object.
37
+ #
38
+ def self.config
39
+ @config
40
+ end
41
+
42
+ end
43
+
44
+ require_rel("geoloader")
45
+
46
+ # Apply default configuration.
47
+ Geoloader.configure_from_yaml("#{Geoloader.gem_dir}/config.yaml")
48
+ Geoloader.configure_from_yaml("~/.geoloader.yaml") rescue nil
@@ -0,0 +1,63 @@
1
+
2
+ require "fileutils"
3
+
4
+ module Geoloader
5
+ module Assets
6
+
7
+ class Asset
8
+
9
+ attr_reader :file_path, :file_base, :file_name, :workspace, :uuid
10
+
11
+ #
12
+ # Set the basename and workspace-prefixed uuid, parse the description.
13
+ #
14
+ # @param [String] file_path
15
+ # @param [String] workspace
16
+ # @param [String] desc_path
17
+ #
18
+ def initialize(file_path, workspace, desc_path)
19
+
20
+ @file_path = File.expand_path(file_path)
21
+ @workspace = workspace
22
+
23
+ # File name, with and without extension.
24
+ @file_base = File.basename(@file_path, ".*")
25
+ @file_name = File.basename(@file_path)
26
+
27
+ # Parse the markdown metadata.
28
+ @description = Description.new(desc_path)
29
+
30
+ # Set a workspace-prefixed uuid.
31
+ @uuid = "#{@workspace}_#{@file_base}"
32
+
33
+ end
34
+
35
+ #
36
+ # Create working copies, yield to a block, remove the copies.
37
+ #
38
+ def stage
39
+
40
+ @tempdir = Dir.mktmpdir
41
+
42
+ begin
43
+
44
+ # Copy the assets into the temp dir.
45
+ files = Dir.glob("#{File.dirname(@file_path)}/#{@file_base}.*")
46
+ FileUtils.cp(files, @tempdir)
47
+
48
+ # Change into the temp dir.
49
+ FileUtils.cd(@tempdir) do yield end
50
+
51
+ ensure
52
+
53
+ # Delete the copies.
54
+ FileUtils.remove_entry @tempdir
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,55 @@
1
+
2
+ require "redcarpet"
3
+ require "jekyll"
4
+ require "nokogiri"
5
+ require "fileutils"
6
+ require "ostruct"
7
+
8
+ module Geoloader
9
+ module Assets
10
+
11
+ class Description
12
+
13
+ attr_reader :title, :abstract, :metadata
14
+
15
+ #
16
+ # Parse the markdown and extract the header.
17
+ #
18
+ # @param [String] file_path
19
+ #
20
+ def initialize(file_path)
21
+
22
+ @title, @abstract = "", ""
23
+ @metadata = {}
24
+
25
+ if file_path
26
+
27
+ @file_path = File.expand_path(file_path)
28
+
29
+ # Read the YAML front matter.
30
+ convertible = OpenStruct.new.extend(Jekyll::Convertible)
31
+ @metadata = convertible.read_yaml(File.dirname(@file_path), File.basename(@file_path))
32
+
33
+ # Scrub the YAML out of the markdown.
34
+ markdown = File.read(@file_path).sub(/---(.|\n)*---/, '')
35
+
36
+ # Parse the cleaned markdown.
37
+ renderer = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
38
+ document = Nokogiri::HTML::fragment(renderer.render(markdown))
39
+
40
+ # Set the title.
41
+ header = document.at_css('h1')
42
+ @title = header.text
43
+ header.remove
44
+
45
+ # Set the abstract.
46
+ @abstract = document.to_s.strip
47
+
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,58 @@
1
+
2
+ require "fileutils"
3
+ require "cgi"
4
+
5
+ module Geoloader
6
+ module Assets
7
+
8
+ module Geonetwork
9
+
10
+ #
11
+ # Form the WMS address.
12
+ #
13
+ def wms_address
14
+ "#{Geoloader.config.geoserver.url}/wms"
15
+ end
16
+
17
+ #
18
+ # Form the WMS layer string.
19
+ #
20
+ def wms_layers
21
+ "#{@workspace}:#{@file_base}"
22
+ end
23
+
24
+ #
25
+ # Convert the ESRI XML into a iso19139 record.
26
+ #
27
+ def iso19139_xml
28
+ `saxon #{@file_path}.xml #{Geoloader.gem_dir}/iso19139.xsl #{xslt_params(
29
+ :identifier => @uuid,
30
+ :categories => get_list_parameter("categories"),
31
+ :keywords => get_list_parameter("keywords"),
32
+ :title => @description.title.to_s,
33
+ :abstract => @description.abstract.to_s,
34
+ :wms_address => wms_address,
35
+ :wms_layers => wms_layers
36
+ )}`
37
+ end
38
+
39
+ #
40
+ # Convert an array metadata attribute to a comma-delimited list.
41
+ #
42
+ def get_list_parameter(key)
43
+ @description.metadata.fetch(key, []).join(",")
44
+ end
45
+
46
+ #
47
+ # Convert a hash to a Saxon XSLT parameter string.
48
+ #
49
+ # @param [Hash] params
50
+ #
51
+ def xslt_params(params)
52
+ params.map { |k, v| "#{k}='#{CGI::escapeHTML(v)}'" }.join(" ")
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,41 @@
1
+
2
+ require "fileutils"
3
+
4
+ module Geoloader
5
+ module Assets
6
+
7
+ module Geotiff
8
+
9
+ #
10
+ # Remove the black borders added by ArcMap.
11
+ #
12
+ def make_borders_transparent
13
+ gdal_command("gdalwarp -srcnodata 0 -dstalpha", @file_name)
14
+ end
15
+
16
+ #
17
+ # (Re)build a EPSG:4326 header.
18
+ #
19
+ def reproject
20
+ srs = Geoloader.config.geoserver.srs
21
+ gdal_command("gdal_translate -of GTiff -a_srs #{srs}", @file_name)
22
+ end
23
+
24
+ private
25
+
26
+ #
27
+ # Run a gdal command on a file, replacing the original file.
28
+ #
29
+ # @param [String] command
30
+ # @param [String] file_path
31
+ #
32
+ def gdal_command(command, file_path)
33
+ `#{command} #{file_path} #{file_path}_`
34
+ FileUtils.rm(file_path)
35
+ FileUtils.mv("#{file_path}_", file_path)
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,28 @@
1
+
2
+ require "zip"
3
+
4
+ module Geoloader
5
+ module Assets
6
+
7
+ module Shapefile
8
+
9
+ #
10
+ # Zip up the Shapefile and its companion files.
11
+ #
12
+ def get_zipfile
13
+
14
+ # Create the zipfile.
15
+ Zip::File.open("#{@file_base}.zip", Zip::File::CREATE) do |zipfile|
16
+ Dir.glob("#{@file_base}.*") do |file|
17
+ zipfile.add(File.basename(file), file)
18
+ end
19
+ end
20
+
21
+ File.read("#{@file_base}.zip")
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+
2
+ module Geoloader
3
+ module Assets
4
+
5
+ module Solr
6
+
7
+ #
8
+ # Get metadata for Solr document.
9
+ #
10
+ def solr_document
11
+ {
12
+ :LayerId => @uuid,
13
+ :LayerDisplayName => @description.title,
14
+ :Abstract => @description.abstract,
15
+ :WorkspaceName => @workspace,
16
+ :Name => @file_base
17
+ }
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+
2
+ require "thor"
3
+
4
+ module Geoloader
5
+ module CLI
6
+
7
+ class App < Thor
8
+
9
+ desc "solr [SUBCOMMAND]", "Manage Solr documents"
10
+ subcommand "solr", Solr
11
+
12
+ desc "geoserver [SUBCOMMAND]", "Manage Geoserver stores and layers"
13
+ subcommand "geoserver", Geoserver
14
+
15
+ desc "geonetwork [SUBCOMMAND]", "Manage Geonetwork records"
16
+ subcommand "geonetwork", Geonetwork
17
+
18
+ desc "work", "Start a Resque worker"
19
+ def work
20
+ Resque::Worker.new("geoloader").work
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+
2
+ require "thor"
3
+
4
+ module Geoloader
5
+ module CLI
6
+
7
+ class Geonetwork < Thor
8
+
9
+ include Tasks
10
+
11
+ desc "load [FILES]", "Load Geonetwork metadata records"
12
+ option :queue, :aliases => "-q", :type => :boolean, :default => false
13
+ option :description, :aliases => "-d", :type => :string
14
+ option :workspace, :aliases => "-w", :type => :string
15
+ def load(*files)
16
+
17
+ files.each { |file_path|
18
+ Geoloader::Loaders::Geonetwork.load_or_enqueue(file_path, options)
19
+ }
20
+
21
+ end
22
+
23
+ desc "publish [WORKSPACE]", "Publish all records in a group"
24
+ def publish(workspace)
25
+ Geoloader::Tasks::Geonetwork.publish(workspace)
26
+ end
27
+
28
+ desc "clear [WORKSPACE]", "Clear all records in a group"
29
+ def clear(workspace)
30
+ Geoloader::Tasks::Geonetwork.clear(workspace) rescue nil
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+
2
+ require "thor"
3
+
4
+ module Geoloader
5
+ module CLI
6
+
7
+ class Geoserver < Thor
8
+
9
+ include Tasks
10
+
11
+ desc "load [FILES]", "Load Geoserver stores and layers"
12
+ option :queue, :aliases => "-q", :type => :boolean, :default => false
13
+ option :description, :aliases => "-d", :type => :string
14
+ option :workspace, :aliases => "-w", :type => :string
15
+ def load(*files)
16
+
17
+ files.each { |file_path|
18
+ case File.extname(file_path)
19
+ when ".tif" # GEOTIFF
20
+ Geoloader::Loaders::GeotiffGeoserver.load_or_enqueue(file_path, options)
21
+ when ".shp" # SHAPEFILE
22
+ Geoloader::Loaders::ShapefileGeoserver.load_or_enqueue(file_path, options)
23
+ end
24
+ }
25
+
26
+ end
27
+
28
+ desc "clear [WORKSPACE]", "Clear all documents in a workspace"
29
+ def clear(workspace)
30
+ Geoloader::Tasks::Geoserver.clear(workspace) rescue nil
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+
2
+ require "thor"
3
+
4
+ module Geoloader
5
+ module CLI
6
+
7
+ class Solr < Thor
8
+
9
+ include Tasks
10
+
11
+ desc "load [FILES]", "Load Solr documents"
12
+ option :queue, :aliases => "-q", :type => :boolean, :default => false
13
+ option :description, :aliases => "-d", :type => :string
14
+ option :workspace, :aliases => "-w", :type => :string
15
+ def load(*files)
16
+
17
+ files.each { |file_path|
18
+ case File.extname(file_path)
19
+ when ".tif" # GEOTIFF
20
+ Geoloader::Loaders::GeotiffSolr.load_or_enqueue(file_path, options)
21
+ when ".shp" # SHAPEFILE
22
+ Geoloader::Loaders::ShapefileSolr.load_or_enqueue(file_path, options)
23
+ end
24
+ }
25
+
26
+ end
27
+
28
+ desc "clear [WORKSPACE]", "Clear all documents in a workspace"
29
+ def clear(workspace)
30
+ Geoloader::Tasks::Solr.clear(workspace) rescue nil
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end