Commit 4c64b8b8 authored by Adrien Pavie's avatar Adrien Pavie
Browse files

Themes configuration files, route for themes list in API

parent fb0c882f
......@@ -18,7 +18,9 @@ Osm4odf (OpenStreetMap pour OpenDataFrance) est un outil simple d'extraction th
## Configuration
Les paramètres généraux de configuration du service sont à renseigner dans le ficchier `config.json`. Les variables à renseigner sont les suivantes :
### Paramètres généraux
Les paramètres généraux de configuration du service sont à renseigner dans le fichier `config.json`. Les variables à renseigner sont les suivantes :
* `WORK_DIR` : dossier de travail, dans lequel les fichiers temporaires sont stockés (exemple: `/tmp/osm4odf`)
* `PBF_URL` : URL de téléchargement de l'extrait OpenStreetMap au format PBF (exemple: `http://download.geofabrik.de/europe/france-latest.osm.pbf`)
......@@ -31,6 +33,39 @@ Les paramètres généraux de configuration du service sont à renseigner dans l
* `PARALLEL_JOBS` : nombre de tâches à exécuter en parallèle, idéalement 75% des coeurs du processeur (exemple: `6`)
* `CACHE_MEM` : mémoire à allouer lors de l'import de données, en MB, idéalement 75% de la mémoire vive disponible (exemple: `10000`)
### Thèmes
Les thèmes de données sont à configurer dans le dossier `themes/`. Chaque thème est représenté par un fichier `.sql` avec une structure précise :
#### 1ère ligne du fichier
Elle décrit les métadonnées du thème, au format JSON avec un préfixe. On y trouve en particulier le nom en français et anglais.
```sql
--METADATA={ "name:fr": "Le nom en français", "name:en": "Le nom en anglais" }
```
### 2e ligne du fichier
Elle décrit le type de géométrie à interroger pour ce thème. Les types possibles sont `point`, `line`, `polygon`. Il est possible d'en renseigner plusieurs, séparés par une virgule.
```sql
--GEOMETRY=point,polygon
```
### Le reste du fichier
Les lignes suivantes du fichiers contiennent la requête SQL permettant d'extraire les données OpenStreetMap souhaitées. La liste des colonnes et leur ordre sera utilisé pour définir les données attributaires du fichier de sortie. La requête est à renseigner une seule fois même si l'on souhaite récupérer différents types de géométries. La table à utiliser dans le `FROM` doit être `<TABLE>` (le motif sera remplacé par l'API par le nom correct). La structure de la table à interroger correspond à ce que vous avez configuré dans le fichier `db/import.style` (voir ci-après).
```sql
SELECT
osm_id, name, access, tags->'operator' AS operator,
tags->'opening_hours' AS opening_hours,
tags->'defibrillator:location' AS location, geom
FROM <TABLE>
WHERE emergency = 'defibrillator'
```
## Base de données
......
......@@ -8,7 +8,7 @@
"test": "echo \"Error: no test specified\" && exit 1",
"doc": "apidoc -i src/ -o doc/",
"clean": "npm run clean:log && rm -rf ./doc",
"clean:log": "rm api.log"
"clean:log": "rm -f api.log"
},
"author": "Adrien Pavie",
"license": "AGPL-3.0",
......
......@@ -6,6 +6,7 @@ const express = require('express');
const cors = require('cors');
const fs = require('fs');
const db = require('./db');
const themes = require('./themes');
// Init API
const app = express();
......@@ -80,6 +81,9 @@ app.use('/doc', express.static(__dirname+'/../doc'));
* ]
* }
*/
app.get("/themes", (req, res) => {
res.send({ themes: themes.display });
});
/**
* @api {get} /boundaries List of administrative boundaries
......
/**
* Allows reading SQL files containing themes metadata
*/
const fs = require('fs');
const folder = '../themes';
const sqlrgx = /^[A-Za-z0-9_\-]+\.sql$/;
const themes = [];
const themesLight = [];
fs.readdirSync(folder).forEach((file) => {
if(sqlrgx.test(file)) {
try {
const themeId = file.substring(0, file.length - 4);
const themeTxt = fs.readFileSync(folder+"/"+file, 'utf8');
// Parse file
let metadata, geom;
let sql = "";
themeTxt.split("\n").forEach(line => {
if(line.startsWith("--METADATA=")) {
metadata = JSON.parse(line.substring(11).trim());
}
else if(line.startsWith("--GEOMETRY=")) {
geom = line.substring(11).trim().split(",");
if(geom.findIndex(g => !["point", "line", "polygon"].includes(g)) >= 0) {
throw new Error("invalid geometry type");
}
}
else if(line.trim().length > 0) {
sql += line.trim() + " ";
}
});
// Append data
themesLight.push(Object.assign({ id: themeId }, metadata));
let completeSQL = "WITH data AS ("+geom.map(g => "SELECT * FROM planet_osm_"+g+" WHERE <GEOMCOND>").join(" UNION ")+") ";
completeSQL += sql.replace("<TABLE>", "data");
themes.push(Object.assign({ id: themeId, sql: completeSQL.trim() }, metadata));
}
catch(e) {
throw new Error("Invalid theme file: "+file+" "+e.message);
}
}
else {
console.log("Ignored file: "+file);
}
});
module.exports = {
display: themesLight,
full: themes
};
--METADATA={ "name:fr": "Défibrillateur", "name:en": "Automated external defibrillator" }
--GEOMETRY=point
SELECT
osm_id, name, access, tags->'operator' AS operator,
tags->'opening_hours' AS opening_hours,
tags->'defibrillator:location' AS location, geom
FROM <TABLE>
WHERE emergency = 'defibrillator'
--METADATA={ "name:fr": "Parking à vélos", "name:en": "Bicycle parking" }
--GEOMETRY=point,polygon
SELECT
osm_id, name, access, tags->'operator' AS operator,
tags->'covered' AS covered, tags->'capacity' AS capacity,
tags->'bicycle_parking' AS type, geom
FROM <TABLE>
WHERE amenity = 'bicycle_parking'
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment