aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2011-01-21 14:39:13 +0100
committerAlexander Sulfrian <alexander@sulfrian.net>2011-01-21 14:39:13 +0100
commit7afd4f2c8d623459f4b4d92a38571408ab2daf04 (patch)
tree773e6ae156d07b5c07a4cd61117b250b3ef5dd01
parentc48ace3cb001659a88483ba5fd4ba3a7721d5c25 (diff)
parent570d3aa1c9bdebfdbf172f0873d7cda94b89fcaf (diff)
downloadosm-xapi-7afd4f2c8d623459f4b4d92a38571408ab2daf04.tar.gz
osm-xapi-7afd4f2c8d623459f4b4d92a38571408ab2daf04.tar.xz
osm-xapi-7afd4f2c8d623459f4b4d92a38571408ab2daf04.zip
Merge remote branch 'upstream/master'
-rw-r--r--.gitignore14
-rw-r--r--README58
-rwxr-xr-xbootstrap.sh47
-rw-r--r--src/nodejs/config.json1
-rw-r--r--src/nodejs/no1.js254
-rw-r--r--src/nodejs/package.json11
6 files changed, 324 insertions, 61 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1608301
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+usr/
+
+# Temp Files #
+##############
+*.swp
+
+
+# OS generated files #
+######################
+*.DS_Store
+ehthumbs.db
+Icon?
+Thumbs.db
+
diff --git a/README b/README
index 8d10021..a11a09b 100644
--- a/README
+++ b/README
@@ -26,7 +26,63 @@ a more formal description
We serve the node endpoint, but no others. We implment the tag based filtering,
for only one tag and a bounding box.
-database shema
+Dabase setup
+=============
+
+We use postgres 9.* with postgis 1.5. Postgres 9.0 is used becaus we need some
+functions on hstores and postgis 1.5 is used for fancy geometry things.
+
+To setup a database you first need a runing postgres 9.0 instance. I hope you know
+how to do this.
+
+Use
+
+ createdb osm
+
+to create a database with name osm. Use
+
+ createlang plpgsql osm
+
+to add plpgsql to your database. If you want to create a database user do so:
+
+ createuser <username>
+
+Add hstore support for your database:
+
+ psql -d osm < /share/contrib/hstore.sql
+
+Add postgis support for your database:
+
+ psql -d osm < /share/contrib/postgis-1.5/postgis.sql
+
+Just do:
+
+ psql -d osm < /share/contrib/postgis-1.5/spatial_ref_sys.sql
+
+Create the actual schema for osm data. For this step you need osmosis. If your
+osmosis build is correct there should be a directory named pacakge/scripts where
+you run:
+
+ psql -d osm < pgsql_simple_schema_0.6.sql
+ psql -d osm < pgsql_simple_schema_0.6_linestring.sql
+Optional/stil to test:
+
+ psql -d osm < pgsql_simple_schema_0.6_action.sql
+ psql -d osm < pgsql_simple_schema_0.6_bbox.sql
+
+For documentation on the schema read pgsql_simple.txt.
+
+Import data from xml with:
+
+ osmosis --read-xml file="planet.osm.bz2" --wp host="localhost" password="TopSecretPassword" user="insertUserNameHere" database="osm"
+
+Before or after import you may want to create a index or two. Examples below:
+ CREATE INDEX idx_nodes_tags ON nodes USING GIN(tags);
+ CREATE INDEX idx_nodes_tags ON nodes USING GIST(tags);
+ CREATE INDEX idx_ways_tags ON ways USING GIN(tags);
+ CREATE INDEX idx_ways_tags ON ways USING GIST(tags);
+
+database shema (out dated)
================
We keep data in a highly specioaliced shema, that allows us to prevent tables
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100755
index 0000000..802b7f1
--- /dev/null
+++ b/bootstrap.sh
@@ -0,0 +1,47 @@
+#! /bin/sh
+
+###########################
+# start config
+
+PREFIX=`pwd`/usr/
+NODE_VERSION=0.3.5
+
+# end config
+###########################
+
+export PATH=${PREFIX}/bin:${PATH}
+
+## Download Helper
+# $1 - url
+# $2 - destdir
+download() {
+ mkdir -p ${PREFIX}/src
+
+ if [ ! -f ${2} ]; then
+ echo "!! saving source to $1"
+ curl ${1} | tar -x -z -C ${PREFIX}/src
+ fi
+}
+
+if [ ! -f ${PREFIX}/bin/node ]; then
+ # fetch and compile nodejs
+ download http://nodejs.org/dist/node-v${NODE_VERSION}.tar.gz ${PREFIX}/src/node-v${NODE_VERSION}
+
+ cd ${PREFIX}/src/node-v${NODE_VERSION}
+ ./configure --prefix=${PREFIX}
+ make install
+ cd ${PREFIX}/..
+else
+ echo "!! node already installed"
+fi
+
+if [ ! -f ${PREFIX}/bin/npm ];then
+ # fetch and compile npm
+ curl http://npmjs.org/install.sh | sh
+else
+ echo "!! npm already installed"
+
+fi
+
+# load development code and compile dependencies
+npm link src/nodejs/
diff --git a/src/nodejs/config.json b/src/nodejs/config.json
new file mode 100644
index 0000000..1025c5b
--- /dev/null
+++ b/src/nodejs/config.json
@@ -0,0 +1 @@
+exports.connectionString = "pg://user:password@host/database";
diff --git a/src/nodejs/no1.js b/src/nodejs/no1.js
index 8eb86d7..1132a11 100644
--- a/src/nodejs/no1.js
+++ b/src/nodejs/no1.js
@@ -1,22 +1,49 @@
var clutch = require('clutch');
-var pg = require('pg')
-var builder = require('xmlbuilder')
+var pg = require('pg');
+var builder = require('xmlbuilder');
+var config = require('./config.json');
-var connectionString = "pg://user:password@host/database";
+var connectionString = config['connectionString'];
+console.log("server starting...");
+console.log("Connection String: " + connectionString);
+
+function toISO8601(date) {
+ //2007-03-31T00:09:22+01:00
+ var pad_two = function(n) {
+ return (n < 10 ? '0' : '') + n;
+ };
+ var pad_three = function(n) {
+ return (n < 100 ? '0' : '') + (n < 10 ? '0' : '') + n;
+ };
+ return [
+ date.getUTCFullYear(),
+ '-',
+ pad_two(date.getUTCMonth() + 1),
+ '-',
+ pad_two(date.getUTCDate()),
+ 'T',
+ pad_two(date.getUTCHours()),
+ ':',
+ pad_two(date.getUTCMinutes()),
+ ':',
+ pad_two(date.getUTCSeconds()),
+ '+01:00' //FIX ME
+ ].join('');
+}
+function createWayBboxQuery(key, value, left, bottom, right, top) {
+ return "SELECT id,tstamp,version,changeset_id, nodes, user_id, hstore_to_array(tags) as tags FROM ways WHERE (tags @> hstore('" + key + "','" + value + "') AND linestring && st_setsrid(st_makebox2d(st_setsrid(st_makepoint(" +
+ left + "," + bottom + "),4326), st_setsrid(st_makepoint(" + right + "," + top + "),4326)),4326));";
+}
function createNodeBboxQuery(key, value, left, bottom, right, top) {
- /*
- * return "SELECT * from nodes WHERE (tags @> '\"" + key
- + "\"=>\"" + value + "\"'" +
- " AND POINT(geom) @ polygon(box('(" + left
- + "," + bottom +")'::point,'(" +
- + right + "," + top + ")'::point)));";
- */
-
- return "SELECT id,tstamp,version,changeset_id, X(geom) as lat, Y(geom) as lon FROM nodes WHERE (tags @> hstore('" + key + "','" + value + "') AND geom && st_setsrid(st_makebox2d(st_setsrid(st_makepoint(" +
- left + "," + bottom + "),4326), st_setsrid(st_makepoint(" + right + "," + top + "),4326)),4326));";
+ return "SELECT id, user_id,tstamp,version,changeset_id, hstore_to_array(tags) as tags, X(geom) as lat, Y(geom) as lon FROM nodes WHERE (tags @> hstore('" + key + "','" + value + "') AND geom && st_setsrid(st_makebox2d(st_setsrid(st_makepoint(" +
+ left + "," + bottom + "),4326), st_setsrid(st_makepoint(" + right + "," + top + "),4326)),4326));";
+}
+
+function createNodesForWayQuery(nodes) {
+ return "SELECT id, tstamp, version, changeset_id, hstore_to_array(tags) as tags, X(geom) as lat, Y(geom) as lon FROM nodes WHERE id = ANY('" + nodes + "');";
}
@@ -35,57 +62,66 @@ function nodeBboxHandler(req, res, key, value, left, bottom, right, top) {
res.end('\n');
}
else {
- console.log(createNodeBboxQuery(key, value, left, bottom, right, top));
- client.query(createNodeBboxQuery(key, value, left, bottom, right, top), function(err,result) {
+ //console.log(createNodeBboxQuery(key, value, left, bottom, right, top));
+ var success = false;
+ var query = client.query(createNodeBboxQuery(key, value, left, bottom, right, top));
+
+ query.on('error', function(err) {
- if (err) {
- console.log(err);
- res.writeHead(404,{});
- res.end('\n');
- }
- else {
- console.log(result.rows);
-
- res.writeHead(200, {'Content-Type': 'text/plain'});
- //res.write("lala");
- res.write("<xml>");
- for(var i=0; i<result.rows.length;i++) {
- /*//res.write(result.rows[i].id);
- res.write("<node id='" + result.rows[i].id + "'" +
- " timestamp='" + result.rows[i].tstamp + "'" +
- + " version='" + result.rows[i].version + "'" +
- //+ " changeset='" + result.rows[i].changeset_id + "'" +
- ">");
- res.write("</node>");
- //console.log(result.rows[i].id);
- */
- var node = builder.begin('node')
- .att('id', result.rows[i].id)
- .att('timetamp', result.rows[i].tstamp)
- .att('version', result.rows[i].version)
- .att('changeset', result.rows[i].changeset_id)
- .att('lat', result.rows[i].lat)
- .att('lon', result.rows[i].lon);
-
-
-
- res.write(builder.toString());
-
- }
+ console.log(err);
+ res.writeHead(404,{});
+ res.end('\n');
+ });
+
+ query.on('end', function() {
+ //console.log("end event\n");
+ if(success) {
res.write("</xml>");
res.end();
}
+ else {
+ //empty response
+ res.writeHead(404,{});
+ res.end();
+ //perhaps write 404? is error also raised?
+ }
});
- }
-
-
+ query.on('row', function(row) {
+
+ if(!success) {
+ success = true;
+ res.writeHead(200, {'Content-Type': 'text/plain'});
+ res.write("<xml>");
+ }
+
+ console.log(row);
+
+ var node = builder.begin('node')
+ .att('id', row.id)
+ .att('timetamp', toISO8601(row.tstamp))
+ .att('version', row.version)
+ .att('changeset', row.changeset_id)
+ .att('lat', row.lat)
+ .att('lon', row.lon);
+ if(row.tags != '{}') {
+ var temp = row.tags.replace("{","").replace("}","").split(",");
+ for(var x=0;x<temp.length;x=x+2)
+ node.ele('tag')
+ .att('k',escape(temp[x]))
+ .att('v',escape(temp[x+1]));
+ }
+ //for(var x=0; x< tags.length;x++)
+ //console.log(tags[x]);
+ /*node.ele('tag')
+ .att('k',tags[x][0])
+ .att('v',tags[x][1]);
+ */
+ res.write(builder.toString({ pretty: true }));
+ //res.write(builder.toString());
+ });
+ }
});
-
- //console.log(createNodeBboxQuery(key, value, left, bottom, right, top));
-
- //res.writeHead(200, {'Content-Type': 'text/plain'});
- //res.end( 'bbox: '+ left + bottom + right + top + ' key:' +key +' value:'+value+'!\n');
}
function wayWorldHandler(req, res, key, value) {
@@ -93,7 +129,105 @@ function wayWorldHandler(req, res, key, value) {
res.writeHead(200, {'Content-Type': 'text/plain'});
}
-function wayBboxHandler(req, res, key, value, bbox, left, bottom, right, top) {
+function wayBboxHandler(req, res, key, value, left, bottom, right, top) {
+ pg.connect(connectionString, function(err,client) {
+ if(err) {
+ console.log(err);
+ res.writeHead(404,{});
+ res.end();
+ }
+ else {
+ var count = 0;
+ var success = false;
+ //console.log(createWayBboxQuery(key, value, left, bottom, right, top));
+ var query = client.query(createWayBboxQuery(key, value, left, bottom, right, top));
+
+ query.on('error', function(err) {
+ console.log(err);
+ res.writeHead(404,{});
+ res.end();
+ });
+
+ query.on('end', function() {
+ if(success) {
+ if(count == 0) {
+ res.write("</xml>");
+ res.end();
+ }
+ //res.write("</xml>");
+ //res.end(); //problem!!!
+ }
+ else {
+ res.writeHead(404,{});
+ res.end();
+ //perhaps write 404?
+ }
+ });
+
+ query.on('row', function(row) {
+ if(!success) {
+ success = true;
+ res.writeHead(200, {'Content-Type': 'text/plain'});
+ res.write("<xml>");
+ }
+ //console.log(row);
+ if(row.nodes != '{}') {
+ count++;
+ var subquery = client.query(createNodesForWayQuery(row.nodes));
+ subquery.on('error',function(err) {});
+ subquery.on('end', function() {
+ count--;
+ if(count==0)
+ res.write("</xml>");
+ res.end();
+ });
+ subquery.on('row', function(row) {
+ console.log(row);
+ var node = builder.begin('node')
+ .att('id', row.id)
+ .att('timetamp', toISO8601(row.tstamp))
+ .att('version', row.version)
+ .att('changeset', row.changeset_id)
+ .att('lat', row.lat)
+ .att('lon', row.lon);
+ if(row.tags != '{}') {
+ var temp = row.tags.replace("{","").replace("}","").split(",");
+ for(var x=0;x<temp.length;x=x+2)
+ node.ele('tag')
+ .att('k',escape(temp[x]))
+ .att('v',escape(temp[x+1]));
+ }
+ res.write(builder.toString({pretty:'true'}));
+ });
+
+ //console.log(createNodesForWayQuery(row.nodes));
+ }
+
+ var way = builder.begin('way')
+ .att('id', row.id)
+ .att('timetamp', toISO8601(row.tstamp))
+ .att('version', row.version)
+ .att('changeset', row.changeset_id);
+ if(row.tags != '{}') {
+ var temp = row.tags.replace("{","").replace("}","").split(",");
+ for(var x=0;x<temp.length;x=x+2)
+ way.ele('tag')
+ .att('k',escape(temp[x]))
+ .att('v',escape(temp[x+1]));
+ }
+
+ var temp = row.nodes.replace("{","").replace("}","").split(",");
+ for(var x=0;x<temp.length;x++)
+ way.ele('nd')
+ .att('ref',temp[x]);
+
+ res.write(builder.toString({pretty:'true'}));
+ });
+
+ }
+
+ });
+
}
function relationWorldHandler(req, res, key, value) {
@@ -112,9 +246,9 @@ myRoutes = clutch.route404([
['GET /api/node\\[(\\w+)=(\\w+)\\]\\[bbox=(\\d+(?:\\.\\d+)?),(\\d+(?:\\.\\d+)?),(\\d+(?:\\.\\d+)?),(\\d+(?:\\.\\d+)?)\\]$',nodeBboxHandler],
//['GET /api/node\\[(\\w+)=(\\w+)\\]\\[bbox=(\\d+\\.\\d+),(\\d+),(\\d+),(\\d+)\\]$',nodeBboxHandler],
['GET /api/way\\[(\\w+)=(\\w+)\\]$',wayWorldHandler],
- ['GET /api/way\\[(\\w+)=(\\w+)\\]\\[bbox=(\\d),(\\d),(\\d),(\\d)\\]$',wayBboxHandler],
+ ['GET /api/way\\[(\\w+)=(\\w+)\\]\\[bbox=(\\d+(?:\\.\\d+)?),(\\d+(?:\\.\\d+)?),(\\d+(?:\\.\\d+)?),(\\d+(?:\\.\\d+)?)\\]$',wayBboxHandler],
['GET /api/relation\\[(\\w+)=(\\w+)\\]$',relationWorldHandler],
- ['GET /api/relation\\[(\\w+)=(\\w+)\\](\\[bbox=(\\d),(\\d),(\\d),(\\d)\\])$',relationBboxHandler],
+ //['GET /api/relation\\[(\\w+)=(\\w+)\\](\\[bbox=(\\d),(\\d),(\\d),(\\d)\\])$',relationBboxHandler],
]);
diff --git a/src/nodejs/package.json b/src/nodejs/package.json
new file mode 100644
index 0000000..cbe341f
--- /dev/null
+++ b/src/nodejs/package.json
@@ -0,0 +1,11 @@
+{ "name" : "xapi-osm-spline"
+, "version" : "0.0.1"
+, "description" : "An osm xapi implementation"
+, "autor" : "osm@spline <osm@lists.spline.de> (http://osm.spline.de)"
+, "files" : ["."]
+, "dependencies" :
+ { "pg" : "*"
+ , "clutch" : "*"
+ , "xmlbuilder" : "*"
+ }
+}