rgovdata 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.document +5 -0
  2. data/.rvmrc +2 -0
  3. data/CHANGELOG +7 -0
  4. data/Gemfile +18 -0
  5. data/Gemfile.lock +48 -0
  6. data/LICENSE +20 -0
  7. data/README.rdoc +114 -0
  8. data/Rakefile +61 -0
  9. data/bin/rgd +12 -0
  10. data/examples/all_quakes.rb +8 -0
  11. data/examples/arbitrary_data.rb +26 -0
  12. data/examples/catalog_traversal.rb +34 -0
  13. data/examples/earthquakes.rb +5 -0
  14. data/lib/rgovdata.rb +4 -0
  15. data/lib/rgovdata/catalog.rb +4 -0
  16. data/lib/rgovdata/catalog/catalog.rb +79 -0
  17. data/lib/rgovdata/catalog/dn.rb +63 -0
  18. data/lib/rgovdata/catalog/registry_strategy/internal_registry.rb +12 -0
  19. data/lib/rgovdata/catalog/registry_strategy/registry_strategy.rb +26 -0
  20. data/lib/rgovdata/config.rb +5 -0
  21. data/lib/rgovdata/config/common_config.rb +13 -0
  22. data/lib/rgovdata/config/config.rb +133 -0
  23. data/lib/rgovdata/data/config_template.yml +19 -0
  24. data/lib/rgovdata/data/sg/registry.yml +147 -0
  25. data/lib/rgovdata/data/template.rb +27 -0
  26. data/lib/rgovdata/data/us/registry.yml +12 -0
  27. data/lib/rgovdata/service.rb +10 -0
  28. data/lib/rgovdata/service/csv_service.rb +3 -0
  29. data/lib/rgovdata/service/dataset/csv_dataset.rb +43 -0
  30. data/lib/rgovdata/service/dataset/dataset.rb +91 -0
  31. data/lib/rgovdata/service/dataset/file_dataset.rb +46 -0
  32. data/lib/rgovdata/service/dataset/odata_dataset.rb +31 -0
  33. data/lib/rgovdata/service/file_service.rb +10 -0
  34. data/lib/rgovdata/service/listing.rb +47 -0
  35. data/lib/rgovdata/service/odata_service.rb +50 -0
  36. data/lib/rgovdata/service/service.rb +93 -0
  37. data/lib/rgovdata/shell/shell.rb +157 -0
  38. data/lib/rgovdata/version.rb +9 -0
  39. data/rgovdata.gemspec +128 -0
  40. data/spec/fixtures/sample.csv +821 -0
  41. data/spec/integration/service/sg/nlb_spec.rb +57 -0
  42. data/spec/integration/service/sg/places_spec.rb +73 -0
  43. data/spec/integration/service/us/eqs7day-M1_spec.rb +57 -0
  44. data/spec/spec_helper.rb +25 -0
  45. data/spec/support/config_examples.rb +8 -0
  46. data/spec/support/mocks.rb +22 -0
  47. data/spec/support/utility.rb +18 -0
  48. data/spec/unit/catalog/base_spec.rb +93 -0
  49. data/spec/unit/catalog/registry_strategy_spec.rb +28 -0
  50. data/spec/unit/config/config_spec.rb +130 -0
  51. data/spec/unit/data/template_spec.rb +32 -0
  52. data/spec/unit/service/dataset/csv_dataset_spec.rb +42 -0
  53. data/spec/unit/service/dataset/dataset_spec.rb +37 -0
  54. data/spec/unit/service/dataset/file_dataset_spec.rb +40 -0
  55. data/spec/unit/service/dataset/odata_dataset_spec.rb +36 -0
  56. data/spec/unit/service/file_service_spec.rb +25 -0
  57. data/spec/unit/service/listing_spec.rb +100 -0
  58. data/spec/unit/service/odata_service_spec.rb +42 -0
  59. data/spec/unit/service/service_spec.rb +82 -0
  60. data/spec/unit/shell/shell_spec.rb +10 -0
  61. metadata +228 -0
@@ -0,0 +1,63 @@
1
+ # This module defines the basic naming interface for catalog objects
2
+ # Override these methods as required
3
+ module RGovData::Dn
4
+
5
+ # Returns the human-readable unique id
6
+ def id
7
+ nameparts = []
8
+ if defined? realm
9
+ nameparts.push('/')
10
+ nameparts.push(realm)
11
+ end
12
+ nameparts.push(service_key) if defined?(service_key) && service_key.present?
13
+ nameparts.push(dataset_key) if defined?(dataset_key) && dataset_key.present?
14
+ nameparts.join('/')
15
+ end
16
+
17
+ # Returns a rails-compatible ID
18
+ def to_param
19
+ id.gsub('/',':')
20
+ end
21
+
22
+ # Returns the human version of the object name/identification
23
+ def to_s
24
+ "#{id} [#{self.class.name}]"
25
+ end
26
+
27
+ # Returns array of attributes that describe the specific entity
28
+ # By default, guesses based on instance variables
29
+ def meta_attributes
30
+ a = [:id]
31
+ instance_variables.each do |v|
32
+ n = v.to_s.gsub('@','').to_sym
33
+ a << n if self.respond_to?(n)
34
+ end
35
+ a
36
+ end
37
+
38
+ # Returns a hash that fully describes this service and can be used as a parameter to +new+
39
+ # By default, returns a hash based on meta_attributes
40
+ def initialization_hash
41
+ h = {}
42
+ meta_attributes.each do |attribute|
43
+ h.merge!(attribute => self.send(attribute))
44
+ end
45
+ h
46
+ end
47
+
48
+ # Returns array of attributes that describe the records of the specific entity
49
+ # By default, it is nil (meaning indeterminate)
50
+ def attributes
51
+ @attributes
52
+ end
53
+
54
+ # Generic interface to return the currently applicable record set
55
+ def records
56
+ if defined? datasets
57
+ datasets
58
+ else
59
+ []
60
+ end
61
+ end
62
+
63
+ end
@@ -0,0 +1,12 @@
1
+ class RGovData::InternalRegistry < RGovData::RegistryStrategy
2
+
3
+ # Returns the list of services for the realm
4
+ # based on internal yml file
5
+ def load_services
6
+ service_array = []
7
+ registry = RGovData::Template.get('registry.yml',realm)
8
+ YAML::load_documents( registry ) { |doc| service_array << doc }
9
+ service_array
10
+ end
11
+
12
+ end
@@ -0,0 +1,26 @@
1
+ class RGovData::RegistryStrategy
2
+ attr_accessor :realm
3
+
4
+ class << self
5
+ # Returns the appropriate RegistryStrategy for the given realm
6
+ # +realm+ is the required realm
7
+ def instance_for_realm(realm)
8
+ # TODO: this is where we can abstract different registry schemes
9
+ # e.g by default we will look for a class called Rgovdata::<realm>Registry (Rgovdata::ZhRegistry)
10
+ # else we take the default strategy
11
+ # Currently this just defaults to internal registry:
12
+ RGovData::InternalRegistry.new(realm)
13
+ end
14
+ end
15
+
16
+ # +new+ accepts realm parameter
17
+ def initialize(default_realm=nil)
18
+ @realm = default_realm
19
+ end
20
+
21
+ # Returns the list of services for the realm
22
+ def load_services
23
+ []
24
+ end
25
+
26
+ end
@@ -0,0 +1,5 @@
1
+ require 'rgovdata/config/config'
2
+ require 'rgovdata/config/common_config'
3
+ require 'rgovdata/data/template'
4
+ require 'rgovdata/shell/shell'
5
+
@@ -0,0 +1,13 @@
1
+ # This module is used to include basic support to access
2
+ # the shared RGovData::Config instance
3
+ module RGovData::CommonConfig
4
+ # Returns the current config instance
5
+ def config
6
+ RGovData::Config.instance
7
+ end
8
+ # Sets the requirement to have a config file
9
+ # Must be called before config is invoked
10
+ def require_config_file
11
+ RGovData::Config.require_config_file
12
+ end
13
+ end
@@ -0,0 +1,133 @@
1
+ require 'ostruct'
2
+ require 'singleton'
3
+
4
+ class RGovData::Config
5
+ include Singleton
6
+ BASE_NAME = 'rgovdata.conf'
7
+
8
+ class ConfigError < StandardError
9
+ end
10
+ class ConfigurationFileNotFound < ConfigError
11
+ end
12
+ class ConfigurationFileInitialized < ConfigError
13
+ end
14
+
15
+ attr_accessor :default_realm, :credentialsets
16
+
17
+ def initialize
18
+ load_default_config
19
+ end
20
+
21
+ # Reloads configuraiton from default config provider
22
+ # - rails config file (if used in Rails)
23
+ # - current directory
24
+ # - environment settings
25
+ def load_default_config
26
+ clear
27
+ # load default config
28
+ if rails_root
29
+ # if rails env, load from Rails.root.join('config',BASE_NAME)
30
+ load_config(rails_root.join('config',BASE_NAME),self.class.default_loader_options)
31
+ elsif
32
+ # else load from pwd
33
+ load_config(self.class.default_config_file,self.class.default_loader_options)
34
+ else
35
+ # else just refresh_from_env
36
+ refresh_from_env
37
+ end
38
+ end
39
+ # Returns the rails root, if the Rails environment is available
40
+ def rails_root
41
+ Rails.root if defined?(Rails)
42
+ end
43
+ protected :rails_root
44
+
45
+ def load_config(configfilepath, options = {})
46
+ options.reverse_merge!(:generate_default => true,:required => true)
47
+ unless File.exists?(configfilepath)
48
+ self.class.reset_configfile(configfilepath) if options[:generate_default]
49
+ if File.exists?(configfilepath)
50
+ raise ConfigurationFileInitialized.new("\n
51
+ No configuration file found.
52
+ A new file has been initialized at: #{configfilepath}
53
+ Please review the configuration and retry..\n\n\n")
54
+ elsif options[:required]
55
+ raise ConfigurationFileNotFound.new("cannot load config file #{configfilepath}")
56
+ else
57
+ return
58
+ end
59
+ end
60
+ update_settings(OpenStruct.new(YAML::load(File.read(configfilepath))))
61
+ end
62
+
63
+ # Updates attributes from config, including env override
64
+ # +config+ OpenStruct structure
65
+ def update_settings(config)
66
+ @credentialsets.merge!(config.credentialsets||{})
67
+ @default_realm = config.default_realm.to_sym if config.default_realm
68
+ refresh_from_env
69
+ end
70
+ protected :update_settings
71
+
72
+ # Clears the current configuration
73
+ def clear
74
+ @credentialsets = {}
75
+ @default_realm = nil
76
+ end
77
+
78
+ # Prints current status
79
+ def show_status
80
+ if credentialsets
81
+ puts "credential sets available: #{credentialsets.keys.join(',')}"
82
+ puts credentialsets.inspect
83
+ else
84
+ puts "credential sets available: none"
85
+ end
86
+ end
87
+
88
+ # Sets environment overrides for supported settings
89
+ def refresh_from_env
90
+ if ENV['projectnimbus_account_key'] || ENV['projectnimbus_unique_user_id']
91
+ @credentialsets['projectnimbus'] ||= {}
92
+ @credentialsets['projectnimbus'].merge!({'AccountKey'=> ENV['projectnimbus_account_key']}) if ENV['projectnimbus_account_key']
93
+ @credentialsets['projectnimbus'].merge!({'UniqueUserID'=> ENV['projectnimbus_unique_user_id']}) if ENV['projectnimbus_unique_user_id']
94
+ end
95
+ if ENV['rgovdata_username'] || ENV['rgovdata_password']
96
+ @credentialsets['basic'] ||= {}
97
+ @credentialsets['basic'].merge!({'username'=> ENV['rgovdata_username']}) if ENV['rgovdata_username']
98
+ @credentialsets['basic'].merge!({'password'=> ENV['rgovdata_password']}) if ENV['rgovdata_password']
99
+ end
100
+ end
101
+ protected :refresh_from_env
102
+
103
+ class << self
104
+ def reset_configfile(configfilepath)
105
+ file = File.new(configfilepath,'w')
106
+ template.each_line do | line|
107
+ file.puts line
108
+ end
109
+ file.close
110
+ end
111
+
112
+ def default_config_file(override = nil)
113
+ File.expand_path(override || BASE_NAME)
114
+ end
115
+
116
+ def template
117
+ RGovData::Template.get('config_template.yml')
118
+ end
119
+
120
+ def template_path
121
+ RGovData::Template.path('config_template.yml')
122
+ end
123
+
124
+ def default_loader_options
125
+ @@default_loader_options ||= {:generate_default => false,:required => false}
126
+ end
127
+
128
+ def require_config_file
129
+ @@default_loader_options = {:generate_default => true,:required => true}
130
+ end
131
+ end
132
+
133
+ end
@@ -0,0 +1,19 @@
1
+
2
+ # Defines the default realm (country)
3
+ default_realm: sg
4
+
5
+ # Define the various credential sets that may be required
6
+ credentialsets:
7
+ # Basic authentication credentials
8
+ basic:
9
+ # ENV['rgovdata_username'] will override username if present
10
+ username: "_insert_your_username_here_"
11
+ # ENV['rgovdata_password'] will override password if present
12
+ password: "your_password"
13
+ # OData credentials for http://projectnimbus.org - APIs for Singapore Government Data
14
+ projectnimbus:
15
+ # ENV['projectnimbus_account_key'] will override AccountKey if present
16
+ AccountKey: "_insert_your_key_here_"
17
+ # ENV['projectnimbus_unique_user_id'] will override UniqueUserID if present
18
+ UniqueUserID: "00000000000000000000000000000001"
19
+
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:RGovData::ServiceListing
2
+ realm: :sg
3
+ key: chlkboard
4
+ name: Chlkboard
5
+ description: Information and promotion of local businesses
6
+ keywords: "F&B, retail"
7
+ publisher: Chlkboard
8
+ info_uri: http://projectnimbus.org/2010/07/17/datasets-chlkboard/
9
+ license:
10
+ uri: https://api.projectnimbus.org/chlkboardodataservice.svc
11
+ type: :odata
12
+ credentialset: projectnimbus
13
+ --- !ruby/object:RGovData::ServiceListing
14
+ realm: :sg
15
+ key: co
16
+ name: Cinema Online
17
+ description: Movie times and locations in Singapore
18
+ keywords: movie, cinema
19
+ publisher: Cinema Online
20
+ info_uri: http://projectnimbus.org/2010/04/12/datasets-cinema-online-co/
21
+ license:
22
+ uri: https://api.projectnimbus.org/coodataservice.svc
23
+ type: :odata
24
+ credentialset: projectnimbus
25
+ --- !ruby/object:RGovData::ServiceListing
26
+ realm: :sg
27
+ key: hgw
28
+ name: HungryGoWhere
29
+ description: Best food, restaurants, bars, and pubs in Singapore, Kuala Lumpur and Hong Kong
30
+ keywords: food, makan
31
+ publisher: HungryGoWhere
32
+ info_uri: http://projectnimbus.org/2010/04/11/datasets-hungrygowhere-hgw/
33
+ license:
34
+ uri: https://api.projectnimbus.org/hgwodataservice.svc
35
+ type: :odata
36
+ credentialset: projectnimbus
37
+ --- !ruby/object:RGovData::ServiceListing
38
+ realm: :sg
39
+ key: lta
40
+ name: Traffic and Road Conditions
41
+ description: Traffic and Road Conditions in Singapore
42
+ keywords: road, traffic, incidents, parking
43
+ publisher: Singapore Land Transport Authority
44
+ info_uri: http://projectnimbus.org/2010/04/05/datasets-singapore-land-transport-authority-lta/
45
+ license:
46
+ uri: https://api.projectnimbus.org/ltaodataservice.svc
47
+ type: :odata
48
+ credentialset: projectnimbus
49
+ --- !ruby/object:RGovData::ServiceListing
50
+ realm: :sg
51
+ key: nea
52
+ name: Meteorological services
53
+ description: Meteorological services in Singapore
54
+ keywords: weather
55
+ publisher: Singapore National Environment Agency
56
+ info_uri: http://projectnimbus.org/2010/04/11/datasets-singapore-national-environment-agency-nea/
57
+ license:
58
+ uri: https://api.projectnimbus.org/neaodataservice.svc
59
+ type: :odata
60
+ credentialset: projectnimbus
61
+ --- !ruby/object:RGovData::ServiceListing
62
+ realm: :sg
63
+ key: nlb
64
+ name: Libraries
65
+ description: Information about the Public Libraries in Singapore and their collections
66
+ keywords: library, book
67
+ publisher: National Library Board Singapore (NLB)
68
+ info_uri: http://projectnimbus.org/2010/04/11/datasets-national-library-board-nlb/
69
+ license:
70
+ uri: https://api.projectnimbus.org/nlbodataservice.svc
71
+ type: :odata
72
+ credentialset: projectnimbus
73
+ --- !ruby/object:RGovData::ServiceListing
74
+ realm: :sg
75
+ key: snb
76
+ name: ShowNearBy
77
+ description: locations of persons, points-of-interest, and activities
78
+ keywords: location, bus stop, ATM, clinic, shops, AED
79
+ publisher: ShowNearBy
80
+ info_uri: http://projectnimbus.org/2010/04/12/datasets-shownearby-snb/
81
+ license:
82
+ uri: https://api.projectnimbus.org/snbodataservice.svc
83
+ type: :odata
84
+ credentialset: projectnimbus
85
+ --- !ruby/object:RGovData::ServiceListing
86
+ realm: :sg
87
+ key: stb
88
+ name: Events and Places
89
+ description: Tourism related events and places
90
+ keywords: event, hotel, places of interest
91
+ publisher: Singapore Tourism Board
92
+ info_uri: http://projectnimbus.org/2010/04/12/datasets-singapore-tourism-board-stb/
93
+ license:
94
+ uri: https://api.projectnimbus.org/stbodataservice.svc
95
+ type: :odata
96
+ credentialset: projectnimbus
97
+ --- !ruby/object:RGovData::ServiceListing
98
+ realm: :sg
99
+ key: sp
100
+ name: Singapore Post
101
+ description: Post Office and SAM locations
102
+ keywords: post, location
103
+ publisher: Singapore Post
104
+ info_uri: http://projectnimbus.org/2010/04/12/datasets-singapore-post-sp/
105
+ license:
106
+ uri: https://api.projectnimbus.org/spodataservice.svc
107
+ type: :odata
108
+ credentialset: projectnimbus
109
+ --- !ruby/object:RGovData::ServiceListing
110
+ realm: :sg
111
+ key: usr
112
+ name: User Contributed Content
113
+ description: User Contributed Datasets is part of the community driven efforts to provide interesting datasets
114
+ keywords: location
115
+ publisher: ProjectNimbus
116
+ info_uri: http://projectnimbus.org/2010/10/04/datasets-user-contributed-content-usr/
117
+ license:
118
+ uri: https://api.projectnimbus.org/usrodataservice.svc
119
+ type: :odata
120
+ credentialset: projectnimbus
121
+ # --- !ruby/object:RGovData::ServiceListing
122
+ ## Places currently excluded wince the metadata doesn't fully describe the mandatory parameters required
123
+ ## for the Detail and Search collections. Leaving places out of the registry until this is sorted.
124
+ # realm: :sg
125
+ # key: places
126
+ # name: Places
127
+ # description: Places.sg aggregates the flow of your information to multiple web and mobile sites, so that when you upload your information and/or promotions in one place, it gets quickly syndicated to many digital properties
128
+ # keywords: location
129
+ # publisher: Places.sg
130
+ # info_uri: http://projectnimbus.org/2010/10/18/datasets-places-sg/
131
+ # license:
132
+ # uri: https://api.projectnimbus.org/placesodataservice.svc
133
+ # type: :odata
134
+ # credentialset: projectnimbus
135
+ --- !ruby/object:RGovData::ServiceListing
136
+ realm: :sg
137
+ key: caas_air_cargo_discharged
138
+ name: Air Cargo Discharged
139
+ description: Air Cargo Discharged - Total by Region and Selected Country of Origin
140
+ keywords: Transportation and Storage
141
+ publisher: Civil Aviation Authority of Singapore
142
+ info_uri:
143
+ license:
144
+ uri: http://data.gov.sg/common/download.aspx?id=13008&rid=1805010000000004396B&filetype=csv
145
+ type: :file
146
+
147
+
@@ -0,0 +1,27 @@
1
+ require 'pathname'
2
+
3
+ # This is a convenience class for accessing disk-based template files
4
+ # It avoids pathname processing from being required where template are used
5
+ class RGovData::Template
6
+
7
+ class << self
8
+ # Returns the template file path
9
+ # +name+ is the filename
10
+ # +realm+ if specified is the subdirectory
11
+ def path(name, realm = nil)
12
+ extra_path = [realm,name].compact.map(&:to_s)
13
+ Pathname.new(File.dirname(__FILE__)).join(*extra_path).to_s
14
+ rescue
15
+ nil
16
+ end
17
+
18
+ # Returns the template file content
19
+ # +name+ is the filename
20
+ # +realm+ if specified is the subdirectory
21
+ def get(name, realm = nil)
22
+ IO.read(path(name, realm))
23
+ rescue
24
+ nil
25
+ end
26
+ end
27
+ end