citysdk 0.1.2.5 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,10 @@
1
+
1
2
  module CitySDK
2
3
 
3
4
  class Importer
4
5
  attr_reader :filereader, :api, :params
5
6
 
6
- def initialize(pars)
7
+ def initialize(pars, fr = nil)
7
8
  @params = pars
8
9
 
9
10
  raise Exception.new("Missing :host in Importer parameters.") if @params[:host].nil?
@@ -11,22 +12,16 @@ module CitySDK
11
12
  raise Exception.new("Missing :file_path in Importer parameters.") if @params[:file_path].nil?
12
13
 
13
14
  @api = CitySDK::API.new(@params[:host])
14
- if @params[:email]
15
- raise Exception.new("Missing :passw in Importer parameters.") if @params[:passw].nil?
16
- raise Exception.new("Failure to authenticate '#{@params[:email]}' with api.") if not @api.authenticate(@params[:email],@params[:passw])
15
+ if @params[:name]
16
+ raise Exception.new("Missing :password in Importer parameters.") if @params[:password].nil?
17
+ raise Exception.new("Failure to authenticate '#{@params[:name]}' with api.") if not @api.authenticate(@params[:name],@params[:password])
17
18
  @api.release
18
19
  end
19
20
 
20
21
  @params[:addresslayer] = 'bag.vbo' if @params[:addressleyer].nil?
21
22
  @params[:addressfield] = 'postcode_huisnummer' if @params[:addressfield].nil?
22
23
 
23
- @params[:create_type] = 'create' if @params[:create_type].nil?
24
- # CREATE_TYPE_UPDATE = 'update'
25
- # CREATE_TYPE_ROUTES = 'routes'
26
- # CREATE_TYPE_CREATE = 'create'
27
-
28
-
29
- @filereader = FileReader.new(@params)
24
+ @filereader = fr || FileReader.new(@params)
30
25
  end
31
26
 
32
27
 
@@ -34,16 +29,6 @@ module CitySDK
34
29
  return @filereader.write(path)
35
30
  end
36
31
 
37
- def setLayerStatus(m)
38
- begin
39
- sign_in
40
- @api.set_layer_status(m.gsub("\n","<br/>"))
41
- sign_out
42
- rescue Exception => e
43
- puts "File Importer setLayerStatus Exception #{e.message}"
44
- end
45
- end
46
-
47
32
  def setParameter(k,v)
48
33
  begin
49
34
  @params[(k.to_sym rescue k) || k] = v
@@ -53,28 +38,12 @@ module CitySDK
53
38
  nil
54
39
  end
55
40
 
56
- def setMatchParameter(l,f,v)
57
- begin
58
- @params[:match] = [] if @params[:match].nil?
59
- @params[:match] << [l,f,v]
60
- return true
61
- rescue
62
- end
63
- nil
64
- end
65
-
66
41
  def sign_in
67
- if @params[:email].nil?
68
- raise Exception.new("No credentials provided..")
69
- end
70
-
71
42
  begin
72
43
  sign_out if @signed_in
73
44
  @api.set_host(@params[:host])
74
45
  @api.set_layer(@params[:layername])
75
- @api.set_matchTemplate(@params[:match_tpl]) if @params[:match_tpl]
76
- @api.set_createTemplate(@params[:create_tpl]) if @params[:create_tpl]
77
- @api.authenticate(@params[:email],@params[:passw])
46
+ @api.authenticate(@params[:name],@params[:password])
78
47
  @signed_in = true
79
48
  rescue => e
80
49
  @api.release
@@ -89,35 +58,32 @@ module CitySDK
89
58
  end
90
59
 
91
60
  def filterFields(h)
92
-
93
- # puts "h: \n#{h}"
94
- # puts "@params[:fields]: \n#{@params[:fields]}"
95
-
96
61
  data = {}
97
62
  h.each_key do |k|
98
63
  k = (k.to_sym rescue k) || k
99
- data[k] = h[k] if @params[:fields].include?(k)
64
+ j = @params[:alternate_fields][k]
65
+ data[j] = h[k] if @params[:fields].include?(k)
100
66
  end
101
- # puts "data: \n#{data}"
102
67
  data
103
68
  end
104
69
 
105
70
 
71
+ def geomToJSON(a)
72
+ # puts JSON.pretty_generate(a)
73
+ a
74
+ end
106
75
 
107
-
108
-
109
- def doImport(dryrun=false, &block)
76
+ def doImport(&block)
110
77
  result = {
111
- :updated => 0,
112
78
  :created => 0,
113
79
  :not_added => 0
114
80
  }
115
81
 
116
82
  failed = nil
117
83
 
118
- if @params[:hasaddress] == 'certain'
119
- failed = addToAddress(dryrun, &block)
120
- end
84
+ # if @params[:hasaddress] == 'certain'
85
+ # failed = addToAddress(&block)
86
+ # end
121
87
 
122
88
  # TODO: add possibility to add node to postal code
123
89
 
@@ -130,72 +96,30 @@ module CitySDK
130
96
  result[:updated] += (@filereader.content.length - failed.length)
131
97
  end
132
98
 
133
- nodes = failed || @filereader.content
134
-
135
- count = nodes.length
136
-
137
- @api.set_createTemplate(
138
- {
139
- :create => {
140
- :params => { #TODO other create types!!
141
- :create_type => @params[:create_type],
142
- :srid => @params[:srid] || 4326
143
- }
144
- }
145
- }
146
- )
147
-
148
- match_tpl = {
149
- :match => {
150
- :params => {
151
- :debug => true,
152
- :layers => {}
153
- }
154
- }
155
- }
99
+ objects = failed || @filereader.content
100
+ count = objects.length
156
101
 
157
102
  begin
158
103
  sign_in
159
- if @params[:unique_id] and @params[:match] and (@params[:hasgeometry] != 'unknown')
160
-
161
- match_tpl[:match][:params][:radius] = @params[:radius] || 200
162
- match_tpl[:match][:params][:geometry_type] = @params[:geometry_type] || :point
163
- @params[:match].each do |a|
164
- match_tpl[:match][:params][:layers][a[0]] = {} if match_tpl[:match][:params][:layers][a[0]].nil?
165
- match_tpl[:match][:params][:layers][a[0]][a[1]] = a[2]
166
- end
167
- @api.set_matchTemplate(match_tpl)
168
- nodes.each do |rec|
169
- node = {
170
- :geom => rec[:geometry],
171
- :id => rec[:id]
172
- }
173
- node[:name] = rec[:properties][@params[:name]] if @params[:name]
174
- node[:data] = filterFields(rec[:properties])
175
-
176
- # puts JSON.pretty_generate(node)
177
-
178
- yield(node) if block_given?
179
-
180
- @api.match_create_node(node) if not dryrun
181
- count -= 1
182
- end
183
- @api.match_create_flush
184
-
185
- elsif @params[:unique_id] and (@params[:hasgeometry] != 'unknown')
186
-
104
+
105
+ if @params[:hasgeometry]
187
106
  begin
188
- nodes.each do |rec|
107
+ objects.each do |record|
108
+
189
109
  node = {
190
- :geom => rec[:geometry],
191
- :id => rec[:id]
110
+ type: 'Feature',
111
+ properties: record[:properties],
112
+ geometry: geomToJSON(record[:geometry]),
192
113
  }
193
- node[:name] = rec[:properties][@params[:name].to_sym] if @params[:name]
194
- node[:data] = filterFields(rec[:properties])
114
+
115
+ node[:properties][:data] = filterFields(record[:properties][:data])
116
+ node[:crs] = { type: 'EPSG', properties: { code: @params[:srid] } } if @params[:srid] != 4326
117
+
118
+ node[:properties][:title] = node[:properties][:data][@params[:title]] if @params[:title]
195
119
 
196
- yield(node) if block_given?
120
+ yield(node[:properties]) if block_given?
197
121
 
198
- @api.create_node(node) if not dryrun
122
+ @api.create_object(node)
199
123
  count -= 1
200
124
  end
201
125
  @api.create_flush
@@ -209,14 +133,13 @@ module CitySDK
209
133
  raise Exception.new(e.message)
210
134
  ensure
211
135
  a = sign_out
212
- result[:updated] += a[0]
213
- result[:created] += a[1]
136
+ result[:created] += a[:created]
214
137
  result[:not_added] = count
215
138
  end
216
139
  return result
217
140
  end
218
141
 
219
- def addToAddress(dryrun=false)
142
+ def addToAddress()
220
143
  failed = []
221
144
  if @params[:postcode] and @params[:housenumber]
222
145
  begin
@@ -240,7 +163,7 @@ module CitySDK
240
163
  url = '/' + qres[:results][0][:cdk_id] + '/' + @params[:layername]
241
164
  data = filterFields(row)
242
165
  yield({addto: qres[:results][0][:cdk_id], data: data}) if block_given?
243
- n = @api.put(url,{'data'=>data}) if not dryrun
166
+ n = @api.put(url,{'data'=>data})
244
167
  else
245
168
  failed << rec
246
169
  end
data/lib/citysdk/util.rb CHANGED
@@ -1,10 +1,32 @@
1
1
  require 'json'
2
2
 
3
- class NilClass
4
- def empty?; true; end
3
+ class String
4
+ def remove_non_ascii
5
+ self.encode( "UTF-8", "binary", :invalid => :replace, :undef => :replace, :replace => '§')
6
+ end
7
+ def starts_with?(aString)
8
+ index(aString) == 0
9
+ end
5
10
  end
6
11
 
12
+ class Object
13
+ def deep_copy
14
+ Marshal.load(Marshal.dump(self))
15
+ end
16
+ def blank?
17
+ return false if self.class == Symbol
18
+ self.nil? or (self.class==String and self.strip == '') or (self.respond_to?(:empty?) ? self.empty? : false)
19
+ end
20
+ end
21
+
22
+
7
23
  module CitySDK
24
+
25
+ # for debugging purposes...
26
+ def jsonlog(o)
27
+ puts JSON.pretty_generate({ o.class.to_s => o })
28
+ end
29
+
8
30
 
9
31
  class Exception < ::Exception
10
32
  def initialize(message,parms=nil,srcfile=nil,srcline=nil)
@@ -21,9 +43,9 @@ module CitySDK
21
43
 
22
44
  def self.parseJson(jsonstring)
23
45
  begin
24
- return JSON.parse(jsonstring,{:symbolize_names => true})
46
+ return jsonstring.blank? ? {} : JSON.parse(jsonstring,symbolize_names: true)
25
47
  rescue Exception => e
26
- raise CitySDK::Exception.new(e.message)
48
+ raise CitySDK::Exception.new("#{e.message}; input: #{jsonstring}")
27
49
  end
28
50
  end
29
51
 
data/lib/citysdk.rb CHANGED
@@ -4,6 +4,6 @@ require 'citysdk/file_reader.rb'
4
4
  require 'citysdk/importer.rb'
5
5
 
6
6
  module CitySDK
7
- VERSION = "0.1.2.5"
7
+ VERSION = "1.0"
8
8
  end
9
9
 
data/spec/api_spec.rb CHANGED
@@ -1,62 +1,69 @@
1
1
 
2
2
 
3
3
  module CitySDK
4
- TEST_HOST = 'test-api.citysdk.waag.org'
5
- TEST_USER = 'test@waag.org'
4
+ TEST_HOST = 'localhost:9292'
5
+ # TEST_HOST = 'test-api.citysdk.waag.org'
6
+ TEST_USER = 'test'
6
7
  TEST_PASS = '123Test321'
7
8
 
9
+ # name=test.rspec title='test layer' owner=citysdk description='for testing' rdf_type=csdk\:Test category=security
10
+
8
11
  TEST_LAYER = {
9
- :data => {
10
- :name => 'test.rspec',
11
- :description => 'for testing',
12
- :organization => 'waag',
13
- :category => 'security.test'
14
- }
12
+ name: "test.rspec",
13
+ title: "test layer",
14
+ owner: TEST_USER,
15
+ description: "for testing",
16
+ data_sources: [""],
17
+ rdf_type: "csdk:Test",
18
+ category: "security",
19
+ subcategory: "test",
20
+ licence: "CC0",
21
+ fields: []
15
22
  }
16
23
 
17
- describe API do
24
+ $api = API.new(TEST_HOST)
18
25
 
19
- before(:each) do
20
- @api = API.new(TEST_HOST)
21
- TEST_USER.should_not == 'citysdk@waag.org'
22
- end
26
+
27
+
28
+ describe API do
23
29
 
24
- after(:each) do
25
- @api.release
26
- end
27
30
 
28
31
  it "can be connected to" do
29
- @api.should_not == nil
32
+ expect($api.class).to be(CitySDK::API)
30
33
  end
31
34
 
32
35
  it "can be queried" do
33
- @api.get('/layers')[:status].should == 'success'
36
+ expect($api.get('/layers').class).to be(Hash)
34
37
  end
35
38
 
36
39
  it "can be authorized against" do
37
- @api.authenticate(TEST_USER,TEST_PASS).should == true
40
+ expect($api.authenticate(TEST_USER,TEST_PASS)).to be(true)
41
+ expect($api.release.class).to be(Array)
42
+ end
43
+
44
+ it "can create and delete a test layer" do
45
+ expect($api.authenticate(TEST_USER,TEST_PASS)).to be(true)
46
+ expect($api.post('/layers',TEST_LAYER)[:features].class).to be(Array)
47
+ expect($api.delete('/layers/test.rspec')).to eq({})
48
+ expect($api.release.class).to be(Array)
38
49
  end
39
-
40
- # it "can create and delete a test layer" do
41
- # @api.authenticate(TEST_USER,TEST_PASS).should == true
42
- # @api.put('/layers',TEST_LAYER)[:status].should == 'success'
43
- # @api.delete('/layer/test.rspec?delete_layer=true')[:status].should == 'success'
44
- # end
45
50
 
46
51
  it "can not create a layer in an unauthorized domain" do
47
52
  h = TEST_LAYER.dup
48
- h[:data][:name] = 'unauthorized.rspec'
49
- @api.authenticate(TEST_USER,TEST_PASS).should == true
50
- expect { @api.put('/layers',h) }.to raise_error(HostException,"Not authorized for domain 'unauthorized'.")
51
- TEST_LAYER[:data][:name] = 'test.rspec'
53
+ h[:name] = 'unauthorized.rsped'
54
+ expect($api.authenticate(TEST_USER,TEST_PASS)).to be(true)
55
+ expect { $api.post('/layers',h) }.to raise_error(HostException,"Owner has no access to domain 'unauthorized'")
56
+ h[:name] = "test.rspec"
57
+ $api.release
52
58
  end
53
59
 
54
60
  it "can not add data to a layer not owned" do
55
- res = @api.get('/nodes?per_page=1')
56
- res[:status].should == 'success'
57
- cdk = res[:results][0][:cdk_id]
58
- @api.authenticate(TEST_USER,TEST_PASS).should == true
59
- expect { @api.put("/#{cdk}/osm",{:data=>{:plop => 'pipo'}}) }.to raise_error(HostException,"Not authorized for layer 'osm'.")
61
+ res = $api.get('/objects?per_page=1')
62
+ expect(res[:type]).to eq('FeatureCollection')
63
+ cdk = res[:features][0][:properties][:cdk_id]
64
+ expect($api.authenticate(TEST_USER,TEST_PASS)).to be(true)
65
+ expect { $api.patch("/objects/#{cdk}/layers/osm",{:plop => 'pipo'}) }.to raise_error(HostException,"Operation requires owners' authorization")
66
+ $api.release
60
67
  end
61
68
 
62
69
  end
data/spec/import_spec.rb CHANGED
@@ -3,82 +3,48 @@
3
3
  module CitySDK
4
4
 
5
5
  describe "Importer" do
6
-
7
-
6
+
8
7
  def newImporter(f)
9
8
  @importer = Importer.new({
10
- :host=>TEST_HOST,
11
- :layername=>'test.rspec',
12
- :file_path => f
9
+ file_path: f,
10
+ host: TEST_HOST,
11
+ layername: TEST_LAYER[:name]
13
12
  })
14
13
  end
15
-
16
- after(:each) do
17
- if @layerCreated
18
- @importer.api.authenticate(TEST_USER,TEST_PASS) do
19
- @importer.api.delete("/layer/test.rspec?delete_layer=true")
20
- end.should_not == nil
21
- end
22
- end
23
-
24
-
14
+
25
15
  it "checks parameters" do
26
16
  expect { Importer.new({:a=>1}) }.to raise_error(CitySDK::Exception)
27
17
  end
28
18
 
29
19
  it "succesfully creates a FileReader" do
30
20
  newImporter('./spec/files/wkb.csv')
31
- @importer.should_not == nil
32
- @importer.filereader.params[:unique_id].should == :gid
21
+ expect(@importer.class).to be(CitySDK::Importer)
22
+ expect(@importer.filereader.params[:unique_id]).to be(:gid)
33
23
  end
34
24
 
35
- it "can add a (match) parameter" do
36
- newImporter('./spec/files/wkb.csv')
37
- @importer.setParameter('freut',:nix).should be_true
38
- @importer.setMatchParameter('freut','pipo',nil).should be_true
39
- end
40
-
41
25
  it "needs authorization to import" do
42
26
  newImporter('./spec/files/hotels.csv')
43
27
  expect { @importer.doImport }.to raise_error(CitySDK::Exception)
44
28
  end
45
29
 
46
- it "can make a match and add data to osm obj" do
47
- newImporter('./spec/files/rk.csv')
48
-
49
- @importer.api.authenticate(TEST_USER,TEST_PASS) do
50
- @importer.api.put('/layers',TEST_LAYER)[:status].should == 'success'
51
- end.should_not == nil
52
- @layerCreated = true
53
- @importer.setParameter(:email,TEST_USER).should be_true
54
- @importer.setParameter(:passw,TEST_PASS).should be_true
55
-
56
- @importer.setMatchParameter('osm','amenity','fuel').should be_true
57
-
58
- res = @importer.doImport[:not_added].should == 0
59
- res = @importer.api.get("/nodes?count&layer=test.rspec")
60
- res[:record_count].should == 5
61
- # puts JSON.pretty_generate(res)
62
- end
30
+ it "can make a layer and delete" do
63
31
 
64
-
65
- it "can make a layer and add data to and address" do
66
-
67
32
  newImporter('./spec/files/hotels.csv')
68
33
 
34
+ @importer.setParameter(:name,TEST_USER)
35
+ @importer.setParameter(:password,TEST_PASS)
36
+ @importer.sign_in
37
+ res = @importer.api.post('/layers',TEST_LAYER)
38
+ expect( (!!res[:features] and res[:features].length == 1) ).to be(true)
39
+ @importer.sign_out
40
+
41
+ expect { @importer.doImport }.to raise_error(CitySDK::Exception)
42
+
43
+ res = @importer.api.get("/layers/test.rspec/objects")
44
+ expect( (!!res[:features] and res[:features].length == 0) ).to be(true)
45
+
69
46
  @importer.api.authenticate(TEST_USER,TEST_PASS) do
70
- @importer.api.put('/layers',TEST_LAYER)[:status].should == 'success'
71
- end.should_not == nil
72
- @layerCreated = true
73
-
74
- @importer.setParameter(:email,TEST_USER).should be_true
75
- @importer.setParameter(:passw,TEST_PASS).should be_true
76
- if TEST_HOST == 'api.citysdk.waag.org'
77
- @importer.doImport[:not_added].should == 0
78
- res = @importer.api.get("/nodes?count&layer=test.rspec")
79
- res[:record_count].should == 4
80
- else
81
- @importer.doImport[:not_added].should == 4
47
+ expect( @importer.api.delete("/layers/#{TEST_LAYER[:name]}") ).to eq({})
82
48
  end
83
49
 
84
50
  end
@@ -89,49 +55,48 @@ module CitySDK
89
55
 
90
56
  it "can parse json" do
91
57
  j = CitySDK::parseJson('{ "arr" : [0,1,1,1], "hash": {"aap": "noot"}, "num": 0 }')
92
- j[:arr].length.should == 4
93
- j[:num].class.should == Fixnum
94
- j[:hash][:aap].should == "noot"
58
+ expect(j[:arr].length).to be(4)
59
+ expect(j[:num].class).to be(Fixnum)
60
+ expect(j[:hash][:aap]).to eq("noot")
95
61
  end
96
62
 
97
63
  it "can read json files" do
98
64
  fr = FileReader.new({:file_path => './spec/files/stations.json'})
99
- File.basename(fr.file).should == 'stations.json'
100
- fr.params[:geomtry_type].should == 'Point'
101
- fr.params[:srid].should == 4326
102
- fr.params[:unique_id].should == :code
65
+ expect(File.basename(fr.file)).to eq('stations.json')
66
+ expect(fr.params[:geomtry_type]).to eq('Point')
67
+ expect(fr.params[:srid]).to be(4326)
68
+ expect(fr.params[:unique_id]).to be(:code)
103
69
  end
104
70
 
105
71
  it "can read geojson files" do
106
72
  fr = FileReader.new({:file_path => './spec/files/geojsonTest.GeoJSON'})
107
- File.basename(fr.file).should == 'geojsonTest.GeoJSON'
108
- fr.params[:unique_id].should == nil
73
+ expect(File.basename(fr.file)).to eq('geojsonTest.GeoJSON')
74
+ expect(fr.params[:unique_id]).to be(:id)#self generated unique id
109
75
  end
110
76
 
111
77
  it "can read csv files" do
112
78
  fr = FileReader.new({:file_path => './spec/files/csvtest.zip'})
113
- File.basename(fr.file).should == 'akw.csv'
114
- fr.params[:srid].should == 4326
115
- fr.params[:colsep].should == ';'
116
- fr.params[:unique_id].should == :ID
79
+ expect(File.basename(fr.file)).to eq('akw.csv')
80
+ expect(fr.params[:srid]).to be(4326)
81
+ expect(fr.params[:colsep]).to eq(';')
82
+ expect(fr.params[:unique_id]).to be(:ID)
117
83
  end
118
84
 
119
85
  it "can read csv files with wkb geometry" do
120
86
  fr = FileReader.new({:file_path => './spec/files/wkb.csv'})
121
- File.basename(fr.file).should == 'wkb.csv'
122
- fr.params[:srid].should == 4326
123
- fr.params[:colsep].should == ';'
124
- fr.params[:unique_id].should == :gid
87
+ expect(File.basename(fr.file)).to eq('wkb.csv')
88
+ expect(fr.params[:srid]).to be(4326)
89
+ expect(fr.params[:colsep]).to eq(';')
90
+ expect(fr.params[:unique_id]).to be(:gid)
125
91
  end
126
92
 
127
93
  it "can read zipped shape files" do
128
94
  fr = FileReader.new({:file_path => './spec/files/shapeTest.zip'})
129
- fr.params[:srid].should == 2100
95
+ expect(fr.params[:srid]).to be(2100)
130
96
  end
131
97
 
132
98
  end
133
-
99
+
134
100
  end
135
101
 
136
102
 
137
- # puts JSON.pretty_generate(fr.content[0])