hdo-storting-importer 0.0.1
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.
- data/.gitignore +16 -0
- data/.gitmodules +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +8 -0
- data/LICENSE +20 -0
- data/README.md +14 -0
- data/Rakefile +11 -0
- data/bin/hdo-converter +7 -0
- data/features/import.feature +85 -0
- data/features/step_definitions/import_steps.rb +0 -0
- data/features/support/env.rb +7 -0
- data/hdo-storting-importer.gemspec +17 -0
- data/lib/hdo/storting_importer/api_data_source.rb +62 -0
- data/lib/hdo/storting_importer/category.rb +55 -0
- data/lib/hdo/storting_importer/cli.rb +141 -0
- data/lib/hdo/storting_importer/committee.rb +35 -0
- data/lib/hdo/storting_importer/converter.rb +45 -0
- data/lib/hdo/storting_importer/core_ext/enumerable.rb +12 -0
- data/lib/hdo/storting_importer/data_source.rb +22 -0
- data/lib/hdo/storting_importer/disk_data_source.rb +61 -0
- data/lib/hdo/storting_importer/district.rb +36 -0
- data/lib/hdo/storting_importer/issue.rb +90 -0
- data/lib/hdo/storting_importer/ivar_equality.rb +22 -0
- data/lib/hdo/storting_importer/parsing_data_source.rb +59 -0
- data/lib/hdo/storting_importer/party.rb +31 -0
- data/lib/hdo/storting_importer/promise.rb +49 -0
- data/lib/hdo/storting_importer/promise_converter.rb +48 -0
- data/lib/hdo/storting_importer/representative.rb +106 -0
- data/lib/hdo/storting_importer/script_importer.rb +20 -0
- data/lib/hdo/storting_importer/util.rb +26 -0
- data/lib/hdo/storting_importer/version.rb +5 -0
- data/lib/hdo/storting_importer/vote.rb +171 -0
- data/lib/hdo/storting_importer.rb +41 -0
- data/spec/fixtures/input/categories.xml +1351 -0
- data/spec/fixtures/input/committees.xml +92 -0
- data/spec/fixtures/input/districts.xml +101 -0
- data/spec/fixtures/input/issues.xml +2852 -0
- data/spec/fixtures/input/parties.xml +42 -0
- data/spec/fixtures/input/promises-a.csv +341 -0
- data/spec/fixtures/input/propositions_2175.xml +64 -0
- data/spec/fixtures/input/propositions_2176.xml +64 -0
- data/spec/fixtures/input/representatives.xml +3218 -0
- data/spec/fixtures/input/representatives_today.xml +4872 -0
- data/spec/fixtures/input/vote_results_2175.xml +4400 -0
- data/spec/fixtures/input/vote_results_2176.xml +4400 -0
- data/spec/fixtures/input/votes.xml +85 -0
- data/spec/fixtures/output/categories.xml +803 -0
- data/spec/fixtures/output/committees.xml +71 -0
- data/spec/fixtures/output/districts.xml +79 -0
- data/spec/fixtures/output/issues.xml +836 -0
- data/spec/fixtures/output/parties.xml +31 -0
- data/spec/fixtures/output/promises-a.xml +3224 -0
- data/spec/fixtures/output/representatives.xml +2567 -0
- data/spec/fixtures/output/votes.xml +4899 -0
- data/spec/hdo/storting_importer/category_spec.rb +76 -0
- data/spec/hdo/storting_importer/committee_spec.rb +46 -0
- data/spec/hdo/storting_importer/converter_spec.rb +72 -0
- data/spec/hdo/storting_importer/district_spec.rb +54 -0
- data/spec/hdo/storting_importer/issue_spec.rb +115 -0
- data/spec/hdo/storting_importer/party_spec.rb +52 -0
- data/spec/hdo/storting_importer/promise_spec.rb +38 -0
- data/spec/hdo/storting_importer/representative_spec.rb +81 -0
- data/spec/hdo/storting_importer/vote_spec.rb +155 -0
- data/spec/spec_helper.rb +39 -0
- metadata +145 -0
data/.gitignore
ADDED
data/.gitmodules
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Holder De Ord
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
What
|
2
|
+
====
|
3
|
+
|
4
|
+
Convert and import XML from data.stortinget.no
|
5
|
+
|
6
|
+
Usage
|
7
|
+
=====
|
8
|
+
|
9
|
+
$ bin/hdo-converter --app-root /src/hdo-site all
|
10
|
+
|
11
|
+
Caveats
|
12
|
+
=======
|
13
|
+
|
14
|
+
Right now we're executing script/import from hdo-site to perform the import. That means running this with bundler may fail if the gems don't match. Don't do that.
|
data/Rakefile
ADDED
data/bin/hdo-converter
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
Feature: Import data
|
2
|
+
Scenario: Import districts
|
3
|
+
When I run `hdo-converter --only-print districts`
|
4
|
+
Then the stdout should contain:
|
5
|
+
"""
|
6
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
7
|
+
<districts>
|
8
|
+
<district>
|
9
|
+
<externalId>Ak</externalId>
|
10
|
+
<name>Akershus</name>
|
11
|
+
</district>
|
12
|
+
<district>
|
13
|
+
<externalId>AA</externalId>
|
14
|
+
<name>Aust-Agder</name>
|
15
|
+
</district>
|
16
|
+
<district>
|
17
|
+
<externalId>Bu</externalId>
|
18
|
+
<name>Buskerud</name>
|
19
|
+
</district>
|
20
|
+
<district>
|
21
|
+
<externalId>Fi</externalId>
|
22
|
+
<name>Finnmark</name>
|
23
|
+
</district>
|
24
|
+
<district>
|
25
|
+
<externalId>He</externalId>
|
26
|
+
<name>Hedmark</name>
|
27
|
+
</district>
|
28
|
+
<district>
|
29
|
+
<externalId>Ho</externalId>
|
30
|
+
<name>Hordaland</name>
|
31
|
+
</district>
|
32
|
+
<district>
|
33
|
+
<externalId>MR</externalId>
|
34
|
+
<name>Møre og Romsdal</name>
|
35
|
+
</district>
|
36
|
+
<district>
|
37
|
+
<externalId>NT</externalId>
|
38
|
+
<name>Nord-Trøndelag</name>
|
39
|
+
</district>
|
40
|
+
<district>
|
41
|
+
<externalId>No</externalId>
|
42
|
+
<name>Nordland</name>
|
43
|
+
</district>
|
44
|
+
<district>
|
45
|
+
<externalId>Op</externalId>
|
46
|
+
<name>Oppland</name>
|
47
|
+
</district>
|
48
|
+
<district>
|
49
|
+
<externalId>Os</externalId>
|
50
|
+
<name>Oslo</name>
|
51
|
+
</district>
|
52
|
+
<district>
|
53
|
+
<externalId>Ro</externalId>
|
54
|
+
<name>Rogaland</name>
|
55
|
+
</district>
|
56
|
+
<district>
|
57
|
+
<externalId>SF</externalId>
|
58
|
+
<name>Sogn og Fjordane</name>
|
59
|
+
</district>
|
60
|
+
<district>
|
61
|
+
<externalId>ST</externalId>
|
62
|
+
<name>Sør-Trøndelag</name>
|
63
|
+
</district>
|
64
|
+
<district>
|
65
|
+
<externalId>Te</externalId>
|
66
|
+
<name>Telemark</name>
|
67
|
+
</district>
|
68
|
+
<district>
|
69
|
+
<externalId>Tr</externalId>
|
70
|
+
<name>Troms</name>
|
71
|
+
</district>
|
72
|
+
<district>
|
73
|
+
<externalId>VA</externalId>
|
74
|
+
<name>Vest-Agder</name>
|
75
|
+
</district>
|
76
|
+
<district>
|
77
|
+
<externalId>Ve</externalId>
|
78
|
+
<name>Vestfold</name>
|
79
|
+
</district>
|
80
|
+
<district>
|
81
|
+
<externalId>Øs</externalId>
|
82
|
+
<name>Østfold</name>
|
83
|
+
</district>
|
84
|
+
</districts>
|
85
|
+
"""
|
File without changes
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/hdo/storting_importer/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Jari Bakken"]
|
6
|
+
gem.email = ["jari.bakken@gmail.com"]
|
7
|
+
gem.description = %q{Gem to process data from data.stortinget.no}
|
8
|
+
gem.summary = %q{Gem to process data from data.stortinget.no}
|
9
|
+
gem.homepage = "http://github.com/holderdeord/hdo-storting-importer"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\).reject { |e| e =~ /^(data|folketingparser)/ }
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "hdo-storting-importer"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Hdo::StortingImporter::VERSION
|
17
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class ApiDataSource < DataSource
|
4
|
+
|
5
|
+
def initialize(url)
|
6
|
+
@log = Logger.new(STDERR)
|
7
|
+
@resource = RestClient::Resource.new(URI.parse(url))
|
8
|
+
end
|
9
|
+
|
10
|
+
def representatives(period = DEFAULT_PERIOD)
|
11
|
+
fetch "eksport/representanter/?StortingsPeriodeId=#{period}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def representatives_today
|
15
|
+
fetch 'eksport/dagensrepresentanter/'
|
16
|
+
end
|
17
|
+
|
18
|
+
def parties(session_id = DEFAULT_SESSION)
|
19
|
+
fetch "eksport/partier/?sesjonid=#{session_id}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def committees(session_id = DEFAULT_SESSION)
|
23
|
+
fetch "eksport/komiteer/?SesjonId=#{session_id}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def districts
|
27
|
+
fetch "eksport/fylker"
|
28
|
+
end
|
29
|
+
|
30
|
+
def categories
|
31
|
+
fetch "eksport/emner"
|
32
|
+
end
|
33
|
+
|
34
|
+
def issues(session_id = DEFAULT_SESSION)
|
35
|
+
fetch "eksport/saker?sesjonid=#{session_id}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def votes_for(issue_id)
|
39
|
+
fetch "eksport/voteringer?sakid=#{issue_id}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def propositions_for(vote_id)
|
43
|
+
fetch "eksport/voteringsforslag/?voteringid=#{vote_id}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def vote_results_for(vote_id)
|
47
|
+
fetch "eksport/voteringsresultat/?voteringid=#{vote_id}"
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def fetch(path)
|
53
|
+
sub_resource = @resource[path]
|
54
|
+
@log.info "parsing #{sub_resource}"
|
55
|
+
|
56
|
+
parse sub_resource.get
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class Category
|
4
|
+
include IvarEquality
|
5
|
+
|
6
|
+
attr_reader :external_id, :name
|
7
|
+
attr_accessor :children
|
8
|
+
|
9
|
+
def self.from_storting_doc(doc)
|
10
|
+
doc.css("emne_liste > emne").map { |xt| from_storting_node(xt) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.from_storting_node(node)
|
14
|
+
cat = Category.new node.css("id").first.text, node.css("navn").first.text
|
15
|
+
|
16
|
+
subnodes = node.css("underemne_liste > emne")
|
17
|
+
subnodes.map do |subnode|
|
18
|
+
cat.children << Category.new(subnode.css("id").first.text, subnode.css("navn").first.text)
|
19
|
+
end
|
20
|
+
|
21
|
+
cat
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.from_hdo_node(node)
|
25
|
+
external_id = node.css("externalId").first.text
|
26
|
+
name = node.css("name").first.text
|
27
|
+
|
28
|
+
cat = new external_id, name
|
29
|
+
cat.children = node.css("subcategories category").map { |e| from_hdo_node(e) }
|
30
|
+
|
31
|
+
cat
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(external_id, name)
|
35
|
+
@external_id = external_id
|
36
|
+
@name = name
|
37
|
+
@children = []
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_hdo_xml(builder = Util.builder)
|
41
|
+
builder.category do |cat|
|
42
|
+
cat.externalId external_id
|
43
|
+
cat.name name
|
44
|
+
|
45
|
+
if children.any?
|
46
|
+
cat.subcategories do |sub|
|
47
|
+
children.each { |child| child.to_hdo_xml(sub) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class CLI
|
4
|
+
def initialize(args)
|
5
|
+
@log = Logger.new(STDERR)
|
6
|
+
@cmd, @options = parse(args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def execute
|
10
|
+
import @cmd.to_sym
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def parse(args)
|
16
|
+
options = {:source => (has_submodule? ? 'disk' : 'api')}
|
17
|
+
|
18
|
+
parser = OptionParser.new do |opt|
|
19
|
+
opt.banner = "Usage: #{$0} <import-type> [options]"
|
20
|
+
|
21
|
+
opt.on("--help", "You're looking at it.") { puts opt; exit; }
|
22
|
+
opt.on("--only-print", "Don't run import, only print generated XML.") { options[:only_print] = true }
|
23
|
+
opt.on("--except WHAT", 'Ignore this comma separated list of entities from import.') { |s| options[:ignore] = s.split(",").map(&:strip).map(&:to_sym) }
|
24
|
+
opt.on("--app-root APP_ROOT", 'Path to clone of git://github.com/holderdeord/hdo-site.git') { |path| options[:app_root] = path }
|
25
|
+
opt.on("--app-url APP_URL", 'URL to hdo-site') { |url| options[:app_url] = url }
|
26
|
+
opt.on("--source SOURCE ", 'Where to take data from [disk|api]') { |source| options[:source] = source }
|
27
|
+
opt.on("--socks PROXY", 'host:port for SOCKS proxy') do |proxy|
|
28
|
+
require 'socksify'
|
29
|
+
host, port = proxy.split ":"
|
30
|
+
TCPSocket.socks_server = host
|
31
|
+
TCPSocket.socks_port = Integer(port)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
parser.parse!(args)
|
36
|
+
|
37
|
+
cmd = args.shift
|
38
|
+
|
39
|
+
unless cmd
|
40
|
+
puts(parser)
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
[cmd, options]
|
45
|
+
end
|
46
|
+
|
47
|
+
def data_source
|
48
|
+
@data_source ||= (
|
49
|
+
ds = if @options[:source] == "disk"
|
50
|
+
DiskDataSource.new(File.join(StortingImporter.root, 'folketingparser/rawdata/data.stortinget.no'))
|
51
|
+
elsif @options[:source] == "api"
|
52
|
+
ApiDataSource.new("http://data.stortinget.no/")
|
53
|
+
else
|
54
|
+
raise ArgumentError, "invalid source: #{@options[:source].inspect}"
|
55
|
+
end
|
56
|
+
|
57
|
+
ParsingDataSource.new(ds)
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
def importer
|
62
|
+
@importer ||= (
|
63
|
+
if @options[:app_root]
|
64
|
+
ScriptImporter.new(@options[:app_root])
|
65
|
+
else
|
66
|
+
raise ArgumentError, "app-root not given, can't import"
|
67
|
+
end
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
def import(what)
|
72
|
+
case what
|
73
|
+
when :dld
|
74
|
+
import_dld
|
75
|
+
when :promises
|
76
|
+
import_promises
|
77
|
+
when :all
|
78
|
+
import_all
|
79
|
+
else
|
80
|
+
import_docs converter.xml_for(what.to_sym)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def import_all
|
85
|
+
ignore = Array(@options[:ignore])
|
86
|
+
|
87
|
+
import_docs converter.xml_for(:parties) unless ignore.include?(:parties)
|
88
|
+
import_docs converter.xml_for(:committees) unless ignore.include?(:committees)
|
89
|
+
import_docs converter.xml_for(:districts) unless ignore.include?(:districts)
|
90
|
+
import_docs converter.xml_for(:representatives) unless ignore.include?(:representatives)
|
91
|
+
import_docs converter.xml_for(:categories) unless ignore.include?(:categories)
|
92
|
+
import_docs converter.xml_for(:issues) unless ignore.include?(:issues)
|
93
|
+
import_docs converter.xml_for(:votes) unless ignore.include?(:votes)
|
94
|
+
|
95
|
+
import_dld unless ignore.include?(:dld)
|
96
|
+
import_promises unless ignore.include?(:promises)
|
97
|
+
end
|
98
|
+
|
99
|
+
def converter
|
100
|
+
@converter ||= Converter.new(data_source)
|
101
|
+
end
|
102
|
+
|
103
|
+
def import_dld
|
104
|
+
if has_submodule?
|
105
|
+
print_or_import File.read(File.join(StortingImporter.root, 'data/dld-issues.xml'))
|
106
|
+
print_or_import File.read(File.join(StortingImporter.root, 'folketingparser/data/votering-2011-04-04-dld-hdo.xml'))
|
107
|
+
else
|
108
|
+
$stderr.puts "folketingparser not found, skipping DLD votes and issues (run `git submodule update --init` if you need this)"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def import_promises
|
113
|
+
csvs = Dir[File.join(StortingImporter.root, 'data/promises-*.csv')].sort_by { |e| File.basename(e) }
|
114
|
+
csvs.each do |path|
|
115
|
+
print_or_import PromiseConverter.new(path).xml
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def import_docs(docs)
|
120
|
+
docs = [docs] unless docs.kind_of?(Array)
|
121
|
+
|
122
|
+
docs.each do |doc|
|
123
|
+
print_or_import doc.to_s
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def print_or_import(xml)
|
128
|
+
if @options[:only_print]
|
129
|
+
puts xml
|
130
|
+
else
|
131
|
+
importer.import xml
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def has_submodule?
|
136
|
+
File.exist?(File.join(StortingImporter.root, 'folketingparser/data'))
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class Committee
|
4
|
+
include IvarEquality
|
5
|
+
|
6
|
+
attr_reader :external_id, :name
|
7
|
+
|
8
|
+
def self.from_storting_doc(doc)
|
9
|
+
doc.css("komiteer_liste komite").map do |node|
|
10
|
+
from_storting_node(node)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.from_storting_node(node)
|
15
|
+
new node.css("id").first.text, node.css("navn").first.text
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.from_hdo_node(node)
|
19
|
+
new node.css("externalId").first.text, node.css("name").first.text
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(external_id, name)
|
23
|
+
@external_id = external_id
|
24
|
+
@name = name
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_hdo_xml(builder = Util.builder)
|
28
|
+
builder.committee do |com|
|
29
|
+
com.externalId external_id
|
30
|
+
com.name name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class Converter
|
4
|
+
|
5
|
+
def initialize(data_source)
|
6
|
+
@data_source = data_source
|
7
|
+
@cache = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def xml_for(name)
|
11
|
+
Util.builder do |xml|
|
12
|
+
xml.instruct!
|
13
|
+
xml.__send__(name) do |builder|
|
14
|
+
data_for(name).each do |obj|
|
15
|
+
obj.to_hdo_xml(builder)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def data_for(name)
|
24
|
+
case name
|
25
|
+
when :votes
|
26
|
+
# not ideal
|
27
|
+
issue_ids = fetch(:issues).map { |e| e.external_id }
|
28
|
+
issue_ids.map { |id| @data_source.votes_for(id) }.flatten.uniq_by { |e| e.external_id }
|
29
|
+
when :districts
|
30
|
+
fetch(name).sort_by { |e| e.name }
|
31
|
+
when :representatives
|
32
|
+
data = fetch(:representatives_today) + fetch(:representatives)
|
33
|
+
data.uniq_by { |e| e.external_id }.sort_by { |e| e.external_id }
|
34
|
+
else
|
35
|
+
fetch(name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def fetch(name)
|
40
|
+
@cache[name] ||= @data_source.__send__(name)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class DataSource
|
4
|
+
|
5
|
+
class NotFoundError < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
DEFAULT_SESSION = '2011-2012'
|
9
|
+
DEFAULT_PERIOD = '2009-2013'
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def parse(str)
|
14
|
+
doc = Nokogiri.XML(str)
|
15
|
+
doc.remove_namespaces!
|
16
|
+
|
17
|
+
doc.first_element_child
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class DiskDataSource < DataSource
|
4
|
+
|
5
|
+
def initialize(root)
|
6
|
+
@root = Pathname.new(root)
|
7
|
+
@log = Logger.new(STDERR)
|
8
|
+
end
|
9
|
+
|
10
|
+
def parties(session_id = DEFAULT_SESSION)
|
11
|
+
fetch "eksport/partier/index.html?sesjonid=#{session_id}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def committees(session_id = DEFAULT_SESSION)
|
15
|
+
fetch "eksport/komiteer/index.html?SesjonId=#{session_id}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def districts
|
19
|
+
fetch "eksport/fylker/index.html"
|
20
|
+
end
|
21
|
+
|
22
|
+
def categories
|
23
|
+
fetch "eksport/emner/index.html"
|
24
|
+
end
|
25
|
+
|
26
|
+
def issues(session_id = DEFAULT_SESSION)
|
27
|
+
fetch "eksport/saker/index.html?sesjonid=#{session_id}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def representatives(period = DEFAULT_PERIOD)
|
31
|
+
fetch "eksport/representanter/index.html?StortingsPeriodeId=#{period}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def representatives_today
|
35
|
+
fetch 'eksport/dagensrepresentanter/index.html'
|
36
|
+
end
|
37
|
+
|
38
|
+
def votes_for(issue_id)
|
39
|
+
fetch "eksport/voteringer/index.html?sakid=#{issue_id}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def propositions_for(vote_id)
|
43
|
+
fetch "eksport/voteringsforslag/index.html?voteringid=#{vote_id}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def vote_results_for(vote_id)
|
47
|
+
fetch "eksport/voteringsresultat/index.html?voteringid=#{vote_id}"
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def fetch(path)
|
53
|
+
subpath = @root.join(path)
|
54
|
+
@log.info "parsing #{subpath}"
|
55
|
+
|
56
|
+
parse subpath.read
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class District
|
4
|
+
include IvarEquality
|
5
|
+
|
6
|
+
attr_reader :external_id, :name
|
7
|
+
|
8
|
+
def self.from_storting_doc(doc)
|
9
|
+
doc.css("fylker_liste fylke").map do |node|
|
10
|
+
from_storting_node(node)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.from_storting_node(node)
|
15
|
+
new node.css("id").first.text, node.css("navn").first.text
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.from_hdo_node(node)
|
19
|
+
new node.css("externalId").first.text, node.css("name").first.text
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(external_id, name)
|
23
|
+
@external_id = external_id
|
24
|
+
@name = name
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_hdo_xml(builder = Util.builder)
|
28
|
+
builder.district do |d|
|
29
|
+
d.externalId external_id
|
30
|
+
d.name name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|