rgovdata 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 (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