tax_generator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.inch.yml +10 -0
  4. data/.reek +10 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +72 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +154 -0
  9. data/LICENSE +20 -0
  10. data/README.md +131 -0
  11. data/Rakefile +26 -0
  12. data/bin/tax_generator +7 -0
  13. data/data/input/.gitignore +25 -0
  14. data/data/input/destinations.xml +1073 -0
  15. data/data/input/taxonomy.xml +78 -0
  16. data/data/output/.gitignore +4 -0
  17. data/init.rb +1 -0
  18. data/lib/tax_generator/all.rb +26 -0
  19. data/lib/tax_generator/application.rb +125 -0
  20. data/lib/tax_generator/classes/destination.rb +103 -0
  21. data/lib/tax_generator/classes/file_creator.rb +100 -0
  22. data/lib/tax_generator/classes/processor.rb +270 -0
  23. data/lib/tax_generator/classes/taxonomy_tree.rb +97 -0
  24. data/lib/tax_generator/cli.rb +14 -0
  25. data/lib/tax_generator/helpers/application_helper.rb +154 -0
  26. data/lib/tax_generator/version.rb +27 -0
  27. data/lib/tax_generator.rb +1 -0
  28. data/spec/lib/tax_generator/application_spec.rb +0 -0
  29. data/spec/lib/tax_generator/classes/destination_spec.rb +62 -0
  30. data/spec/lib/tax_generator/classes/file_creator_spec.rb +96 -0
  31. data/spec/lib/tax_generator/classes/processor_spec.rb +30 -0
  32. data/spec/lib/tax_generator/classes/taxonomy_tree_spec.rb +0 -0
  33. data/spec/lib/tax_generator/cli_spec.rb +0 -0
  34. data/spec/lib/tax_generator/helpers/application_helper_spec.rb +0 -0
  35. data/spec/spec_helper.rb +60 -0
  36. data/tax_generator.gemspec +40 -0
  37. data/templates/static/all.css +586 -0
  38. data/templates/template.html.erb +91 -0
  39. metadata +452 -0
@@ -0,0 +1,78 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <taxonomies>
3
+ <taxonomy>
4
+ <taxonomy_name>World</taxonomy_name>
5
+ <node atlas_node_id = "355064" ethyl_content_object_id="82534" geo_id = "355064">
6
+ <node_name>Africa</node_name>
7
+ <node atlas_node_id = "355611" ethyl_content_object_id="3210" geo_id = "355611">
8
+ <node_name>South Africa</node_name>
9
+ <node atlas_node_id = "355612" ethyl_content_object_id="35474" geo_id = "355612">
10
+ <node_name>Cape Town</node_name>
11
+ <node atlas_node_id = "355613" ethyl_content_object_id="" geo_id = "355613">
12
+ <node_name>Table Mountain National Park</node_name>
13
+ </node>
14
+ </node>
15
+ <node atlas_node_id = "355614" ethyl_content_object_id="" geo_id = "355614">
16
+ <node_name>Free State</node_name>
17
+ <node atlas_node_id = "355615" ethyl_content_object_id="1000550692" geo_id = "355615">
18
+ <node_name>Bloemfontein</node_name>
19
+ </node>
20
+ </node>
21
+ <node atlas_node_id = "355616" ethyl_content_object_id="" geo_id = "355616">
22
+ <node_name>Gauteng</node_name>
23
+ <node atlas_node_id = "355617" ethyl_content_object_id="37710" geo_id = "355617">
24
+ <node_name>Johannesburg</node_name>
25
+ </node>
26
+ <node atlas_node_id = "355618" ethyl_content_object_id="1000548256" geo_id = "355618">
27
+ <node_name>Pretoria</node_name>
28
+ </node>
29
+ </node>
30
+ <node atlas_node_id = "355619" ethyl_content_object_id="" geo_id = "355619">
31
+ <node_name>KwaZulu-Natal</node_name>
32
+ <node atlas_node_id = "355620" ethyl_content_object_id="43725" geo_id = "355620">
33
+ <node_name>Durban</node_name>
34
+ </node>
35
+ <node atlas_node_id = "355621" ethyl_content_object_id="1000576780" geo_id = "355621">
36
+ <node_name>Pietermaritzburg</node_name>
37
+ </node>
38
+ </node>
39
+ <node atlas_node_id = "355622" ethyl_content_object_id="" geo_id = "355622">
40
+ <node_name>Mpumalanga</node_name>
41
+ <node atlas_node_id = "355623" ethyl_content_object_id="67561" geo_id = "355623">
42
+ <node_name>Kruger National Park</node_name>
43
+ </node>
44
+ </node>
45
+ <node atlas_node_id = "355624" ethyl_content_object_id="" geo_id = "355624">
46
+ <node_name>The Drakensberg</node_name>
47
+ <node atlas_node_id = "355625" ethyl_content_object_id="" geo_id = "355625">
48
+ <node_name>Royal Natal National Park</node_name>
49
+ </node>
50
+ </node>
51
+ <node atlas_node_id = "355626" ethyl_content_object_id="" geo_id = "355626">
52
+ <node_name>The Garden Route</node_name>
53
+ <node atlas_node_id = "355627" ethyl_content_object_id="" geo_id = "355627">
54
+ <node_name>Oudtshoorn</node_name>
55
+ </node>
56
+ <node atlas_node_id = "355628" ethyl_content_object_id="" geo_id = "355628">
57
+ <node_name>Tsitsikamma Coastal National Park</node_name>
58
+ </node>
59
+ </node>
60
+ </node>
61
+ <node atlas_node_id = "355629" ethyl_content_object_id="3263" geo_id = "355629">
62
+ <node_name>Sudan</node_name>
63
+ <node atlas_node_id = "355630" ethyl_content_object_id="" geo_id = "355630">
64
+ <node_name>Eastern Sudan</node_name>
65
+ <node atlas_node_id = "355631" ethyl_content_object_id="" geo_id = "355631">
66
+ <node_name>Port Sudan</node_name>
67
+ </node>
68
+ </node>
69
+ <node atlas_node_id = "355632" ethyl_content_object_id="" geo_id = "355632">
70
+ <node_name>Khartoum</node_name>
71
+ </node>
72
+ </node>
73
+ <node atlas_node_id = "355633" ethyl_content_object_id="3272" geo_id = "355633">
74
+ <node_name>Swaziland</node_name>
75
+ </node>
76
+ </node>
77
+ </taxonomy>
78
+ </taxonomies>
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'tax_generator'
@@ -0,0 +1,26 @@
1
+ $stdin.sync = true # if $stdin.isatty
2
+ $stdout.sync = true # if $stdout.isatty
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ require 'bundler/setup'
6
+ require 'active_support/core_ext/object/blank'
7
+ require 'active_support/core_ext/hash/keys'
8
+ require 'active_support/core_ext/module/delegation'
9
+
10
+ require 'slop'
11
+ require 'nokogiri'
12
+ require 'tree'
13
+ require 'celluloid/autostart'
14
+ require 'celluloid/pmap'
15
+
16
+ require 'logger'
17
+ require 'fileutils'
18
+ require 'ostruct'
19
+ require 'erb'
20
+ require 'tilt'
21
+
22
+ %w(classes helpers).each do |folder_name|
23
+ Gem.find_files("tax_generator/#{folder_name}/**/*.rb").each { |path| require path }
24
+ end
25
+ require_relative './application'
26
+ require_relative './version'
@@ -0,0 +1,125 @@
1
+ require_relative './helpers/application_helper'
2
+ module TaxGenerator
3
+ # class used run the processsor
4
+ #
5
+ # @!attribute opts
6
+ # @return [Slop::Options] the options that are used for command line access
7
+ #
8
+ class Application
9
+ include TaxGenerator::ApplicationHelper
10
+
11
+ attr_reader :opts
12
+
13
+ # method used to initialize the application, by initializing the options for command line
14
+ # access
15
+ #
16
+ #
17
+ # @return [void]
18
+ #
19
+ # @api public
20
+ def initialize
21
+ @opts = Slop::Options.new
22
+ @opts.banner = 'usage: tax_generator [options] ...'
23
+ end
24
+
25
+ # receives a list of options that are used to determine the input files and output and input folders
26
+ #
27
+ # @param [Hash] options the options that are used for command line access
28
+ #
29
+ # @see #execute_with_rescue
30
+ # @see TaxGenerator::Processor#new
31
+ # @see TaxGenerator::Processor#work
32
+ #
33
+ # @return [void]
34
+ #
35
+ # @api public
36
+ def run(options = {})
37
+ execute_with_rescue do
38
+ options = options.present? ? options : parse_options
39
+ processor = TaxGenerator::Processor.new(options)
40
+ processor.work
41
+ end
42
+ end
43
+
44
+ # returns the logger used to log messages and errors
45
+ #
46
+ # @return [Logger]
47
+ #
48
+ # @api public
49
+ def self.app_logger
50
+ @logger ||= Logger.new($stdout)
51
+ end
52
+
53
+ # returns the options list as a hash after parsing command line arguments
54
+ #
55
+ # @return [Hash]
56
+ #
57
+ # @api public
58
+ def parse_options
59
+ setup_command_line_options
60
+ parser = Slop::Parser.new(@opts)
61
+ result = parser.parse(ARGV.dup)
62
+ result.to_hash
63
+ end
64
+
65
+ # sets the directory options for command line access
66
+ #
67
+ # @return [void]
68
+ #
69
+ # @api public
70
+ def directory_options
71
+ @opts.separator ''
72
+ @opts.separator 'Directory options:'
73
+ @opts.string '-i', '--input_dir', 'The input directory ', default: "#{root}/data/input"
74
+ @opts.string '-o', '--output_dir', 'The ouput directory', default: "#{root}/data/output"
75
+ end
76
+
77
+ # sets the file options for command line access
78
+ #
79
+ # @return [void]
80
+ #
81
+ # @api public
82
+ def file_options
83
+ @opts.separator ''
84
+ @opts.separator 'Extra options:'
85
+ @opts.string '-t', '--taxonomy_filename', 'The taxonomy file name', default: 'taxonomy.xml'
86
+ @opts.string '-d', '--destinations_filename', 'The destinations file name', default: 'destinations.xml'
87
+ end
88
+
89
+ # sets the version of the gem available to be displayed from command line
90
+ #
91
+ # @return [void]
92
+ #
93
+ # @api public
94
+ def setup_version
95
+ @opts.on '--version', 'The destinations file name' do
96
+ puts TaxGenerator.gem_version
97
+ exit
98
+ end
99
+ end
100
+
101
+ # sets the help menu for command line access
102
+ #
103
+ # @return [void]
104
+ #
105
+ # @api public
106
+ def setup_help
107
+ @opts.on '--help', 'print the help' do
108
+ puts @opts
109
+ exit
110
+ end
111
+ end
112
+
113
+ # sets the command line options
114
+ #
115
+ # @return [void]
116
+ #
117
+ # @api public
118
+ def setup_command_line_options
119
+ directory_options
120
+ file_options
121
+ setup_version
122
+ setup_help
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,103 @@
1
+ require_relative '../helpers/application_helper'
2
+ module TaxGenerator
3
+ # class used to find xpaths from the destination node from xml
4
+ #
5
+ # @!attribute destination
6
+ # @return [Nokogiri::Element] the element from the xml document that need to be parsed
7
+ class Destination
8
+ include TaxGenerator::ApplicationHelper
9
+
10
+ delegate :xpath,
11
+ to: :destination
12
+
13
+ attr_reader :destination
14
+
15
+ # receives destination node (xml element) that need to be parsed
16
+ #
17
+ # @param [Nokogiri::Element] destination_node the element from the xml document that need to be parsed
18
+ #
19
+ # @return [void]
20
+ #
21
+ # @api public
22
+ def initialize(destination_node)
23
+ @destination = destination_node
24
+ end
25
+
26
+ # returns the information about the introduction
27
+ #
28
+ # @return [Nokogiri::NodeSet]
29
+ #
30
+ # @api public
31
+ def introduction
32
+ xpath('.//introductory/introduction/overview')
33
+ end
34
+
35
+ # returns the information about the history
36
+ #
37
+ # @return [Nokogiri::NodeSet]
38
+ #
39
+ # @api public
40
+ def history
41
+ xpath('./history/history/history')
42
+ end
43
+
44
+ # returns the information about the practical_information
45
+ #
46
+ # @return [Nokogiri::NodeSet]
47
+ #
48
+ # @api public
49
+ def practical_information
50
+ base = './/practical_information/health_and_safety'
51
+ xpath("#{base}/dangers_and_annoyances") + xpath("#{base}/while_youre_there") + \
52
+ xpath("#{base}/before_you_go") + xpath("#{base}/money_and_costs/money")
53
+ end
54
+
55
+ # returns the information about the transport
56
+ #
57
+ # @return [Nokogiri::NodeSet]
58
+ #
59
+ # @api public
60
+ def transport
61
+ xpath('.//transport/getting_around')
62
+ end
63
+
64
+ # returns the information about the weather
65
+ #
66
+ # @return [Nokogiri::NodeSet]
67
+ #
68
+ # @api public
69
+ def weather
70
+ xpath('.//weather')
71
+ end
72
+
73
+ # returns the information about the work_live_study
74
+ #
75
+ # @return [Nokogiri::NodeSet]
76
+ #
77
+ # @api public
78
+ def work_live_study
79
+ xpath('.//work_live_study')
80
+ end
81
+
82
+ # returns the a hash containing all the parsed information from the xml document
83
+ # and makes sure that only elements with content not blank will be returned
84
+ #
85
+ # @see #elements_with_content
86
+ # @return [Nokogiri::NodeSet]
87
+ #
88
+ # @api public
89
+ def to_hash
90
+ {
91
+ introduction: introduction,
92
+ history: history,
93
+ practical_information: practical_information,
94
+ transport: transport,
95
+ weather: weather,
96
+ work_live_study: work_live_study
97
+ }.each_with_object({}) do |(key, value), hsh|
98
+ hsh[key] = elements_with_content(value)
99
+ hsh
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,100 @@
1
+ require_relative '../helpers/application_helper'
2
+ module TaxGenerator
3
+ # class used to create the files
4
+ #
5
+ # @!attribute processor
6
+ # @return [TaxGenerator::Processor] the manager that manages the current actor
7
+ # @!attribute job
8
+ # @return [Hash] the job that this actor received
9
+ # @!attribute job_id
10
+ # @return [String] the id of the node from the taxonomy tree
11
+ # @!attribute destination
12
+ # @return [Nokogiri::Element] the destination node from the xml document
13
+ # @!attribute taxonomy
14
+ # @return [TaxGenerator::TaxonomyTree] the taxonomy tree holding all the nodes from the taxonomy xml document
15
+ # @!attribute output_folder
16
+ # @return [String] the output folder where the new files will be created
17
+ class FileCreator
18
+ include Celluloid
19
+ include Celluloid::Logger
20
+ include TaxGenerator::ApplicationHelper
21
+
22
+ attr_reader :processor, :job, :job_id, :destination, :taxonomy, :output_folder
23
+
24
+ # returns the template file path used for generating the files
25
+ #
26
+ # @return [void]
27
+ #
28
+ # @api public
29
+ def template_name
30
+ File.join(root, 'templates', 'template.html.erb')
31
+ end
32
+
33
+ # processes the job received and registers itself inside the manager
34
+ # @see TaxGenerator::Processor#register_worker_for_job
35
+ # @see #process_job
36
+ #
37
+ # @param [Hash] job the job that is passed to the current actor
38
+ # @param [TaxGenerator::Processor] manager the manager that manages the actor
39
+ #
40
+ # @return [void]
41
+ #
42
+ # @api public
43
+ def work(job, manager)
44
+ job = job.stringify_keys
45
+ @job = job
46
+ @processor = manager
47
+ process_job(job)
48
+ @processor.register_worker_for_job(job, Actor.current)
49
+ end
50
+
51
+ # processes the job information by retrieving keys from the hash
52
+ #
53
+ # @param [Hash] job the job that is passed to the current actor
54
+ #
55
+ # @return [void]
56
+ #
57
+ # @api public
58
+ def process_job(job)
59
+ job = job.stringify_keys
60
+ @destination = job['destination']
61
+ @job_id = job['atlas_id']
62
+ @taxonomy = job['taxonomy']
63
+ @output_folder = job['output_folder']
64
+ end
65
+
66
+ # renders the template and creates new file with the template html
67
+ #
68
+ # @return [void]
69
+ #
70
+ # @api public
71
+ def start_work
72
+ log_message "Generating html for destination #{@job_id}"
73
+ output = Tilt.new(template_name).render(Actor.current, fetch_atlas_details)
74
+ File.open(File.join(@output_folder, "#{@job_id}.html"), 'w') { |file| file << output }
75
+ mark_job_completed
76
+ end
77
+
78
+ # marks the job as completed after file is generated
79
+ #
80
+ # @return [void]
81
+ #
82
+ # @api public
83
+ def mark_job_completed
84
+ @processor.jobs[@job_id]['status'] = 'finished'
85
+ @processor.condition.signal('completed') if @processor.alive? && @processor.all_workers_finished?
86
+ end
87
+
88
+ # fetches the details needed to be passed to the erb template
89
+ # @see TaxGenerator::Destination#new
90
+ #
91
+ # @return [void]
92
+ #
93
+ # @api public
94
+ def fetch_atlas_details
95
+ atlas_node = @taxonomy[@job_id]
96
+ content = @destination.present? ? TaxGenerator::Destination.new(@destination).to_hash : {}
97
+ content.merge(details: atlas_node, root: root)
98
+ end
99
+ end
100
+ end