From da242452ecd1c838eea0883c2ade752dd882ae67 Mon Sep 17 00:00:00 2001
From: "amaury.zarzelli"
Date: Wed, 23 Feb 2022 12:38:44 +0100
Subject: [PATCH 01/93] start of 1.1.2-DEVELOP
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 0f4f918..1201a7b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "road2",
- "version": "1.1.1",
+ "version": "1.1.2-DEVELOP",
"description": "Calcul d'itinéraire",
"author": "RDEV - IGN",
From a9a45f795964f2c11caf840840875b8cacc04063 Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 7 Mar 2022 13:28:55 +0100
Subject: [PATCH 02/93] doc : maj des serveurs et mail
---
documentation/apis/simple/1.0.0/api.yaml | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/documentation/apis/simple/1.0.0/api.yaml b/documentation/apis/simple/1.0.0/api.yaml
index cf1570a..ba528f4 100644
--- a/documentation/apis/simple/1.0.0/api.yaml
+++ b/documentation/apis/simple/1.0.0/api.yaml
@@ -4,10 +4,12 @@ info:
version: "1.0.0"
title: "Service d'itinéraire"
contact:
- email: "idev@ign.fr"
+ email: "contact.geoservices@ign.fr"
servers:
- - url: "https://itineraire.ign.fr/simple/1.0.0/"
- description: "Serveur de test IGN"
+ - url: "https://wxs.ign.fr/calcul/geoportail/itineraire/rest/1.0.0/"
+ description: "Serveur de test IGN pour l'itinéraire"
+ - url: "https://wxs.ign.fr/calcul/geoportail/isochrone/rest/1.0.0/"
+ description: "Serveur de test IGN pour l'isochrone"
- url: "http://localhost:8080/simple/1.0.0/"
description: "Serveur de test local"
tags:
From 30d82d2fa3f25d4abd4e1ffe74842704253ed089 Mon Sep 17 00:00:00 2001
From: Loic
Date: Fri, 18 Mar 2022 14:00:10 +0100
Subject: [PATCH 03/93] test: relecture des tests deja existant
---
package.json | 8 ++---
.../simple/1.0.0/controller/controller.js | 2 +-
.../configurationComplementTest.feature | 12 -------
.../features/configurationTest.feature | 12 ++++---
test/functional/request/cucumber/data/2.json | 2 +-
test/functional/request/cucumber/data/3.json | 2 +-
.../cucumber/features/requestDataTest.feature | 34 +++++++++++++------
test/unit/mocha/utils/testsStorageManager.js | 2 +-
8 files changed, 38 insertions(+), 36 deletions(-)
diff --git a/package.json b/package.json
index 1201a7b..5f52cd9 100644
--- a/package.json
+++ b/package.json
@@ -10,10 +10,10 @@
"configCheck": "node ./src/js/road2.js --configCheck",
"utest": "mocha --recursive './test/unit/mocha/**/*.js'",
"itest": "mocha --recursive './test/integration/mocha/**/*.js'",
- "rtest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestTest.feature",
- "crtest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestComplementTest.feature",
- "drtest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestDataTest.feature",
- "artest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestAdminTest.feature",
+ "rtest": "HTTP_PROXY='' ./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestTest.feature",
+ "crtest": "HTTP_PROXY='' ./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestComplementTest.feature",
+ "drtest": "HTTP_PROXY='' ./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestDataTest.feature",
+ "artest": "HTTP_PROXY='' ./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestAdminTest.feature",
"ctest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/configuration/cucumber/features/configurationTest.feature",
"cctest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/configuration/cucumber/features/configurationComplementTest.feature",
"lint": "eslint -c eslint.json ./src/",
diff --git a/src/js/apis/simple/1.0.0/controller/controller.js b/src/js/apis/simple/1.0.0/controller/controller.js
index f4dadc4..d5b298f 100644
--- a/src/js/apis/simple/1.0.0/controller/controller.js
+++ b/src/js/apis/simple/1.0.0/controller/controller.js
@@ -218,7 +218,7 @@ module.exports = {
finalIntermediates = this.convertPostArrayToGetParameters(parameters.intermediates, routeOperation.getParameterById("intermediates").serviceParameter, "intermediates");
LOGGER.debug("POST intermediates:");
- LOGGER.debug(parameters.intermediates);
+ LOGGER.debug(finalIntermediates);
} else {
finalIntermediates = parameters.intermediates;
diff --git a/test/functional/configuration/cucumber/features/configurationComplementTest.feature b/test/functional/configuration/cucumber/features/configurationComplementTest.feature
index ec2b4e5..18b1b83 100644
--- a/test/functional/configuration/cucumber/features/configurationComplementTest.feature
+++ b/test/functional/configuration/cucumber/features/configurationComplementTest.feature
@@ -1,15 +1,3 @@
# Tests fonctionnels de Road2 sur la configuration du serveur pour les cas particuliers suivants:
# - problèmes dans la configuration mais on veut que le service démarre quand même
-Feature: Road2 configuration
- Tests fonctionnels de Road2 sur la configuration du serveur
-
- Background:
- Given I have loaded all my test configuration
-
-Scenario: [osrm resource] resource absent
- Given a valid configuration
- And without attribute "resource" in "corse.resource" resource
- When I load the server
- Then the server log should contain "Les demarrages se sont bien deroules"
-
diff --git a/test/functional/configuration/cucumber/features/configurationTest.feature b/test/functional/configuration/cucumber/features/configurationTest.feature
index 82f5134..1daf995 100644
--- a/test/functional/configuration/cucumber/features/configurationTest.feature
+++ b/test/functional/configuration/cucumber/features/configurationTest.feature
@@ -405,7 +405,7 @@ Feature: Road2 configuration
Scenario: [server.json] (resources.directories sur un dossier qui n'existe pas et en chemin relatif)
Given a valid configuration
- And with parameter "test" for attribute "application.resources.directories.[0]" in server configuration
+ And with parameter "test" for attribute "application.resources.directories.[1]" in server configuration
When I test the configuration
Then the configuration analysis should give an exit code 0
Then the server log should contain "Mauvaise configuration: Le dossier n'existe pas:"
@@ -1340,13 +1340,15 @@ Feature: Road2 configuration
Scenario: [osrm resource] resource absent
Given a valid configuration
- And without attribute "resource" in "corse.resource" resource
+ And without attribute "resource" in "data-osm.resource" resource
When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "Erreur lors de la lecture de la ressource"
+ Then the configuration analysis should give an exit code 1
+ # TODO : avoir plusieurs ressources dans le dossier pour qu'une d'entre elles marche
+ # Then the configuration analysis should give an exit code 0
+ # Then the server log should contain "Erreur lors de la lecture de la ressource"
Scenario: [osrm resource] id different
Given a valid configuration
- And with parameter "test" for attribute "resource.id" in "corse.resource" resource
+ And with parameter "test" for attribute "resource.id" in "data-osm.resource" resource
When I test the configuration
Then the configuration analysis should give an exit code 0
diff --git a/test/functional/request/cucumber/data/2.json b/test/functional/request/cucumber/data/2.json
index 86166ff..a0083bf 100644
--- a/test/functional/request/cucumber/data/2.json
+++ b/test/functional/request/cucumber/data/2.json
@@ -1 +1 @@
-{"resource":"bdtopo-pgr","resourceVersion":"2020-09-28","start":"3.818441,49.081297","end":"3.847338,49.083684","profile":"car","optimization":"shortest","geometry":{"type":"LineString","coordinates":[[3.818441,49.081297],[3.818461,49.081299],[3.818745,49.081328],[3.819184,49.081377],[3.81969,49.081443],[3.820034,49.081486],[3.820113,49.081497],[3.820449,49.081545],[3.820537,49.081557],[3.820779,49.08159],[3.821035,49.081633],[3.821098,49.081646],[3.821215,49.081672],[3.821351,49.081708],[3.821538,49.081768],[3.821834,49.081871],[3.822306,49.082038],[3.822916,49.082256],[3.822938,49.082264],[3.822965,49.082273],[3.823033,49.082298],[3.823248,49.082375],[3.823867,49.082589],[3.823901,49.082601],[3.824389,49.082776],[3.824803,49.082931],[3.825105,49.083056],[3.825282,49.083139],[3.825447,49.08323],[3.825685,49.083355],[3.825787,49.083416],[3.825963,49.08352],[3.826084,49.083588],[3.82615,49.083624],[3.826436,49.083796],[3.826597,49.083889],[3.826823,49.08402],[3.826927,49.084079],[3.826927,49.084079],[3.82702,49.084133],[3.827145,49.084213],[3.827216,49.084257],[3.827373,49.084377],[3.827529,49.084512],[3.827653,49.084633],[3.82779,49.084784],[3.827823,49.084819],[3.827974,49.084985],[3.828195,49.085215],[3.828298,49.085318],[3.828415,49.085424],[3.828498,49.085487],[3.828535,49.08551],[3.828595,49.085547],[3.828698,49.085591],[3.828803,49.085632],[3.828928,49.085678],[3.828962,49.085688],[3.829224,49.085763],[3.829261,49.085772],[3.829569,49.085851],[3.830101,49.085987],[3.830571,49.086138],[3.830614,49.086152],[3.830676,49.086164],[3.830735,49.086187],[3.830786,49.086216],[3.830825,49.086241],[3.830854,49.086268],[3.830981,49.086256],[3.831069,49.086209],[3.831103,49.086085],[3.831105,49.086035],[3.831091,49.085941],[3.831079,49.085808],[3.831101,49.085709],[3.831134,49.085544],[3.831154,49.085516],[3.831189,49.085471],[3.831221,49.085445],[3.831295,49.085417],[3.831379,49.085402],[3.831444,49.085395],[3.831598,49.085374],[3.831767,49.085351],[3.831924,49.085327],[3.83211,49.085298],[3.832166,49.085287],[3.832475,49.085228],[3.832738,49.085168],[3.833038,49.085088],[3.833334,49.085011],[3.833426,49.084988],[3.833748,49.084889],[3.833912,49.084827],[3.833963,49.084817],[3.834028,49.084802],[3.834155,49.084791],[3.83431,49.08477],[3.834359,49.084762],[3.834495,49.084739],[3.834624,49.0847],[3.834796,49.084603],[3.834983,49.084513],[3.835017,49.084495],[3.835073,49.084472],[3.835114,49.084456],[3.835194,49.08442],[3.835371,49.084375],[3.835431,49.084358],[3.835591,49.084315],[3.835748,49.084279],[3.835869,49.084256],[3.835933,49.084253],[3.835965,49.084253],[3.835967,49.084213],[3.83598,49.084117],[3.836,49.084045],[3.836021,49.08399],[3.836051,49.083929],[3.836097,49.083867],[3.836165,49.083785],[3.836219,49.083737],[3.836279,49.083684],[3.836398,49.083595],[3.836547,49.083495],[3.836571,49.083478],[3.836571,49.083478],[3.836716,49.083376],[3.836848,49.083278],[3.836982,49.083143],[3.837105,49.082991],[3.837189,49.082829],[3.837261,49.082694],[3.83731,49.08261],[3.837354,49.082538],[3.837436,49.082419],[3.837539,49.0823],[3.837571,49.082273],[3.837621,49.08223],[3.837724,49.082163],[3.837838,49.082098],[3.837932,49.082052],[3.838048,49.082011],[3.838138,49.081985],[3.838247,49.081957],[3.83842,49.081927],[3.838591,49.081908],[3.838775,49.081895],[3.838764,49.081636],[3.838746,49.081505],[3.838749,49.081467],[3.838771,49.081435],[3.838803,49.081418],[3.838906,49.081397],[3.839109,49.081368],[3.839172,49.081358],[3.839476,49.081302],[3.839797,49.081234],[3.839924,49.081207],[3.840354,49.081129],[3.840692,49.081053],[3.840727,49.081045],[3.841322,49.080895],[3.841424,49.080868],[3.841479,49.080855],[3.841532,49.080844],[3.841653,49.080838],[3.841801,49.080839],[3.842051,49.080844],[3.842238,49.08085],[3.842247,49.080817],[3.842278,49.080704],[3.842329,49.080606],[3.842387,49.080512],[3.842479,49.080411],[3.842628,49.080271],[3.842806,49.080135],[3.842991,49.080007],[3.843052,49.079965],[3.843431,49.079698],[3.843711,49.079492],[3.843835,49.079402],[3.844178,49.079159],[3.844303,49.079071],[3.844303,49.079071],[3.844178,49.079159],[3.843835,49.079402],[3.843711,49.079492],[3.843431,49.079698],[3.843052,49.079965],[3.842991,49.080007],[3.842806,49.080135],[3.842628,49.080271],[3.842479,49.080411],[3.842387,49.080512],[3.842329,49.080606],[3.842278,49.080704],[3.842247,49.080817],[3.842238,49.08085],[3.842051,49.080844],[3.841801,49.080839],[3.841653,49.080838],[3.841532,49.080844],[3.841479,49.080855],[3.841424,49.080868],[3.841322,49.080895],[3.840727,49.081045],[3.840692,49.081053],[3.840354,49.081129],[3.839924,49.081207],[3.839797,49.081234],[3.839476,49.081302],[3.839172,49.081358],[3.839109,49.081368],[3.838906,49.081397],[3.838803,49.081418],[3.838771,49.081435],[3.838749,49.081467],[3.838746,49.081505],[3.838764,49.081636],[3.838775,49.081895],[3.838633,49.081836],[3.838298,49.081747],[3.838119,49.081701],[3.837844,49.081628],[3.83759,49.081547],[3.837467,49.081514],[3.837275,49.081492],[3.837214,49.081486],[3.837045,49.081472],[3.836823,49.081464],[3.836746,49.081453],[3.836683,49.081443],[3.836354,49.081965],[3.836257,49.082076],[3.836139,49.082139],[3.835806,49.082207],[3.835284,49.082288],[3.835146,49.08231],[3.834731,49.082354],[3.834381,49.082406],[3.834245,49.082447],[3.834184,49.082484],[3.834145,49.082533],[3.834116,49.082583],[3.83411,49.082633],[3.834118,49.082699],[3.83414,49.082751],[3.834291,49.083026],[3.834429,49.083254],[3.834469,49.083373],[3.834466,49.083429],[3.834423,49.083485],[3.834328,49.083543],[3.834074,49.083648],[3.833836,49.083741],[3.833707,49.083777],[3.833611,49.083794],[3.833473,49.083806],[3.833384,49.083809],[3.833264,49.083811],[3.832843,49.083813],[3.83242,49.083796],[3.83209,49.083771],[3.832035,49.083764],[3.831976,49.083756],[3.83194,49.08375],[3.831858,49.083739],[3.831778,49.08373],[3.831566,49.083713],[3.830829,49.08366],[3.83032,49.083608],[3.830201,49.083601],[3.830212,49.083571],[3.830237,49.083326],[3.830242,49.083287],[3.830268,49.083122],[3.830278,49.083038],[3.830258,49.08292],[3.830209,49.082759],[3.830184,49.082671],[3.830093,49.082424],[3.830052,49.082345],[3.83003,49.082326],[3.829982,49.082282],[3.829895,49.082228],[3.829777,49.082207],[3.829628,49.0822],[3.82941,49.082205],[3.829187,49.082218],[3.829105,49.082221],[3.828895,49.082229],[3.828454,49.082244],[3.828454,49.082244],[3.828895,49.082229],[3.829105,49.082221],[3.829187,49.082218],[3.82941,49.082205],[3.829628,49.0822],[3.829777,49.082207],[3.829895,49.082228],[3.829982,49.082282],[3.83003,49.082326],[3.830052,49.082345],[3.830093,49.082424],[3.830184,49.082671],[3.830209,49.082759],[3.830258,49.08292],[3.830278,49.083038],[3.830268,49.083122],[3.830242,49.083287],[3.830237,49.083326],[3.830212,49.083571],[3.830201,49.083601],[3.83032,49.083608],[3.830829,49.08366],[3.831566,49.083713],[3.831778,49.08373],[3.831858,49.083739],[3.83194,49.08375],[3.831976,49.083756],[3.832035,49.083764],[3.83209,49.083771],[3.83242,49.083796],[3.832843,49.083813],[3.833264,49.083811],[3.833384,49.083809],[3.833473,49.083806],[3.833611,49.083794],[3.833707,49.083777],[3.833836,49.083741],[3.834074,49.083648],[3.834328,49.083543],[3.834423,49.083485],[3.834466,49.083429],[3.834469,49.083373],[3.834429,49.083254],[3.834291,49.083026],[3.83414,49.082751],[3.834118,49.082699],[3.83411,49.082633],[3.834116,49.082583],[3.834145,49.082533],[3.834184,49.082484],[3.834245,49.082447],[3.834381,49.082406],[3.834731,49.082354],[3.835146,49.08231],[3.835284,49.082288],[3.835806,49.082207],[3.836139,49.082139],[3.836257,49.082076],[3.836354,49.081965],[3.836683,49.081443],[3.836746,49.081453],[3.836823,49.081464],[3.837045,49.081472],[3.837214,49.081486],[3.837275,49.081492],[3.837467,49.081514],[3.83759,49.081547],[3.837844,49.081628],[3.838119,49.081701],[3.838298,49.081747],[3.838633,49.081836],[3.838775,49.081895],[3.838875,49.081889],[3.839348,49.081854],[3.839414,49.081849],[3.839745,49.081829],[3.840027,49.08181],[3.840343,49.081797],[3.840575,49.081792],[3.840769,49.081787],[3.840938,49.081784],[3.841079,49.081774],[3.841185,49.081761],[3.841316,49.081736],[3.841342,49.081727],[3.841477,49.081687],[3.841747,49.08161],[3.841786,49.081599],[3.842034,49.081519],[3.842151,49.081476],[3.842177,49.081447],[3.842217,49.08146],[3.842264,49.08149],[3.842448,49.081714],[3.842725,49.082069],[3.842814,49.082145],[3.842944,49.082265],[3.84313,49.082441],[3.843226,49.082526],[3.843422,49.082681],[3.843632,49.082864],[3.843684,49.082919],[3.843749,49.083007],[3.8438,49.083112],[3.843855,49.083297],[3.843932,49.083499],[3.84399,49.083638],[3.844061,49.083789],[3.84413,49.083879],[3.84424,49.083993],[3.844374,49.0841],[3.844616,49.084238],[3.844774,49.084327],[3.844905,49.0843],[3.845309,49.084164],[3.845546,49.084092],[3.845922,49.083996],[3.846568,49.083856],[3.846689,49.083829],[3.846761,49.083814],[3.847138,49.083724],[3.847338,49.083684]]},"crs":"EPSG:4326","distanceUnit":"meter","timeUnit":"minute","bbox":[3.818441,49.079071,3.847338,49.086268],"distance":6110.2,"duration":99.93166666666666,"constraints":[],"portions":[{"start":"3.818441,49.081297","end":"3.826922,49.084083","distance":705.5,"duration":0.6716666666666666,"bbox":[3.818441,49.081297,3.82692723197936,49.084079134697696],"steps":[{"geometry":{"type":"LineString","coordinates":[[3.818441,49.081297],[3.818461,49.081299],[3.818745,49.081328],[3.819184,49.081377],[3.81969,49.081443],[3.820034,49.081486],[3.820113,49.081497],[3.820449,49.081545],[3.820537,49.081557]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":155.8,"duration":0.14833333333333334,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.820779,49.08159],[3.821035,49.081633],[3.821098,49.081646],[3.821215,49.081672],[3.821351,49.081708],[3.821538,49.081768],[3.821834,49.081871],[3.822306,49.082038],[3.822916,49.082256]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":191.5,"duration":0.18166666666666667,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.822938,49.082264],[3.822965,49.082273],[3.823033,49.082298]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":9.7,"duration":0.01,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.823248,49.082375],[3.823867,49.082589],[3.823901,49.082601],[3.824389,49.082776],[3.824803,49.082931],[3.825105,49.083056],[3.825282,49.083139],[3.825447,49.08323],[3.825685,49.083355],[3.825787,49.083416],[3.825963,49.08352],[3.826084,49.083588]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":266.2,"duration":0.2533333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.82615,49.083624],[3.826436,49.083796],[3.826597,49.083889]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":50.3,"duration":0.04833333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.826823,49.08402],[3.826927,49.084079]]},"attributes":{"nom_1_gauche":"GRANDE RUE","nom_1_droite":"GRANDE RUE","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":32,"duration":0.030000000000000002,"instruction":""}]},{"start":"3.826922,49.084083","end":"3.83657,49.083477","distance":969.6,"duration":1.4016666666666666,"bbox":[3.82692723197936,49.083477790843915,3.8365712973297255,49.086268],"steps":[{"geometry":{"type":"LineString","coordinates":[[3.826927,49.084079],[3.82702,49.084133],[3.827145,49.084213],[3.827216,49.084257],[3.827373,49.084377],[3.827529,49.084512],[3.827653,49.084633],[3.82779,49.084784],[3.827823,49.084819],[3.827974,49.084985],[3.828195,49.085215],[3.828298,49.085318],[3.828415,49.085424],[3.828498,49.085487],[3.828535,49.08551]]},"attributes":{"nom_1_gauche":"GRANDE RUE","nom_1_droite":"GRANDE RUE","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":198.8,"duration":0.19,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.828595,49.085547],[3.828698,49.085591]]},"attributes":{"nom_1_gauche":"GRANDE RUE","nom_1_droite":"GRANDE RUE","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":15,"duration":0.015000000000000001,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.828803,49.085632],[3.828928,49.085678],[3.828962,49.085688],[3.829224,49.085763],[3.829261,49.085772],[3.829569,49.085851],[3.830101,49.085987],[3.830571,49.086138]]},"attributes":{"nom_1_gauche":"GRANDE RUE","nom_1_droite":"GRANDE RUE","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":150,"duration":0.2,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.830614,49.086152],[3.830676,49.086164],[3.830735,49.086187],[3.830786,49.086216],[3.830825,49.086241],[3.830854,49.086268]]},"attributes":{"nom_1_gauche":"GRANDE RUE","nom_1_droite":"GRANDE RUE","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":25.8,"duration":0.035,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.830981,49.086256],[3.831069,49.086209],[3.831103,49.086085],[3.831105,49.086035],[3.831091,49.085941],[3.831079,49.085808],[3.831101,49.085709],[3.831134,49.085544],[3.831154,49.085516],[3.831189,49.085471],[3.831221,49.085445],[3.831295,49.085417],[3.831379,49.085402],[3.831444,49.085395],[3.831598,49.085374],[3.831767,49.085351],[3.831924,49.085327]]},"attributes":{"nom_1_gauche":"R DES VIGNES","nom_1_droite":"R DES VIGNES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":158.3,"duration":0.31666666666666665,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.83211,49.085298],[3.832166,49.085287],[3.832475,49.085228],[3.832738,49.085168],[3.833038,49.085088],[3.833334,49.085011],[3.833426,49.084988],[3.833748,49.084889],[3.833912,49.084827],[3.833963,49.084817]]},"attributes":{"nom_1_gauche":"R DES VIGNES","nom_1_droite":"R DES VIGNES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":159.8,"duration":0.2733333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.834028,49.084802],[3.834155,49.084791],[3.83431,49.08477],[3.834359,49.084762],[3.834495,49.084739],[3.834624,49.0847],[3.834796,49.084603],[3.834983,49.084513],[3.835017,49.084495],[3.835073,49.084472],[3.835114,49.084456],[3.835194,49.08442],[3.835371,49.084375],[3.835431,49.084358],[3.835591,49.084315],[3.835748,49.084279],[3.835869,49.084256],[3.835933,49.084253],[3.835965,49.084253]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":162,"duration":0.2783333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.835967,49.084213],[3.83598,49.084117],[3.836,49.084045],[3.836021,49.08399],[3.836051,49.083929],[3.836097,49.083867],[3.836165,49.083785],[3.836219,49.083737],[3.836279,49.083684],[3.836398,49.083595],[3.836547,49.083495],[3.836571,49.083478]]},"attributes":{"nom_1_gauche":"R DE CHAMPAGNE","nom_1_droite":"R DE CHAMPAGNE","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":100.1,"duration":0.095,"instruction":""}]},{"start":"3.83657,49.083477","end":"3.844303,49.079071","distance":823.4,"duration":1.2416666666666667,"bbox":[3.8365712973297255,49.079071,3.844303,49.083477790843915],"steps":[{"geometry":{"type":"LineString","coordinates":[[3.836571,49.083478],[3.836716,49.083376],[3.836848,49.083278],[3.836982,49.083143],[3.837105,49.082991],[3.837189,49.082829],[3.837261,49.082694],[3.83731,49.08261]]},"attributes":{"nom_1_gauche":"R DE CHAMPAGNE","nom_1_droite":"R DE CHAMPAGNE","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":112.1,"duration":0.10666666666666667,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.837354,49.082538],[3.837436,49.082419],[3.837539,49.0823],[3.837571,49.082273],[3.837621,49.08223],[3.837724,49.082163],[3.837838,49.082098],[3.837932,49.082052],[3.838048,49.082011],[3.838138,49.081985],[3.838247,49.081957],[3.83842,49.081927],[3.838591,49.081908],[3.838775,49.081895]]},"attributes":{"nom_1_gauche":"R DE CHAMPAGNE","nom_1_droite":"R DE CHAMPAGNE","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":143,"duration":0.19,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.838764,49.081636],[3.838746,49.081505],[3.838749,49.081467],[3.838771,49.081435]]},"attributes":{"nom_1_gauche":"R DES FOSSES","nom_1_droite":"R DES FOSSES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":51.5,"duration":0.10333333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.838803,49.081418],[3.838906,49.081397],[3.839109,49.081368]]},"attributes":{"nom_1_gauche":"R DES FOSSES","nom_1_droite":"R DES FOSSES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":26.1,"duration":0.051666666666666666,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.839172,49.081358],[3.839476,49.081302],[3.839797,49.081234],[3.839924,49.081207],[3.840354,49.081129],[3.840692,49.081053],[3.840727,49.081045],[3.841322,49.080895],[3.841424,49.080868],[3.841479,49.080855]]},"attributes":{"nom_1_gauche":"R DES FOSSES","nom_1_droite":"R DES FOSSES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":182.4,"duration":0.365,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.841532,49.080844],[3.841653,49.080838],[3.841801,49.080839],[3.842051,49.080844],[3.842238,49.08085]]},"attributes":{"nom_1_gauche":"R DES FOSSES","nom_1_droite":"R DES FOSSES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":55.7,"duration":0.11166666666666666,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.842247,49.080817],[3.842278,49.080704],[3.842329,49.080606],[3.842387,49.080512],[3.842479,49.080411],[3.842628,49.080271],[3.842806,49.080135],[3.842991,49.080007],[3.843052,49.079965],[3.843431,49.079698],[3.843711,49.079492]]},"attributes":{"nom_1_gauche":"R DE CHAMPAGNE","nom_1_droite":"R DE CHAMPAGNE","cpx_numero":"D1","cpx_toponyme_route_nommee":"Route Touristique du Champagne de la Vallée de la Marne"},"distance":188.7,"duration":0.25166666666666665,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.843835,49.079402],[3.844178,49.079159],[3.844303,49.079071]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"D1","cpx_toponyme_route_nommee":"Route Touristique du Champagne de la Vallée de la Marne"},"distance":63.8,"duration":0.060000000000000005,"instruction":""}]},{"start":"3.844303,49.079071","end":"3.828454,49.082244","distance":1670.7,"duration":42.20666666666667,"bbox":[3.828454,49.079071,3.844303,49.083813],"steps":[{"geometry":{"type":"LineString","coordinates":[[3.844303,49.079071],[3.844178,49.079159],[3.843835,49.079402],[3.843711,49.079492]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"D1","cpx_toponyme_route_nommee":"Route Touristique du Champagne de la Vallée de la Marne"},"distance":63.8,"duration":0.060000000000000005,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.843431,49.079698],[3.843052,49.079965],[3.842991,49.080007],[3.842806,49.080135],[3.842628,49.080271],[3.842479,49.080411],[3.842387,49.080512],[3.842329,49.080606],[3.842278,49.080704],[3.842247,49.080817],[3.842238,49.08085]]},"attributes":{"nom_1_gauche":"R DE CHAMPAGNE","nom_1_droite":"R DE CHAMPAGNE","cpx_numero":"D1","cpx_toponyme_route_nommee":"Route Touristique du Champagne de la Vallée de la Marne"},"distance":188.7,"duration":0.25166666666666665,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.842051,49.080844],[3.841801,49.080839],[3.841653,49.080838],[3.841532,49.080844],[3.841479,49.080855]]},"attributes":{"nom_1_gauche":"R DES FOSSES","nom_1_droite":"R DES FOSSES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":55.7,"duration":0.11166666666666666,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.841424,49.080868],[3.841322,49.080895],[3.840727,49.081045],[3.840692,49.081053],[3.840354,49.081129],[3.839924,49.081207],[3.839797,49.081234],[3.839476,49.081302],[3.839172,49.081358],[3.839109,49.081368]]},"attributes":{"nom_1_gauche":"R DES FOSSES","nom_1_droite":"R DES FOSSES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":182.4,"duration":0.365,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.838906,49.081397],[3.838803,49.081418],[3.838771,49.081435]]},"attributes":{"nom_1_gauche":"R DES FOSSES","nom_1_droite":"R DES FOSSES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":26.1,"duration":0.051666666666666666,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.838749,49.081467],[3.838746,49.081505],[3.838764,49.081636],[3.838775,49.081895]]},"attributes":{"nom_1_gauche":"R DES FOSSES","nom_1_droite":"R DES FOSSES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":51.5,"duration":0.10333333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.838633,49.081836],[3.838298,49.081747],[3.838119,49.081701]]},"attributes":{"nom_1_gauche":"R DES CRAYERES","nom_1_droite":"R DES CRAYERES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":52.7,"duration":0.105,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.837844,49.081628],[3.83759,49.081547],[3.837467,49.081514],[3.837275,49.081492],[3.837214,49.081486],[3.837045,49.081472],[3.836823,49.081464],[3.836746,49.081453],[3.836683,49.081443]]},"attributes":{"nom_1_gauche":"R DES CRAYERES","nom_1_droite":"R DES CRAYERES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":109.9,"duration":0.22,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.836354,49.081965],[3.836257,49.082076],[3.836139,49.082139],[3.835806,49.082207],[3.835284,49.082288],[3.835146,49.08231],[3.834731,49.082354],[3.834381,49.082406],[3.834245,49.082447],[3.834184,49.082484],[3.834145,49.082533],[3.834116,49.082583],[3.83411,49.082633],[3.834118,49.082699],[3.83414,49.082751],[3.834291,49.083026],[3.834429,49.083254],[3.834469,49.083373],[3.834466,49.083429],[3.834423,49.083485],[3.834328,49.083543],[3.834074,49.083648],[3.833836,49.083741],[3.833707,49.083777],[3.833611,49.083794],[3.833473,49.083806]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":434.1,"duration":26.045,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.833384,49.083809],[3.833264,49.083811],[3.832843,49.083813],[3.83242,49.083796],[3.83209,49.083771],[3.832035,49.083764],[3.831976,49.083756],[3.83194,49.08375],[3.831858,49.083739],[3.831778,49.08373],[3.831566,49.083713],[3.830829,49.08366],[3.83032,49.083608],[3.830201,49.083601]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":240.6,"duration":14.438333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.830212,49.083571],[3.830237,49.083326],[3.830242,49.083287],[3.830268,49.083122],[3.830278,49.083038]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":62.9,"duration":0.10833333333333334,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.830258,49.08292],[3.830209,49.082759],[3.830184,49.082671],[3.830093,49.082424],[3.830052,49.082345],[3.83003,49.082326],[3.829982,49.082282],[3.829895,49.082228],[3.829777,49.082207],[3.829628,49.0822],[3.82941,49.082205],[3.829187,49.082218],[3.829105,49.082221],[3.828895,49.082229],[3.828454,49.082244]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":202.2,"duration":0.3466666666666667,"instruction":""}]},{"start":"3.828454,49.082244","end":"3.847338,49.083684","distance":1940.9,"duration":54.41,"bbox":[3.828454,49.081443,3.847338,49.084327],"steps":[{"geometry":{"type":"LineString","coordinates":[[3.828454,49.082244],[3.828895,49.082229],[3.829105,49.082221],[3.829187,49.082218],[3.82941,49.082205],[3.829628,49.0822],[3.829777,49.082207],[3.829895,49.082228],[3.829982,49.082282],[3.83003,49.082326],[3.830052,49.082345],[3.830093,49.082424],[3.830184,49.082671],[3.830209,49.082759],[3.830258,49.08292],[3.830278,49.083038]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":202.2,"duration":0.3466666666666667,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.830268,49.083122],[3.830242,49.083287],[3.830237,49.083326],[3.830212,49.083571],[3.830201,49.083601]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":62.9,"duration":0.10833333333333334,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.83032,49.083608],[3.830829,49.08366],[3.831566,49.083713],[3.831778,49.08373],[3.831858,49.083739],[3.83194,49.08375],[3.831976,49.083756],[3.832035,49.083764],[3.83209,49.083771],[3.83242,49.083796],[3.832843,49.083813],[3.833264,49.083811],[3.833384,49.083809],[3.833473,49.083806]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":240.6,"duration":14.438333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.833611,49.083794],[3.833707,49.083777],[3.833836,49.083741],[3.834074,49.083648],[3.834328,49.083543],[3.834423,49.083485],[3.834466,49.083429],[3.834469,49.083373],[3.834429,49.083254],[3.834291,49.083026],[3.83414,49.082751],[3.834118,49.082699],[3.83411,49.082633],[3.834116,49.082583],[3.834145,49.082533],[3.834184,49.082484],[3.834245,49.082447],[3.834381,49.082406],[3.834731,49.082354],[3.835146,49.08231],[3.835284,49.082288],[3.835806,49.082207],[3.836139,49.082139],[3.836257,49.082076],[3.836354,49.081965],[3.836683,49.081443]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":434.1,"duration":26.045,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.836746,49.081453],[3.836823,49.081464],[3.837045,49.081472],[3.837214,49.081486],[3.837275,49.081492],[3.837467,49.081514],[3.83759,49.081547],[3.837844,49.081628],[3.838119,49.081701]]},"attributes":{"nom_1_gauche":"R DES CRAYERES","nom_1_droite":"R DES CRAYERES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":109.9,"duration":0.22,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.838298,49.081747],[3.838633,49.081836],[3.838775,49.081895]]},"attributes":{"nom_1_gauche":"R DES CRAYERES","nom_1_droite":"R DES CRAYERES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":52.7,"duration":0.105,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.838875,49.081889]]},"attributes":{"nom_1_gauche":"R DE CHAMPAGNE","nom_1_droite":"R DE CHAMPAGNE","cpx_numero":"D1","cpx_toponyme_route_nommee":""},"distance":7.3,"duration":0.01,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.839348,49.081854]]},"attributes":{"nom_1_gauche":"R DE CHAMPAGNE","nom_1_droite":"R DE CHAMPAGNE","cpx_numero":"D1","cpx_toponyme_route_nommee":"Route Touristique du Champagne de la Vallée de la Marne"},"distance":34.8,"duration":0.04666666666666666,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.839414,49.081849],[3.839745,49.081829],[3.840027,49.08181],[3.840343,49.081797],[3.840575,49.081792],[3.840769,49.081787],[3.840938,49.081784],[3.841079,49.081774],[3.841185,49.081761],[3.841316,49.081736],[3.841342,49.081727]]},"attributes":{"nom_1_gauche":"R DE CHAMPAGNE","nom_1_droite":"R DE CHAMPAGNE","cpx_numero":"D1","cpx_toponyme_route_nommee":"Route Touristique du Champagne de la Vallée de la Marne"},"distance":146.8,"duration":0.19499999999999998,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.841477,49.081687],[3.841747,49.08161]]},"attributes":{"nom_1_gauche":"R DE CHAMPAGNE","nom_1_droite":"R DE CHAMPAGNE","cpx_numero":"D1","cpx_toponyme_route_nommee":"Route Touristique du Champagne de la Vallée de la Marne"},"distance":32.3,"duration":0.043333333333333335,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.841786,49.081599],[3.842034,49.081519],[3.842151,49.081476],[3.842177,49.081447]]},"attributes":{"nom_1_gauche":"R DE CHAMPAGNE","nom_1_droite":"R DE CHAMPAGNE","cpx_numero":"D1","cpx_toponyme_route_nommee":"Route Touristique du Champagne de la Vallée de la Marne"},"distance":36.8,"duration":0.04833333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.842217,49.08146],[3.842264,49.08149],[3.842448,49.081714]]},"attributes":{"nom_1_gauche":"R DU BANC DE PIERRE","nom_1_droite":"R DU BANC DE PIERRE","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":36.4,"duration":0.07333333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.842725,49.082069]]},"attributes":{"nom_1_gauche":"R DU BANC DE PIERRE","nom_1_droite":"R DU BANC DE PIERRE","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":44.4,"duration":0.08833333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.842814,49.082145],[3.842944,49.082265],[3.84313,49.082441]]},"attributes":{"nom_1_gauche":"R DU FBG D ARNOTAY","nom_1_droite":"R DU FBG D ARNOTAY","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":50.8,"duration":0.10166666666666666,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.843226,49.082526],[3.843422,49.082681],[3.843632,49.082864],[3.843684,49.082919],[3.843749,49.083007],[3.8438,49.083112],[3.843855,49.083297],[3.843932,49.083499],[3.84399,49.083638],[3.844061,49.083789],[3.84413,49.083879],[3.84424,49.083993],[3.844374,49.0841]]},"attributes":{"nom_1_gauche":"R DU FBG D ARNOTAY","nom_1_droite":"R DU FBG D ARNOTAY","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":209.4,"duration":0.41833333333333333,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.844616,49.084238],[3.844774,49.084327]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":38.6,"duration":0.06666666666666667,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.844905,49.0843],[3.845309,49.084164],[3.845546,49.084092],[3.845922,49.083996],[3.846568,49.083856],[3.846689,49.083829],[3.846761,49.083814],[3.847138,49.083724],[3.847338,49.083684]]},"attributes":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":200.9,"duration":12.055,"instruction":""}]}]}
+{"resource":"bdtopo-pgr","resourceVersion":"2022-01-24","start":"2.557209,48.742584","end":"2.561383,48.741514","profile":"car","optimization":"fastest","geometry":{"type":"LineString","coordinates":[[2.557209,48.742584],[2.557236,48.742585],[2.557472,48.742585],[2.557542,48.742582],[2.557592,48.74258],[2.557654,48.742573],[2.557708,48.742566],[2.557769,48.742555],[2.557833,48.742542],[2.557913,48.742522],[2.557991,48.742499],[2.558086,48.742473],[2.55818,48.742452],[2.558281,48.742434],[2.558353,48.742427],[2.558445,48.742418],[2.558534,48.742415],[2.558534,48.742352],[2.558541,48.742295],[2.558554,48.742214],[2.558553,48.742145],[2.558551,48.742101],[2.558536,48.742056],[2.558509,48.742012],[2.558476,48.74197],[2.558424,48.741924],[2.558397,48.741907],[2.558397,48.741907],[2.558424,48.741924],[2.558476,48.74197],[2.558509,48.742012],[2.558536,48.742056],[2.558551,48.742101],[2.558553,48.742145],[2.558554,48.742214],[2.558541,48.742295],[2.558534,48.742352],[2.558534,48.742415],[2.558658,48.742411],[2.558744,48.742411],[2.558853,48.742409],[2.558956,48.742411],[2.559256,48.742421],[2.559396,48.742424],[2.559537,48.742427],[2.559794,48.742423],[2.559913,48.742421],[2.560004,48.742414],[2.560105,48.742407],[2.560166,48.742398],[2.560226,48.742391],[2.560308,48.742377],[2.560395,48.74236],[2.560497,48.742335],[2.56059,48.742309],[2.560763,48.742253],[2.560812,48.742228],[2.560862,48.742203],[2.560952,48.742152],[2.561031,48.742097],[2.561104,48.742034],[2.561167,48.741969],[2.561218,48.741912],[2.561259,48.741852],[2.561289,48.741792],[2.561317,48.741737],[2.561348,48.741648],[2.561373,48.741568],[2.561384,48.741514]]},"crs":"EPSG:4326","distanceUnit":"meter","timeUnit":"minute","bbox":[2.557209,48.741514,2.561384,48.742585],"distance":484.4,"duration":0.7866666666666667,"constraints":[],"portions":[{"start":"2.557209,48.742584","end":"2.558397,48.741907","distance":160.1,"duration":0.26999999999999996,"bbox":[2.557209,48.741907,2.558554,48.742585],"steps":[{"geometry":{"type":"LineString","coordinates":[[2.557209,48.742584],[2.557236,48.742585],[2.557472,48.742585],[2.557542,48.742582],[2.557592,48.74258],[2.557654,48.742573],[2.557708,48.742566],[2.557769,48.742555],[2.557833,48.742542],[2.557913,48.742522]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":52.7,"duration":0.07833333333333334,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.557991,48.742499],[2.558086,48.742473],[2.55818,48.742452],[2.558281,48.742434],[2.558353,48.742427],[2.558445,48.742418],[2.558534,48.742415]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":47.6,"duration":0.07166666666666667,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.558534,48.742352],[2.558541,48.742295],[2.558554,48.742214],[2.558553,48.742145],[2.558551,48.742101],[2.558536,48.742056],[2.558509,48.742012],[2.558476,48.74197],[2.558424,48.741924],[2.558397,48.741907]]},"attributes":{"nom_1_gauche":"R DES AUBEPINES","nom_1_droite":"R DES AUBEPINES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":59.8,"duration":0.12000000000000001,"instruction":{}}]},{"start":"2.558397,48.741907","end":"2.561383,48.741514","distance":324.3,"duration":0.5166666666666667,"bbox":[2.558397,48.741514086987735,2.561383982280277,48.742427],"steps":[{"geometry":{"type":"LineString","coordinates":[[2.558397,48.741907],[2.558424,48.741924],[2.558476,48.74197],[2.558509,48.742012],[2.558536,48.742056],[2.558551,48.742101],[2.558553,48.742145],[2.558554,48.742214],[2.558541,48.742295],[2.558534,48.742352],[2.558534,48.742415]]},"attributes":{"nom_1_gauche":"R DES AUBEPINES","nom_1_droite":"R DES AUBEPINES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":59.8,"duration":0.12000000000000001,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.558658,48.742411],[2.558744,48.742411],[2.558853,48.742409],[2.558956,48.742411],[2.559256,48.742421],[2.559396,48.742424],[2.559537,48.742427]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":73.8,"duration":0.11,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.559794,48.742423],[2.559913,48.742421],[2.560004,48.742414]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":34.5,"duration":0.051666666666666666,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560105,48.742407]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":7.5,"duration":0.011666666666666665,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560166,48.742398],[2.560226,48.742391]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":9.1,"duration":0.013333333333333334,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560308,48.742377]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":6.2,"duration":0.01,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560395,48.74236],[2.560497,48.742335],[2.56059,48.742309],[2.560763,48.742253]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":36.3,"duration":0.055,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560812,48.742228],[2.560862,48.742203],[2.560952,48.742152],[2.561031,48.742097],[2.561104,48.742034],[2.561167,48.741969],[2.561218,48.741912],[2.561259,48.741852],[2.561289,48.741792]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":65.4,"duration":0.09833333333333334,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.561317,48.741737],[2.561348,48.741648],[2.561373,48.741568],[2.561384,48.741514]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":31.8,"duration":0.04833333333333333,"instruction":{}}]}]}
\ No newline at end of file
diff --git a/test/functional/request/cucumber/data/3.json b/test/functional/request/cucumber/data/3.json
index fbc863b..f7e25b7 100644
--- a/test/functional/request/cucumber/data/3.json
+++ b/test/functional/request/cucumber/data/3.json
@@ -1 +1 @@
-{"resource":"bdtopo-pgr","resourceVersion":"2020-09-28","start":"3.337845,43.310028","end":"3.339036,43.310531","profile":"car","optimization":"fastest","geometry":{"type":"LineString","coordinates":[[3.337845,43.310027],[3.337827,43.310028],[3.337773,43.310036],[3.337727,43.310054],[3.337699,43.310081],[3.337688,43.310114],[3.337693,43.310148],[3.33771,43.31018],[3.337736,43.310207],[3.33778,43.310225],[3.337838,43.310231],[3.337902,43.310229],[3.337961,43.310226],[3.338012,43.310225],[3.338057,43.310225],[3.338059,43.310229],[3.338062,43.310243],[3.338071,43.310265],[3.338077,43.310306],[3.338068,43.310363],[3.33805,43.310431],[3.338031,43.310506],[3.338012,43.310572],[3.338127,43.310571],[3.339036,43.310531]]},"crs":"EPSG:4326","distanceUnit":"meter","timeUnit":"minute","bbox":[3.337688,43.310027,3.339036,43.310572],"distance":178,"duration":0.305,"constraints":[],"portions":[{"start":"3.337845,43.310028","end":"3.339036,43.310531","distance":178,"duration":0.305,"bbox":[3.337688,43.310027,3.339036,43.310572],"steps":[{"geometry":{"type":"LineString","coordinates":[[3.337845,43.310027],[3.337827,43.310028],[3.337773,43.310036],[3.337727,43.310054],[3.337699,43.310081],[3.337688,43.310114],[3.337693,43.310148],[3.33771,43.31018],[3.337736,43.310207],[3.33778,43.310225],[3.337838,43.310231],[3.337902,43.310229],[3.337961,43.310226],[3.338012,43.310225],[3.338057,43.310225]]},"attributes":{"nom_1_gauche":"PL JEAN CHARRON","nom_1_droite":"PL JEAN CHARRON","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":55.6,"duration":0.095,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.338059,43.310229],[3.338062,43.310243],[3.338071,43.310265],[3.338077,43.310306],[3.338068,43.310363],[3.33805,43.310431],[3.338031,43.310506],[3.338012,43.310572]]},"attributes":{"nom_1_gauche":"PL JEAN CHARRON","nom_1_droite":"PL JEAN CHARRON","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":39.2,"duration":0.06666666666666667,"instruction":""},{"geometry":{"type":"LineString","coordinates":[[3.338127,43.310571],[3.339036,43.310531]]},"attributes":{"nom_1_gauche":"R PIERRE AIGRAIN","nom_1_droite":"R PIERRE AIGRAIN","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":83.1,"duration":0.14166666666666666,"instruction":""}]}]}
+{"resource":"bdtopo-pgr","resourceVersion":"2022-01-24","start":"2.558203,48.741424","end":"2.559756,48.742116","profile":"car","optimization":"fastest","geometry":{"type":"LineString","coordinates":[[2.558203,48.741424],[2.558191,48.741421],[2.55814,48.741427],[2.558098,48.741441],[2.558069,48.741464],[2.558055,48.741493],[2.558056,48.741526],[2.558067,48.741554],[2.558044,48.741581],[2.558028,48.741616],[2.558028,48.741643],[2.558036,48.741677],[2.558055,48.741702],[2.558085,48.741727],[2.558189,48.741785],[2.558339,48.74187],[2.558424,48.741924],[2.558476,48.74197],[2.558509,48.742012],[2.558536,48.742056],[2.558551,48.742101],[2.558553,48.742145],[2.558554,48.742214],[2.558541,48.742295],[2.558534,48.742352],[2.558534,48.742415],[2.558658,48.742411],[2.558744,48.742411],[2.558853,48.742409],[2.558956,48.742411],[2.559256,48.742421],[2.559396,48.742424],[2.559537,48.742427],[2.559794,48.742423],[2.559913,48.742421],[2.560004,48.742414],[2.560105,48.742407],[2.560166,48.742398],[2.560226,48.742391],[2.560308,48.742377],[2.560395,48.74236],[2.560497,48.742335],[2.56059,48.742309],[2.560763,48.742253],[2.560812,48.742228],[2.560862,48.742203],[2.560952,48.742152],[2.561031,48.742097],[2.561104,48.742034],[2.561167,48.741969],[2.561218,48.741912],[2.561259,48.741852],[2.561289,48.741792],[2.561317,48.741737],[2.561348,48.741648],[2.561373,48.741568],[2.561388,48.741491],[2.561403,48.741414],[2.561412,48.741293],[2.561415,48.74122],[2.561419,48.741112],[2.561381,48.741109],[2.56134,48.741101],[2.561306,48.741087],[2.56128,48.741068],[2.561262,48.741048],[2.561247,48.741027],[2.561239,48.741005],[2.561236,48.740984],[2.561182,48.740983],[2.561054,48.740979],[2.560777,48.740973],[2.560673,48.740993],[2.5606,48.741012],[2.56054,48.741029],[2.56048,48.741057],[2.560425,48.741097],[2.560382,48.741132],[2.560356,48.74117],[2.560337,48.741218],[2.56033,48.741253],[2.560335,48.741304],[2.560344,48.741367],[2.560383,48.741534],[2.56039,48.741581],[2.5604,48.741622],[2.560422,48.74172],[2.56043,48.741776],[2.560431,48.741817],[2.560425,48.741851],[2.56041,48.741889],[2.560388,48.741921],[2.560366,48.741949],[2.560332,48.741969],[2.560306,48.741979],[2.560226,48.741992],[2.560106,48.742004],[2.560045,48.742009],[2.559921,48.742019],[2.559836,48.742029],[2.559793,48.742039],[2.559801,48.742063],[2.559794,48.742088],[2.559776,48.742108],[2.559757,48.742117]]},"crs":"EPSG:4326","distanceUnit":"meter","timeUnit":"minute","bbox":[2.558028,48.740973,2.561419,48.742427],"distance":679.6,"duration":1.2133333333333334,"constraints":[],"portions":[{"start":"2.558203,48.741424","end":"2.559756,48.742116","distance":679.6,"duration":1.2133333333333334,"bbox":[2.558028,48.740973,2.561419,48.742427],"steps":[{"geometry":{"type":"LineString","coordinates":[[2.558203,48.741424],[2.558191,48.741421],[2.55814,48.741427]]},"attributes":{"nom_1_gauche":"R DES AUBEPINES","nom_1_droite":"R DES AUBEPINES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":4.8,"duration":0.01,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.558098,48.741441],[2.558069,48.741464],[2.558055,48.741493],[2.558056,48.741526],[2.558067,48.741554]]},"attributes":{"nom_1_gauche":"R DES AUBEPINES","nom_1_droite":"R DES AUBEPINES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":17,"duration":0.03333333333333333,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.558044,48.741581],[2.558028,48.741616],[2.558028,48.741643],[2.558036,48.741677],[2.558055,48.741702],[2.558085,48.741727],[2.558189,48.741785],[2.558339,48.74187],[2.558424,48.741924],[2.558476,48.74197],[2.558509,48.742012],[2.558536,48.742056],[2.558551,48.742101],[2.558553,48.742145],[2.558554,48.742214],[2.558541,48.742295],[2.558534,48.742352],[2.558534,48.742415]]},"attributes":{"nom_1_gauche":"R DES AUBEPINES","nom_1_droite":"R DES AUBEPINES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":111.3,"duration":0.22333333333333333,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.558658,48.742411],[2.558744,48.742411],[2.558853,48.742409],[2.558956,48.742411],[2.559256,48.742421],[2.559396,48.742424],[2.559537,48.742427]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":73.8,"duration":0.11,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.559794,48.742423],[2.559913,48.742421],[2.560004,48.742414]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":34.5,"duration":0.051666666666666666,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560105,48.742407]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":7.5,"duration":0.011666666666666665,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560166,48.742398],[2.560226,48.742391]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":9.1,"duration":0.013333333333333334,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560308,48.742377]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":6.2,"duration":0.01,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560395,48.74236],[2.560497,48.742335],[2.56059,48.742309],[2.560763,48.742253]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":36.3,"duration":0.055,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560812,48.742228],[2.560862,48.742203],[2.560952,48.742152],[2.561031,48.742097],[2.561104,48.742034],[2.561167,48.741969],[2.561218,48.741912],[2.561259,48.741852],[2.561289,48.741792]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":65.4,"duration":0.09833333333333334,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.561317,48.741737],[2.561348,48.741648],[2.561373,48.741568],[2.561388,48.741491],[2.561403,48.741414],[2.561412,48.741293]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":56.5,"duration":0.08499999999999999,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.561415,48.74122],[2.561419,48.741112]]},"attributes":{"nom_1_gauche":"AV DES UZELLES","nom_1_droite":"AV DES UZELLES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":20.1,"duration":0.030000000000000002,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.561381,48.741109],[2.56134,48.741101],[2.561306,48.741087],[2.56128,48.741068],[2.561262,48.741048],[2.561247,48.741027],[2.561239,48.741005],[2.561236,48.740984]]},"attributes":{"nom_1_gauche":"RPT DE LA BUTTE AU BERGER","nom_1_droite":"RPT DE LA BUTTE AU BERGER","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":21.7,"duration":0.051666666666666666,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.561182,48.740983],[2.561054,48.740979],[2.560777,48.740973]]},"attributes":{"nom_1_gauche":"R DES JACHERES","nom_1_droite":"R DES JACHERES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":33.8,"duration":0.06833333333333333,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560673,48.740993],[2.5606,48.741012],[2.56054,48.741029],[2.56048,48.741057]]},"attributes":{"nom_1_gauche":"R DES JACHERES","nom_1_droite":"R DES JACHERES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":24,"duration":0.04833333333333333,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.560425,48.741097],[2.560382,48.741132],[2.560356,48.74117],[2.560337,48.741218],[2.56033,48.741253],[2.560335,48.741304],[2.560344,48.741367],[2.560383,48.741534],[2.56039,48.741581]]},"attributes":{"nom_1_gauche":"R DES JACHERES","nom_1_droite":"R DES JACHERES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":61.8,"duration":0.12333333333333334,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.5604,48.741622],[2.560422,48.74172],[2.56043,48.741776],[2.560431,48.741817],[2.560425,48.741851],[2.56041,48.741889],[2.560388,48.741921],[2.560366,48.741949],[2.560332,48.741969],[2.560306,48.741979],[2.560226,48.741992],[2.560106,48.742004],[2.560045,48.742009]]},"attributes":{"nom_1_gauche":"R DES JACHERES","nom_1_droite":"R DES JACHERES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":67.1,"duration":0.13499999999999998,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.559921,48.742019],[2.559836,48.742029],[2.559793,48.742039]]},"attributes":{"nom_1_gauche":"R DES JACHERES","nom_1_droite":"R DES JACHERES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":18.9,"duration":0.03833333333333333,"instruction":{}},{"geometry":{"type":"LineString","coordinates":[[2.559801,48.742063],[2.559794,48.742088],[2.559776,48.742108],[2.559757,48.742117]]},"attributes":{"nom_1_gauche":"R DES JACHERES","nom_1_droite":"R DES JACHERES","cpx_numero":"","cpx_toponyme_route_nommee":""},"distance":9.8,"duration":0.02,"instruction":{}}]}]}
\ No newline at end of file
diff --git a/test/functional/request/cucumber/features/requestDataTest.feature b/test/functional/request/cucumber/features/requestDataTest.feature
index ce5e133..fee32ef 100644
--- a/test/functional/request/cucumber/features/requestDataTest.feature
+++ b/test/functional/request/cucumber/features/requestDataTest.feature
@@ -36,32 +36,44 @@ Feature: Road2 with data
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "No path found"
- Scenario Outline: [] [simple/1.0.0] Route avec point intermediaire qui provoque un demi-tour (voir ticket #36883)
- Given an "" request on operation "route" in api "simple" "1.0.0"
+ Scenario: [GET] [simple/1.0.0] Route avec point intermediaire qui provoque un demi-tour (voir ticket #36883)
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
| key | value |
- | start | 3.818431,49.081335 |
- | end | 3.847342,49.083691 |
- | intermediates | 3.826778,49.084188\|3.83656,49.083471\|3.844352,49.079101\|3.828451,49.082207 |
+ | start | 2.557207345962524,48.74254989437114 |
+ | end | 2.5614130496978755,48.74151692471051 |
+ | intermediates | 2.558408975601196,48.74189898445621 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the road should be similar to "../../data/2.json"
+
+ Scenario: [POST] [simple/1.0.0] Route avec point intermediaire qui provoque un demi-tour (voir ticket #36883)
+ Given an "POST" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-pgr"
+ And with query parameters:
+ | key | value |
+ | start | 2.557207345962524,48.74254989437114 |
+ | end | 2.5614130496978755,48.74151692471051 |
+ And with table parameters for "intermediates":
+ | value |
+ | 2.558408975601196,48.74189898445621 |
When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
And the road should be similar to "../../data/2.json"
- Examples:
- | method |
- | GET |
- | POST |
Scenario Outline: [] [simple/1.0.0] Route commençant sur une raquette (voir ticket #37674)
Given an "" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
| key | value |
- | start | 3.3378517,43.310043 |
- | end | 3.3390372,43.310542 |
+ | start | 2.558207,48.741417 |
+ | end | 2.559752,48.742114 |
When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
diff --git a/test/unit/mocha/utils/testsStorageManager.js b/test/unit/mocha/utils/testsStorageManager.js
index ba5685b..9db60b0 100644
--- a/test/unit/mocha/utils/testsStorageManager.js
+++ b/test/unit/mocha/utils/testsStorageManager.js
@@ -12,7 +12,7 @@ describe('Test du storageManager', function() {
describe('Test de la fonction checkJsonStorage()', function() {
let json = {
- "file": "/home/docker/internal/corse-latest.osrm"
+ "file": "/home/docker/data/bduni-idf-car-fastest/bduni-idf-car-fastest.osrm"
};
let jsonNoFile = {
From efff1ac90a296dd962e9b29605817c8c10d74c88 Mon Sep 17 00:00:00 2001
From: Loic
Date: Fri, 1 Apr 2022 14:25:47 +0200
Subject: [PATCH 04/93] test: refacto et ajout de tests sur les donnees
---
documentation/apis/simple/1.0.0/api.yaml | 18 --
package.json | 8 +-
.../cucumber/data/bduni/common/boucle.json | 1 +
.../{1.json => bduni/common/normale.json} | 0
.../cucumber/data/bduni/common/point.json | 1 +
.../data/bduni/common/unique-direct.json | 1 +
.../data/bduni/common/unique-inverse.json | 1 +
.../data/{2.json => bduni/pgr/1.json} | 0
.../data/{3.json => bduni/pgr/2.json} | 0
...inTest.feature => req-admin-1.0.0.feature} | 0
.../features/req-data-bduni-osrm.feature | 90 +++++++
...est.feature => req-data-bduni-pgr.feature} | 23 +-
.../features/req-simple-1.0.0-common.feature | 52 ++++
....feature => req-simple-1.0.0-osrm.feature} | 254 ++++++++++++++----
...t.feature => req-simple-1.0.0-pgr.feature} | 197 --------------
.../cucumber/features/support/world.js | 154 +++++++----
16 files changed, 461 insertions(+), 339 deletions(-)
create mode 100644 test/functional/request/cucumber/data/bduni/common/boucle.json
rename test/functional/request/cucumber/data/{1.json => bduni/common/normale.json} (100%)
create mode 100644 test/functional/request/cucumber/data/bduni/common/point.json
create mode 100644 test/functional/request/cucumber/data/bduni/common/unique-direct.json
create mode 100644 test/functional/request/cucumber/data/bduni/common/unique-inverse.json
rename test/functional/request/cucumber/data/{2.json => bduni/pgr/1.json} (100%)
rename test/functional/request/cucumber/data/{3.json => bduni/pgr/2.json} (100%)
rename test/functional/request/cucumber/features/{requestAdminTest.feature => req-admin-1.0.0.feature} (100%)
create mode 100644 test/functional/request/cucumber/features/req-data-bduni-osrm.feature
rename test/functional/request/cucumber/features/{requestDataTest.feature => req-data-bduni-pgr.feature} (87%)
create mode 100644 test/functional/request/cucumber/features/req-simple-1.0.0-common.feature
rename test/functional/request/cucumber/features/{requestTest.feature => req-simple-1.0.0-osrm.feature} (81%)
rename test/functional/request/cucumber/features/{requestComplementTest.feature => req-simple-1.0.0-pgr.feature} (79%)
diff --git a/documentation/apis/simple/1.0.0/api.yaml b/documentation/apis/simple/1.0.0/api.yaml
index ba528f4..24fb6fa 100644
--- a/documentation/apis/simple/1.0.0/api.yaml
+++ b/documentation/apis/simple/1.0.0/api.yaml
@@ -608,12 +608,6 @@ components:
format: "float"
bbox:
type: "string"
- departure:
- type: "string"
- format: "date"
- arrival:
- type: "string"
- format: "date"
resource:
type: "string"
resourceVersion:
@@ -652,12 +646,6 @@ components:
format: "float"
bbox:
type: "string"
- departure:
- type: "string"
- format: "date"
- arrival:
- type: "string"
- format: "date"
steps:
type: "array"
items:
@@ -745,12 +733,6 @@ components:
type: "string"
geometry:
type: "string"
- departure:
- type: "string"
- format: "date"
- arrival:
- type: "string"
- format: "date"
alerts:
type: "array"
items:
diff --git a/package.json b/package.json
index 5f52cd9..213b832 100644
--- a/package.json
+++ b/package.json
@@ -10,12 +10,8 @@
"configCheck": "node ./src/js/road2.js --configCheck",
"utest": "mocha --recursive './test/unit/mocha/**/*.js'",
"itest": "mocha --recursive './test/integration/mocha/**/*.js'",
- "rtest": "HTTP_PROXY='' ./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestTest.feature",
- "crtest": "HTTP_PROXY='' ./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestComplementTest.feature",
- "drtest": "HTTP_PROXY='' ./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestDataTest.feature",
- "artest": "HTTP_PROXY='' ./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/requestAdminTest.feature",
- "ctest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/configuration/cucumber/features/configurationTest.feature",
- "cctest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/configuration/cucumber/features/configurationComplementTest.feature",
+ "rtest": "HTTP_PROXY='' ./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/req*.feature",
+ "ctest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/configuration/cucumber/features/configuration*.feature",
"lint": "eslint -c eslint.json ./src/",
"jsdoc": "jsdoc -c jsdoc.json",
"debug": "node --inspect=0.0.0.0:9229 ./src/js/road2.js"
diff --git a/test/functional/request/cucumber/data/bduni/common/boucle.json b/test/functional/request/cucumber/data/bduni/common/boucle.json
new file mode 100644
index 0000000..e397acc
--- /dev/null
+++ b/test/functional/request/cucumber/data/bduni/common/boucle.json
@@ -0,0 +1 @@
+{"resource":"bduni-idf-osrm","resourceVersion":"2022-01-24","start":"2.276358,48.874805","end":"2.276358,48.874805","profile":"car","optimization":"fastest","geometry":{"coordinates":[[2.276358,48.874805],[2.276375,48.874824],[2.276477,48.874928],[2.27659,48.875039],[2.276766,48.875191],[2.276885,48.875288],[2.277016,48.875386],[2.277332,48.875602],[2.278009,48.876024],[2.278673,48.876429],[2.279096,48.876688],[2.279429,48.876889],[2.279631,48.877032],[2.279784,48.877153],[2.280005,48.877345],[2.280303,48.877632],[2.28042,48.877754],[2.280548,48.877903],[2.280842,48.878287],[2.281187,48.87872],[2.281232,48.87878],[2.281295,48.878874],[2.281402,48.879042],[2.281411,48.879069],[2.281525,48.87929],[2.281605,48.879462],[2.281727,48.879753],[2.281776,48.879879],[2.281825,48.880006],[2.281875,48.880128],[2.281993,48.880409],[2.282105,48.880641],[2.282335,48.88102],[2.28285,48.881737],[2.282976,48.881934],[2.283273,48.882379],[2.283489,48.882622],[2.283756,48.882865],[2.283966,48.883036],[2.284105,48.88314],[2.284243,48.883232],[2.284312,48.883279],[2.284462,48.883378],[2.284622,48.883483],[2.285374,48.884],[2.285497,48.884078],[2.285735,48.884228],[2.286194,48.88449],[2.28621,48.8845],[2.286283,48.884542],[2.286386,48.884607],[2.286483,48.884666],[2.286789,48.884856],[2.288282,48.885779],[2.288482,48.885906],[2.291512,48.887778],[2.291519,48.88778],[2.291821,48.88794],[2.292073,48.888063],[2.29227,48.888148],[2.292586,48.888267],[2.293182,48.888454],[2.293242,48.888471],[2.293391,48.888514],[2.294673,48.88883],[2.294932,48.888897],[2.295799,48.889119],[2.29595,48.889171],[2.296047,48.889204],[2.296524,48.889364],[2.296938,48.889514],[2.297352,48.889671],[2.297596,48.889769],[2.29783,48.889873],[2.298168,48.890025],[2.298538,48.890219],[2.298874,48.890405],[2.299141,48.890552],[2.299423,48.890708],[2.299433,48.890713],[2.299437,48.890715],[2.299474,48.890735],[2.299502,48.890754],[2.29959,48.890815],[2.299904,48.891],[2.300193,48.89118],[2.301175,48.891803],[2.302226,48.892458],[2.302526,48.892636],[2.302728,48.892748],[2.303489,48.893151],[2.303953,48.893422],[2.305199,48.894188],[2.305831,48.894591],[2.30643,48.894945],[2.30654,48.895004],[2.306799,48.895144],[2.30704,48.895261],[2.307251,48.895362],[2.307457,48.895456],[2.307935,48.895648],[2.308562,48.895884],[2.309725,48.896323],[2.31042,48.896584],[2.310511,48.896619],[2.310637,48.896667],[2.310754,48.896711],[2.310921,48.896778],[2.311318,48.896925],[2.312616,48.897413],[2.312695,48.897443],[2.312771,48.897471],[2.313171,48.89762],[2.313288,48.897663],[2.313349,48.897686],[2.313399,48.897704],[2.3135,48.897742],[2.313669,48.897805],[2.314429,48.898085],[2.314628,48.898159],[2.315319,48.898368],[2.31616,48.898622],[2.316335,48.898675],[2.316588,48.898752],[2.317634,48.899068],[2.317956,48.899166],[2.318126,48.899218],[2.318473,48.899322],[2.318788,48.899417],[2.318955,48.899466],[2.319266,48.89956],[2.3195,48.899628],[2.320254,48.899851],[2.321234,48.900141],[2.321749,48.900273],[2.321996,48.900324],[2.322084,48.900339],[2.322218,48.90036],[2.322707,48.90042],[2.323153,48.900456],[2.323487,48.900469],[2.323606,48.900472],[2.324354,48.900488],[2.324701,48.900494],[2.325501,48.90051],[2.326311,48.900529],[2.326809,48.900538],[2.327929,48.900562],[2.328804,48.900578],[2.329538,48.900593],[2.329656,48.900596],[2.329813,48.9006],[2.329992,48.900604],[2.330454,48.900615],[2.331245,48.90063],[2.33256,48.900657],[2.333407,48.900674],[2.333835,48.900682],[2.334262,48.900691],[2.334723,48.900702],[2.334922,48.900705],[2.335799,48.900725],[2.336386,48.900737],[2.338163,48.900773],[2.339749,48.900803],[2.340347,48.900818],[2.340719,48.900825],[2.34081,48.900828],[2.341157,48.900835],[2.342546,48.900864],[2.343506,48.900884],[2.344754,48.900911],[2.345508,48.900926],[2.346254,48.900942],[2.346991,48.900958],[2.347523,48.900969],[2.347727,48.900973],[2.348652,48.900992],[2.349821,48.901013],[2.350997,48.90104],[2.351402,48.90105],[2.351786,48.901058],[2.352035,48.901064],[2.352416,48.901071],[2.352583,48.901072],[2.352698,48.901071],[2.352946,48.901068],[2.353087,48.901066],[2.35326,48.901063],[2.353412,48.901057],[2.353608,48.90105],[2.353776,48.901041],[2.353889,48.901035],[2.354008,48.901027],[2.354161,48.901016],[2.354576,48.900986],[2.354724,48.900976],[2.354844,48.900968],[2.354976,48.90096],[2.355259,48.90094],[2.355439,48.900927],[2.355716,48.900908],[2.355982,48.900887],[2.356238,48.900867],[2.356515,48.900846],[2.356726,48.900831],[2.356926,48.90082],[2.357152,48.900808],[2.35733,48.9008],[2.357585,48.90079],[2.35787,48.900785],[2.358203,48.900781],[2.358491,48.900779],[2.359129,48.900772],[2.359338,48.90077],[2.359878,48.900761],[2.36017,48.900758],[2.361686,48.900743],[2.36241,48.900733],[2.362745,48.900725],[2.36328,48.900722],[2.363907,48.900709],[2.364585,48.900699],[2.364961,48.900673],[2.365082,48.900668],[2.365611,48.900663],[2.365891,48.90066],[2.366295,48.900666],[2.366524,48.900683],[2.367089,48.900677],[2.367712,48.900673],[2.368821,48.900661],[2.370117,48.900646],[2.370341,48.900644],[2.371803,48.900626],[2.372022,48.90062],[2.37222,48.900612],[2.372504,48.900596],[2.372788,48.900575],[2.373259,48.900532],[2.374532,48.90041],[2.375668,48.900301],[2.376187,48.900253],[2.376361,48.900238],[2.376797,48.900202],[2.377193,48.900183],[2.377382,48.900177],[2.377582,48.900171],[2.377861,48.900168],[2.379157,48.900179],[2.379801,48.900187],[2.380034,48.900189],[2.38024,48.90019],[2.380462,48.900194],[2.380891,48.900197],[2.381042,48.900199],[2.381307,48.900201],[2.381457,48.900205],[2.381668,48.900207],[2.381912,48.900212],[2.382279,48.900226],[2.382637,48.900241],[2.383761,48.900301],[2.383927,48.900311],[2.384186,48.900327],[2.384583,48.900347],[2.384814,48.90036],[2.385027,48.900371],[2.385288,48.900386],[2.385556,48.900402],[2.38666,48.900458],[2.387187,48.900471],[2.387938,48.900468],[2.388398,48.900452],[2.388528,48.900445],[2.388801,48.900428],[2.388962,48.900418],[2.389202,48.900397],[2.389463,48.90037],[2.389716,48.900337],[2.389921,48.900308],[2.390182,48.900262],[2.390436,48.900212],[2.390621,48.900165],[2.390836,48.90011],[2.391141,48.900021],[2.391442,48.899912],[2.391658,48.899822],[2.391807,48.899754],[2.391965,48.899673],[2.392127,48.899585],[2.392249,48.899512],[2.392437,48.899392],[2.392867,48.899064],[2.392922,48.899019],[2.393087,48.898862],[2.393197,48.898738],[2.39331,48.898592],[2.393375,48.898506],[2.393435,48.898423],[2.39349,48.89833],[2.393535,48.898253],[2.393587,48.89816],[2.393616,48.898109],[2.393652,48.898038],[2.393797,48.89767],[2.393835,48.897561],[2.393862,48.897478],[2.393897,48.897367],[2.39404,48.896913],[2.394145,48.896571],[2.394271,48.896169],[2.394334,48.895967],[2.394542,48.895303],[2.394614,48.895078],[2.394657,48.894932],[2.394702,48.894743],[2.394876,48.894151],[2.395207,48.892952],[2.39525,48.892796],[2.395314,48.892569],[2.395353,48.892436],[2.39538,48.892328],[2.395445,48.892093],[2.395475,48.891971],[2.395606,48.891515],[2.395666,48.891297],[2.395784,48.890884],[2.395886,48.890523],[2.39593,48.890356],[2.395987,48.890157],[2.396026,48.89002],[2.396216,48.889343],[2.396268,48.88916],[2.39634,48.888901],[2.396407,48.888668],[2.396542,48.888203],[2.396791,48.887311],[2.396957,48.886704],[2.397,48.886577],[2.397035,48.88646],[2.397121,48.886236],[2.397134,48.886201],[2.397165,48.886126],[2.397169,48.886116],[2.397186,48.886076],[2.397211,48.886017],[2.397239,48.885954],[2.397267,48.885893],[2.397361,48.885743],[2.397493,48.88553],[2.397568,48.885416],[2.397572,48.885411],[2.397856,48.885048],[2.3982,48.884679],[2.398452,48.884437],[2.398704,48.884223],[2.398993,48.883996],[2.399132,48.883887],[2.400334,48.88291],[2.400377,48.882876],[2.400437,48.882827],[2.400839,48.88251],[2.401151,48.882264],[2.401876,48.881723],[2.401989,48.881659],[2.402255,48.881514],[2.402391,48.881446],[2.402657,48.881323],[2.402973,48.881197],[2.403259,48.881096],[2.403627,48.880988],[2.404029,48.880881],[2.404386,48.880789],[2.404887,48.880646],[2.405281,48.880534],[2.405579,48.880433],[2.405884,48.880314],[2.406192,48.880188],[2.406488,48.880045],[2.406747,48.879904],[2.406995,48.879734],[2.407217,48.879565],[2.407472,48.879354],[2.407708,48.879135],[2.407833,48.878993],[2.407962,48.878833],[2.408108,48.878628],[2.408613,48.877783],[2.4087,48.877647],[2.408844,48.877415],[2.408998,48.877156],[2.409142,48.876903],[2.409355,48.876522],[2.409575,48.876174],[2.409724,48.875938],[2.409856,48.875708],[2.40992,48.875605],[2.409981,48.875513],[2.410057,48.875393],[2.410192,48.875192],[2.410264,48.875101],[2.410676,48.874603],[2.410922,48.874309],[2.41113,48.874072],[2.41145,48.873713],[2.411788,48.873307],[2.412022,48.873009],[2.412247,48.872718],[2.412431,48.872474],[2.412591,48.872236],[2.412727,48.871998],[2.412855,48.871771],[2.412933,48.871598],[2.413002,48.871424],[2.413068,48.871219],[2.413129,48.871],[2.413177,48.870783],[2.413222,48.870535],[2.413249,48.870277],[2.413255,48.870096],[2.413251,48.869494],[2.413247,48.869154],[2.41324,48.868837],[2.413237,48.868553],[2.413235,48.868322],[2.413217,48.867349],[2.413216,48.867179],[2.413204,48.866639],[2.413196,48.866153],[2.413192,48.865816],[2.41319,48.865646],[2.413191,48.865416],[2.413201,48.865129],[2.413212,48.864882],[2.413248,48.864475],[2.413275,48.864257],[2.413349,48.863769],[2.413394,48.863481],[2.413453,48.863109],[2.413527,48.862657],[2.413541,48.862566],[2.413757,48.86123],[2.413806,48.860938],[2.413825,48.86082],[2.413901,48.860344],[2.414005,48.859689],[2.414098,48.85891],[2.414107,48.858463],[2.414102,48.858357],[2.414058,48.857807],[2.413942,48.856712],[2.413917,48.856465],[2.413894,48.856234],[2.413728,48.856099],[2.413657,48.855853],[2.413637,48.855785],[2.413554,48.855404],[2.413465,48.854779],[2.413454,48.854686],[2.413414,48.85457],[2.41332,48.854534],[2.413227,48.854486],[2.413125,48.854421],[2.413056,48.85436],[2.412996,48.854266],[2.412966,48.854148],[2.412968,48.85403],[2.413002,48.853911],[2.413045,48.853831],[2.413104,48.853755],[2.413196,48.853678],[2.413295,48.853625],[2.413431,48.853572],[2.413581,48.853535],[2.413659,48.853518],[2.413773,48.853505],[2.413891,48.853503],[2.413938,48.853508],[2.414068,48.853528],[2.414193,48.853557],[2.414301,48.853592],[2.414387,48.853627],[2.414463,48.85367],[2.414515,48.853715],[2.414562,48.853769],[2.414607,48.85383],[2.414664,48.853934],[2.41468,48.854045],[2.414644,48.854219],[2.414827,48.854252],[2.415051,48.854292],[2.415301,48.854333],[2.415303,48.854181],[2.415316,48.854132],[2.41537,48.853941],[2.41544,48.853559],[2.415461,48.853438],[2.41549,48.853284],[2.415512,48.853136],[2.415546,48.852928],[2.415576,48.85273],[2.415611,48.852522],[2.415654,48.852303],[2.41569,48.852111],[2.415738,48.851857],[2.415786,48.851571],[2.415843,48.851245],[2.415892,48.85099],[2.416038,48.850121],[2.416138,48.84958],[2.41615,48.849515],[2.416193,48.849311],[2.416205,48.849264],[2.416341,48.849234],[2.416456,48.849239],[2.416695,48.849247],[2.417537,48.849284],[2.417644,48.849309],[2.417666,48.849106],[2.417672,48.848878],[2.417658,48.848204],[2.417638,48.847609],[2.417621,48.847135],[2.417613,48.846795],[2.417548,48.846708],[2.417515,48.846656],[2.417488,48.846611],[2.417463,48.846558],[2.41703,48.846601],[2.416487,48.846657],[2.415984,48.846695],[2.415876,48.846703],[2.415579,48.846718],[2.415407,48.846732],[2.415317,48.846748],[2.415191,48.846788],[2.415173,48.846822],[2.41515,48.846855],[2.415119,48.846886],[2.415085,48.846912],[2.415035,48.846945],[2.414955,48.846986],[2.414886,48.84701],[2.414871,48.847016],[2.414766,48.847041],[2.414698,48.847054],[2.414647,48.847065],[2.414509,48.847082],[2.414466,48.847084],[2.41437,48.847086],[2.414313,48.847084],[2.414222,48.847079],[2.414135,48.847055],[2.414068,48.847033],[2.41401,48.847002],[2.413932,48.846954],[2.413875,48.846892],[2.413846,48.846844],[2.413831,48.846808],[2.413826,48.846767],[2.413828,48.846703],[2.413837,48.846678],[2.413852,48.846649],[2.413878,48.84662],[2.413899,48.846597],[2.413927,48.846505],[2.413948,48.846432],[2.413946,48.846359],[2.413944,48.846212],[2.413913,48.845791],[2.413883,48.845437],[2.413872,48.845339],[2.413818,48.844854],[2.413805,48.844646],[2.413823,48.844497],[2.413888,48.844319],[2.413772,48.843733],[2.413728,48.843378],[2.413689,48.842958],[2.413644,48.842399],[2.413591,48.841949],[2.413538,48.841324],[2.41353,48.841221],[2.413518,48.841103],[2.413485,48.840716],[2.413397,48.840249],[2.41327,48.839717],[2.413155,48.839322],[2.412712,48.837848],[2.412689,48.837778],[2.412558,48.837402],[2.412405,48.836955],[2.412346,48.836759],[2.412264,48.836524],[2.412154,48.83626],[2.412062,48.836069],[2.412054,48.836052],[2.411979,48.835919],[2.411862,48.835716],[2.41159,48.835392],[2.411407,48.835215],[2.411195,48.835031],[2.410971,48.834865],[2.410738,48.834707],[2.410336,48.834484],[2.407818,48.833547],[2.407161,48.833284],[2.406761,48.833093],[2.406444,48.832921],[2.405585,48.832424],[2.403557,48.831274],[2.403116,48.831011],[2.402789,48.830802],[2.402264,48.830454],[2.401597,48.829992],[2.400881,48.829523],[2.400482,48.829315],[2.399929,48.829095],[2.399509,48.828973],[2.399047,48.828858],[2.398973,48.82884],[2.398666,48.828772],[2.398606,48.828758],[2.398496,48.828734],[2.398392,48.828711],[2.398269,48.828682],[2.398156,48.828657],[2.398041,48.828631],[2.397993,48.828619],[2.397905,48.8286],[2.397842,48.828585],[2.397735,48.828561],[2.397504,48.828508],[2.397318,48.828466],[2.397151,48.828428],[2.396988,48.828391],[2.396819,48.828353],[2.396732,48.828333],[2.396641,48.828311],[2.396561,48.828293],[2.396471,48.828273],[2.396329,48.828241],[2.396209,48.828212],[2.396088,48.828184],[2.395923,48.828148],[2.395849,48.82813],[2.395762,48.82811],[2.395601,48.828074],[2.395537,48.828061],[2.395345,48.828022],[2.395302,48.828014],[2.395032,48.827967],[2.394724,48.827922],[2.394633,48.827911],[2.394395,48.827883],[2.393827,48.827816],[2.393325,48.827757],[2.393191,48.82774],[2.393029,48.82772],[2.392921,48.827708],[2.392795,48.827692],[2.3927,48.827682],[2.392585,48.827668],[2.392466,48.827652],[2.392338,48.827629],[2.392233,48.827612],[2.392119,48.827592],[2.391964,48.827564],[2.391794,48.827524],[2.391619,48.827481],[2.391425,48.827431],[2.391199,48.827371],[2.390958,48.827298],[2.390753,48.827229],[2.390586,48.827173],[2.390467,48.827131],[2.390334,48.827086],[2.390206,48.827042],[2.390051,48.826988],[2.38997,48.826962],[2.389928,48.826947],[2.389878,48.826932],[2.389802,48.82691],[2.389662,48.826867],[2.389409,48.82679],[2.388766,48.826572],[2.388407,48.82645],[2.38826,48.826396],[2.38814,48.826353],[2.387619,48.826164],[2.387259,48.82604],[2.386911,48.825914],[2.386329,48.825715],[2.385977,48.825599],[2.385652,48.825478],[2.38553,48.825433],[2.385187,48.825288],[2.384936,48.82517],[2.384745,48.825084],[2.384645,48.825035],[2.384079,48.824744],[2.383898,48.824636],[2.383593,48.824457],[2.383238,48.824247],[2.383006,48.824107],[2.38285,48.824013],[2.382547,48.82383],[2.382407,48.823747],[2.382191,48.823617],[2.381742,48.823348],[2.38144,48.82317],[2.381124,48.822979],[2.380803,48.822788],[2.3806,48.822666],[2.380366,48.822526],[2.380128,48.822383],[2.379803,48.822189],[2.37952,48.82202],[2.379316,48.821897],[2.379161,48.821806],[2.378941,48.821681],[2.378784,48.821602],[2.378689,48.821554],[2.378394,48.821418],[2.378134,48.821315],[2.377899,48.821227],[2.377479,48.821071],[2.376993,48.820912],[2.376639,48.820796],[2.376082,48.820622],[2.37545,48.820418],[2.3744,48.820074],[2.373528,48.819784],[2.37279,48.819542],[2.372131,48.819325],[2.371375,48.819076],[2.371196,48.819017],[2.370556,48.818809],[2.370503,48.818792],[2.370092,48.818658],[2.370065,48.81865],[2.36967,48.818522],[2.369162,48.818354],[2.368644,48.818185],[2.368019,48.817978],[2.367392,48.81777],[2.366903,48.817604],[2.366375,48.817427],[2.365957,48.817272],[2.3657,48.817166],[2.365391,48.817036],[2.365033,48.816878],[2.364681,48.816717],[2.364464,48.81662],[2.364347,48.816567],[2.364073,48.816453],[2.363893,48.816379],[2.363716,48.816318],[2.363476,48.816259],[2.363295,48.816219],[2.363097,48.816187],[2.362909,48.816159],[2.362752,48.816144],[2.362455,48.816121],[2.361998,48.81611],[2.36135,48.816142],[2.360513,48.816197],[2.359615,48.816261],[2.358972,48.816306],[2.358403,48.81634],[2.357982,48.816359],[2.357687,48.816379],[2.357531,48.81639],[2.357128,48.816433],[2.35689,48.816466],[2.356625,48.816524],[2.356465,48.816563],[2.356278,48.816626],[2.356171,48.816662],[2.356061,48.816702],[2.355917,48.816754],[2.355694,48.816862],[2.355498,48.816961],[2.355481,48.816969],[2.355347,48.817047],[2.355122,48.81717],[2.354727,48.817401],[2.354294,48.817621],[2.354051,48.817728],[2.354038,48.817733],[2.353661,48.817836],[2.353324,48.817919],[2.353166,48.81795],[2.353042,48.817965],[2.352841,48.817993],[2.352653,48.818013],[2.352447,48.818023],[2.352133,48.818024],[2.351862,48.818016],[2.351557,48.817988],[2.351254,48.817962],[2.350977,48.817915],[2.350701,48.817857],[2.350401,48.817787],[2.350146,48.817718],[2.349869,48.817636],[2.349633,48.817554],[2.349307,48.81744],[2.348986,48.81731],[2.348672,48.817181],[2.348511,48.817108],[2.348438,48.817073],[2.348383,48.817047],[2.348214,48.816969],[2.347954,48.816866],[2.347816,48.816811],[2.347703,48.816765],[2.347503,48.816691],[2.347341,48.816638],[2.346982,48.816537],[2.346709,48.81648],[2.346404,48.816438],[2.346227,48.816424],[2.345991,48.816495],[2.345548,48.816523],[2.345225,48.816546],[2.344809,48.816566],[2.344701,48.816579],[2.34461,48.816597],[2.344525,48.816624],[2.344424,48.816671],[2.344311,48.816745],[2.344223,48.816805],[2.344177,48.816819],[2.344124,48.816822],[2.344076,48.816818],[2.344024,48.81681],[2.343978,48.816795],[2.343973,48.816685],[2.343968,48.816605],[2.343956,48.816306],[2.343946,48.81621],[2.343941,48.816158],[2.34393,48.816104],[2.343919,48.816048],[2.343909,48.815999],[2.343919,48.81595],[2.343929,48.815925],[2.343866,48.815897],[2.343811,48.815882],[2.343775,48.815877],[2.343724,48.815872],[2.343685,48.815875],[2.343646,48.815879],[2.343582,48.815891],[2.34343,48.815944],[2.343296,48.815992],[2.343157,48.816045],[2.343013,48.816085],[2.342877,48.816112],[2.342187,48.81624],[2.341801,48.816308],[2.341658,48.816322],[2.34103,48.81636],[2.340512,48.816372],[2.34032,48.816386],[2.339543,48.816436],[2.338645,48.816485],[2.338007,48.816515],[2.33751,48.816546],[2.337275,48.816558],[2.336674,48.816592],[2.336332,48.816611],[2.336103,48.816624],[2.335581,48.816655],[2.335146,48.816682],[2.334935,48.816694],[2.333711,48.816771],[2.332145,48.816982],[2.331996,48.817001],[2.331898,48.817011],[2.331773,48.817026],[2.331642,48.817038],[2.331433,48.817061],[2.330791,48.817132],[2.330155,48.817182],[2.329947,48.817192],[2.328821,48.817283],[2.328496,48.817306],[2.328341,48.817309],[2.32818,48.817308],[2.327906,48.817285],[2.326756,48.817399],[2.325667,48.817501],[2.325647,48.817662],[2.325654,48.817827],[2.325665,48.818221],[2.325682,48.818822],[2.325709,48.819386],[2.325739,48.819612],[2.325748,48.81972],[2.325759,48.819798],[2.326214,48.819708],[2.326682,48.819571],[2.326787,48.819543],[2.327213,48.819445],[2.328492,48.819159],[2.328617,48.819131],[2.329311,48.818978],[2.329301,48.81895],[2.329165,48.818481],[2.329109,48.818308],[2.328855,48.817409],[2.328821,48.817283],[2.328496,48.817306],[2.328341,48.817309],[2.32818,48.817308],[2.327906,48.817285],[2.326756,48.817399],[2.325667,48.817501],[2.325647,48.817662],[2.325654,48.817827],[2.325665,48.818221],[2.325682,48.818822],[2.325709,48.819386],[2.325739,48.819612],[2.325748,48.81972],[2.325759,48.819798],[2.325764,48.819897],[2.325732,48.820159],[2.325739,48.820252],[2.325606,48.820298],[2.3255,48.820341],[2.325425,48.820376],[2.324625,48.820558],[2.324213,48.820559],[2.324063,48.820583],[2.32304,48.820803],[2.322535,48.820898],[2.322348,48.820929],[2.322132,48.82095],[2.321882,48.820961],[2.321592,48.820955],[2.320486,48.821176],[2.319356,48.821429],[2.318717,48.821568],[2.316763,48.822014],[2.316574,48.82207],[2.315929,48.822258],[2.315623,48.822338],[2.31524,48.822423],[2.31409,48.822684],[2.312227,48.823099],[2.311364,48.823291],[2.310272,48.823537],[2.308081,48.82402],[2.307599,48.824127],[2.304842,48.824742],[2.304372,48.82485],[2.301721,48.82546],[2.29952,48.825923],[2.298956,48.826049],[2.298438,48.826164],[2.296875,48.826518],[2.296547,48.826588],[2.29558,48.8268],[2.294579,48.82703],[2.29399,48.827159],[2.293614,48.827237],[2.293121,48.827358],[2.292475,48.827532],[2.291797,48.827741],[2.291232,48.827941],[2.290752,48.82813],[2.290645,48.828178],[2.290401,48.828282],[2.290015,48.828459],[2.288973,48.828931],[2.288394,48.829182],[2.287685,48.8295],[2.286752,48.82992],[2.285798,48.830338],[2.2849,48.830715],[2.284032,48.831075],[2.283048,48.831473],[2.281608,48.832068],[2.280687,48.83244],[2.279812,48.832798],[2.279223,48.833043],[2.278582,48.833298],[2.277536,48.833724],[2.277457,48.833757],[2.277128,48.833891],[2.276843,48.834007],[2.276681,48.834072],[2.276542,48.834129],[2.275811,48.834425],[2.275496,48.83454],[2.275331,48.834599],[2.275272,48.834617],[2.27505,48.834687],[2.2748,48.834761],[2.274514,48.834842],[2.274295,48.834899],[2.274187,48.834922],[2.273996,48.834968],[2.273706,48.835035],[2.273385,48.835103],[2.273089,48.835165],[2.272665,48.835244],[2.272454,48.835278],[2.272378,48.835288],[2.272108,48.835325],[2.271826,48.835358],[2.271582,48.835377],[2.271344,48.835388],[2.271042,48.8354],[2.270637,48.835402],[2.270374,48.835395],[2.270174,48.835385],[2.269966,48.83537],[2.269826,48.835358],[2.269615,48.835333],[2.269463,48.835314],[2.267892,48.835081],[2.267539,48.835027],[2.267302,48.834994],[2.267132,48.834968],[2.266962,48.834949],[2.266742,48.834931],[2.266399,48.83491],[2.26614,48.8349],[2.265899,48.834897],[2.265662,48.834901],[2.265332,48.834916],[2.26505,48.834933],[2.263967,48.835],[2.261195,48.835157],[2.261139,48.83516],[2.260977,48.83517],[2.260546,48.835197],[2.260157,48.835237],[2.259959,48.835263],[2.259621,48.835317],[2.259388,48.835359],[2.259162,48.8354],[2.259006,48.83544],[2.258741,48.835511],[2.258422,48.835603],[2.258148,48.835692],[2.257899,48.835778],[2.257597,48.835902],[2.257381,48.836],[2.257223,48.836072],[2.257164,48.836104],[2.257147,48.836112],[2.257098,48.836138],[2.256946,48.83622],[2.256786,48.836305],[2.256344,48.836546],[2.25586,48.836875],[2.255626,48.837061],[2.255502,48.837168],[2.255381,48.837279],[2.255282,48.837373],[2.255164,48.837497],[2.255012,48.837671],[2.254929,48.83777],[2.254865,48.837849],[2.254766,48.837986],[2.254594,48.838234],[2.25451,48.838377],[2.254439,48.838524],[2.254359,48.838736],[2.254322,48.838856],[2.254243,48.839141],[2.254202,48.839347],[2.254162,48.839587],[2.254111,48.839893],[2.254095,48.840042],[2.254089,48.840367],[2.254115,48.840634],[2.254196,48.841089],[2.254294,48.841654],[2.254443,48.8425],[2.25453,48.843011],[2.254601,48.843273],[2.254705,48.843652],[2.254996,48.844689],[2.255041,48.844872],[2.25508,48.845097],[2.255125,48.845517],[2.255114,48.84572],[2.255103,48.845806],[2.255069,48.845987],[2.255034,48.846152],[2.254996,48.846301],[2.254945,48.84645],[2.254832,48.846722],[2.254666,48.847012],[2.254617,48.847081],[2.254558,48.847164],[2.254444,48.847316],[2.254277,48.847502],[2.254119,48.847653],[2.253895,48.847863],[2.25354,48.848177],[2.253125,48.848603],[2.252935,48.848846],[2.252677,48.849234],[2.252516,48.849538],[2.252419,48.849746],[2.252351,48.849947],[2.252296,48.850136],[2.252231,48.850441],[2.252214,48.850682],[2.252211,48.850967],[2.252228,48.85119],[2.252289,48.851621],[2.252328,48.851812],[2.252354,48.85193],[2.252375,48.851991],[2.252426,48.852106],[2.252471,48.852203],[2.252583,48.852397],[2.252649,48.852511],[2.252801,48.852748],[2.252894,48.852877],[2.25299,48.853004],[2.253253,48.853276],[2.253326,48.853344],[2.253627,48.853608],[2.25387,48.853809],[2.253975,48.853887],[2.254075,48.853962],[2.254201,48.85406],[2.254243,48.854088],[2.254865,48.854511],[2.255578,48.855011],[2.256824,48.855854],[2.2575,48.856298],[2.258365,48.856901],[2.259231,48.857461],[2.259504,48.857616],[2.259818,48.857782],[2.260034,48.857893],[2.260244,48.857992],[2.260644,48.858164],[2.260979,48.858306],[2.261367,48.858477],[2.261783,48.858677],[2.262025,48.858806],[2.262214,48.85892],[2.262414,48.859051],[2.262565,48.85916],[2.262741,48.859297],[2.262986,48.859513],[2.263149,48.859687],[2.263252,48.859787],[2.263362,48.859906],[2.263441,48.86001],[2.2635,48.860088],[2.263638,48.860301],[2.263694,48.860395],[2.263757,48.860494],[2.263835,48.860633],[2.26396,48.86085],[2.264194,48.861267],[2.264305,48.861452],[2.264676,48.862075],[2.264804,48.862286],[2.265001,48.862561],[2.265203,48.862816],[2.265376,48.863016],[2.265784,48.863383],[2.266052,48.863609],[2.2666,48.864023],[2.267077,48.864383],[2.267251,48.864546],[2.267521,48.864809],[2.267675,48.864973],[2.267874,48.865197],[2.268028,48.865385],[2.268175,48.86558],[2.268249,48.865681],[2.268334,48.865807],[2.268498,48.866059],[2.268689,48.866351],[2.268811,48.866539],[2.268949,48.866755],[2.269079,48.866955],[2.269253,48.867206],[2.269453,48.867482],[2.26965,48.867732],[2.269844,48.867992],[2.270022,48.868211],[2.270565,48.868765],[2.271253,48.869398],[2.271342,48.869471],[2.271532,48.86964],[2.271985,48.870027],[2.272335,48.87032],[2.272646,48.870586],[2.272953,48.870882],[2.273484,48.871388],[2.273666,48.871563],[2.273833,48.871737],[2.273989,48.871937],[2.274135,48.872154],[2.274314,48.872405],[2.274552,48.872716],[2.27488,48.873106],[2.275289,48.87358],[2.275799,48.874167],[2.276083,48.874497],[2.276239,48.874676],[2.276358,48.874805]],"type":"LineString"},"crs":"EPSG:4326","distanceUnit":"meter","timeUnit":"minute","bbox":[2.252211,48.815872,2.417672,48.901072],"distance":36965.5,"duration":25.944999999999997,"constraints":[],"portions":[{"start":"2.276358,48.874805","end":"2.416138,48.84958","distance":16046.7,"duration":10.25,"bbox":[2.276358,48.84958,2.416138,48.901072],"steps":[{"geometry":{"coordinates":[[2.276358,48.874805],[2.276375,48.874824],[2.276477,48.874928],[2.27659,48.875039],[2.276766,48.875191],[2.276885,48.875288],[2.277016,48.875386],[2.277332,48.875602],[2.278009,48.876024],[2.278673,48.876429],[2.279096,48.876688],[2.279429,48.876889],[2.279631,48.877032],[2.279784,48.877153],[2.280005,48.877345],[2.280303,48.877632],[2.28042,48.877754],[2.280548,48.877903],[2.280842,48.878287],[2.281187,48.87872],[2.281232,48.87878],[2.281295,48.878874],[2.281402,48.879042],[2.281411,48.879069],[2.281525,48.87929],[2.281605,48.879462],[2.281727,48.879753],[2.281776,48.879879],[2.281825,48.880006],[2.281875,48.880128],[2.281993,48.880409],[2.282105,48.880641],[2.282335,48.88102],[2.28285,48.881737],[2.282976,48.881934],[2.283273,48.882379],[2.283489,48.882622],[2.283756,48.882865],[2.283966,48.883036],[2.284105,48.88314],[2.284243,48.883232],[2.284312,48.883279],[2.284462,48.883378],[2.284622,48.883483],[2.285374,48.884],[2.285497,48.884078],[2.285735,48.884228],[2.286194,48.88449],[2.28621,48.8845],[2.286283,48.884542],[2.286386,48.884607],[2.286483,48.884666],[2.286789,48.884856],[2.288282,48.885779],[2.288482,48.885906],[2.291512,48.887778],[2.291519,48.88778],[2.291821,48.88794],[2.292073,48.888063],[2.29227,48.888148],[2.292586,48.888267],[2.293182,48.888454],[2.293242,48.888471],[2.293391,48.888514],[2.294673,48.88883],[2.294932,48.888897],[2.295799,48.889119],[2.29595,48.889171],[2.296047,48.889204],[2.296524,48.889364],[2.296938,48.889514],[2.297352,48.889671],[2.297596,48.889769],[2.29783,48.889873],[2.298168,48.890025],[2.298538,48.890219],[2.298874,48.890405],[2.299141,48.890552],[2.299423,48.890708],[2.299433,48.890713],[2.299437,48.890715],[2.299474,48.890735],[2.299502,48.890754],[2.29959,48.890815],[2.299904,48.891],[2.300193,48.89118],[2.301175,48.891803],[2.302226,48.892458],[2.302526,48.892636],[2.302728,48.892748],[2.303489,48.893151],[2.303953,48.893422],[2.305199,48.894188],[2.305831,48.894591],[2.30643,48.894945],[2.30654,48.895004],[2.306799,48.895144],[2.30704,48.895261],[2.307251,48.895362],[2.307457,48.895456],[2.307935,48.895648],[2.308562,48.895884],[2.309725,48.896323],[2.31042,48.896584],[2.310511,48.896619],[2.310637,48.896667],[2.310754,48.896711],[2.310921,48.896778],[2.311318,48.896925],[2.312616,48.897413],[2.312695,48.897443],[2.312771,48.897471],[2.313171,48.89762],[2.313288,48.897663],[2.313349,48.897686],[2.313399,48.897704],[2.3135,48.897742],[2.313669,48.897805],[2.314429,48.898085],[2.314628,48.898159],[2.315319,48.898368],[2.31616,48.898622],[2.316335,48.898675],[2.316588,48.898752],[2.317634,48.899068],[2.317956,48.899166],[2.318126,48.899218],[2.318473,48.899322],[2.318788,48.899417],[2.318955,48.899466],[2.319266,48.89956],[2.3195,48.899628],[2.320254,48.899851],[2.321234,48.900141],[2.321749,48.900273],[2.321996,48.900324],[2.322084,48.900339],[2.322218,48.90036],[2.322707,48.90042],[2.323153,48.900456],[2.323487,48.900469],[2.323606,48.900472],[2.324354,48.900488],[2.324701,48.900494],[2.325501,48.90051],[2.326311,48.900529],[2.326809,48.900538],[2.327929,48.900562],[2.328804,48.900578],[2.329538,48.900593],[2.329656,48.900596],[2.329813,48.9006],[2.329992,48.900604],[2.330454,48.900615],[2.331245,48.90063],[2.33256,48.900657],[2.333407,48.900674],[2.333835,48.900682],[2.334262,48.900691],[2.334723,48.900702],[2.334922,48.900705],[2.335799,48.900725],[2.336386,48.900737],[2.338163,48.900773],[2.339749,48.900803],[2.340347,48.900818],[2.340719,48.900825],[2.34081,48.900828],[2.341157,48.900835],[2.342546,48.900864],[2.343506,48.900884],[2.344754,48.900911],[2.345508,48.900926],[2.346254,48.900942],[2.346991,48.900958],[2.347523,48.900969],[2.347727,48.900973],[2.348652,48.900992],[2.349821,48.901013],[2.350997,48.90104],[2.351402,48.90105],[2.351786,48.901058],[2.352035,48.901064],[2.352416,48.901071],[2.352583,48.901072],[2.352698,48.901071],[2.352946,48.901068],[2.353087,48.901066],[2.35326,48.901063],[2.353412,48.901057],[2.353608,48.90105],[2.353776,48.901041],[2.353889,48.901035],[2.354008,48.901027],[2.354161,48.901016],[2.354576,48.900986],[2.354724,48.900976],[2.354844,48.900968],[2.354976,48.90096],[2.355259,48.90094],[2.355439,48.900927],[2.355716,48.900908],[2.355982,48.900887],[2.356238,48.900867],[2.356515,48.900846],[2.356726,48.900831],[2.356926,48.90082],[2.357152,48.900808],[2.35733,48.9008],[2.357585,48.90079],[2.35787,48.900785],[2.358203,48.900781],[2.358491,48.900779],[2.359129,48.900772],[2.359338,48.90077],[2.359878,48.900761],[2.36017,48.900758],[2.361686,48.900743],[2.36241,48.900733],[2.362745,48.900725],[2.36328,48.900722],[2.363907,48.900709],[2.364585,48.900699],[2.364961,48.900673],[2.365082,48.900668],[2.365611,48.900663],[2.365891,48.90066],[2.366295,48.900666],[2.366524,48.900683],[2.367089,48.900677],[2.367712,48.900673],[2.368821,48.900661],[2.370117,48.900646],[2.370341,48.900644],[2.371803,48.900626],[2.372022,48.90062],[2.37222,48.900612],[2.372504,48.900596],[2.372788,48.900575],[2.373259,48.900532],[2.374532,48.90041],[2.375668,48.900301],[2.376187,48.900253],[2.376361,48.900238],[2.376797,48.900202],[2.377193,48.900183],[2.377382,48.900177],[2.377582,48.900171],[2.377861,48.900168],[2.379157,48.900179],[2.379801,48.900187],[2.380034,48.900189],[2.38024,48.90019],[2.380462,48.900194],[2.380891,48.900197],[2.381042,48.900199],[2.381307,48.900201],[2.381457,48.900205],[2.381668,48.900207],[2.381912,48.900212],[2.382279,48.900226],[2.382637,48.900241],[2.383761,48.900301],[2.383927,48.900311],[2.384186,48.900327],[2.384583,48.900347],[2.384814,48.90036],[2.385027,48.900371],[2.385288,48.900386],[2.385556,48.900402],[2.38666,48.900458],[2.387187,48.900471],[2.387938,48.900468],[2.388398,48.900452],[2.388528,48.900445],[2.388801,48.900428],[2.388962,48.900418],[2.389202,48.900397],[2.389463,48.90037],[2.389716,48.900337],[2.389921,48.900308],[2.390182,48.900262],[2.390436,48.900212],[2.390621,48.900165],[2.390836,48.90011],[2.391141,48.900021],[2.391442,48.899912],[2.391658,48.899822],[2.391807,48.899754],[2.391965,48.899673],[2.392127,48.899585],[2.392249,48.899512],[2.392437,48.899392],[2.392867,48.899064],[2.392922,48.899019],[2.393087,48.898862],[2.393197,48.898738],[2.39331,48.898592],[2.393375,48.898506],[2.393435,48.898423],[2.39349,48.89833],[2.393535,48.898253],[2.393587,48.89816],[2.393616,48.898109],[2.393652,48.898038],[2.393797,48.89767],[2.393835,48.897561],[2.393862,48.897478],[2.393897,48.897367],[2.39404,48.896913],[2.394145,48.896571],[2.394271,48.896169],[2.394334,48.895967],[2.394542,48.895303],[2.394614,48.895078],[2.394657,48.894932],[2.394702,48.894743],[2.394876,48.894151],[2.395207,48.892952],[2.39525,48.892796],[2.395314,48.892569],[2.395353,48.892436],[2.39538,48.892328],[2.395445,48.892093],[2.395475,48.891971],[2.395606,48.891515],[2.395666,48.891297],[2.395784,48.890884],[2.395886,48.890523],[2.39593,48.890356],[2.395987,48.890157],[2.396026,48.89002],[2.396216,48.889343],[2.396268,48.88916],[2.39634,48.888901],[2.396407,48.888668],[2.396542,48.888203],[2.396791,48.887311],[2.396957,48.886704],[2.397,48.886577],[2.397035,48.88646],[2.397121,48.886236],[2.397134,48.886201],[2.397165,48.886126],[2.397169,48.886116],[2.397186,48.886076],[2.397211,48.886017],[2.397239,48.885954],[2.397267,48.885893],[2.397361,48.885743],[2.397493,48.88553],[2.397568,48.885416],[2.397572,48.885411],[2.397856,48.885048],[2.3982,48.884679],[2.398452,48.884437],[2.398704,48.884223],[2.398993,48.883996],[2.399132,48.883887],[2.400334,48.88291],[2.400377,48.882876],[2.400437,48.882827],[2.400839,48.88251]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":11712.7,"duration":7.111666666666666,"instruction":{"type":"depart","modifier":"right"}},{"geometry":{"coordinates":[[2.400839,48.88251],[2.401151,48.882264],[2.401876,48.881723],[2.401989,48.881659],[2.402255,48.881514],[2.402391,48.881446],[2.402657,48.881323],[2.402973,48.881197],[2.403259,48.881096],[2.403627,48.880988],[2.404029,48.880881],[2.404386,48.880789],[2.404887,48.880646],[2.405281,48.880534],[2.405579,48.880433],[2.405884,48.880314],[2.406192,48.880188],[2.406488,48.880045],[2.406747,48.879904],[2.406995,48.879734],[2.407217,48.879565],[2.407472,48.879354],[2.407708,48.879135],[2.407833,48.878993],[2.407962,48.878833],[2.408108,48.878628],[2.408613,48.877783],[2.4087,48.877647],[2.408844,48.877415],[2.408998,48.877156],[2.409142,48.876903],[2.409355,48.876522],[2.409575,48.876174],[2.409724,48.875938],[2.409856,48.875708],[2.40992,48.875605],[2.409981,48.875513],[2.410057,48.875393],[2.410192,48.875192],[2.410264,48.875101],[2.410676,48.874603],[2.410922,48.874309],[2.41113,48.874072],[2.41145,48.873713],[2.411788,48.873307],[2.412022,48.873009],[2.412247,48.872718],[2.412431,48.872474],[2.412591,48.872236],[2.412727,48.871998],[2.412855,48.871771],[2.412933,48.871598],[2.413002,48.871424],[2.413068,48.871219],[2.413129,48.871],[2.413177,48.870783],[2.413222,48.870535],[2.413249,48.870277],[2.413255,48.870096],[2.413251,48.869494],[2.413247,48.869154],[2.41324,48.868837],[2.413237,48.868553],[2.413235,48.868322],[2.413217,48.867349],[2.413216,48.867179],[2.413204,48.866639],[2.413196,48.866153],[2.413192,48.865816],[2.41319,48.865646],[2.413191,48.865416],[2.413201,48.865129],[2.413212,48.864882],[2.413248,48.864475],[2.413275,48.864257],[2.413349,48.863769],[2.413394,48.863481],[2.413453,48.863109],[2.413527,48.862657],[2.413541,48.862566],[2.413757,48.86123],[2.413806,48.860938],[2.413825,48.86082],[2.413901,48.860344],[2.414005,48.859689],[2.414098,48.85891],[2.414107,48.858463],[2.414102,48.858357],[2.414058,48.857807],[2.413942,48.856712],[2.413917,48.856465],[2.413894,48.856234]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":3277,"duration":1.995,"instruction":{"type":"fork","modifier":"slight left"}},{"geometry":{"coordinates":[[2.413894,48.856234],[2.413728,48.856099],[2.413657,48.855853],[2.413637,48.855785],[2.413554,48.855404],[2.413465,48.854779],[2.413454,48.854686],[2.413414,48.85457]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":""}},"distance":191.1,"duration":0.2533333333333333,"instruction":{"type":"turn","modifier":"slight right"}},{"geometry":{"coordinates":[[2.413414,48.85457],[2.41332,48.854534],[2.413227,48.854486],[2.413125,48.854421],[2.413056,48.85436],[2.412996,48.854266],[2.412966,48.854148],[2.412968,48.85403],[2.413002,48.853911],[2.413045,48.853831],[2.413104,48.853755],[2.413196,48.853678],[2.413295,48.853625],[2.413431,48.853572],[2.413581,48.853535],[2.413659,48.853518],[2.413773,48.853505],[2.413891,48.853503],[2.413938,48.853508],[2.414068,48.853528],[2.414193,48.853557],[2.414301,48.853592],[2.414387,48.853627],[2.414463,48.85367],[2.414515,48.853715],[2.414562,48.853769],[2.414607,48.85383],[2.414664,48.853934],[2.41468,48.854045],[2.414644,48.854219]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"PL DE LA PORTE DE MONTREUIL","nom_1_droite":"PL DE LA PORTE DE MONTREUIL","cpx_numero":"","cpx_toponyme":""}},"distance":283.8,"duration":0.3383333333333333,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.414644,48.854219],[2.414827,48.854252],[2.415051,48.854292],[2.415301,48.854333]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"PL DE LA PORTE DE MONTREUIL","nom_1_droite":"PL DE LA PORTE DE MONTREUIL","cpx_numero":"","cpx_toponyme":""}},"distance":49.7,"duration":0.04833333333333333,"instruction":{"type":"continue","modifier":"right"}},{"geometry":{"coordinates":[[2.415301,48.854333],[2.415303,48.854181],[2.415316,48.854132],[2.41537,48.853941],[2.41544,48.853559],[2.415461,48.853438],[2.41549,48.853284],[2.415512,48.853136],[2.415546,48.852928],[2.415576,48.85273],[2.415611,48.852522],[2.415654,48.852303],[2.41569,48.852111]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV BENOIT FRACHON","nom_1_droite":"AV BENOIT FRACHON","cpx_numero":"","cpx_toponyme":""}},"distance":248.9,"duration":0.235,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.41569,48.852111],[2.415738,48.851857],[2.415786,48.851571],[2.415843,48.851245],[2.415892,48.85099],[2.416038,48.850121],[2.416138,48.84958]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV LEON GAUMONT","nom_1_droite":"AV LEON GAUMONT","cpx_numero":"","cpx_toponyme":""}},"distance":283.4,"duration":0.26833333333333337,"instruction":{"type":"new name","modifier":"straight"}},{"geometry":{"coordinates":[[2.416138,48.84958],[2.416138,48.84958]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV LEON GAUMONT","nom_1_droite":"AV LEON GAUMONT","cpx_numero":"","cpx_toponyme":""}},"distance":0,"duration":0,"instruction":{"type":"arrive"}}]},{"start":"2.416138,48.84958","end":"2.328617,48.819131","distance":9680.3,"duration":8.101666666666667,"bbox":[2.325647,48.815872,2.417672,48.84958],"steps":[{"geometry":{"coordinates":[[2.416138,48.84958],[2.41615,48.849515],[2.416193,48.849311],[2.416205,48.849264]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV LEON GAUMONT","nom_1_droite":"AV LEON GAUMONT","cpx_numero":"","cpx_toponyme":""}},"distance":35.5,"duration":0.03666666666666667,"instruction":{"type":"depart"}},{"geometry":{"coordinates":[[2.416205,48.849264],[2.416341,48.849234],[2.416456,48.849239],[2.416695,48.849247],[2.417537,48.849284],[2.417644,48.849309]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE LAGNY","nom_1_droite":"R DE LAGNY","cpx_numero":"D143A","cpx_toponyme":""}},"distance":106.5,"duration":0.14166666666666666,"instruction":{"type":"turn","modifier":"left"}},{"geometry":{"coordinates":[[2.417644,48.849309],[2.417666,48.849106],[2.417672,48.848878],[2.417658,48.848204],[2.417638,48.847609],[2.417621,48.847135],[2.417613,48.846795],[2.417548,48.846708],[2.417515,48.846656],[2.417488,48.846611],[2.417463,48.846558]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV JOFFRE","nom_1_droite":"AV JOFFRE","cpx_numero":"D158","cpx_toponyme":""}},"distance":308.3,"duration":0.41000000000000003,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.417463,48.846558],[2.41703,48.846601],[2.416487,48.846657],[2.415984,48.846695],[2.415876,48.846703],[2.415579,48.846718],[2.415407,48.846732],[2.415317,48.846748],[2.415191,48.846788],[2.415173,48.846822],[2.41515,48.846855],[2.415119,48.846886],[2.415085,48.846912]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV GALLIENI","nom_1_droite":"AV GALLIENI","cpx_numero":"D120","cpx_toponyme":""}},"distance":184.8,"duration":0.24333333333333335,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.415085,48.846912],[2.415035,48.846945],[2.414955,48.846986],[2.414886,48.84701],[2.414871,48.847016],[2.414766,48.847041],[2.414698,48.847054],[2.414647,48.847065],[2.414509,48.847082],[2.414466,48.847084],[2.41437,48.847086],[2.414313,48.847084],[2.414222,48.847079],[2.414135,48.847055],[2.414068,48.847033],[2.41401,48.847002],[2.413932,48.846954],[2.413875,48.846892]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV DE LA PORTE DE VINCENNES","nom_1_droite":"AV DE LA PORTE DE VINCENNES","cpx_numero":"","cpx_toponyme":""}},"distance":101.9,"duration":0.12333333333333334,"instruction":{"type":"fork","modifier":"slight left"}},{"geometry":{"coordinates":[[2.413875,48.846892],[2.413846,48.846844],[2.413831,48.846808],[2.413826,48.846767],[2.413828,48.846703],[2.413837,48.846678],[2.413852,48.846649],[2.413878,48.84662],[2.413899,48.846597]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV DE LA PORTE DE VINCENNES","nom_1_droite":"AV DE LA PORTE DE VINCENNES","cpx_numero":"","cpx_toponyme":""}},"distance":34.6,"duration":0.04,"instruction":{"type":"continue","modifier":"left"}},{"geometry":{"coordinates":[[2.413899,48.846597],[2.413927,48.846505],[2.413948,48.846432],[2.413946,48.846359],[2.413944,48.846212],[2.413913,48.845791],[2.413883,48.845437],[2.413872,48.845339],[2.413818,48.844854],[2.413805,48.844646],[2.413823,48.844497],[2.413888,48.844319]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":""}},"distance":254.6,"duration":0.33999999999999997,"instruction":{"type":"turn","modifier":"straight"}},{"geometry":{"coordinates":[[2.413888,48.844319],[2.413772,48.843733],[2.413728,48.843378],[2.413689,48.842958],[2.413644,48.842399],[2.413591,48.841949],[2.413538,48.841324],[2.41353,48.841221],[2.413518,48.841103],[2.413485,48.840716],[2.413397,48.840249],[2.41327,48.839717],[2.413155,48.839322],[2.412712,48.837848],[2.412689,48.837778],[2.412558,48.837402],[2.412405,48.836955],[2.412346,48.836759],[2.412264,48.836524],[2.412154,48.83626],[2.412062,48.836069],[2.412054,48.836052],[2.411979,48.835919],[2.411862,48.835716],[2.41159,48.835392],[2.411407,48.835215],[2.411195,48.835031],[2.410971,48.834865],[2.410738,48.834707],[2.410336,48.834484],[2.407818,48.833547],[2.407161,48.833284],[2.406761,48.833093],[2.406444,48.832921],[2.405585,48.832424],[2.403557,48.831274],[2.403116,48.831011],[2.402789,48.830802],[2.402264,48.830454],[2.401597,48.829992],[2.400881,48.829523],[2.400482,48.829315],[2.399929,48.829095],[2.399509,48.828973],[2.399047,48.828858],[2.398973,48.82884],[2.398666,48.828772],[2.398606,48.828758],[2.398496,48.828734],[2.398392,48.828711],[2.398269,48.828682],[2.398156,48.828657],[2.398041,48.828631],[2.397993,48.828619],[2.397905,48.8286],[2.397842,48.828585],[2.397735,48.828561],[2.397504,48.828508],[2.397318,48.828466],[2.397151,48.828428],[2.396988,48.828391],[2.396819,48.828353],[2.396732,48.828333],[2.396641,48.828311],[2.396561,48.828293],[2.396471,48.828273],[2.396329,48.828241],[2.396209,48.828212],[2.396088,48.828184],[2.395923,48.828148],[2.395849,48.82813],[2.395762,48.82811],[2.395601,48.828074],[2.395537,48.828061],[2.395345,48.828022],[2.395302,48.828014],[2.395032,48.827967],[2.394724,48.827922]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":2528.1,"duration":1.52,"instruction":{"type":"turn","modifier":"straight"}},{"geometry":{"coordinates":[[2.394724,48.827922],[2.394633,48.827911],[2.394395,48.827883],[2.393827,48.827816],[2.393325,48.827757],[2.393191,48.82774],[2.393029,48.82772],[2.392921,48.827708],[2.392795,48.827692],[2.3927,48.827682],[2.392585,48.827668],[2.392466,48.827652],[2.392338,48.827629],[2.392233,48.827612],[2.392119,48.827592],[2.391964,48.827564],[2.391794,48.827524],[2.391619,48.827481],[2.391425,48.827431],[2.391199,48.827371],[2.390958,48.827298],[2.390753,48.827229],[2.390586,48.827173],[2.390467,48.827131],[2.390334,48.827086],[2.390206,48.827042],[2.390051,48.826988],[2.38997,48.826962],[2.389928,48.826947],[2.389878,48.826932],[2.389802,48.82691],[2.389662,48.826867],[2.389409,48.82679],[2.388766,48.826572],[2.388407,48.82645],[2.38826,48.826396],[2.38814,48.826353],[2.387619,48.826164],[2.387259,48.82604],[2.386911,48.825914],[2.386329,48.825715],[2.385977,48.825599],[2.385652,48.825478],[2.38553,48.825433],[2.385187,48.825288],[2.384936,48.82517],[2.384745,48.825084],[2.384645,48.825035],[2.384079,48.824744],[2.383898,48.824636],[2.383593,48.824457],[2.383238,48.824247],[2.383006,48.824107],[2.38285,48.824013],[2.382547,48.82383],[2.382407,48.823747],[2.382191,48.823617],[2.381742,48.823348],[2.38144,48.82317],[2.381124,48.822979],[2.380803,48.822788],[2.3806,48.822666],[2.380366,48.822526],[2.380128,48.822383],[2.379803,48.822189],[2.37952,48.82202],[2.379316,48.821897],[2.379161,48.821806],[2.378941,48.821681],[2.378784,48.821602],[2.378689,48.821554],[2.378394,48.821418],[2.378134,48.821315],[2.377899,48.821227],[2.377479,48.821071],[2.376993,48.820912],[2.376639,48.820796],[2.376082,48.820622],[2.37545,48.820418],[2.3744,48.820074],[2.373528,48.819784],[2.37279,48.819542],[2.372131,48.819325],[2.371375,48.819076],[2.371196,48.819017],[2.370556,48.818809],[2.370503,48.818792],[2.370092,48.818658],[2.370065,48.81865],[2.36967,48.818522],[2.369162,48.818354],[2.368644,48.818185],[2.368019,48.817978],[2.367392,48.81777],[2.366903,48.817604],[2.366375,48.817427]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":2408.2,"duration":1.4633333333333336,"instruction":{"type":"fork","modifier":"slight left"}},{"geometry":{"coordinates":[[2.366375,48.817427],[2.365957,48.817272],[2.3657,48.817166],[2.365391,48.817036],[2.365033,48.816878],[2.364681,48.816717],[2.364464,48.81662]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":166.4,"duration":0.10333333333333333,"instruction":{"type":"fork","modifier":"slight left"}},{"geometry":{"coordinates":[[2.364464,48.81662],[2.364347,48.816567],[2.364073,48.816453],[2.363893,48.816379],[2.363716,48.816318],[2.363476,48.816259],[2.363295,48.816219],[2.363097,48.816187],[2.362909,48.816159],[2.362752,48.816144],[2.362455,48.816121],[2.361998,48.81611],[2.36135,48.816142],[2.360513,48.816197],[2.359615,48.816261],[2.358972,48.816306],[2.358403,48.81634],[2.357982,48.816359],[2.357687,48.816379],[2.357531,48.81639],[2.357128,48.816433],[2.35689,48.816466],[2.356625,48.816524],[2.356465,48.816563],[2.356278,48.816626],[2.356171,48.816662],[2.356061,48.816702],[2.355917,48.816754],[2.355694,48.816862],[2.355498,48.816961],[2.355481,48.816969],[2.355347,48.817047],[2.355122,48.81717],[2.354727,48.817401],[2.354294,48.817621],[2.354051,48.817728],[2.354038,48.817733],[2.353661,48.817836],[2.353324,48.817919],[2.353166,48.81795],[2.353042,48.817965],[2.352841,48.817993],[2.352653,48.818013],[2.352447,48.818023],[2.352133,48.818024],[2.351862,48.818016],[2.351557,48.817988],[2.351254,48.817962],[2.350977,48.817915],[2.350701,48.817857],[2.350401,48.817787],[2.350146,48.817718],[2.349869,48.817636],[2.349633,48.817554],[2.349307,48.81744],[2.348986,48.81731],[2.348672,48.817181],[2.348511,48.817108],[2.348438,48.817073],[2.348383,48.817047],[2.348214,48.816969],[2.347954,48.816866],[2.347816,48.816811],[2.347703,48.816765],[2.347503,48.816691],[2.347341,48.816638],[2.346982,48.816537],[2.346709,48.81648],[2.346404,48.816438],[2.346227,48.816424]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":1442.5,"duration":0.9116666666666665,"instruction":{"type":"fork","modifier":"slight left"}},{"geometry":{"coordinates":[[2.346227,48.816424],[2.345991,48.816495],[2.345548,48.816523],[2.345225,48.816546],[2.344809,48.816566],[2.344701,48.816579],[2.34461,48.816597],[2.344525,48.816624],[2.344424,48.816671],[2.344311,48.816745],[2.344223,48.816805],[2.344177,48.816819],[2.344124,48.816822],[2.344076,48.816818],[2.344024,48.81681],[2.343978,48.816795]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":""}},"distance":176.7,"duration":0.23333333333333334,"instruction":{"type":"turn","modifier":"slight right"}},{"geometry":{"coordinates":[[2.343978,48.816795],[2.343973,48.816685],[2.343968,48.816605],[2.343956,48.816306],[2.343946,48.81621],[2.343941,48.816158],[2.34393,48.816104],[2.343919,48.816048],[2.343909,48.815999],[2.343919,48.81595],[2.343929,48.815925]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV PIERRE DE COUBERTIN","nom_1_droite":"AV PIERRE DE COUBERTIN","cpx_numero":"","cpx_toponyme":""}},"distance":97.1,"duration":0.14,"instruction":{"type":"end of road","modifier":"left"}},{"geometry":{"coordinates":[[2.343929,48.815925],[2.343866,48.815897],[2.343811,48.815882],[2.343775,48.815877],[2.343724,48.815872],[2.343685,48.815875],[2.343646,48.815879],[2.343582,48.815891],[2.34343,48.815944],[2.343296,48.815992],[2.343157,48.816045],[2.343013,48.816085],[2.342877,48.816112],[2.342187,48.81624],[2.341801,48.816308],[2.341658,48.816322],[2.34103,48.81636],[2.340512,48.816372],[2.34032,48.816386],[2.339543,48.816436],[2.338645,48.816485],[2.338007,48.816515],[2.33751,48.816546],[2.337275,48.816558],[2.336674,48.816592],[2.336332,48.816611],[2.336103,48.816624],[2.335581,48.816655],[2.335146,48.816682],[2.334935,48.816694],[2.333711,48.816771],[2.332145,48.816982],[2.331996,48.817001],[2.331898,48.817011]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV PAUL VAILLANT-COUTURIER","nom_1_droite":"AV PAUL VAILLANT-COUTURIER","cpx_numero":"D150","cpx_toponyme":""}},"distance":896.5,"duration":1.1883333333333335,"instruction":{"type":"end of road","modifier":"right"}},{"geometry":{"coordinates":[[2.331898,48.817011],[2.331773,48.817026],[2.331642,48.817038],[2.331433,48.817061],[2.330791,48.817132],[2.330155,48.817182],[2.329947,48.817192],[2.328821,48.817283],[2.328496,48.817306],[2.328341,48.817309],[2.32818,48.817308],[2.327906,48.817285],[2.326756,48.817399],[2.325667,48.817501]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R BARBES","nom_1_droite":"R BARBES","cpx_numero":"D50","cpx_toponyme":""}},"distance":460.5,"duration":0.61,"instruction":{"type":"new name","modifier":"straight"}},{"geometry":{"coordinates":[[2.325667,48.817501],[2.325647,48.817662],[2.325654,48.817827],[2.325665,48.818221],[2.325682,48.818822],[2.325709,48.819386],[2.325739,48.819612],[2.325748,48.81972],[2.325759,48.819798]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV ARISTIDE BRIAND","nom_1_droite":"AV ARISTIDE BRIAND","cpx_numero":"D920","cpx_toponyme":""}},"distance":255.8,"duration":0.30666666666666664,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.325759,48.819798],[2.326214,48.819708]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"BD ROMAIN ROLLAND","nom_1_droite":"BD ROMAIN ROLLAND","cpx_numero":"","cpx_toponyme":""}},"distance":34.8,"duration":0.041666666666666664,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.326214,48.819708],[2.326682,48.819571],[2.326787,48.819543],[2.327213,48.819445],[2.328492,48.819159],[2.328617,48.819131]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"BD ROMAIN ROLLAND","nom_1_droite":"BD ROMAIN ROLLAND","cpx_numero":"","cpx_toponyme":""}},"distance":187.4,"duration":0.24833333333333332,"instruction":{"type":"fork","modifier":"slight right"}},{"geometry":{"coordinates":[[2.328617,48.819131],[2.328617,48.819131]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"BD ROMAIN ROLLAND","nom_1_droite":"BD ROMAIN ROLLAND","cpx_numero":"","cpx_toponyme":""}},"distance":0,"duration":0,"instruction":{"type":"arrive","modifier":"right"}}]},{"start":"2.328617,48.819131","end":"2.276358,48.874805","distance":11238.5,"duration":7.593333333333334,"bbox":[2.276358,48.815872,2.417672,48.901072],"steps":[{"geometry":{"coordinates":[[2.328617,48.819131],[2.329311,48.818978]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"BD ROMAIN ROLLAND","nom_1_droite":"BD ROMAIN ROLLAND","cpx_numero":"","cpx_toponyme":""}},"distance":53.6,"duration":0.07333333333333333,"instruction":{"type":"depart","modifier":"right"}},{"geometry":{"coordinates":[[2.329311,48.818978],[2.329301,48.81895],[2.329165,48.818481],[2.329109,48.818308],[2.328855,48.817409],[2.328821,48.817283]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R FRANCOIS ORY","nom_1_droite":"R FRANCOIS ORY","cpx_numero":"","cpx_toponyme":""}},"distance":191.9,"duration":0.385,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.328821,48.817283],[2.328496,48.817306],[2.328341,48.817309],[2.32818,48.817308],[2.327906,48.817285],[2.326756,48.817399],[2.325667,48.817501]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R BARBES","nom_1_droite":"R BARBES","cpx_numero":"D50","cpx_toponyme":""}},"distance":233.1,"duration":0.30833333333333335,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.325667,48.817501],[2.325647,48.817662],[2.325654,48.817827],[2.325665,48.818221],[2.325682,48.818822],[2.325709,48.819386],[2.325739,48.819612],[2.325748,48.81972],[2.325759,48.819798],[2.325764,48.819897],[2.325732,48.820159],[2.325739,48.820252]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"AV ARISTIDE BRIAND","nom_1_droite":"AV ARISTIDE BRIAND","cpx_numero":"D920","cpx_toponyme":""}},"distance":306.4,"duration":0.36666666666666664,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.325739,48.820252],[2.325606,48.820298],[2.3255,48.820341],[2.325425,48.820376],[2.324625,48.820558],[2.324213,48.820559],[2.324063,48.820583],[2.32304,48.820803],[2.322535,48.820898],[2.322348,48.820929],[2.322132,48.82095],[2.321882,48.820961],[2.321592,48.820955]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":""}},"distance":317.3,"duration":0.41000000000000003,"instruction":{"type":"turn","modifier":"left"}},{"geometry":{"coordinates":[[2.321592,48.820955],[2.320486,48.821176],[2.319356,48.821429],[2.318717,48.821568],[2.316763,48.822014],[2.316574,48.82207],[2.315929,48.822258],[2.315623,48.822338],[2.31524,48.822423],[2.31409,48.822684],[2.312227,48.823099],[2.311364,48.823291],[2.310272,48.823537],[2.308081,48.82402],[2.307599,48.824127],[2.304842,48.824742],[2.304372,48.82485]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":1333.7,"duration":0.8433333333333334,"instruction":{"type":"turn","modifier":"straight"}},{"geometry":{"coordinates":[[2.304372,48.82485],[2.301721,48.82546],[2.29952,48.825923],[2.298956,48.826049],[2.298438,48.826164],[2.296875,48.826518],[2.296547,48.826588],[2.29558,48.8268],[2.294579,48.82703],[2.29399,48.827159],[2.293614,48.827237],[2.293121,48.827358],[2.292475,48.827532],[2.291797,48.827741],[2.291232,48.827941],[2.290752,48.82813],[2.290645,48.828178],[2.290401,48.828282],[2.290015,48.828459],[2.288973,48.828931],[2.288394,48.829182],[2.287685,48.8295],[2.286752,48.82992],[2.285798,48.830338],[2.2849,48.830715],[2.284032,48.831075],[2.283048,48.831473],[2.281608,48.832068],[2.280687,48.83244],[2.279812,48.832798],[2.279223,48.833043],[2.278582,48.833298],[2.277536,48.833724],[2.277457,48.833757],[2.277128,48.833891],[2.276843,48.834007],[2.276681,48.834072],[2.276542,48.834129],[2.275811,48.834425],[2.275496,48.83454],[2.275331,48.834599],[2.275272,48.834617],[2.27505,48.834687],[2.2748,48.834761],[2.274514,48.834842],[2.274295,48.834899],[2.274187,48.834922],[2.273996,48.834968],[2.273706,48.835035],[2.273385,48.835103],[2.273089,48.835165],[2.272665,48.835244],[2.272454,48.835278],[2.272378,48.835288]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":2632.8,"duration":1.5716666666666663,"instruction":{"type":"fork","modifier":"slight left"}},{"geometry":{"coordinates":[[2.272378,48.835288],[2.272108,48.835325],[2.271826,48.835358],[2.271582,48.835377],[2.271344,48.835388],[2.271042,48.8354],[2.270637,48.835402],[2.270374,48.835395],[2.270174,48.835385],[2.269966,48.83537],[2.269826,48.835358],[2.269615,48.835333],[2.269463,48.835314],[2.267892,48.835081],[2.267539,48.835027],[2.267302,48.834994],[2.267132,48.834968],[2.266962,48.834949],[2.266742,48.834931],[2.266399,48.83491],[2.26614,48.8349],[2.265899,48.834897],[2.265662,48.834901],[2.265332,48.834916],[2.26505,48.834933],[2.263967,48.835],[2.261195,48.835157],[2.261139,48.83516],[2.260977,48.83517]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":842.4,"duration":0.495,"instruction":{"type":"fork","modifier":"slight left"}},{"geometry":{"coordinates":[[2.260977,48.83517],[2.260546,48.835197],[2.260157,48.835237],[2.259959,48.835263],[2.259621,48.835317],[2.259388,48.835359],[2.259162,48.8354],[2.259006,48.83544],[2.258741,48.835511],[2.258422,48.835603],[2.258148,48.835692],[2.257899,48.835778],[2.257597,48.835902],[2.257381,48.836],[2.257223,48.836072],[2.257164,48.836104],[2.257147,48.836112],[2.257098,48.836138],[2.256946,48.83622],[2.256786,48.836305],[2.256344,48.836546],[2.25586,48.836875],[2.255626,48.837061],[2.255502,48.837168],[2.255381,48.837279],[2.255282,48.837373],[2.255164,48.837497],[2.255012,48.837671],[2.254929,48.83777],[2.254865,48.837849],[2.254766,48.837986],[2.254594,48.838234],[2.25451,48.838377],[2.254439,48.838524],[2.254359,48.838736],[2.254322,48.838856],[2.254243,48.839141],[2.254202,48.839347],[2.254162,48.839587],[2.254111,48.839893],[2.254095,48.840042],[2.254089,48.840367],[2.254115,48.840634],[2.254196,48.841089],[2.254294,48.841654],[2.254443,48.8425],[2.25453,48.843011],[2.254601,48.843273]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":1175.6,"duration":0.7283333333333334,"instruction":{"type":"fork","modifier":"slight left"}},{"geometry":{"coordinates":[[2.254601,48.843273],[2.254705,48.843652],[2.254996,48.844689],[2.255041,48.844872],[2.25508,48.845097],[2.255125,48.845517],[2.255114,48.84572],[2.255103,48.845806],[2.255069,48.845987]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":305.2,"duration":0.19499999999999998,"instruction":{"type":"fork","modifier":"slight left"}},{"geometry":{"coordinates":[[2.255069,48.845987],[2.255034,48.846152],[2.254996,48.846301],[2.254945,48.84645],[2.254832,48.846722],[2.254666,48.847012],[2.254617,48.847081],[2.254558,48.847164],[2.254444,48.847316],[2.254277,48.847502],[2.254119,48.847653],[2.253895,48.847863],[2.25354,48.848177],[2.253125,48.848603],[2.252935,48.848846],[2.252677,48.849234],[2.252516,48.849538],[2.252419,48.849746],[2.252351,48.849947],[2.252296,48.850136],[2.252231,48.850441],[2.252214,48.850682],[2.252211,48.850967],[2.252228,48.85119],[2.252289,48.851621],[2.252328,48.851812],[2.252354,48.85193],[2.252375,48.851991],[2.252426,48.852106],[2.252471,48.852203],[2.252583,48.852397],[2.252649,48.852511],[2.252801,48.852748],[2.252894,48.852877],[2.25299,48.853004],[2.253253,48.853276],[2.253326,48.853344],[2.253627,48.853608],[2.25387,48.853809],[2.253975,48.853887],[2.254075,48.853962],[2.254201,48.85406],[2.254243,48.854088],[2.254865,48.854511],[2.255578,48.855011],[2.256824,48.855854],[2.2575,48.856298],[2.258365,48.856901],[2.259231,48.857461],[2.259504,48.857616],[2.259818,48.857782],[2.260034,48.857893],[2.260244,48.857992],[2.260644,48.858164],[2.260979,48.858306],[2.261367,48.858477],[2.261783,48.858677],[2.262025,48.858806],[2.262214,48.85892],[2.262414,48.859051],[2.262565,48.85916],[2.262741,48.859297],[2.262986,48.859513],[2.263149,48.859687],[2.263252,48.859787],[2.263362,48.859906],[2.263441,48.86001],[2.2635,48.860088],[2.263638,48.860301],[2.263694,48.860395],[2.263757,48.860494],[2.263835,48.860633],[2.26396,48.86085],[2.264194,48.861267],[2.264305,48.861452],[2.264676,48.862075],[2.264804,48.862286],[2.265001,48.862561],[2.265203,48.862816],[2.265376,48.863016],[2.265784,48.863383],[2.266052,48.863609],[2.2666,48.864023],[2.267077,48.864383],[2.267251,48.864546],[2.267521,48.864809],[2.267675,48.864973],[2.267874,48.865197],[2.268028,48.865385],[2.268175,48.86558],[2.268249,48.865681],[2.268334,48.865807],[2.268498,48.866059],[2.268689,48.866351],[2.268811,48.866539],[2.268949,48.866755],[2.269079,48.866955],[2.269253,48.867206],[2.269453,48.867482],[2.26965,48.867732],[2.269844,48.867992],[2.270022,48.868211],[2.270565,48.868765],[2.271253,48.869398],[2.271342,48.869471],[2.271532,48.86964],[2.271985,48.870027],[2.272335,48.87032],[2.272646,48.870586],[2.272953,48.870882],[2.273484,48.871388],[2.273666,48.871563],[2.273833,48.871737],[2.273989,48.871937],[2.274135,48.872154],[2.274314,48.872405],[2.274552,48.872716],[2.27488,48.873106],[2.275289,48.87358],[2.275799,48.874167],[2.276083,48.874497],[2.276239,48.874676],[2.276358,48.874805]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":3846.5,"duration":2.216666666666667,"instruction":{"type":"fork","modifier":"slight left"}},{"geometry":{"coordinates":[[2.276358,48.874805],[2.276358,48.874805]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":0,"duration":0,"instruction":{"type":"arrive","modifier":"right"}}]}]}
\ No newline at end of file
diff --git a/test/functional/request/cucumber/data/1.json b/test/functional/request/cucumber/data/bduni/common/normale.json
similarity index 100%
rename from test/functional/request/cucumber/data/1.json
rename to test/functional/request/cucumber/data/bduni/common/normale.json
diff --git a/test/functional/request/cucumber/data/bduni/common/point.json b/test/functional/request/cucumber/data/bduni/common/point.json
new file mode 100644
index 0000000..f7c6c7b
--- /dev/null
+++ b/test/functional/request/cucumber/data/bduni/common/point.json
@@ -0,0 +1 @@
+{"resource":"bdtopo-osrm","resourceVersion":"2022-01-24","start":"2.276358,48.874805","end":"2.276358,48.874805","profile":"car","optimization":"fastest","geometry":{"coordinates":[[2.276358,48.874805],[2.276358,48.874805]],"type":"LineString"},"crs":"EPSG:4326","distanceUnit":"meter","timeUnit":"minute","bbox":[2.276358,48.874805,2.276358,48.874805],"distance":0,"duration":0,"constraints":[],"portions":[{"start":"2.276358,48.874805","end":"2.276358,48.874805","distance":0,"duration":0,"bbox":[2.276358,48.874805,2.276358,48.874805],"steps":[{"geometry":{"coordinates":[[2.276358,48.874805],[2.276358,48.874805]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":0,"duration":0,"instruction":{"type":"depart","modifier":"straight"}},{"geometry":{"coordinates":[[2.276358,48.874805],[2.276358,48.874805]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"","nom_1_droite":"","cpx_numero":"","cpx_toponyme":"Boulevard Périphérique Intérieur"}},"distance":0,"duration":0,"instruction":{"type":"arrive","modifier":"straight"}}]}]}
\ No newline at end of file
diff --git a/test/functional/request/cucumber/data/bduni/common/unique-direct.json b/test/functional/request/cucumber/data/bduni/common/unique-direct.json
new file mode 100644
index 0000000..55e34ba
--- /dev/null
+++ b/test/functional/request/cucumber/data/bduni/common/unique-direct.json
@@ -0,0 +1 @@
+{"resource":"bdtopo-osrm","resourceVersion":"2022-01-24","start":"2.326638,48.875382","end":"2.326728,48.874912","profile":"car","optimization":"fastest","geometry":{"coordinates":[[2.326638,48.875382],[2.326637,48.875355],[2.326663,48.875223],[2.326707,48.875012],[2.326728,48.874912]],"type":"LineString"},"crs":"EPSG:4326","distanceUnit":"meter","timeUnit":"minute","bbox":[2.326637,48.874912,2.326728,48.875382],"distance":52.7,"duration":0.07833333333333334,"constraints":[],"portions":[{"start":"2.326638,48.875382","end":"2.326728,48.874912","distance":52.7,"duration":0.07833333333333334,"bbox":[2.326637,48.874912,2.326728,48.875382],"steps":[{"geometry":{"coordinates":[[2.326638,48.875382],[2.326637,48.875355],[2.326663,48.875223],[2.326707,48.875012],[2.326728,48.874912]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DU HAVRE","nom_1_droite":"R DU HAVRE","cpx_numero":"","cpx_toponyme":""}},"distance":52.7,"duration":0.07833333333333334,"instruction":{"type":"depart"}},{"geometry":{"coordinates":[[2.326728,48.874912],[2.326728,48.874912]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DU HAVRE","nom_1_droite":"R DU HAVRE","cpx_numero":"","cpx_toponyme":""}},"distance":0,"duration":0,"instruction":{"type":"arrive"}}]}]}
\ No newline at end of file
diff --git a/test/functional/request/cucumber/data/bduni/common/unique-inverse.json b/test/functional/request/cucumber/data/bduni/common/unique-inverse.json
new file mode 100644
index 0000000..ddd9e30
--- /dev/null
+++ b/test/functional/request/cucumber/data/bduni/common/unique-inverse.json
@@ -0,0 +1 @@
+{"resource":"bdtopo-osrm","resourceVersion":"2022-01-24","start":"2.326877,48.874383","end":"2.326638,48.875371","profile":"car","optimization":"fastest","geometry":{"coordinates":[[2.326877,48.874383],[2.326937,48.874179],[2.325756,48.874164],[2.324868,48.874785],[2.324727,48.874875],[2.324579,48.874965],[2.324501,48.875021],[2.324217,48.875252],[2.324436,48.875289],[2.32484,48.875341],[2.32499,48.875355],[2.325089,48.875369],[2.326288,48.875547],[2.3264,48.875558],[2.326506,48.875562],[2.326666,48.875544],[2.32664,48.875446],[2.326638,48.875371]],"type":"LineString"},"crs":"EPSG:4326","distanceUnit":"meter","timeUnit":"minute","bbox":[2.324217,48.874164,2.326937,48.875562],"distance":477.3,"duration":0.6883333333333332,"constraints":[],"portions":[{"start":"2.326877,48.874383","end":"2.326638,48.875371","distance":477.3,"duration":0.6883333333333332,"bbox":[2.324217,48.874164,2.326937,48.875562],"steps":[{"geometry":{"coordinates":[[2.326877,48.874383],[2.326937,48.874179]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DU HAVRE","nom_1_droite":"R DU HAVRE","cpx_numero":"","cpx_toponyme":""}},"distance":23.1,"duration":0.035,"instruction":{"type":"depart"}},{"geometry":{"coordinates":[[2.326937,48.874179],[2.325756,48.874164]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE PROVENCE","nom_1_droite":"R DE PROVENCE","cpx_numero":"","cpx_toponyme":""}},"distance":86.4,"duration":0.13,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.325756,48.874164],[2.324868,48.874785],[2.324727,48.874875],[2.324579,48.874965],[2.324501,48.875021],[2.324217,48.875252]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE ROME","nom_1_droite":"R DE ROME","cpx_numero":"","cpx_toponyme":""}},"distance":165.4,"duration":0.22,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.324217,48.875252],[2.324436,48.875289],[2.32484,48.875341]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"PL GABRIEL PERI","nom_1_droite":"PL GABRIEL PERI","cpx_numero":"","cpx_toponyme":""}},"distance":46.7,"duration":0.07,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.32484,48.875341],[2.32499,48.875355],[2.325089,48.875369],[2.326288,48.875547],[2.3264,48.875558],[2.326506,48.875562],[2.326666,48.875544]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R SAINT-LAZARE","nom_1_droite":"R SAINT-LAZARE","cpx_numero":"","cpx_toponyme":""}},"distance":136.3,"duration":0.20500000000000002,"instruction":{"type":"new name","modifier":"straight"}},{"geometry":{"coordinates":[[2.326666,48.875544],[2.32664,48.875446],[2.326638,48.875371]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DU HAVRE","nom_1_droite":"R DU HAVRE","cpx_numero":"","cpx_toponyme":""}},"distance":19.4,"duration":0.028333333333333332,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.326638,48.875371],[2.326638,48.875371]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DU HAVRE","nom_1_droite":"R DU HAVRE","cpx_numero":"","cpx_toponyme":""}},"distance":0,"duration":0,"instruction":{"type":"arrive"}}]}]}
\ No newline at end of file
diff --git a/test/functional/request/cucumber/data/2.json b/test/functional/request/cucumber/data/bduni/pgr/1.json
similarity index 100%
rename from test/functional/request/cucumber/data/2.json
rename to test/functional/request/cucumber/data/bduni/pgr/1.json
diff --git a/test/functional/request/cucumber/data/3.json b/test/functional/request/cucumber/data/bduni/pgr/2.json
similarity index 100%
rename from test/functional/request/cucumber/data/3.json
rename to test/functional/request/cucumber/data/bduni/pgr/2.json
diff --git a/test/functional/request/cucumber/features/requestAdminTest.feature b/test/functional/request/cucumber/features/req-admin-1.0.0.feature
similarity index 100%
rename from test/functional/request/cucumber/features/requestAdminTest.feature
rename to test/functional/request/cucumber/features/req-admin-1.0.0.feature
diff --git a/test/functional/request/cucumber/features/req-data-bduni-osrm.feature b/test/functional/request/cucumber/features/req-data-bduni-osrm.feature
new file mode 100644
index 0000000..f43685e
--- /dev/null
+++ b/test/functional/request/cucumber/features/req-data-bduni-osrm.feature
@@ -0,0 +1,90 @@
+Feature: Road2 with Bduni data via OSRM
+ Tests fonctionnels de Road2 prenant en compte la donnée Bduni via le moteur OSRM
+
+ Background:
+ Given I have loaded all my test configuration in "../../configurations/local.json"
+
+ Scenario Outline: [] [simple/1.0.0] Route normale
+ Given an "" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | start | 2.3420083522796626,48.845718486262086 |
+ | end | 2.3216879367828365,48.84558433605804 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the road should be similar to "../../data/bduni/common/normale.json"
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+ Scenario: [GET] [simple/1.0.0] Route qui fait une boucle
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | start | 2.276744842529297,48.874651226434366 |
+ | end | 2.276744842529297,48.874651226434366 |
+ | intermediates | 2.4161338806152344,48.84958044593267\|2.3285865783691406,48.819072029824866 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the road should be similar to "../../data/bduni/common/boucle.json"
+
+ Scenario: [GET] [simple/1.0.0] Route qui fait du sur place
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | start | 2.276744842529297,48.874651226434366 |
+ | end | 2.276744842529297,48.874651226434366 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the road should be similar to "../../data/bduni/common/point.json"
+
+ Scenario: [GET] [simple/1.0.0] Route à sens unique en sens direct
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | start | 2.3266366124153137,48.87538156341441 |
+ | end | 2.3267331719398494,48.87491231430877 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the road should be similar to "../../data/bduni/common/unique-direct.json"
+
+ Scenario: [GET] [simple/1.0.0] Routes à sens unique en sens inverse
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | start | 2.326878011226654,48.87438308071262 |
+ | end | 2.3266473412513733,48.875370978896655 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the road should be similar to "../../data/bduni/common/unique-inverse.json"
+
+ Scenario: [GET] [simple/1.0.0] Route qui doit passer sur un pont mais en interdisant les ponts
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | start | 2.3491859436035156,48.857111116502665 |
+ | end | 2.347555160522461,48.85404215643837 |
+ | constraints | {"constraintType":"banned","key":"wayType","operator":"=","value":"pont"} |
+ When I send the request
+ Then the server should send a response with status 404
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain an attribute "error.message" with value "No path found"
+
diff --git a/test/functional/request/cucumber/features/requestDataTest.feature b/test/functional/request/cucumber/features/req-data-bduni-pgr.feature
similarity index 87%
rename from test/functional/request/cucumber/features/requestDataTest.feature
rename to test/functional/request/cucumber/features/req-data-bduni-pgr.feature
index fee32ef..4b87879 100644
--- a/test/functional/request/cucumber/features/requestDataTest.feature
+++ b/test/functional/request/cucumber/features/req-data-bduni-pgr.feature
@@ -1,13 +1,12 @@
-# Tests fonctionnels de Road2 prenant en compte la donnée
-Feature: Road2 with data
- Tests fonctionnels de Road2 prenant en compte la donnée
+Feature: Road2 with Bduni data via PGR
+ Tests fonctionnels de Road2 prenant en compte la donnée Bduni via PGR
Background:
Given I have loaded all my test configuration in "../../configurations/local.json"
Scenario Outline: [] [simple/1.0.0] Route normale
Given an "" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
+ And with default parameters for "route-pgr"
And with query parameters:
| key | value |
| start | 2.3420083522796626,48.845718486262086 |
@@ -16,7 +15,7 @@ Feature: Road2 with data
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
- And the road should be similar to "../../data/1.json"
+ And the road should be similar to "../../data/bduni/common/normale.json"
Examples:
| method |
@@ -25,7 +24,7 @@ Feature: Road2 with data
Scenario: [GET] [simple/1.0.0] Route qui doit passer sur un pont mais en interdisant les ponts
Given an "GET" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
+ And with default parameters for "route-pgr"
And with query parameters:
| key | value |
| start | 2.3491859436035156,48.857111116502665 |
@@ -36,7 +35,7 @@ Feature: Road2 with data
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "No path found"
- Scenario: [GET] [simple/1.0.0] Route avec point intermediaire qui provoque un demi-tour (voir ticket #36883)
+ Scenario: [GET] [simple/1.0.0] Route avec point intermediaire qui provoque un demi-tour
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
@@ -48,9 +47,9 @@ Feature: Road2 with data
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
- And the road should be similar to "../../data/2.json"
+ And the road should be similar to "../../data/bduni/pgr/1.json"
- Scenario: [POST] [simple/1.0.0] Route avec point intermediaire qui provoque un demi-tour (voir ticket #36883)
+ Scenario: [POST] [simple/1.0.0] Route avec point intermediaire qui provoque un demi-tour
Given an "POST" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
@@ -64,10 +63,10 @@ Feature: Road2 with data
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
- And the road should be similar to "../../data/2.json"
+ And the road should be similar to "../../data/bduni/pgr/1.json"
- Scenario Outline: [] [simple/1.0.0] Route commençant sur une raquette (voir ticket #37674)
+ Scenario Outline: [] [simple/1.0.0] Route commençant sur une raquette
Given an "" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
@@ -78,7 +77,7 @@ Feature: Road2 with data
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
- And the road should be similar to "../../data/3.json"
+ And the road should be similar to "../../data/bduni/pgr/2.json"
Examples:
| method |
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-common.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-common.feature
new file mode 100644
index 0000000..870b1d9
--- /dev/null
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-common.feature
@@ -0,0 +1,52 @@
+Feature: Road2
+ Tests fonctionnels de Road2 sur les requêtes de l'API simple 1.0.0
+
+ Background:
+ Given I have loaded all my test configuration in "../../configurations/local.json"
+
+ Scenario Outline: [] Route principale
+ Given an "" request on "/"
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should contain "Road2"
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+ Scenario: API simple 1.0.0
+ Given an "GET" request on "/simple/1.0.0/"
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should contain "Road2 via l'API simple 1.0.0"
+
+ Scenario: GetCapabilities sur l'API simple 1.0.0
+ Given an "GET" request on operation "getcapabilities" in api "simple" "1.0.0"
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain an attribute "info.name" with value "Road2"
+ And the response should contain an attribute "api.name" with value "simple"
+ And the response should contain an attribute "api.version" with value "1.0.0"
+ And the response should contain an attribute "operations.[0].id" with value "route"
+ And the response should contain an attribute "operations.[0].methods.[1]" with value "POST"
+ And the response should contain an attribute "operations.[0].parameters.[0].name" with value "resource"
+ And the response should contain an attribute "operations.[1].id" with value "isochrone"
+ And the response should contain an attribute "operations.[1].methods.[0]" with value "GET"
+ And the response should contain an attribute "operations.[1].parameters.[1].name" with value "point"
+
+ Scenario: GetCapabilities sur l'API simple 1.0.0 sans changer le host
+ Given an "GET" request on operation "getcapabilities" in api "simple" "1.0.0"
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain an attribute "info.url" with configuration value of "url"
+
+ Scenario: GetCapabilities sur l'API simple 1.0.0 en changeant le host
+ Given an "GET" request on operation "getcapabilities" in api "simple" "1.0.0"
+ And with the alternative url
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain an attribute "info.url" with configuration value of "alternativeParameters.url"
diff --git a/test/functional/request/cucumber/features/requestTest.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
similarity index 81%
rename from test/functional/request/cucumber/features/requestTest.feature
rename to test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
index 2efe4a7..c259ad2 100644
--- a/test/functional/request/cucumber/features/requestTest.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
@@ -1,56 +1,10 @@
-# Tests fonctionnels de Road2
-Feature: Road2
- Tests fonctionnels de Road2
+# Tests fonctionnels complémentaires de Road2
+Feature: Road2-Osrm
+ Tests fonctionnels complémentaires de Road2 sur OSRM
Background:
- Given I have loaded all my test configuration in "../../configurations/local.json"
+ Given I have loaded all my test configuration in "../../configurations/local.json"
- Scenario Outline: [] Route principale
- Given an "" request on "/"
- When I send the request
- Then the server should send a response with status 200
- And the response should contain "Road2"
-
- Examples:
- | method |
- | GET |
- | POST |
-
- Scenario: API simple 1.0.0
- Given an "GET" request on "/simple/1.0.0/"
- When I send the request
- Then the server should send a response with status 200
- And the response should contain "Road2 via l'API simple 1.0.0"
-
- Scenario: GetCapabilities sur l'API simple 1.0.0
- Given an "GET" request on operation "getcapabilities" in api "simple" "1.0.0"
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain an attribute "info.name" with value "Road2"
- And the response should contain an attribute "api.name" with value "simple"
- And the response should contain an attribute "api.version" with value "1.0.0"
- And the response should contain an attribute "operations.[0].id" with value "route"
- And the response should contain an attribute "operations.[0].methods.[1]" with value "POST"
- And the response should contain an attribute "operations.[0].parameters.[0].name" with value "resource"
- And the response should contain an attribute "operations.[1].id" with value "isochrone"
- And the response should contain an attribute "operations.[1].methods.[0]" with value "GET"
- And the response should contain an attribute "operations.[1].parameters.[1].name" with value "point"
-
- Scenario: GetCapabilities sur l'API simple 1.0.0 sans changer le host
- Given an "GET" request on operation "getcapabilities" in api "simple" "1.0.0"
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain an attribute "info.url" with configuration value of "url"
-
- Scenario: GetCapabilities sur l'API simple 1.0.0 en changeant le host
- Given an "GET" request on operation "getcapabilities" in api "simple" "1.0.0"
- And with the alternative url
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain an attribute "info.url" with configuration value of "alternativeParameters.url"
Scenario Outline: [] Route sur l'API simple 1.0.0
Given an "" request on operation "route" in api "simple" "1.0.0"
@@ -976,6 +930,204 @@ Scenario Outline: [] Route sur l'API simple 1.0.0 avec geometryFormat=po
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'start' is invalid"
+
+ Scenario Outline: [] Route sur l'API simple 1.0.0
+ Given an "" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+ Scenario Outline: [GET] Route sur l'API simple 1.0.0 avec plusieurs waysAttributes
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | waysAttributes | name \| nature \| importance |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain an attribute "portions.[0].steps.[0].attributes.name"
+ And the response should contain an attribute "portions.[0].steps.[0].attributes.nature"
+ And the response should contain an attribute "portions.[0].steps.[0].attributes.importance"
+
+ Scenario Outline: [POST] Route sur l'API simple 1.0.0 avec plusieurs waysAttributes
+ Given an "POST" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with table parameters for "waysAttributes":
+ | value |
+ | name |
+ | nature |
+ | importance |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain an attribute "portions.[0].steps.[0].attributes.name"
+ And the response should contain an attribute "portions.[0].steps.[0].attributes.nature"
+ And the response should contain an attribute "portions.[0].steps.[0].attributes.importance"
+
+ Scenario Outline: [GET] Route sur l'API simple 1.0.0 avec plusieurs waysAttributes
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | waysAttributes | name \| nature \| importance \| cleabs \| urbain \| access_pieton \| cpx_numero \| largeur_de_chaussee \| position_par_rapport_au_sol \| restriction_de_hauteur \| sens_de_circulation |
+ When I send the request
+ Then the server should send a response with status 400
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain "Parameter 'waysAttributes' is invalid"
+
+ Scenario Outline: [POST] Route sur l'API simple 1.0.0 avec plusieurs waysAttributes
+ Given an "POST" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with table parameters for "waysAttributes":
+ | value |
+ | name |
+ | nature |
+ | importance |
+ | cleabs |
+ | urbain |
+ | access_pieton |
+ | cpx_numero |
+ | largeur_de_chaussee |
+ | position_par_rapport_au_sol |
+ | restriction_de_hauteur |
+ | sens_de_circulation |
+ When I send the request
+ Then the server should send a response with status 400
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain "Parameter 'waysAttributes' is invalid"
+
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes sur une ressource OSRM
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain an attribute "constraints.[1].key"
+
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes dont une invalide sur une ressource OSRM
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"test"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
+ When I send the request
+ Then the server should send a response with status 400
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain "Parameter 'constraints' is invalid"
+
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes sur une ressource OSRM
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain an attribute "constraints.[1].key"
+
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes dont une invalide sur une ressource OSRM
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"test"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
+ When I send the request
+ Then the server should send a response with status 400
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain "Parameter 'constraints' is invalid"
+
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes dont deux invalides sur une ressource OSRM
+ Given an "GET" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"test1"}\|{"constraintType":"test2","key":"waytype","operator":"=","value":"tunnel"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
+ When I send the request
+ Then the server should send a response with status 400
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain "Parameter 'constraints' is invalid"
+
+ Scenario: [POST] Route sur l'API simple 1.0.0 avec deux contraintes sur une ressource OSRM
+ Given an "POST" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with table parameters of object for "constraints":
+ | value |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain an attribute "constraints.[1].key"
+
+ Scenario: [POST] Route sur l'API simple 1.0.0 avec deux contraintes dont une ivalide sur une ressource OSRM
+ Given an "POST" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with table parameters of object for "constraints":
+ | value |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"test"} |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
+ When I send the request
+ Then the server should send a response with status 400
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain "Parameter 'constraints' is invalid"
+
+ Scenario: [POST] Route sur l'API simple 1.0.0 avec trois contraintes sur une ressource OSRM
+ Given an "POST" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with table parameters of object for "constraints":
+ | value |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain an attribute "constraints.[2].key"
+
+ Scenario: [POST] Route sur l'API simple 1.0.0 avec trois contraintes dont une invalide sur une ressource OSRM
+ Given an "POST" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with table parameters of object for "constraints":
+ | value |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"test"} |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
+ When I send the request
+ Then the server should send a response with status 400
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain "Parameter 'constraints' is invalid"
+
+ Scenario: [POST] Route sur l'API simple 1.0.0 avec trois contraintes dont deux invalides sur une ressource OSRM
+ Given an "POST" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with table parameters of object for "constraints":
+ | value |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"test1"} |
+ | {"constraintType":"test2","key":"waytype","operator":"=","value":"tunnel"} |
+ | {"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
+ When I send the request
+ Then the server should send a response with status 400
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain "Parameter 'constraints' is invalid"
+
Scenario Outline: [] Nearest sur l'API simple 1.0.0
Given an "" request on operation "nearest" in api "simple" "1.0.0"
And with default parameters for "nearest-osrm"
@@ -1125,4 +1277,4 @@ Scenario Outline: [] Nearest sur l'API simple 1.0.0 avec un autre crs
Examples:
| method |
| GET |
- | POST |
\ No newline at end of file
+ | POST |
diff --git a/test/functional/request/cucumber/features/requestComplementTest.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
similarity index 79%
rename from test/functional/request/cucumber/features/requestComplementTest.feature
rename to test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
index 684ed00..218f088 100644
--- a/test/functional/request/cucumber/features/requestComplementTest.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
@@ -5,19 +5,6 @@ Feature: Road2-complement
Background:
Given I have loaded all my test configuration in "../../configurations/local.json"
- Scenario Outline: [] Route sur l'API simple 1.0.0
- Given an "" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid road
-
- Examples:
- | method |
- | GET |
- | POST |
-
Scenario Outline: [] Route sur l'API simple 1.0.0
Given an "" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
@@ -31,190 +18,6 @@ Feature: Road2-complement
| GET |
| POST |
- Scenario Outline: [GET] Route sur l'API simple 1.0.0 avec plusieurs waysAttributes
- Given an "GET" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with query parameters:
- | key | value |
- | waysAttributes | name \| nature \| importance |
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid road
- And the response should contain an attribute "portions.[0].steps.[0].attributes.name"
- And the response should contain an attribute "portions.[0].steps.[0].attributes.nature"
- And the response should contain an attribute "portions.[0].steps.[0].attributes.importance"
-
- Scenario Outline: [POST] Route sur l'API simple 1.0.0 avec plusieurs waysAttributes
- Given an "POST" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with table parameters for "waysAttributes":
- | value |
- | name |
- | nature |
- | importance |
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid road
- And the response should contain an attribute "portions.[0].steps.[0].attributes.name"
- And the response should contain an attribute "portions.[0].steps.[0].attributes.nature"
- And the response should contain an attribute "portions.[0].steps.[0].attributes.importance"
-
- Scenario Outline: [GET] Route sur l'API simple 1.0.0 avec plusieurs waysAttributes
- Given an "GET" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with query parameters:
- | key | value |
- | waysAttributes | name \| nature \| importance \| cleabs \| urbain \| access_pieton \| cpx_numero \| largeur_de_chaussee \| position_par_rapport_au_sol \| restriction_de_hauteur \| sens_de_circulation |
- When I send the request
- Then the server should send a response with status 400
- And the response should have an header "content-type" with value "application/json"
- And the response should contain "Parameter 'waysAttributes' is invalid"
-
- Scenario Outline: [POST] Route sur l'API simple 1.0.0 avec plusieurs waysAttributes
- Given an "POST" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with table parameters for "waysAttributes":
- | value |
- | name |
- | nature |
- | importance |
- | cleabs |
- | urbain |
- | access_pieton |
- | cpx_numero |
- | largeur_de_chaussee |
- | position_par_rapport_au_sol |
- | restriction_de_hauteur |
- | sens_de_circulation |
- When I send the request
- Then the server should send a response with status 400
- And the response should have an header "content-type" with value "application/json"
- And the response should contain "Parameter 'waysAttributes' is invalid"
-
- Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes sur une ressource OSRM
- Given an "GET" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with query parameters:
- | key | value |
- | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid road
- And the response should contain an attribute "constraints.[1].key"
-
- Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes dont une invalide sur une ressource OSRM
- Given an "GET" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with query parameters:
- | key | value |
- | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"test"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
- When I send the request
- Then the server should send a response with status 400
- And the response should have an header "content-type" with value "application/json"
- And the response should contain "Parameter 'constraints' is invalid"
-
- Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes sur une ressource OSRM
- Given an "GET" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with query parameters:
- | key | value |
- | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid road
- And the response should contain an attribute "constraints.[1].key"
-
- Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes dont une invalide sur une ressource OSRM
- Given an "GET" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with query parameters:
- | key | value |
- | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"test"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
- Then the server should send a response with status 400
- And the response should have an header "content-type" with value "application/json"
- And the response should contain "Parameter 'constraints' is invalid"
-
- Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes dont deux invalides sur une ressource OSRM
- Given an "GET" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with query parameters:
- | key | value |
- | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"test1"}\|{"constraintType":"test2","key":"waytype","operator":"=","value":"tunnel"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
- Then the server should send a response with status 400
- And the response should have an header "content-type" with value "application/json"
- And the response should contain "Parameter 'constraints' is invalid"
-
- Scenario: [POST] Route sur l'API simple 1.0.0 avec deux contraintes sur une ressource OSRM
- Given an "POST" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with table parameters of object for "constraints":
- | value |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid road
- And the response should contain an attribute "constraints.[1].key"
-
- Scenario: [POST] Route sur l'API simple 1.0.0 avec deux contraintes dont une ivalide sur une ressource OSRM
- Given an "POST" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with table parameters of object for "constraints":
- | value |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"test"} |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
- When I send the request
- Then the server should send a response with status 400
- And the response should have an header "content-type" with value "application/json"
- And the response should contain "Parameter 'constraints' is invalid"
-
- Scenario: [POST] Route sur l'API simple 1.0.0 avec trois contraintes sur une ressource OSRM
- Given an "POST" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with table parameters of object for "constraints":
- | value |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid road
- And the response should contain an attribute "constraints.[2].key"
-
- Scenario: [POST] Route sur l'API simple 1.0.0 avec trois contraintes dont une invalide sur une ressource OSRM
- Given an "POST" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with table parameters of object for "constraints":
- | value |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"test"} |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
- Then the server should send a response with status 400
- And the response should have an header "content-type" with value "application/json"
- And the response should contain "Parameter 'constraints' is invalid"
-
- Scenario: [POST] Route sur l'API simple 1.0.0 avec trois contraintes dont deux invalides sur une ressource OSRM
- Given an "POST" request on operation "route" in api "simple" "1.0.0"
- And with default parameters for "route-osrm"
- And with table parameters of object for "constraints":
- | value |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"test1"} |
- | {"constraintType":"test2","key":"waytype","operator":"=","value":"tunnel"} |
- | {"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
- Then the server should send a response with status 400
- And the response should have an header "content-type" with value "application/json"
- And the response should contain "Parameter 'constraints' is invalid"
-
Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes sur une ressource pgr
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
diff --git a/test/functional/request/cucumber/features/support/world.js b/test/functional/request/cucumber/features/support/world.js
index 6912433..5d40a0c 100644
--- a/test/functional/request/cucumber/features/support/world.js
+++ b/test/functional/request/cucumber/features/support/world.js
@@ -317,7 +317,12 @@ class road2World {
getConfigurationValueof(key) {
- return this.getJsonContentByKey(this._configuration, key);
+ let response = this.getJsonContentByKey(this._configuration, key);
+ if (response.status === "found") {
+ return response.content;
+ } else {
+ return false;
+ }
}
@@ -334,14 +339,19 @@ class road2World {
responseJSON = this._response;
}
- let jsonValue = this.getJsonContentByKey(responseJSON, key);
-
- if (jsonValue.includes(value)) {
- return true;
+ let result = this.getJsonContentByKey(responseJSON, key);
+ if (result.status === "found") {
+ if (result.content.includes(value)) {
+ return true;
+ } else {
+ return false;
+ }
} else {
return false;
}
+
+
} catch(error) {
console.log(error);
return false;
@@ -366,9 +376,8 @@ class road2World {
responseJSON = this._response;
}
- let jsonValue = this.getJsonContentByKey(responseJSON, key);
-
- if (jsonValue) {
+ let result = this.getJsonContentByKey(responseJSON, key);
+ if (result.status === "found") {
return true;
} else {
return false;
@@ -397,10 +406,13 @@ class road2World {
responseJSON = this._response;
}
- let jsonValue = this.getJsonContentByKey(responseJSON, key);
-
- if (typeof jsonValue === "string") {
- return true;
+ let result = this.getJsonContentByKey(responseJSON, key);
+ if (result.status = "found") {
+ if (typeof result.content === "string") {
+ return true;
+ } else {
+ return false;
+ }
} else {
return false;
}
@@ -417,6 +429,11 @@ class road2World {
getJsonContentByKey(jsonContent, key) {
+ let returnObject = {
+ status: "not found",
+ content: {}
+ };
+
let keysTable = new Array();
keysTable = key.split('.');
@@ -424,19 +441,30 @@ class road2World {
let tmpJson = jsonContent;
for (let i = 0; i < keysTable.length; i++) {
- tmpJson = this.getJsonContentByKeyLO(tmpJson, keysTable[i]);
+ let response = this.getJsonContentByKeyLO(tmpJson, keysTable[i]);
// Gérer le cas vide
- if (tmpJson === false) {
- return false;
+ if (response.status === "not found") {
+ returnObject.status = "not found";
+ returnObject.content = {};
+ return returnObject;
+ } else {
+ returnObject.status = "found";
+ returnObject.content = response.content;
+ tmpJson = response.content;
}
}
- // à enlever
- return tmpJson;
+
+ return returnObject;
}
getJsonContentByKeyLO(jsonContent, key) {
+ let returnObject = {
+ status: "not found",
+ content: {}
+ };
+
// Gérer les tableaux
if (Array.isArray(jsonContent)) {
@@ -446,90 +474,94 @@ class road2World {
let indiceNum = parseInt(indiceTable[0]);
if (jsonContent.length > indiceNum) {
- return jsonContent[indiceNum];
+ returnObject.status = "found";
+ returnObject.content = jsonContent[indiceNum];
+ return returnObject;
} else {
- return false;
+ return returnObject;
}
} else {
- return false;
+ return returnObject;
}
} else {
for (let tmpKey in jsonContent) {
if (tmpKey === key) {
- return jsonContent[tmpKey];
+ returnObject.status = "found";
+ returnObject.content = jsonContent[tmpKey];
+ return returnObject;
}
}
}
- return false;
+ return returnObject;
}
checkCompleteRoad() {
if (!this.checkResponseAttribut("resource")) {
- return false;
+ return 1;
}
if (!this.checkResponseAttribut("profile")) {
- return false;
+ return 2;
}
if (!this.checkResponseAttribut("optimization")) {
- return false;
+ return 3;
}
if (!this.checkResponseAttribut("distanceUnit")) {
- return false;
+ return 4;
}
if (!this.checkResponseAttribut("timeUnit")) {
- return false;
+ return 5;
}
if (!this.checkResponseAttribut("crs")) {
- return false;
+ return 6;
}
if (!this.checkResponseAttribut("geometry")) {
- return false;
+ return 7;
}
if (!this.checkResponseAttribut("bbox")) {
- return false;
+ return 8;
}
if (!this.checkResponseAttribut("distance")) {
- return false;
+ return 9;
}
if (!this.checkResponseAttribut("duration")) {
- return false;
+ return 10;
}
if (!this.checkResponseAttribut("portions.[0]")) {
- return false;
+ return 11;
}
if (!this.checkResponseAttribut("portions.[0].start")) {
- return false;
+ return 12;
}
if (!this.checkResponseAttribut("portions.[0].end")) {
- return false;
+ return 13;
}
if (!this.checkResponseAttribut("portions.[0].distance")) {
- return false;
+ return 14;
}
if (!this.checkResponseAttribut("portions.[0].duration")) {
- return false;
+ return 15;
}
if (!this.checkResponseAttribut("portions.[0].steps.[0]")) {
- return false;
+ return 16;
}
if (!this.checkResponseAttribut("portions.[0].steps.[0].geometry")) {
- return false;
+ return 17;
}
if (!this.checkResponseAttribut("portions.[0].steps.[0].attributes")) {
- return false;
+ return 18;
}
if (!this.checkResponseAttribut("portions.[0].steps.[0].distance")) {
- return false;
+ return 19;
}
if (!this.checkResponseAttribut("portions.[0].steps.[0].duration")) {
- return false;
+ return 20;
}
return true;
@@ -539,31 +571,31 @@ class road2World {
checkCompleteIso() {
if (!this.checkResponseAttribut("point")) {
- return false;
+ return 1;
}
if (!this.checkResponseAttribut("resource")) {
- return false;
+ return 2;
}
if (!this.checkResponseAttribut("resourceVersion")) {
- return false;
+ return 3;
}
if (!this.checkResponseAttribut("profile")) {
- return false;
+ return 4;
}
if (!this.checkResponseAttribut("costType")) {
- return false;
+ return 5;
}
if (!this.checkResponseAttribut("costValue")) {
- return false;
+ return 6;
}
if (!this.checkResponseAttribut("crs")) {
- return false;
+ return 7;
}
if (!this.checkResponseAttribut("geometry")) {
- return false;
+ return 8;
}
if (!this.checkResponseAttribut("direction")) {
- return false;
+ return 9;
}
return true;
@@ -606,6 +638,8 @@ class road2World {
let refDurationMin = 0;
let refDurationMax = 0;
let responseJSON = {};
+ let tablePoint = new Array();
+ let curPoint = {};
if (typeof this._response === "string") {
responseJSON = JSON.parse(this._response);
@@ -638,15 +672,25 @@ class road2World {
return "Duration is out of boundaries";
}
- let bufferStart = turf.buffer(turf.point(referenceRoad.start.split(",")), 0.01, {units: "kilometers"});
+ tablePoint = referenceRoad.start.split(",");
+ curPoint = turf.point([Number(tablePoint[0]), Number(tablePoint[1])]);
+ let bufferStart = turf.buffer(curPoint, 0.01, {units: "kilometers"});
- if (!turf.booleanWithin(turf.point(responseJSON.start.split(",")), bufferStart)) {
+ tablePoint = responseJSON.start.split(",");
+ curPoint = turf.point([Number(tablePoint[0]), Number(tablePoint[1])]);
+
+ if (!turf.booleanWithin(curPoint, bufferStart)) {
return "Start is out of the buffer";
}
- let bufferEnd = turf.buffer(turf.point(referenceRoad.end.split(",")), 0.01, {units: "kilometers"});
+ tablePoint = referenceRoad.end.split(",");
+ curPoint = turf.point([Number(tablePoint[0]), Number(tablePoint[1])]);
+ let bufferEnd = turf.buffer(curPoint, 0.01, {units: "kilometers"});
+
+ tablePoint = responseJSON.end.split(",");
+ curPoint = turf.point([Number(tablePoint[0]), Number(tablePoint[1])]);
- if (!turf.booleanWithin(turf.point(responseJSON.end.split(",")), bufferEnd)) {
+ if (!turf.booleanWithin(curPoint, bufferEnd)) {
return "End is out of the buffer";
}
From a5db1fe6532a0d566c44b77a0ee0d10dbdac7013 Mon Sep 17 00:00:00 2001
From: Loic
Date: Wed, 20 Apr 2022 18:15:27 +0200
Subject: [PATCH 05/93] test: refactoring et ajout de tests sur turfJS
---
src/js/geometry/polygon.js | 46 ++++---
.../features/req-simple-1.0.0-osrm.feature | 3 +-
.../features/req-simple-1.0.0-pgr.feature | 81 +++---------
.../req-simple-1.0.0-smartrouting.feature | 84 ++++++++++++
.../mocha/geometry/integrationPolygon.js | 58 +++++++--
test/unit/mocha/npm/testsTurf.js | 123 ++++++++++++++++++
6 files changed, 299 insertions(+), 96 deletions(-)
create mode 100644 test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
create mode 100644 test/unit/mocha/npm/testsTurf.js
diff --git a/src/js/geometry/polygon.js b/src/js/geometry/polygon.js
index f185ece..e04c5d0 100644
--- a/src/js/geometry/polygon.js
+++ b/src/js/geometry/polygon.js
@@ -65,44 +65,48 @@ module.exports = class Polygon extends Geometry {
*
*/
_convertGeometry (geom, srcFormat, outFormat) {
- // Création d'un objet Polygon depuis les coordonées reçues.
- const polygon = turf.polygon(geom);
if (srcFormat === outFormat) {
return geom;
} else if (srcFormat === "polyline" && outFormat === "geojson") {
- return polyline.toGeoJSON(polygon); // À tester..
+ let tmpPolygon = polyline.toGeoJSON(geom);
+ tmpPolygon.type = "Polygon";
+ return tmpPolygon;
} else if (srcFormat === "geojson" && outFormat === "polyline") {
+
let result = [];
if (geom.type === "Point") {
// Cas où l'isochrone est un simple point
result = polyline.encode([geom.coordinates]);
return result
- }
- if (geom.type === "LineString") {
- // Cas où l'isochrone est un simple point
+ } else if (geom.type === "LineString") {
+ // Cas où l'isochrone est une line
result = polyline.encode(geom.coordinates);
return result
- }
+ } else {
+
+ // Conversion du polygone en (Multi)LineString.
+ let polygon = turf.polygon(geom.coordinates);
+ const lines = turf.polygonToLine(polygon);
+
+ if (lines.geometry.type === "LineString") {
+ // Une seule ligne, nous convertissons donc directement.
+ result = polyline.fromGeoJSON(lines);
+ } else if (lines.geometry.type === "MultiLineString") {
+ // Plusieurs lignes, convertion ligne par ligne.
+ lines.geometry.coordinates.forEach( function(element) {
+ result.push(polyline.fromGeoJSON({
+ "type": "LineString",
+ "coordinates": element
+ }));
+ });
+ }
- // Conversion du polygone en (Multi)LineString.
- const lines = turf.polygonToLine(polygon.geometry.coordinates);
+ return result;
- if (lines.geometry.type === "LineString") {
- // Une seule ligne, nous convertissons donc directement.
- result = polyline.fromGeoJSON(lines);
- } else if (lines.geometry.type === "MultiLineString") {
- // Plusieurs lignes, convertion ligne par ligne.
- lines.geometry.coordinates.forEach( function(element) {
- result.push(polyline.fromGeoJSON({
- "type": "LineString",
- "coordinates": element
- }));
- });
}
- return result;
} else {
//TODO: voir si on peut remplacer ce throw par un return {}
throw errorManager.createError("Unsupported geometry conversion");
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
index c259ad2..41d1d95 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
@@ -1,5 +1,4 @@
-# Tests fonctionnels complémentaires de Road2
-Feature: Road2-Osrm
+Feature: Road2-OSRM
Tests fonctionnels complémentaires de Road2 sur OSRM
Background:
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
index 218f088..aa73d59 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
@@ -1,6 +1,5 @@
-# Tests fonctionnels complémentaires de Road2
-Feature: Road2-complement
- Tests fonctionnels complémentaires de Road2
+Feature: Road2-PGR
+ Tests fonctionnels complémentaires de Road2 via PGRouting
Background:
Given I have loaded all my test configuration in "../../configurations/local.json"
@@ -737,6 +736,21 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
| GET |
| POST |
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un geometryFormat polyline
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone"
+ And with query parameters:
+ | key | value |
+ | geometryFormat | polyline |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais distanceUnit
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
@@ -810,64 +824,3 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And the response should contain a complete and valid iso
And the response should contain an attribute "constraints.[0].key"
- Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource smartpgr avec appel à la source smartrouting
- Given an "" request on operation "isochrone" in api "simple" "1.0.0"
- And with default parameters for "isochrone-smartpgr"
- And with query parameters:
- | key | value |
- | costType | distance |
- | costValue | 31000 |
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid iso
-
- Examples:
- | method |
- | GET |
- | POST |
-
- Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource smartpgr avec appel à la source pgr
- Given an "" request on operation "isochrone" in api "simple" "1.0.0"
- And with default parameters for "isochrone-smartpgr"
- And with query parameters:
- | key | value |
- | costType | distance |
- | costValue | 1000 |
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid iso
-
- Examples:
- | method |
- | GET |
- | POST |
-
- Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource smartpgr avec appel à la source smartrouting
- Given an "GET" request on operation "isochrone" in api "simple" "1.0.0"
- And with default parameters for "isochrone-smartpgr"
- And with query parameters:
- | key | value |
- | costType | distance |
- | costValue | 1000 |
- | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid iso
- And the response should contain an attribute "constraints.[0].key"
-
- Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource smartpgr avec appel à la source pgr
- Given an "GET" request on operation "isochrone" in api "simple" "1.0.0"
- And with default parameters for "isochrone-smartpgr"
- And with query parameters:
- | key | value |
- | costType | distance |
- | costValue | 31000 |
- | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
- When I send the request
- Then the server should send a response with status 200
- And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid iso
- And the response should contain an attribute "constraints.[0].key"
\ No newline at end of file
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
new file mode 100644
index 0000000..9197368
--- /dev/null
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
@@ -0,0 +1,84 @@
+Feature: Road2-SMARTROUTING
+ Tests fonctionnels complémentaires de Road2 via SmartRouting
+
+ Background:
+ Given I have loaded all my test configuration in "../../configurations/local.json"
+
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource smartpgr avec appel à la source smartrouting
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone-smartpgr"
+ And with query parameters:
+ | key | value |
+ | costType | distance |
+ | costValue | 31000 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource smartpgr avec appel à la source pgr
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone-smartpgr"
+ And with query parameters:
+ | key | value |
+ | costType | distance |
+ | costValue | 1000 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+ Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource smartpgr avec appel à la source smartrouting
+ Given an "GET" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone-smartpgr"
+ And with query parameters:
+ | key | value |
+ | costType | distance |
+ | costValue | 1000 |
+ | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+ And the response should contain an attribute "constraints.[0].key"
+
+ Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource smartpgr avec appel à la source pgr
+ Given an "GET" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone-smartpgr"
+ And with query parameters:
+ | key | value |
+ | costType | distance |
+ | costValue | 31000 |
+ | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+ And the response should contain an attribute "constraints.[0].key"
+
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un geometryFormat polyline à partir d'une géométrie générée par smartrouting
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone-smartpgr"
+ And with query parameters:
+ | key | value |
+ | costType | distance |
+ | costValue | 31000 |
+ | geometryFormat | polyline |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
\ No newline at end of file
diff --git a/test/integration/mocha/geometry/integrationPolygon.js b/test/integration/mocha/geometry/integrationPolygon.js
index 9a30dfe..1f4f10e 100644
--- a/test/integration/mocha/geometry/integrationPolygon.js
+++ b/test/integration/mocha/geometry/integrationPolygon.js
@@ -10,13 +10,22 @@ describe('Test de la classe Polygon', function() {
logManager.manageLogs();
});
- let refGeom = {"type":"Polygon","coordinates":[[[2.32689460427517,48.8796664760288],[2.32472468908434,48.8806534168629],[2.32338130915736,48.8825632112067],[2.32206953790069,48.882561186561],[2.32095428209082,48.8823381270098],[2.32092436698872,48.8823316620015],[2.32242419764372,48.8840192132601],[2.3245085041333,48.884600267544],[2.32477614691189,48.8847825427569],[2.32501420082458,48.8849331739511],[2.32574230742436,48.88715232559],[2.32559587720714,48.8875076350737],[2.32576801732307,48.8880104297148],[2.32715614178612,48.8871800641188],[2.3288567997417,48.8857983467344],[2.33075204345075,48.8853970623475],[2.33185424388145,48.8885589613481],[2.33180026632535,48.888726834289],[2.3317775934945,48.8887932579532],[2.33337839987913,48.889453293149],[2.33574382909869,48.8895123042427],[2.33701742654633,48.8879203602709],[2.33750337619062,48.8876703390523],[2.33909347535874,48.8868130741082],[2.33976160902747,48.8846691634537],[2.34172981868777,48.8834479189961],[2.34386348025055,48.8829407175301],[2.34433279903902,48.8830305236972],[2.34443888269128,48.8830526885388],[2.34468547821561,48.8828534878423],[2.34474999949318,48.8827108474226],[2.34255154287428,48.8811150723814],[2.34044822598183,48.8804155140435],[2.33984157112535,48.8788994912569],[2.33737131803045,48.8776861309969],[2.33709317504751,48.8767214024118],[2.33535461098932,48.8761991404349],[2.3327040299337,48.8742867916612],[2.3314074826543,48.8750269072541],[2.32956775219663,48.8769708782012],[2.32700731273326,48.8795969615579],[2.32689460427517,48.8796664760288]]]};
- let refPolyline = "}xiiHaneMcEpL}JjG?dGj@~E@DqIkHsBaLc@u@]m@{LqCgAZcBa@dDuGrGsInAyJwR{Ea@HKBcC_IKwM|H_Gp@_BjD}HjLeCrFiKdBiLQ}ACUf@q@ZK|HvLjCbLnHxBpFlN`Ev@fBzI|JpOsC`GcKnJmO~NMV";
+ let refGeomPolygon = {"type":"Polygon","coordinates":[[[2.32689460427517,48.8796664760288],[2.32472468908434,48.8806534168629],[2.32338130915736,48.8825632112067],[2.32206953790069,48.882561186561],[2.32095428209082,48.8823381270098],[2.32092436698872,48.8823316620015],[2.32242419764372,48.8840192132601],[2.3245085041333,48.884600267544],[2.32477614691189,48.8847825427569],[2.32501420082458,48.8849331739511],[2.32574230742436,48.88715232559],[2.32559587720714,48.8875076350737],[2.32576801732307,48.8880104297148],[2.32715614178612,48.8871800641188],[2.3288567997417,48.8857983467344],[2.33075204345075,48.8853970623475],[2.33185424388145,48.8885589613481],[2.33180026632535,48.888726834289],[2.3317775934945,48.8887932579532],[2.33337839987913,48.889453293149],[2.33574382909869,48.8895123042427],[2.33701742654633,48.8879203602709],[2.33750337619062,48.8876703390523],[2.33909347535874,48.8868130741082],[2.33976160902747,48.8846691634537],[2.34172981868777,48.8834479189961],[2.34386348025055,48.8829407175301],[2.34433279903902,48.8830305236972],[2.34443888269128,48.8830526885388],[2.34468547821561,48.8828534878423],[2.34474999949318,48.8827108474226],[2.34255154287428,48.8811150723814],[2.34044822598183,48.8804155140435],[2.33984157112535,48.8788994912569],[2.33737131803045,48.8776861309969],[2.33709317504751,48.8767214024118],[2.33535461098932,48.8761991404349],[2.3327040299337,48.8742867916612],[2.3314074826543,48.8750269072541],[2.32956775219663,48.8769708782012],[2.32700731273326,48.8795969615579],[2.32689460427517,48.8796664760288]]]};
+ let refPolylinePolygon = "}xiiHaneMcEpL}JjG?dGj@~E@DqIkHsBaLc@u@]m@{LqCgAZcBa@dDuGrGsInAyJwR{Ea@HKBcC_IKwM|H_Gp@_BjD}HjLeCrFiKdBiLQ}ACUf@q@ZK|HvLjCbLnHxBpFlN`Ev@fBzI|JpOsC`GcKnJmO~NMV";
+ let newGeomPolygon = {"type":"Polygon","coordinates":[[2.32689,48.87967],[2.32472,48.88065],[2.32338,48.88256],[2.32207,48.88256],[2.32095,48.88234],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32478,48.88478],[2.32501,48.88493],[2.32574,48.88715],[2.3256,48.88751],[2.32577,48.88801],[2.32716,48.88718],[2.32886,48.8858],[2.33075,48.8854],[2.33185,48.88856],[2.3318,48.88873],[2.33178,48.88879],[2.33338,48.88945],[2.33574,48.88951],[2.33702,48.88792],[2.3375,48.88767],[2.33909,48.88681],[2.33976,48.88467],[2.34173,48.88345],[2.34386,48.88294],[2.34433,48.88303],[2.34444,48.88305],[2.34469,48.88285],[2.34475,48.88271],[2.34255,48.88112],[2.34045,48.88042],[2.33984,48.8789],[2.33737,48.87769],[2.33709,48.87672],[2.33535,48.8762],[2.3327,48.87429],[2.33141,48.87503],[2.32957,48.87697],[2.32701,48.8796],[2.32689,48.87967]]};
+
+ let refGeomLine = {"type":"LineString","coordinates":[[2.32689460427517,48.8796664760288],[2.32472468908434,48.8806534168629],[2.32338130915736,48.8825632112067]]};
+ let refPolylineLine = "aneM}xiiHpLcEjG}J";
+ let newGeomLine = {"type":"Polygon","coordinates":[[48.87967,2.32689],[48.88065,2.32472],[48.88256,2.32338]]};
+
+ let refGeomPoint = {"type":"Point","coordinates":[2.32689460427517,48.8796664760288]};
+ let refPolylinePoint = "aneM}xiiH";
+ let newGeomPoint = {"type":"Polygon","coordinates":[[48.87967,2.32689]]};
- let polygon = new Polygon(refGeom, "geojson", "EPSG:4326");
-
describe('Test du constructeur et des getters/setters', function() {
+ let polygon = new Polygon(refGeomPolygon, "geojson", "EPSG:4326");
+
it('Get type', function() {
assert.equal(polygon.type, "polygon");
});
@@ -26,16 +35,47 @@ describe('Test de la classe Polygon', function() {
});
it('Get geom', function() {
- assert.equal(polygon.geom, refGeom);
+ assert.equal(polygon.geom, refGeomPolygon);
});
});
- describe('Changer le format', function() {
+ describe('Changer le format avec getGeometryWithFormat()', function() {
+
+ it('Polygon : geojson to polyline', function() {
+ let polygon = new Polygon(refGeomPolygon, "geojson", "EPSG:4326");
+ let tmpGeom = polygon.getGeometryWithFormat("polyline");
+ assert.equal(tmpGeom, refPolylinePolygon);
+ });
+
+ it('Polygon : polyline to geojson', function() {
+ let polygonPoly = new Polygon(refPolylinePolygon, "polyline", "EPSG:4326");
+ let tmpGeom = polygonPoly.getGeometryWithFormat("geojson");
+ assert.deepEqual(tmpGeom, newGeomPolygon);
+ });
+
+ it('Line : geojson to polyline', function() {
+ let polygon = new Polygon(refGeomLine, "geojson", "EPSG:4326");
+ let tmpGeom = polygon.getGeometryWithFormat("polyline");
+ assert.equal(tmpGeom, refPolylineLine);
+ });
+
+ it('Line : polyline to geojson', function() {
+ let polygonPoly = new Polygon(refPolylineLine, "polyline", "EPSG:4326");
+ let tmpGeom = polygonPoly.getGeometryWithFormat("geojson");
+ assert.deepEqual(tmpGeom, newGeomLine);
+ });
+
+ it('Point : geojson to polyline', function() {
+ let polygon = new Polygon(refGeomPoint, "geojson", "EPSG:4326");
+ let tmpGeom = polygon.getGeometryWithFormat("polyline");
+ assert.equal(tmpGeom, refPolylinePoint);
+ });
- it('getGeometryWithFormat()', function() {
- let tmpPolyline = polygon.getGeometryWithFormat("polyline");
- assert.equal(tmpPolyline, refPolyline);
+ it('Point : polyline to geojson', function() {
+ let polygonPoly = new Polygon(refPolylinePoint, "polyline", "EPSG:4326");
+ let tmpGeom = polygonPoly.getGeometryWithFormat("geojson");
+ assert.deepEqual(tmpGeom, newGeomPoint);
});
});
diff --git a/test/unit/mocha/npm/testsTurf.js b/test/unit/mocha/npm/testsTurf.js
new file mode 100644
index 0000000..a93e18a
--- /dev/null
+++ b/test/unit/mocha/npm/testsTurf.js
@@ -0,0 +1,123 @@
+const assert = require('assert');
+const logManager = require('../logManager');
+const turf = require('@turf/turf');
+
+describe('Test de la dépendance NPM TurfJS', function() {
+
+ before(function() {
+ // runs before all tests in this block
+ logManager.manageLogs();
+ });
+
+ describe('Test de la fonction point', function() {
+
+ let refPoint = {"geometry": {"coordinates": [2,48],"type": "Point"},"properties": {},"type": "Feature"};
+
+ it('Creation d\'un point à partir de nombres', function() {
+ let point = turf.point([2,48]);
+ assert.deepEqual(point, refPoint);
+ });
+
+ });
+
+ describe('Test de la fonction bbox', function() {
+
+ let refBbox = [-82, 35, -74, 42];
+
+ it('Creation d\'une bbox à partir d\'une ligne en geojson ', function() {
+ let line = turf.lineString([[-74, 40], [-78, 42], [-82, 35]]);
+ let bbox = turf.bbox(line);
+ assert.deepEqual(bbox, refBbox);
+ });
+
+ });
+
+ describe('Test de la fonction polygon', function() {
+
+ let refPolygon = {"type":"Feature", "properties":{},"geometry":{"type": "Polygon","coordinates":[[[2.32689,48.87967],[2.32472,48.88065],[2.32338,48.88256],[2.32207,48.88256],[2.32095,48.88234],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32478,48.88478],[2.32501,48.88493],[2.32574,48.88715],[2.3256,48.88751],[2.32577,48.88801],[2.32716,48.88718],[2.32886,48.8858],[2.33075,48.8854],[2.33185,48.88856],[2.3318,48.88873],[2.33178,48.88879],[2.33338,48.88945],[2.33574,48.88951],[2.33702,48.88792],[2.3375,48.88767],[2.33909,48.88681],[2.33976,48.88467],[2.34173,48.88345],[2.34386,48.88294],[2.34433,48.88303],[2.34444,48.88305],[2.34469,48.88285],[2.34475,48.88271],[2.34255,48.88112],[2.34045,48.88042],[2.33984,48.8789],[2.33737,48.87769],[2.33709,48.87672],[2.33535,48.8762],[2.3327,48.87429],[2.33141,48.87503],[2.32957,48.87697],[2.32701,48.8796],[2.32689,48.87967]]]}};
+
+ it('Creation d\'un polygon à partir des coordonnées d\'un polygon en geojson', function() {
+ let geojsonCoord = [[[2.32689,48.87967],[2.32472,48.88065],[2.32338,48.88256],[2.32207,48.88256],[2.32095,48.88234],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32478,48.88478],[2.32501,48.88493],[2.32574,48.88715],[2.3256,48.88751],[2.32577,48.88801],[2.32716,48.88718],[2.32886,48.8858],[2.33075,48.8854],[2.33185,48.88856],[2.3318,48.88873],[2.33178,48.88879],[2.33338,48.88945],[2.33574,48.88951],[2.33702,48.88792],[2.3375,48.88767],[2.33909,48.88681],[2.33976,48.88467],[2.34173,48.88345],[2.34386,48.88294],[2.34433,48.88303],[2.34444,48.88305],[2.34469,48.88285],[2.34475,48.88271],[2.34255,48.88112],[2.34045,48.88042],[2.33984,48.8789],[2.33737,48.87769],[2.33709,48.87672],[2.33535,48.8762],[2.3327,48.87429],[2.33141,48.87503],[2.32957,48.87697],[2.32701,48.8796],[2.32689,48.87967]]];
+ let polygon = turf.polygon(geojsonCoord);
+ assert.deepEqual(polygon, refPolygon);
+ });
+
+ });
+
+ describe('Test de la fonction polygonToLine', function() {
+
+ let refLine = {"type":"Feature", "properties":{},"geometry":{"type": "LineString","coordinates":[[2.32689,48.87967],[2.32472,48.88065],[2.32338,48.88256],[2.32207,48.88256],[2.32095,48.88234],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32478,48.88478],[2.32501,48.88493],[2.32574,48.88715],[2.3256,48.88751],[2.32577,48.88801],[2.32716,48.88718],[2.32886,48.8858],[2.33075,48.8854],[2.33185,48.88856],[2.3318,48.88873],[2.33178,48.88879],[2.33338,48.88945],[2.33574,48.88951],[2.33702,48.88792],[2.3375,48.88767],[2.33909,48.88681],[2.33976,48.88467],[2.34173,48.88345],[2.34386,48.88294],[2.34433,48.88303],[2.34444,48.88305],[2.34469,48.88285],[2.34475,48.88271],[2.34255,48.88112],[2.34045,48.88042],[2.33984,48.8789],[2.33737,48.87769],[2.33709,48.87672],[2.33535,48.8762],[2.3327,48.87429],[2.33141,48.87503],[2.32957,48.87697],[2.32701,48.8796],[2.32689,48.87967]]}};
+
+ it('Creation d\'une ligne à partir des coordonnées d\'un polygon en geojson', function() {
+ let geojsonCoord = [[[2.32689,48.87967],[2.32472,48.88065],[2.32338,48.88256],[2.32207,48.88256],[2.32095,48.88234],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32478,48.88478],[2.32501,48.88493],[2.32574,48.88715],[2.3256,48.88751],[2.32577,48.88801],[2.32716,48.88718],[2.32886,48.8858],[2.33075,48.8854],[2.33185,48.88856],[2.3318,48.88873],[2.33178,48.88879],[2.33338,48.88945],[2.33574,48.88951],[2.33702,48.88792],[2.3375,48.88767],[2.33909,48.88681],[2.33976,48.88467],[2.34173,48.88345],[2.34386,48.88294],[2.34433,48.88303],[2.34444,48.88305],[2.34469,48.88285],[2.34475,48.88271],[2.34255,48.88112],[2.34045,48.88042],[2.33984,48.8789],[2.33737,48.87769],[2.33709,48.87672],[2.33535,48.8762],[2.3327,48.87429],[2.33141,48.87503],[2.32957,48.87697],[2.32701,48.8796],[2.32689,48.87967]]];
+ let polygon = turf.polygon(geojsonCoord);
+ let line = turf.polygonToLine(polygon);
+ assert.deepEqual(line, refLine);
+ });
+
+ });
+
+ describe('Test de la fonction lineSlice', function() {
+
+ let line = {"type":"Feature", "properties":{},"geometry":{"type": "LineString","coordinates":[[2.32689,48.87967],[2.32472,48.88065],[2.32338,48.88256],[2.32207,48.88256],[2.32095,48.88234],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32478,48.88478],[2.32501,48.88493],[2.32574,48.88715],[2.3256,48.88751],[2.32577,48.88801],[2.32716,48.88718],[2.32886,48.8858],[2.33075,48.8854],[2.33185,48.88856],[2.3318,48.88873],[2.33178,48.88879],[2.33338,48.88945],[2.33574,48.88951],[2.33702,48.88792],[2.3375,48.88767],[2.33909,48.88681],[2.33976,48.88467],[2.34173,48.88345],[2.34386,48.88294],[2.34433,48.88303],[2.34444,48.88305],[2.34469,48.88285],[2.34475,48.88271],[2.34255,48.88112],[2.34045,48.88042],[2.33984,48.8789],[2.33737,48.87769],[2.33709,48.87672],[2.33535,48.8762],[2.3327,48.87429],[2.33141,48.87503],[2.32957,48.87697],[2.32701,48.8796],[2.32689,48.87967]]}};
+ let start = turf.point([2.32207,48.88256]);
+ let stop = turf.point([2.32451,48.8846]);
+ let refSliced = {"geometry":{"coordinates":[[2.32207,48.88256],[2.32095,48.88234],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32451,48.8846]],"type":"LineString"},"properties":{},"type":"Feature"};
+
+ it('Découpage d\'une ligne à partir d\'une ligne en geojson', function() {
+ let lineSliced = turf.lineSlice(start, stop, line);
+ assert.deepEqual(lineSliced, refSliced);
+ });
+
+ });
+
+ describe('Test de la fonction truncate', function() {
+
+ let line = {"geometry":{"coordinates":[[2.322075785,48.882563257],[2.320957896,48.8823445245],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32451,48.8846]],"type":"LineString"},"properties":{},"type":"Feature"};
+ let refTrunc = {"geometry":{"coordinates":[[2.322076,48.882563],[2.320958,48.882345],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32451,48.8846]],"type":"LineString"},"properties":{},"type":"Feature"};
+
+ it('Modification de la géométrie par découpage des coordonnées', function() {
+ let lineTrunc = turf.truncate(line, {precision: 6});
+ assert.deepEqual(lineTrunc, refTrunc);
+ });
+
+ });
+
+ describe('Test de la fonction nearestPointOnLine', function() {
+
+ let line = {"geometry":{"coordinates":[[2.322075785,48.882563257],[2.320957896,48.8823445245],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32451,48.8846]],"type":"LineString"},"properties":{},"type":"Feature"};
+ let point = turf.point([2.32207,48.88256]);
+ let refPoint = {geometry: {coordinates: [2.3220691120694474,48.88256195133658],type: 'Point'},properties: {dist: 0.00022648508237084762,index: 0,location: 0.0005090817926782273},type: 'Feature'};
+
+ it('Calcul du point le plus proche d\'un autre sur une ligne ', function() {
+ let nearest = turf.nearestPointOnLine(line, point,{precision: 6});
+ assert.deepEqual(nearest, refPoint);
+ });
+
+ });
+
+ describe('Test de la fonction length', function() {
+
+ let line = {"geometry":{"coordinates":[[2.322075785,48.882563257],[2.320957896,48.8823445245],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32451,48.8846]],"type":"LineString"},"properties":{},"type":"Feature"};
+ let refLength = 0.4719505233593252;
+
+ it('Calcul du point le plus proche d\'un autre sur une ligne ', function() {
+ let lengthOfLine = turf.length(line);
+ assert.equal(lengthOfLine, refLength);
+ });
+
+ });
+
+ describe('Test de la fonction cleanCoords', function() {
+
+ let line = {"geometry":{"coordinates":[[2.322075785,48.882563257],[2.320957896,48.8823445245],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846],[2.32451,48.8846]],"type":"LineString"},"properties":{},"type":"Feature"};
+ let refLine = {"geometry":{"coordinates":[[2.322075785,48.882563257],[2.320957896,48.8823445245],[2.32092,48.88233],[2.32242,48.88402],[2.32451,48.8846]],"type":"LineString"},"properties":{},"type":"Feature"};
+
+ it('Calcul du point le plus proche d\'un autre sur une ligne ', function() {
+ let cleanedLine = turf.cleanCoords(line);
+ assert.deepEqual(cleanedLine, refLine);
+ });
+
+ });
+
+});
From a585ef1fe3afe77d053633f76e19991b69835319 Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 26 Sep 2022 11:20:35 +0200
Subject: [PATCH 06/93] creation d'une roadmap pour le projet
---
documentation/developers/roadmap.md | 12 ++++++++++++
readme.md | 2 ++
2 files changed, 14 insertions(+)
create mode 100644 documentation/developers/roadmap.md
diff --git a/documentation/developers/roadmap.md b/documentation/developers/roadmap.md
new file mode 100644
index 0000000..7138fdb
--- /dev/null
+++ b/documentation/developers/roadmap.md
@@ -0,0 +1,12 @@
+# Roadmap du projet Road2
+
+## Développements en cours
+
+Pour la fin de l'année 2022 :
+
+- Intégration de Valhalla dans Road2 et Route-graph-generator
+- Refactorisation d'une partie du code pour :
+ - une meilleure gestion de la configuration
+ - la création d'un processus administrateur du service. Ce nouveau processus portera l'API admin sans impacter les requêtes des utilisateurs classiques du service.
+
+
diff --git a/readme.md b/readme.md
index 76e3a83..72c7f32 100644
--- a/readme.md
+++ b/readme.md
@@ -84,6 +84,8 @@ On trouvera dans le dossier [docker/distrubutions](./docker/distributions) diff
On trouvera une documentation dédiée aux développeurs [ici](./documentation/developers/readme.md). Elle indique les concepts utiles pour effectuer des développements sur Road2.
+Pour en savoir plus sur notre roadmap, vous pouvez regarder ce [document](./documentation/developers/roadmap.md).
+
De plus, il est possible d'utiliser ce [docker-compose](./docker/dev/readme.md) pour avoir un environnement de développement incluant la construction des binaires, des modules et la génération des données.
## Utilisation en production
From cf39701b06b34a463b04253bea4d6b882ba2e786 Mon Sep 17 00:00:00 2001
From: Loic
Date: Thu, 20 Oct 2022 14:26:27 +0200
Subject: [PATCH 07/93] Merge : refactoring de la gestion de la configuration
et creation d'un processus administrateur
---
.vscode/launch.json | 13 +-
changelog.md | 10 +
docker/config/log4js-administration.json | 18 +
.../{log4js.json => log4js-service.json} | 0
docker/config/road2.json | 66 +-
docker/config/service.json | 59 +
docker/dev/docker-compose.yml | 3 +-
documentation/configuration/admin_model.yaml | 94 ++
documentation/configuration/readme.md | 28 +-
...guration_model.yaml => service_model.yaml} | 17 +-
documentation/developers/concepts.md | 38 +-
documentation/developers/readme.md | 10 +-
package.json | 4 +-
readme.md | 2 +-
src/js/administrator/administrator.js | 479 ++++++
src/js/apis/apisManager.js | 291 +++-
src/js/apis/simple/1.0.0/init.js | 2 +-
src/js/base/base.js | 4 +
src/js/base/baseManager.js | 101 +-
src/js/geography/projectionManager.js | 260 +++-
src/js/operations/operationManager.js | 384 +++--
src/js/parameters/parameterManager.js | 336 ++--
src/js/resources/osrmResource.js | 26 -
src/js/resources/pgrResource.js | 26 -
src/js/resources/resource.js | 16 -
src/js/resources/resourceManager.js | 405 +++--
src/js/resources/smartpgrResource.js | 26 -
src/js/road2.js | 174 ++-
src/js/server/serverManager.js | 109 +-
src/js/service/main.js | 250 +++
src/js/service/service.js | 816 +++++-----
src/js/service/serviceAdministered.js | 55 +
src/js/service/serviceManager.js | 130 ++
src/js/service/serviceProcess.js | 118 ++
src/js/sources/osrmSource.js | 5 +-
src/js/sources/pgrSource.js | 6 +-
src/js/sources/smartroutingSource.js | 4 -
src/js/sources/source.js | 31 -
src/js/sources/sourceManager.js | 474 +++---
src/js/topology/topologyManager.js | 206 ++-
src/js/utils/logManager.js | 91 ++
src/js/utils/processManager.js | 10 +-
.../cucumber/features/conf-admin.feature | 351 +++++
.../cucumber/features/conf-common.feature | 51 +
.../cucumber/features/conf-cors.feature | 21 +
.../cucumber/features/conf-log.feature | 88 ++
.../cucumber/features/conf-operation.feature | 122 ++
.../features/conf-osrm-ressource.feature | 21 +
.../cucumber/features/conf-parameter.feature | 307 ++++
.../cucumber/features/conf-projection.feature | 110 ++
.../cucumber/features/conf-service.feature | 677 +++++++++
.../features/configurationTest.feature | 1354 -----------------
.../cucumber/features/support/steps.js | 19 +-
.../cucumber/features/support/world.js | 107 +-
.../cucumber/configurations/local-admin.json | 17 +
.../{local.json => local-service.json} | 6 -
.../cucumber/features/req-admin-1.0.0.feature | 2 +-
.../features/req-data-bduni-osrm.feature | 2 +-
.../features/req-data-bduni-pgr.feature | 2 +-
.../features/req-simple-1.0.0-common.feature | 2 +-
.../features/req-simple-1.0.0-osrm.feature | 2 +-
.../features/req-simple-1.0.0-pgr.feature | 2 +-
.../req-simple-1.0.0-smartrouting.feature | 2 +-
.../mocha/apis/integrationApiManager.js | 6 +-
.../mocha/base/integrationBaseManager.js | 19 +-
.../mocha/service/integrationService.js | 2 +-
test/integration/readme.md | 4 +-
.../mocha/geography/testsProjectionManager.js | 88 +-
68 files changed, 5487 insertions(+), 3094 deletions(-)
create mode 100644 docker/config/log4js-administration.json
rename docker/config/{log4js.json => log4js-service.json} (100%)
create mode 100644 docker/config/service.json
create mode 100644 documentation/configuration/admin_model.yaml
rename documentation/configuration/{configuration_model.yaml => service_model.yaml} (88%)
create mode 100644 src/js/administrator/administrator.js
create mode 100644 src/js/service/main.js
create mode 100644 src/js/service/serviceAdministered.js
create mode 100644 src/js/service/serviceManager.js
create mode 100644 src/js/service/serviceProcess.js
create mode 100644 src/js/utils/logManager.js
create mode 100644 test/functional/configuration/cucumber/features/conf-admin.feature
create mode 100644 test/functional/configuration/cucumber/features/conf-common.feature
create mode 100644 test/functional/configuration/cucumber/features/conf-cors.feature
create mode 100644 test/functional/configuration/cucumber/features/conf-log.feature
create mode 100644 test/functional/configuration/cucumber/features/conf-operation.feature
create mode 100644 test/functional/configuration/cucumber/features/conf-osrm-ressource.feature
create mode 100644 test/functional/configuration/cucumber/features/conf-parameter.feature
create mode 100644 test/functional/configuration/cucumber/features/conf-projection.feature
create mode 100644 test/functional/configuration/cucumber/features/conf-service.feature
delete mode 100644 test/functional/configuration/cucumber/features/configurationTest.feature
create mode 100644 test/functional/request/cucumber/configurations/local-admin.json
rename test/functional/request/cucumber/configurations/{local.json => local-service.json} (90%)
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 9c54d6c..47ec703 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -6,7 +6,7 @@
"configurations": [
{
- "name": "Docker: Attach to Node",
+ "name": "Docker: Attach to Road2 Administrator",
"type": "node",
"request": "attach",
"port": 9229,
@@ -14,6 +14,17 @@
"protocol": "inspector",
"localRoot": "${workspaceFolder}",
"remoteRoot": "/home/docker/app/"
+ },
+ {
+ "name": "Docker: Attach to Road2 Service",
+ "type": "node",
+ "request": "attach",
+ "port": 9230,
+ "address": "localhost",
+ "protocol": "inspector",
+ "localRoot": "${workspaceFolder}",
+ "remoteRoot": "/home/docker/app/"
}
+
]
}
\ No newline at end of file
diff --git a/changelog.md b/changelog.md
index dca08fe..49dcf98 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,13 @@
+# 2.0.0
+
+ADDED:
+ - La classe Administrator permet de gérer le service via une API. Notamment la création, la suppression et la modification d'un service seront possible.
+ - Cette classe est configurée par un nouveau fichier de configuration.
+
+CHANGED:
+ - L'option --configCheck au démarrage de Road2 n'a plus exactement le même comportement.
+ - Le fichier server.json permet maintenant de configurer l'administrateur et donc n'a plus le même contenu. Ce dernier est dans service.json.
+
# 1.O.14
FIXED:
- Mauvaise ligne pour un log
diff --git a/docker/config/log4js-administration.json b/docker/config/log4js-administration.json
new file mode 100644
index 0000000..e9bfd49
--- /dev/null
+++ b/docker/config/log4js-administration.json
@@ -0,0 +1,18 @@
+{ "mainConf":
+ {
+ "appenders": {
+ "console": { "type": "console", "layout": {"type": "pattern", "pattern": "%[[%d] [%p] %c %z -%] %m"} },
+ "file": { "type": "file", "filename": "/var/log/road2/road2-admin.log", "layout": {"type": "pattern", "pattern": "[%d] [%p] %c %z - %m%n"} },
+ "http": { "type": "file", "filename": "/var/log/road2/access-admin.log"}
+ },
+ "categories": {
+ "default": { "appenders": ["console","file"], "level": "debug" },
+ "request": { "appenders": ["console","http"], "level": "info" }
+ },
+ "disableClustering": true
+ },
+ "httpConf": {
+ "level": "info",
+ "format": ":remote-addr - :method :url HTTP/:http-version :status :content-length :referrer :user-agent"
+ }
+}
diff --git a/docker/config/log4js.json b/docker/config/log4js-service.json
similarity index 100%
rename from docker/config/log4js.json
rename to docker/config/log4js-service.json
diff --git a/docker/config/road2.json b/docker/config/road2.json
index b774844..4799842 100644
--- a/docker/config/road2.json
+++ b/docker/config/road2.json
@@ -1,53 +1,27 @@
{
- "application": {
- "name": "Road2",
- "title": "Service de calcul d'itinéraire",
- "description": "Ce service permet de calculer des itinéraires sur les données du Géoportail.",
- "url": "https://localhost/",
- "provider": {
- "name": "IGN",
- "site": "www.ign.fr",
- "mail": "sav@ign.fr"
+ "administration":{
+ "api" : {
+ "name" : "admin",
+ "version" : "1.0.0"
},
- "logs": {
- "configuration": "/home/docker/config/log4js.json"
- },
- "operations":{
- "directory": "/home/docker/app/src/resources/operations",
- "parameters": {
- "directory": "/home/docker/app/src/resources/parameters"
+ "services": [
+ {
+ "id": "main",
+ "configuration": "/home/docker/config/service.json",
+ "onStart": "true",
+ "creationType": "newProcess"
}
- },
- "resources": {
- "directories": [
- "/home/docker/data/resources/"
- ]
- },
- "network": {
- "servers": [
- {
- "id": "internalServer",
- "https": "false",
- "host": "0.0.0.0",
- "port": "8080"
- },
- {
- "id": "externalServer",
- "https": "true",
- "host": "0.0.0.0",
- "port": "443",
- "options": {
- "key": "/run/secrets/key",
- "cert": "/run/secrets/cert"
- }
- }
- ],
- "cors": {
- "configuration": "/home/docker/config/cors.json"
+ ],
+ "network" : {
+ "server" : {
+ "id": "administrator",
+ "https": "false",
+ "host": "0.0.0.0",
+ "port": "8079"
}
- },
- "projections": {
- "directory": "/home/docker/config/projections/"
+ },
+ "logs": {
+ "configuration": "/home/docker/config/log4js-administration.json"
}
}
}
diff --git a/docker/config/service.json b/docker/config/service.json
new file mode 100644
index 0000000..b9c0620
--- /dev/null
+++ b/docker/config/service.json
@@ -0,0 +1,59 @@
+{
+ "application": {
+ "name": "Road2",
+ "title": "Service de calcul d'itinéraire",
+ "description": "Ce service permet de calculer des itinéraires sur les données du Géoportail.",
+ "url": "https://localhost/",
+ "provider": {
+ "name": "IGN",
+ "site": "www.ign.fr",
+ "mail": "sav@ign.fr"
+ },
+ "logs": {
+ "configuration": "/home/docker/config/log4js-service.json"
+ },
+ "operations":{
+ "directory": "/home/docker/app/src/resources/operations",
+ "parameters": {
+ "directory": "/home/docker/app/src/resources/parameters"
+ }
+ },
+ "resources": {
+ "directories": [
+ "/home/docker/data/resources/"
+ ]
+ },
+ "network": {
+ "servers": [
+ {
+ "id": "internalServer",
+ "https": "false",
+ "host": "0.0.0.0",
+ "port": "8080"
+ },
+ {
+ "id": "externalServer",
+ "https": "true",
+ "host": "0.0.0.0",
+ "port": "443",
+ "options": {
+ "key": "/run/secrets/key",
+ "cert": "/run/secrets/cert"
+ }
+ }
+ ],
+ "cors": {
+ "configuration": "/home/docker/config/cors.json"
+ }
+ },
+ "projections": {
+ "directory": "/home/docker/config/projections/"
+ },
+ "apis": [
+ {
+ "name" : "simple",
+ "version" : "1.0.0"
+ }
+ ]
+ }
+}
diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml
index ee365b8..d4756d8 100644
--- a/docker/dev/docker-compose.yml
+++ b/docker/dev/docker-compose.yml
@@ -11,10 +11,11 @@ services:
- pgrouting
environment:
- NODE_ENV=debug
- command : "npm run debug -- --ROAD2_CONF_FILE=../config/road2.json"
+ command : "sleep 60000"
ports:
- 8080:8080
- 9229:9229
+ - 9230:9230
- 443:443
volumes:
- iti-data-volume:/home/docker/data
diff --git a/documentation/configuration/admin_model.yaml b/documentation/configuration/admin_model.yaml
new file mode 100644
index 0000000..db8b60e
--- /dev/null
+++ b/documentation/configuration/admin_model.yaml
@@ -0,0 +1,94 @@
+# Description d'un fichier de configuration d'administration
+
+# Une application est un objet qui contient toutes les informations utiles pour que l'application puisse diffuser ses services.
+"administration":
+ type: object
+ required: true
+ properties:
+ # Indication de l'api utilisée pour cette instance. Cela doit correspondre avec un dossier présent dans les APIs du projet
+ "api":
+ type: object
+ required: true
+ properties:
+ # Nom de l'api
+ "name":
+ type: string
+ required: true
+ # Version de l'api
+ "version":
+ type: string
+ required: true
+ # Configurations des services gérés par l'administrateur
+ "services":
+ type: array
+ required: true
+ minItems: 1
+ items:
+ type: object
+ properties:
+ # Id du service. Utile pour administrer le serivce via l'API
+ "id":
+ type: string
+ required: true
+ # Configuration du service. Pour le moment, c'est le fichier de configuration du service (service.json)
+ "configuration":
+ type: string
+ required: true
+ # Indiquer si on souhaite que le service soit démarré au lancement de l'admin
+ "onStart":
+ type: string
+ required: true
+ # Type de création du service. Pour le moment, il seul 'newProcess' est accepté. On crée un nouveau processus pour le service.
+ "creationType":
+ type: string
+ required: true
+ # Configuration des logs de l'application
+ "logs":
+ type: object
+ required: true
+ properties:
+ # Emplacement du fichier de configuration
+ "configuration":
+ type: string
+ required: true
+ # Configuration du network
+ "network":
+ type: object
+ required: true
+ properties:
+ # Liste des serveurs que l'on veut instancier
+ "server":
+ type: object
+ properties:
+ # Id du serveur
+ "id":
+ type: string
+ required: true
+ # Host
+ "host":
+ type: string
+ required: true
+ # Port
+ "port":
+ type: string
+ required: true
+ # Utilisation du HTTPS
+ "https":
+ type: string
+ enum: ["true", "false"]
+ required: true
+ # Options pour le HTTPS (nécessaire si https="true")
+ "options":
+ type: object
+ required: false
+ properties:
+ # Chemin du fichier .key
+ "key":
+ type: string
+ required: true
+ # Chemin du fichier .cert
+ "cert":
+ type: string
+ required: true
+
+
diff --git a/documentation/configuration/readme.md b/documentation/configuration/readme.md
index 06a0a30..ed6e663 100644
--- a/documentation/configuration/readme.md
+++ b/documentation/configuration/readme.md
@@ -2,13 +2,33 @@
## Vue globale
-Pour instancier Road2, il est nécessaire de lui fournir un certain nombre d'informations. Pour cela, il y a un unique point d'entrée qui est le *server.json*. Ce fichier va indiquer l'emplacement des autres: *log4js.json* pour les logs, le *cors.json* si on souhaite spécifier une politique de CORS, le dossier des *projections* et les dossiers des *ressources*.
+Pour instancier Road2, il est nécessaire de lui fournir un certain nombre d'informations. Pour cela, il y a différents JSON. Les fichiers que l'on va remplir vont dépendre de l'usage que l'on veut en faire. Nous allons présenter un usage complet. Ce dernier permettra de comprendre les autres usages.
-## server.json
+Un usage complet des possibilités offertes par le projet Road2 est le suivant : on veut instancier, dès le démarrage, un administrateur et son service.
+
+Dans ce cas là, nous aurons pour point d'entrée, le fichier *administration.json*.
+
+Ce fichier va indiquer plusieurs informations et deux éléments :
+- l'emplacement de la configuration des services : un *service.json* par services associés.
+- un *log4js.json* pour les logs de l'administrateur
+
+Chaque *service.json* va indiquer les éléments suivants :
+- un *log4js.json* pour les logs de l'administrateur et un par service,
+- un *cors.json* par service si on souhaite spécifier une politique de CORS,
+- le dossier des *projections*,
+- les dossiers des *ressources*.
+
+## administration.json
+
+Ce fichier indique quelques informations générales liées à l'instance d'administration. Son principal objectif est l'indication des logs et des services gérés.
+
+On peut trouver un [exemple](../../docker/config/road2.json) de ce fichier et le [modèle](./admin_model.yaml) au format YAML.
+
+## service.json
Ce fichier indique quelques informations générales liées à l'instance de Road2. Son principal objectif est l'indication des logs et des ressources du serveur. Néanmoins, il permet de préciser beaucoup plus d'informations, comme les opérations ou les projections disponibles sur l'instance.
-On peut trouver un [exemple](../../docker/config/road2.json) de ce fichier et le [modèle](./configuration_model.yaml) au format YAML.
+On peut trouver un [exemple](../../docker/config/service.json) de ce fichier et le [modèle](./service_model.yaml) au format YAML.
## log4js.json
@@ -17,7 +37,7 @@ Le format est celui d'un JSON qui contient deux objets `mainConf` et `httpConf`.
Le contenu de `mainConf` est un objet de configuration log4js. Le contenu de `httpConf` est un attribut `level` reprenant les niveaux proposés par log4js et un attribut `format` reprenant la syntaxe disponible pour log4js. Ces deux attributs doivent être présents.
-On peut trouver un [exemple](../../docker/config/log4js.json) de ce fichier au format JSON. C'est celui qui est utilisé dans les images docker.
+On peut trouver un [exemple](../../docker/config/log4js-service.json) de ce fichier au format JSON. C'est celui qui est utilisé dans les images docker.
## cors.json
diff --git a/documentation/configuration/configuration_model.yaml b/documentation/configuration/service_model.yaml
similarity index 88%
rename from documentation/configuration/configuration_model.yaml
rename to documentation/configuration/service_model.yaml
index 37e0750..5edef64 100644
--- a/documentation/configuration/configuration_model.yaml
+++ b/documentation/configuration/service_model.yaml
@@ -1,4 +1,4 @@
-# Description d'un fichier de configuration de l'application Road4
+# Description d'un fichier de configuration de service
# Une application est un objet qui contient toutes les informations utiles pour que l'application puisse diffuser ses services.
"application":
@@ -138,3 +138,18 @@
"directory":
type: string
required: true
+ # Indication des apis utilisées pour cette instance. Cela doit correspondre avec un dossier présent dans les APIs du projet
+ "apis":
+ required: true
+ minItems: 1
+ items:
+ type: object
+ properties:
+ # Nom de l'api
+ "name":
+ type: string
+ required: true
+ # Version de l'api
+ "version":
+ type: string
+ required: true
diff --git a/documentation/developers/concepts.md b/documentation/developers/concepts.md
index d154121..ee3e3fe 100644
--- a/documentation/developers/concepts.md
+++ b/documentation/developers/concepts.md
@@ -112,7 +112,23 @@ Cette partie décrit l'application de ces concepts dans le code au cours d'une e
### 2.1 Au lancement de l'application
-Road2 est un serveur web. Son point d'entrée est le fichier `src/js/road2.js`. Ce fichier va générer une instance de la classe `Service`.
+Le projet Road2 propose deux serveurs web, un service et un administrateur. Il donc possède deux points d'entrée selon l'usage que l'on souhaite en faire. On peut lancer uniquement le service et cela fonctionnera très bien. Et on peut aussi lancer un administrateur uniquement. Celui-ci lancera un service quand on le lui demandera. Enfin, on peut lancer les deux d'un coup.
+
+#### 2.1.1 Lancement de l'administrateur
+
+Le premier point d'entrée possible est le fichier `src/js/road2.js`. Ce fichier va générer une instance de la classe `Administrator`.
+
+Cet administrateur permet plusieurs choses :
+- On peut le lancer uniquement pour vérifier la bonne configuration de l'administrateur et des services associés. Dans ce cas là, le processus s'éteint après la vérification et renvoie un code d'erreur permettant de déterminer s'il y a eu un problème et son type.
+- On peut le lancer en mode serveur pour administrer un ou plusieurs services via une API HTTP(S). Dans ce cas là, il est possible de lui demander de lancer les service à son démarrage. Il sera aussi possible de les démarrer plus tard.
+
+Un administrateur a été créé pour réaliser des tâches qui auraient gêné la bonne exécution du service.
+
+L'administrateur a donc été créé pour être indépendant du service. Si l'administrateur a des tâches fastidieuses, cela n'impacte pas le service. Si l'un tombe, l'autre non.
+
+#### 2.1.2 Lancement d'un service
+
+Le point d'entrée historique est le fichier `src/js/service/main.js`. Ce fichier va générer une instance de la classe `Service`.
Ce service est l'objet qui permet de gérer les ressources proposées par l'instance en cours. Il contient donc un catalogue de ressources et un manager de ressources.
@@ -122,7 +138,25 @@ Lorsque l'application est lancée, on commence par lire la configuration de l'ap
Après cela, on charge les ressources et les sources du service indiquées dans la configuration. C'est à ce moment que les fichiers sont lus, stockés en RAM si nécessaire, et que les connexions aux bases de données sont effectuées.
-Enfin, on finit par charger les APIs exposées par le service. C'est là qu'ExpressJS crée le ou les serveurs Node et charge les routes disponibles.
+Enfin, on finit par charger les APIs exposées par le service. C'est là qu'ExpressJS crée le ou les serveurs Node et charge les routes disponibles.
+
+#### 2.1.3 Zoom sur la vérification de la configuration
+
+Que ce soit un administrateur ou un service, la configuration sera vérifiée.
+
+Cela passe généralement par des managers.
+
+##### Les managers
+
+La plupart des classes ont un manager. Ce manager permet comme précisé juste avant de vérifier les configurations. Mais il permet aussi de créer les instances des classes concernées. Enfin, il garde aussi un trace des différentes instances et permet donc de les gérer.
+
+Les managers sont conçus pour être utilisés de la manière suivante : on le crée sans configuration. Par contre, il peut avoir d'autres managers en paramètre.
+Une fois créé, ce manager peut être utilisé pour vérifier une configuration. On peut lui donner la configuration d'un objet ou on peut parfois lui donner un ensemble de configuration. Dans ce deuxième cas, il y aura généralement une cohérence à vérifier entre chaque configuration.
+Ensuite, on pourra charger des objets à partir de leur configuration. Il est important de faire un check avant un load. Car les load présupposent la validité de la configuration. Ce qui est connu par un check. De la même manière, on pourra parfois en charger plusieurs par un seul appel au manager. Le fait de charger une seule fois une configuration présente en divers endroits sera géré dans le manager.
+
+Pour bien fonctionner, le manager aura donc deux listes. Une liste plutôt éphémère qui gardera une trace des configurations déjà vérifiées. Elle servira à vérifier la cohérence de l'ensemble des configurations. Cette liste devra être vidée quand les vérifications seront terminées.
+La deuxième liste sera une liste des configurations déjà chargées. Cette liste est persistante et indique l'état du manager. Elle sert à s'assurer que l'on charge une seule fois chaque configuration même si elle est demandée plusieurs fois.
+Aussi, quand on souhaitera modifier la configuration durant la vie de l'application, c'est cette liste qui sera considérée la première pour vérifier la cohérence. La première liste ne sera réutilisée que si c'est un ensemble censé être cohérent que l'on vérifie.
### 2.2 : A la réception d'une requête
diff --git a/documentation/developers/readme.md b/documentation/developers/readme.md
index 5edb197..088204c 100644
--- a/documentation/developers/readme.md
+++ b/documentation/developers/readme.md
@@ -16,11 +16,17 @@ L'ensemble des fonctionnalités sont répertoriées à [part](./functionnalities
## Participer aux développements
-Les participations à ce projet sont encouragées. L'ajout de moteurs ou d'API, bien évidemment. Mais toutes autres fonctionnalités sont les bienvenues. Nous avons mis en place une [documentation](./modification.md) afin de faciliter des développements.
+Les participations à ce projet sont encouragées. L'ajout de moteurs ou d'API, bien évidemment. Mais toutes autres fonctionnalités sont les bienvenues.
+
+### Prise en main du projet
+
+Nous avons mis en place une [documentation](./modification.md) afin de faciliter la prise en main du projet.
### GIT
-Comme cela aura certainement déjà été compris, ce projet utilise GIT. La gestion des branches et des versions pour les développements est détaillée [ici](./version.md).
+Afin de pousser des développements sur le projet, ces derniers doivent être fournis par l'intermédiaire de `Pull Request` depuis votre branche vers la branche `develop` du projet.
+
+Plus généralement, la gestion des branches et des versions pour les développements est détaillée [ici](./version.md).
## Outils pour le développement
diff --git a/package.json b/package.json
index ef2427c..83c4c1b 100644
--- a/package.json
+++ b/package.json
@@ -11,10 +11,10 @@
"utest": "mocha --recursive './test/unit/mocha/**/*.js'",
"itest": "mocha --recursive './test/integration/mocha/**/*.js'",
"rtest": "HTTP_PROXY='' ./node_modules/cucumber/bin/cucumber-js ./test/functional/request/cucumber/features/req*.feature",
- "ctest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/configuration/cucumber/features/configuration*.feature",
+ "ctest": "./node_modules/cucumber/bin/cucumber-js ./test/functional/configuration/cucumber/features/conf*.feature",
"lint": "eslint -c eslint.json ./src/",
"jsdoc": "jsdoc -c jsdoc.json",
- "debug": "node --inspect=0.0.0.0:9229 ./src/js/road2.js"
+ "debug": "env NODE_ENV=debug node --inspect=0.0.0.0:9229 ./src/js/road2.js"
},
"dependencies": {
"@mapbox/polyline": "1.1.1",
diff --git a/readme.md b/readme.md
index 72c7f32..627a1c1 100644
--- a/readme.md
+++ b/readme.md
@@ -71,7 +71,7 @@ Afin que le serveur fonctionne, il est nécessaire de le [configurer](./document
### Lancement
-Une fois configuré, il est possible de lancer le serveur avec la commande:
+Une fois configuré, il est possible de lancer une instance de Road2 avec la commande:
```
node ${road2}/src/js/road2.js --ROAD2_CONF_FILE=${configuration}/server.json
```
diff --git a/src/js/administrator/administrator.js b/src/js/administrator/administrator.js
new file mode 100644
index 0000000..32ba3bd
--- /dev/null
+++ b/src/js/administrator/administrator.js
@@ -0,0 +1,479 @@
+'use strict';
+
+const express = require('express');
+const log4js = require('log4js');
+const helmet = require('helmet');
+const path = require('path');
+const fs = require('fs');
+const assert = require('assert').strict;
+const serverManager = require('../server/serverManager');
+const serviceManager = require('../service/serviceManager');
+const apisManager = require('../apis/apisManager');
+
+// Création du LOGGER
+const LOGGER = log4js.getLogger("ADMINISTRATOR");
+
+/**
+*
+* @class
+* @name Administrator
+* @description Pour chaque démarrage de Road2, il y a un Administrateur qui gère les services rendus. C'est un serveur qui écoute sur un port différent des serveurs des services.
+*
+*/
+
+module.exports = class Administrator {
+
+ /**
+ *
+ * @function
+ * @name constructor
+ * @description Constructeur de la classe Administrator
+ *
+ */
+
+ constructor() {
+
+ // Manager des serveurs, il contient la liste des serveurs diponibles
+ this._serverManager = new serverManager();
+
+ // APIs utilisées pour parler avec l'administrateur
+ this._apisManager = new apisManager();
+
+ // Manager des services gérés par l'administrateur
+ this._serviceManager = new serviceManager();
+
+ // Configuration de l'administration
+ this._configuration = {};
+
+ // Chemin absolu de la configuration
+ this._configurationPath = "";
+
+ // Configuration des logs
+ this._logConfiguration = {};
+
+
+ }
+
+ /**
+ *
+ * @function
+ * @name checkAdminConfiguration
+ * @description Vérifier la partie administration de la configuration
+ * @param {json} configuration - Configuration de Road2 (contenu du server.json)
+ * @param {string} configurationPath - Chemin de la configuration de Road2 (chemin du server.json)
+ *
+ */
+
+ checkAdminConfiguration(configuration, configurationPath) {
+
+ LOGGER.info("Verification de la configuration de l'administrateur...");
+
+ // Fichier complet
+ if (!configuration) {
+ LOGGER.error("Configuration absente");
+ return false;
+ } else {
+ LOGGER.debug("Configuration présente");
+ }
+
+ // Partie administration
+ if (!configuration.administration) {
+ LOGGER.error("Mauvaise configuration: 'administration' absent.");
+ return false;
+ } else {
+ LOGGER.debug("configuration.administration présent");
+ }
+
+ // Services à administrer
+ if (!configuration.administration.services) {
+ LOGGER.error("Mauvaise configuration: 'administration.services' absent.");
+ return false;
+ } else {
+ LOGGER.debug("configuration.administration.services présent");
+
+ if (!Array.isArray(configuration.administration.services)) {
+ LOGGER.error("Mauvaise configuration: 'administration.services' n'est pas un tableau.");
+ return false;
+ } else {
+
+ LOGGER.debug("configuration.administration.services est bien un tableau");
+
+ if (configuration.administration.services.length === 0) {
+ LOGGER.error("Mauvaise configuration: 'administration.services' est un tableau vide.");
+ return false;
+ } else {
+ LOGGER.debug("configuration.administration.services est bien un tableau qui contient des éléments");
+ }
+
+ }
+ }
+
+ // On ne veut pas que les Id soient réutilisés
+ let checkedServiceId = new Array();
+ let checkedServiceConf = new Array();
+ let checkedServiceConfLocation = new Array();
+
+ for (let i = 0; i < configuration.administration.services.length; i++) {
+
+ let curServiceConf = configuration.administration.services[i];
+
+ let configurationLocation = "";
+ let configurationContent = {};
+
+ if (!curServiceConf.id) {
+ LOGGER.error("Mauvaise configuration: 'id' absent.");
+ return false;
+ } else {
+
+ if (typeof(curServiceConf.id) !== "string") {
+ LOGGER.error("Mauvaise configuration: 'id' n'est pas une string.");
+ return false;
+ }
+ if (curServiceConf.id === "") {
+ LOGGER.error("Mauvaise configuration: 'id' est une string vide.");
+ return false;
+ }
+
+ LOGGER.debug("Id présent : " + curServiceConf.id);
+
+ // On vérifie que l'id n'est pas déjà pris
+ if (checkedServiceId.length === 0) {
+ // On continue la suite de la vérification
+ } else {
+
+ for (let j = 0; j < checkedServiceId.length; j++) {
+ if (curServiceConf.id === checkedServiceId[j]) {
+ LOGGER.error("Id de service déjà pris : " + curServiceConf.id);
+ return false;
+ }
+ }
+
+ }
+
+ }
+
+ if (!curServiceConf.configuration) {
+ LOGGER.error("Mauvaise configuration: 'configuration' absent.");
+ return false;
+ } else {
+
+ LOGGER.debug("configuration présent");
+
+ try {
+ configurationLocation = path.resolve(path.dirname(this._configurationPath), curServiceConf.configuration);
+ LOGGER.debug("Chemin absolu du fichier de configuration du service : " + configurationLocation);
+ } catch (error) {
+ LOGGER.error("Can't get absolute path of service configuration: " + curServiceConf.configuration);
+ LOGGER.error(error);
+ return false;
+ }
+
+ // On vérifie que ce chemin n'est pas déjà utilisé
+ if (checkedServiceConfLocation.length !== 0) {
+ for (let cs = 0; cs < checkedServiceConfLocation.length; cs++) {
+ if (configurationLocation === checkedServiceConfLocation[cs]) {
+ LOGGER.error("La configuration indiquée est déjà vérifiée. Elle ne peut être utilisée pour un autre service géré par cet administrateur.");
+ return false;
+ }
+ }
+ }
+
+ try {
+ // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard
+ configurationContent = JSON.parse(fs.readFileSync(configurationLocation));
+ LOGGER.debug("Le contenu du fichier est accessible par Road2");
+ } catch (error) {
+ LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de configuration du service: " + configurationLocation);
+ LOGGER.error(error);
+ return false;
+ }
+
+ // On vérifie que ce contenu n'est pas déjà utilisé
+ if (checkedServiceConf.length !== 0) {
+ for (let cs = 0; cs < checkedServiceConf.length; cs++) {
+ try {
+ assert.deepStrictEqual(configurationContent, checkedServiceConf[cs]);
+ LOGGER.error("Le contenu de configuration indiqué est déjà vérifié pour un autre service. Il ne peut être utilisée pour plus d'un service géré par cet administrateur.");
+ return false;
+ } catch (err) {
+ LOGGER.debug("Les deux configuration de service ne sont pas identiques.");
+ }
+ }
+ }
+
+
+
+ }
+
+ if (!curServiceConf.onStart) {
+ LOGGER.error("Mauvaise configuration: 'onStart' absent.");
+ return false;
+ } else {
+
+ LOGGER.debug("configuration.onStart présent");
+
+ if (curServiceConf.onStart !== "true" && curServiceConf.onStart !== "false") {
+ LOGGER.error("Mauvaise configuration: 'onStart' doit être 'true' ou 'false'.");
+ return false;
+ } else {
+ LOGGER.debug("configuration.onStart bien configuré");
+ }
+
+ }
+
+ if (!curServiceConf.creationType) {
+ LOGGER.error("Mauvaise configuration: 'creationType' absent.");
+ return false;
+ } else {
+
+ LOGGER.debug("configuration.creationType présent");
+
+ if (!["sameProcess","newProcess","findByURI"].includes(curServiceConf.creationType)) {
+ LOGGER.error("Mauvaise configuration: 'creationType' doit être parmi 'sameProcess', 'newProcess', 'findByURI'.");
+ return false;
+ } else {
+ LOGGER.debug("configuration.creationType bien configuré");
+ }
+
+ }
+
+ LOGGER.debug("Vérification du service en cours terminée");
+ checkedServiceId.push(curServiceConf.id);
+ checkedServiceConf.push(configurationContent);
+ checkedServiceConfLocation.push(configurationLocation);
+
+
+ }
+
+ LOGGER.debug("Vérification des services terminée");
+
+ // API utilisée pour administrer
+ if (!configuration.administration.api) {
+ LOGGER.fatal("Mauvaise configuration: 'administration.api' absent.");
+ return false;
+ } else {
+ LOGGER.debug("configuration.administration.api présent");
+ }
+
+ if (!this._apisManager.checkApiConfiguration(configuration.administration.api)) {
+ LOGGER.fatal("Mauvaise configuration: 'administration.api' mal configuré.");
+ return false;
+ } else {
+ LOGGER.debug("configuration.administration.api bien configuré");
+ }
+
+ // Partie network de l'administrateur
+ if (!configuration.administration.network) {
+ LOGGER.fatal("Mauvaise configuration: 'administration.network' absent.");
+ return false;
+ } else {
+ LOGGER.debug("configuration.administration.network présent");
+ }
+
+ if (!configuration.administration.network.server) {
+ LOGGER.fatal("Mauvaise configuration: 'administration.network.server' absent.");
+ return false;
+ } else {
+ LOGGER.debug("configuration.administration.network.server présent");
+ }
+
+ if (!this._serverManager.checkServerConfiguration(configuration.administration.network.server)){
+ LOGGER.fatal("Mauvaise configuration: 'administration.network.server' mal configuré.");
+ return false;
+ } else {
+ LOGGER.debug("configuration.administration.network.server bien configuré");
+ }
+
+ LOGGER.info("La configuration de l'administrateur est correcte");
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name saveAdminConfiguration
+ * @description Sauvegarder la partie administration de la configuration
+ * @param {json} configuration - Configuration de Road2 (contenu du server.json)
+ * @param {string} configurationPath - Chemin de la configuration de Road2 (chemin du server.json)
+ * @param {json} logConfiguration - Configuration des logs Road2 (contenu du log4js-administrator.json)
+ *
+ */
+
+ saveAdminConfiguration(configuration, configurationPath, logConfiguration) {
+
+ LOGGER.info("Sauvegarde de la configuration de l'administrateur dans son instance...");
+
+ this._configuration = configuration;
+ this._configurationPath = configurationPath;
+ this._logConfiguration = logConfiguration;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name createServer
+ * @description Création et démarrage du serveur pour l'administration
+ *
+ */
+
+ createServer() {
+
+ LOGGER.info("Creation de l'application web Express...");
+
+ // Application Express
+ let administrator = express();
+
+ // Gestion des en-têtes avec helmet selon les préconisations d'ExpressJS
+ administrator.use(helmet());
+
+ // Pour le log des requêtes reçues sur le service avec la syntaxe
+ LOGGER.info("Instanciation du logger pour les requêtes...");
+
+ try {
+
+ administrator.use(log4js.connectLogger(log4js.getLogger('request'), {
+ level: this._logConfiguration.httpConf.level,
+ format: (req, res, format) => format(this._logConfiguration.httpConf.format)
+ }));
+
+ } catch (error) {
+ LOGGER.fatal("Impossible de connecter le logger pour les requetes: ");
+ LOGGER.error(this._logConfiguration.httpConf)
+ LOGGER.error(error);
+ return false;
+ }
+
+ // Chargement de l'API
+ LOGGER.info("Chargement de l'API d'administration...");
+ if (!this._apisManager.loadApiConfiguration(administrator, this._configuration.administration.api)) {
+ LOGGER.error("Erreur lors du chargement de l'API.");
+ return false;
+ } else {
+ LOGGER.debug("API chargée");
+ }
+
+ administrator.all('/', (req, res) => {
+ res.send('Road2 Administrator');
+ });
+
+ // Création du serveur
+ LOGGER.info("Création du serveur d'administration...");
+ if (!this._serverManager.loadServerConfiguration(administrator, this._configuration.administration.network.server)) {
+ LOGGER.fatal("Impossible de creer le serveur d'administration.");
+ return false;
+ } else {
+ LOGGER.debug("Serveur d'administration créé");
+ }
+
+ // Démarrage du serveur
+ LOGGER.info("Démarrage du serveur d'administration...");
+ if (!this._serverManager.startAllServers()) {
+ LOGGER.fatal("Impossible de démarrer le serveur d'administration.");
+ return false;
+ } else {
+ LOGGER.debug("Serveur d'administration démarré");
+ }
+
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name checkServicesConfiguration
+ * @description Vérification de la configuration des services indiqués dans server.json
+ *
+ */
+
+ async checkServicesConfiguration() {
+
+ LOGGER.info("Vérification de la configuration des services...");
+
+ for (let i = 0; i < this._configuration.administration.services.length; i++) {
+
+ let curIASConf = this._configuration.administration.services[i];
+ LOGGER.debug("Vérification du service : " + curIASConf.id);
+
+ // Récupération de la configuration
+ let file = path.resolve(path.dirname(this._configurationPath), curIASConf.configuration);
+ let serviceConfiguration = JSON.parse(fs.readFileSync(file));
+
+ // Vérification
+ if (!(await this._serviceManager.checkServiceConfiguration(serviceConfiguration, file))) {
+ LOGGER.error("La configuration du service "+ curIASConf.id +" est incorrecte");
+ return false;
+ } else {
+ LOGGER.info("La configuration du service "+ curIASConf.id +" est correcte");
+ }
+
+
+ }
+
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name createServicesOnStart
+ * @description Création des services gérés par cet administrateur dont la création a été demandé au démarrage de l'administrateur
+ *
+ */
+
+ async createServicesOnStart() {
+
+ LOGGER.info("Vérification et création des services onStart=true...");
+
+ // Pour chaque service, on va voir s'il doit être démarré
+ // Si oui, on vérifie sa configuration puis on le démarre
+
+ for (let i = 0; i < this._configuration.administration.services.length; i++) {
+
+ let curIASConf = this._configuration.administration.services[i];
+ LOGGER.debug("Analyse du service : " + curIASConf.id);
+
+ if (curIASConf.onStart === "false") {
+ // il n'y a rien à faire
+ LOGGER.debug("Le service " + curIASConf.id + " n'est à démarrer tout de suite");
+ continue;
+ } else {
+ LOGGER.info("Le service " + curIASConf.id + " est à démarrer");
+ }
+
+ // Récupération de la configuration
+ LOGGER.info("Récupération de la configuration du service");
+ let serviceConfLocation = path.resolve(path.dirname(this._configurationPath), curIASConf.configuration);
+ let serviceConfiguration = JSON.parse(fs.readFileSync(serviceConfLocation));
+
+ // Vérification de la configuration
+ LOGGER.info("Vérification de la configuration...");
+ if (!(await this._serviceManager.checkServiceConfiguration(serviceConfiguration, serviceConfLocation))) {
+ LOGGER.error("La configuration du service "+ curIASConf.id +" est incorrecte");
+ return false;
+ } else {
+ LOGGER.info("La configuration du service "+ curIASConf.id +" est correcte");
+ }
+
+ // Chargement du service
+ LOGGER.info("Chargement du service...");
+ if (!this._serviceManager.loadService(curIASConf.creationType, curIASConf.id, serviceConfLocation, serviceConfiguration)) {
+ LOGGER.error("Impossible de créer le service "+ curIASConf.id);
+ // On essaye les suivants
+ continue;
+ } else {
+ LOGGER.info("Le service " + curIASConf.id + " a été lancé correctement");
+ }
+
+ }
+
+ return true;
+
+ }
+
+}
+
+
diff --git a/src/js/apis/apisManager.js b/src/js/apis/apisManager.js
index df9c68a..5cbf799 100644
--- a/src/js/apis/apisManager.js
+++ b/src/js/apis/apisManager.js
@@ -19,7 +19,13 @@ module.exports = class apisManager {
*/
constructor() {
- // Liste des routes chargées par app
+ // Dossier contenant les APIs du projet
+ this._apisDirectory = "../apis/";
+
+ // Prefix utilisé pour chaque route des APIS
+ this._prefix = "";
+
+ // Liste des routes chargées par l'app Express
this._listOfRoutes = new Array();
// Catalogue des apis
@@ -27,6 +33,28 @@ module.exports = class apisManager {
}
+ /**
+ *
+ * @function
+ * @name get apisDirectory
+ * @description Récupérer le chemin du dossier qui contient les APIs
+ *
+ */
+ get apisDirectory () {
+ return this._apisDirectory;
+ }
+
+ /**
+ *
+ * @function
+ * @name get prefix
+ * @description Récupérer le prefix utilisé par ce manager
+ *
+ */
+ get prefix () {
+ return this._prefix;
+ }
+
/**
*
* @function
@@ -54,31 +82,119 @@ module.exports = class apisManager {
* @function
* @name getApi
* @description Récupérer l'api qui correspond à l'id et la version demandée
- * @param {string} id - Id de l'api concerné (simple)
+ * @param {string} name - Nom de l'api concerné (simple)
* @param {string} version - Version de l'api concerné (1.0.0)
*
*/
- getApi (id, version) {
- return this._apisCatalog[id+version];
+ getApi (name, version) {
+ return this._apisCatalog[name+version];
+ }
+
+ /**
+ *
+ * @function
+ * @name checkApiConfiguration
+ * @description Vérifier la configuration d'une API
+ * @param {object} configuration - Configuration de l'API à vérifier
+ * @return {boolean}
+ *
+ */
+ checkApiConfiguration (configuration) {
+
+ // Nom de l'API
+ if (!configuration.name) {
+
+ LOGGER.error("Mauvaise configuration de l'api: 'name' absent.");
+ return false;
+
+ } else {
+
+ if (typeof configuration.name !== "string") {
+ LOGGER.error("Mauvaise configuration: 'name' n'est pas une string.");
+ return false;
+ } else {
+
+ // On vérifie que le dossier correspondant existe
+ let tmpPathName = path.resolve(__dirname, this._apisDirectory) + "/" + configuration.name;
+ let availableAPI = false;
+ try {
+ availableAPI= fs.statSync(tmpPathName).isDirectory()
+ } catch(error) {
+ LOGGER.error("Mauvaise configuration: 'name' ne peut être évalué.");
+ return false;
+ }
+
+ if (!availableAPI) {
+ LOGGER.error("Mauvaise configuration de l'api: 'name' n'est pas disponible.");
+ return false;
+ } else {
+
+ // Version de l'API
+ if (!configuration.version) {
+ LOGGER.error("Mauvaise configuration de l'api: 'version' absent.");
+ return false;
+ } else {
+
+ if (typeof configuration.name !== "string") {
+ LOGGER.error("Mauvaise configuration de l'api: 'name' n'est pas une string.");
+ return false;
+ } else {
+
+ // On vérifie que le dossier correspondant existe
+ let tmpPathVersion = tmpPathName + "/" + configuration.version;
+ let availableVersion = false;
+
+ try {
+ availableVersion= fs.statSync(tmpPathVersion).isDirectory()
+ } catch(error) {
+ LOGGER.error("Mauvaise configuration de l'api: 'version' ne peut être évalué.");
+ return false;
+ }
+
+ if (!availableVersion) {
+ LOGGER.error("Mauvaise configuration de l'api: 'version' n'est pas disponible.");
+ return false;
+ } else {
+
+ // On vérifie qu'il y a au moins un index.js
+ let tmpIndex = tmpPathVersion + "/index.js";
+ try {
+ fs.accessSync(tmpIndex, fs.constants.R_OK);
+ return true;
+ } catch (err) {
+ LOGGER.error("Le fichier " + tmpIndex + " ne peut etre lu.");
+ return false;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
}
/**
*
* @function
- * @name loadAPISDirectory
+ * @name loadApiDirectory
* @description Fonction utilisée pour charger l'ensemble des APIs disponibles dans un dossier.
* @param {express} app - Objet créé par ExpressJS représentant l'application
- * @param {string} dir - Dossier contenant les routers à charger dans app
- * @param {string} prefix - Préfixe utilisé pour chaque router ajouté
*
*/
- loadAPISDirectory (app, dir, prefix) {
+ loadApiDirectory (app) {
LOGGER.info("Chargement des APIS...");
- // Soit dir est un chemin absolu qui pointe vers un autre repo d'APIs, soit c'est celui du repo officiel de Road2 (usage de __dirname)
- let APIsDirectory = path.resolve(__dirname, dir);
+ // Soit _apisDirectory est un chemin absolu qui pointe vers un autre repo d'APIs, soit c'est celui du repo officiel de Road2 (usage de __dirname)
+ let APIsDirectory = path.resolve(__dirname, this._apisDirectory);
// on lit le contenu du dossier
let APIsDirectoryTable = new Array();
@@ -126,86 +242,119 @@ module.exports = class apisManager {
// c'est un dossier qui contient potentiellement une version de l'API
LOGGER.info("Nouvelle version: " + apiVersion);
- let APIFile = APIDirectoryVersion + "/index.js";
- //on cherche le fichier index.js qui contient la description de l'API
- if (fs.statSync(APIFile).isFile()) {
-
- // Gestion du router
- // ------------------
- let route;
-
- if (prefix !== "") {
- route = "/" + prefix + "/" + apiName + "/" + apiVersion;
- } else {
- route = "/"+ apiName + "/" + apiVersion;
- }
- // On vérifie que la route n'existe pas déjà
- if (this.verifyRouteExistanceById(route)) {
- // Si elle existe c'est un vrai problème donc on arrête le chargement
- LOGGER.error("La route " + route + " existe deja. L'api n'est donc pas chargee.");
- return false;
- }
+ let configuration = {
+ name: apiName,
+ version: apiVersion
+ };
- // on crée un objet Api qui va permettre de suivre l'évolution de l'api au cours de la vie du service
- let api = new Api(apiName, apiVersion, APIFile);
+ if (!this.loadApiConfiguration(app, configuration)) {
+ LOGGER.error("Impossible de charger l'API " + apiName + "/" + apiVersion);
+ }
- // Gestion de l'initialisation de l'api
- // ----------------------
- let initFile = APIDirectoryVersion + "/init.js";
- try {
+ } else {
+ // Si ce n'est pas un dossier, on ne fait rien
+ }
- fs.statSync(initFile);
- api.initFile = initFile;
+ }
- } catch(err) {
- // Ce n'est pas obligatoire, on ne fait donc rien
- }
+ } else {
+ // Si ce n'est pas un dossier, on ne fait rien
+ }
- // ----------------------
+ }
- // Gestion de l'update de l'api
- // ----------------------
- let updateFile = APIDirectoryVersion + "/update.js";
- try {
+ LOGGER.info("APIS chargees.");
+ return true;
- fs.statSync(updateFile);
- api.updateFile = updateFile;
+ }
- } catch(err) {
- // Ce n'est pas obligatoire, on ne fait donc rien
- }
- // ----------------------
+ /**
+ *
+ * @function
+ * @name loadApiConfiguration
+ * @description Fonction utilisée pour charger l'API d'un seul dossier
+ * @param {express} app - Objet créé par ExpressJS représentant l'application
+ * @param {object} configuration - Configuration d'une API
+ *
+ */
- if (!api.initialize(route, app)) {
- LOGGER.error("L'initialisation de l'api s'est mal deroulee.");
- return false;
- }
+ loadApiConfiguration (app, configuration) {
- // on stocke l'objet Api dans l'apiManager
- this._apisCatalog[apiName+apiVersion] = api;
- // on stocke la route
- this._listOfRoutes.push(route);
+ let apiName = configuration.name;
+ let apiVersion = configuration.version;
- } else {
- // le fichier index.js n'existe pas donc on ne fait rien
- LOGGER.error("Pas de fichier index.js dans le dossier " + APIDirectoryVersion);
- }
+ // Soit _apisDirectory est un chemin absolu qui pointe vers un autre repo d'APIs, soit c'est celui du repo officiel de Road2 (usage de __dirname)
+ let APIDirectory = path.resolve(__dirname, this._apisDirectory) + "/" + apiName + "/" + apiVersion;
- } else {
- // Si ce n'est pas un dossier, on ne fait rien
- }
+ let APIFile = APIDirectory + "/index.js";
+ //on cherche le fichier index.js qui contient la description de l'API
+ if (fs.statSync(APIFile).isFile()) {
- }
+ // Gestion du router
+ // ------------------
+ let route;
+ if (this._prefix !== "") {
+ route = "/" + this._prefix + "/" + apiName + "/" + apiVersion;
} else {
- // Si ce n'est pas un dossier, on ne fait rien
+ route = "/"+ apiName + "/" + apiVersion;
}
- }
+ // On vérifie que la route n'existe pas déjà
+ if (this.verifyRouteExistanceById(route)) {
+ // Si elle existe c'est un vrai problème donc on arrête le chargement
+ LOGGER.error("La route " + route + " existe deja. L'api n'est donc pas chargee.");
+ return false;
+ }
- LOGGER.info("APIS chargees.");
- return true;
+ // on crée un objet Api qui va permettre de suivre l'évolution de l'api au cours de la vie du service
+ let api = new Api(apiName, apiVersion, APIFile);
+
+ // Gestion de l'initialisation de l'api
+ // ----------------------
+ let initFile = APIDirectory + "/init.js";
+ try {
+
+ fs.statSync(initFile);
+ api.initFile = initFile;
+
+ } catch(err) {
+ // Ce n'est pas obligatoire, on ne fait donc rien
+ }
+
+ // ----------------------
+
+ // Gestion de l'update de l'api
+ // ----------------------
+ let updateFile = APIDirectory + "/update.js";
+ try {
+
+ fs.statSync(updateFile);
+ api.updateFile = updateFile;
+
+ } catch(err) {
+ // Ce n'est pas obligatoire, on ne fait donc rien
+ }
+ // ----------------------
+
+ if (!api.initialize(route, app)) {
+ LOGGER.error("L'initialisation de l'api s'est mal deroulee.");
+ return false;
+ }
+
+ // on stocke l'objet Api dans l'apisManager
+ this._apisCatalog[apiName+apiVersion] = api;
+ // on stocke la route
+ this._listOfRoutes.push(route);
+
+ return true;
+
+ } else {
+ // le fichier index.js n'existe pas donc on ne fait rien
+ LOGGER.error("Pas de fichier index.js dans le dossier " + APIDirectory);
+ return false;
+ }
}
diff --git a/src/js/apis/simple/1.0.0/init.js b/src/js/apis/simple/1.0.0/init.js
index 63eb3f2..1ce8980 100644
--- a/src/js/apis/simple/1.0.0/init.js
+++ b/src/js/apis/simple/1.0.0/init.js
@@ -588,7 +588,7 @@ module.exports = {
// --- resources
getCapabilities.resources = new Array();
- let resources = service.resourceCatalog;
+ let resources = service.getResources();
for(let resourceId in resources) {
diff --git a/src/js/base/base.js b/src/js/base/base.js
index e4231f8..b20e576 100644
--- a/src/js/base/base.js
+++ b/src/js/base/base.js
@@ -86,11 +86,15 @@ module.exports = class Base {
throw errorManager.createError("PG is not available");
}
+ // TODO : supprimer le return si pas utile
+ // return new Promise();
+
} catch (err) {
LOGGER.error("connection error", err.stack)
throw errorManager.createError("Cannot connect to database");
}
+
}
/**
diff --git a/src/js/base/baseManager.js b/src/js/base/baseManager.js
index d6c20cd..0866f49 100644
--- a/src/js/base/baseManager.js
+++ b/src/js/base/baseManager.js
@@ -1,7 +1,6 @@
'use strict';
const log4js = require('log4js');
-const path = require('path');
const fs = require('fs');
const Base = require('./base');
@@ -26,8 +25,12 @@ module.exports = class baseManager {
*/
constructor() {
- // Liste des descriptions de bases vérifiées et validées par le manager
- this._listOfVerifiedDbConfig = new Array();
+ // Liste des descriptions de bases déjà chargées par le manager
+ this._loadedBaseConfiguration = new Array();
+
+ // Liste des descriptions de bases déjà vérifiées par le manager et qui doivent être cohérentes avec les prochaines qui seront vérifiés
+ // Cet objet doit être vidé quand l'ensemble des configurations a été vérifié
+ this._checkedBaseConfiguration = new Array();
// Le catalogue des bases créées par le manager
this._baseCatalog = {};
@@ -37,12 +40,12 @@ module.exports = class baseManager {
/**
*
* @function
- * @name get listOfVerifiedDbConfig
- * @description Récupérer la liste des configurations
+ * @name get loadedBaseConfiguration
+ * @description Récupérer la liste des configurations déjà chargées par ce manager
*
*/
- get listOfVerifiedDbConfig() {
- return this._listOfVerifiedDbConfig;
+ get loadedBaseConfiguration() {
+ return this._loadedBaseConfiguration;
}
/**
@@ -59,20 +62,45 @@ module.exports = class baseManager {
/**
*
* @function
- * @name checkBase
+ * @name getBase
+ * @description Récupérer une base par sa configuration
+ * @param {string} configPath - Chemin de la configuration
+ *
+ */
+ getBase(configPath) {
+ return this._baseCatalog[configPath];
+ }
+
+ /**
+ *
+ * @function
+ * @name checkBaseConfiguration
* @description Vérification de la description de la configuration à une base de données.
* @param{string} dbConfigPath - Nom du fichier contenant les informations de connexion à la base (chemin absolu)
*
*/
- async checkBase(dbConfigPath) {
+ async checkBaseConfiguration(dbConfigPath) {
LOGGER.info("Verification de la configuration de la base de donnees...");
- if (this._listOfVerifiedDbConfig.length !== 0) {
+ if (this._loadedBaseConfiguration.length !== 0) {
+
+ for (let i = 0; i < this._loadedBaseConfiguration.length; i++) {
+ if (dbConfigPath === this._loadedBaseConfiguration[i]) {
+ LOGGER.info("Configuration deja chargée.")
+ return true;
+ }
+ }
- for (let i = 0; i < this._listOfVerifiedDbConfig.length; i++) {
- if (dbConfigPath === this._listOfVerifiedDbConfig[i]) {
- LOGGER.info("Configuration deja verifiee.")
+ } else {
+ // C'est le premier, donc on continue
+ }
+
+ if (this._checkedBaseConfiguration.length !== 0) {
+
+ for (let i = 0; i < this._checkedBaseConfiguration.length; i++) {
+ if (dbConfigPath === this._checkedBaseConfiguration[i]) {
+ LOGGER.info("Configuration deja vérifiée.")
return true;
}
}
@@ -105,7 +133,7 @@ module.exports = class baseManager {
return false;
}
- const base = new Base(configuration);
+ let base = new Base(configuration);
try {
LOGGER.info("Test de connexion à la base de donnees...");
@@ -116,9 +144,6 @@ module.exports = class baseManager {
return false;
}
- // on stocke le chemin du fichier
- this._listOfVerifiedDbConfig.push(dbConfigPath);
-
LOGGER.info("Configuration de la base de donnees valide.");
return true;
@@ -127,20 +152,49 @@ module.exports = class baseManager {
/**
*
* @function
- * @name createBase
- * @description Création de la connexion à une base de données
+ * @name flushCheckedBaseConfiguration
+ * @description Vider la liste des configurations de bases déjà vérifiées
+ *
+ */
+ flushCheckedBaseConfiguration() {
+
+ this._checkedBaseConfiguration = new Array();
+
+ }
+
+ /**
+ *
+ * @function
+ * @name saveCheckedBaseConfiguration
+ * @description Sauvegarde de la description de la configuration à une base de données.
+ * @param {string} dbConfigPath - Nom du fichier contenant les informations de connexion à la base (chemin absolu)
+ *
+ */
+ saveCheckedBaseConfiguration(dbConfigPath) {
+
+ this._checkedBaseConfiguration.push(dbConfigPath);
+
+ }
+
+ /**
+ *
+ * @function
+ * @name loadBaseConfiguration
+ * @description Création de la base de données
* @param{string} dbConfigPath - Nom du fichier contenant les informations de connexion à la base (chemin absolu)
*
*/
- createBase(dbConfigPath) {
+ loadBaseConfiguration(dbConfigPath) {
let base;
// on vérifie d'abord que la base n'a pas déjà été créée
if (this._baseCatalog[dbConfigPath]) {
- return this._baseCatalog[dbConfigPath];
+ return true;
} else {
- // la base n'existe pas, on continue
+ // TODO la base n'existe pas, on vérifie que le contenu de la conf n'est pas le même qu'une base déjà chargée.
+ // Cela permet d'éviter de créer des connexions inutiles.
+ // Si elle existe déjà, il faut bien veiller à renvoyer le this._baseCatalog[dbConfigPath] correspondant.
}
let configuration = {};
@@ -155,8 +209,9 @@ module.exports = class baseManager {
base = new Base(configuration);
this._baseCatalog[dbConfigPath] = base;
+ this._loadedBaseConfiguration = dbConfigPath;
- return base;
+ return true;
}
diff --git a/src/js/geography/projectionManager.js b/src/js/geography/projectionManager.js
index 1b89530..fb1d755 100644
--- a/src/js/geography/projectionManager.js
+++ b/src/js/geography/projectionManager.js
@@ -1,7 +1,6 @@
'use strict';
const fs = require('fs');
-const path = require('path');
const proj4 = require('proj4');
const log4js = require('log4js');
@@ -28,40 +27,72 @@ module.exports = class ProjectionManager {
*/
constructor() {
- // Liste des ids de projections disponibles
- this._listOfProjectionId = new Array();
+ // Liste des ids de projections disponibles car déjà chargées dans proj4
+ this._loadedProjectionId = new Array();
+
+ // Liste des ids des projections déjà vérifiées et qui doivent être cohérentes avec les prochaines qui seront vérifiés
+ // Cet objet doit être vidé quand l'ensemble des configurations a été vérifié
+ this._checkedProjectionId = new Array();
}
/**
*
* @function
- * @name get listOfProjectionId
+ * @name get loadedProjectionId
* @description Récupérer la liste des ids de projections disponibles
*
*/
- get listOfProjectionId () {
- return this._listOfProjectionId;
+ get loadedProjectionId () {
+ return this._loadedProjectionId;
+ }
+
+ /**
+ *
+ * @function
+ * @name isAvailable
+ * @description Savoir si une projection est disponible dans l'instance de proj4
+ * @param {string} id - ID de la projection
+ *
+ */
+ isAvailable (id) {
+
+ if (!id) {
+ return false;
+ }
+ if (this._loadedProjectionId.length === 0) {
+ return false;
+ }
+
+ for (let i = 0; i < this._loadedProjectionId.length; i++) {
+ if (id === this._loadedProjectionId[i]) {
+ return true;
+ }
+ }
+
+ return false;
+
}
/**
*
* @function
- * @name isAvailableById
- * @description Savoir si une projection est disponible
+ * @name isChecked
+ * @description Savoir si une projection a été validé durant l'étape de vérification
+ * @param {string} id - ID de la projection
*
*/
- isAvailableById (id) {
+ isChecked (id) {
if (!id) {
return false;
}
- if (this._listOfProjectionId.length === 0) {
+ if (this._checkedProjectionId.length === 0) {
return false;
}
- for (let i = 0; i < this._listOfProjectionId.length; i++) {
- if (id === this._listOfProjectionId[i]) {
+ for (let i = 0; i < this._checkedProjectionId.length; i++) {
+ if (id === this._checkedProjectionId[i]) {
return true;
}
}
@@ -70,6 +101,190 @@ module.exports = class ProjectionManager {
}
+ /**
+ *
+ * @function
+ * @name checkProjectionDirectory
+ * @description Vérifier les projections d'un dossier
+ * @param {string} projectionDirectory - Chemin absolu d'un dossier de projections
+ *
+ */
+ checkProjectionDirectory(projectionDirectory) {
+
+ LOGGER.info("Vérification du dossier de projections...");
+
+ if (fs.existsSync(projectionDirectory)) {
+
+ try {
+
+ // On vérifie que l'application peut lire les fichiers du dossier
+ if (!fs.readdirSync(projectionDirectory).every(projectionName => {
+
+ let projectionFile = projectionDirectory + "/" + projectionName;
+
+ if (!this.checkProjectionFile(projectionFile)) {
+ LOGGER.error("Le fichier " + projectionFile + " est mal configuré");
+ return false;
+ } else {
+ LOGGER.info("Le fichier " + projectionFile + " est bien configuré");
+ return true;
+ }
+
+ })
+ ) {
+ LOGGER.error("Un des fichiers de projection est mal configuré");
+ return false;
+ }
+
+ } catch(error) {
+ LOGGER.error("Impossible de lire le dossier");
+ return false;
+ }
+
+ return true;
+
+ } else {
+ LOGGER.fatal("Mauvaise configuration: Dossier de projections inexistant : " + projectionDirectory);
+ return false;
+ }
+
+ }
+
+
+ /**
+ *
+ * @function
+ * @name checkProjectionFile
+ * @description Vérifier les projections d'un fichier
+ * @param {string} projectionFile - Chemin absolu d'un fichier de projections
+ *
+ */
+ checkProjectionFile(projectionFile) {
+
+ LOGGER.info("Vérification du fichier de projections : " + projectionFile);
+
+ try {
+ fs.accessSync(projectionFile, fs.constants.R_OK);
+ } catch (err) {
+ LOGGER.error("Le fichier de projection ne peut etre lu: " + projectionFile);
+ return false;
+ }
+
+ let fileContent = {};
+ try {
+ fileContent = JSON.parse(fs.readFileSync(projectionFile));
+ } catch (error) {
+ LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de projection: " + projectionFile);
+ LOGGER.error(error);
+ return false;
+ }
+
+ if (!fileContent.projectionsList) {
+ LOGGER.error("La fichier des projections ne contient pas de liste");
+ return false;
+ }
+
+ if (!Array.isArray(fileContent.projectionsList)) {
+ LOGGER.error("L'attribut projectionsList de la configuration n'est pas un tableau.");
+ return false;
+ }
+
+ if (fileContent.projectionsList.length === 0) {
+ LOGGER.error("L'attribut projectionsList de la configuration est un tableau vide.");
+ return false;
+ }
+
+ for (let i = 0; i < fileContent.projectionsList.length; i++) {
+ if (!this.checkProjectionConfiguration(fileContent.projectionsList[i])) {
+ LOGGER.error("Mauvaise configuration d'une projection dans le fichier.");
+ return false;
+ } else {
+ this._checkedProjectionId.push(fileContent.projectionsList[i].id);
+ }
+ }
+
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name checkProjectionConfiguration
+ * @description Vérifier les projections d'un fichier
+ * @param {object} configuration - Configuration d'une projection
+ *
+ */
+ checkProjectionConfiguration(configuration) {
+
+ LOGGER.info("Vérification d'une projection");
+
+ // id de la projection
+ if (!configuration) {
+ LOGGER.error("La configuration de la projection est vide");
+ return false;
+ }
+
+ // id de la projection
+ if (!configuration.id) {
+ LOGGER.error("La configuration de la projection n'a pas d'id");
+ return false;
+ } else {
+ LOGGER.debug("Projection id : " + configuration.id);
+ }
+
+ // Parametres de la projection
+ if (!configuration.parameters) {
+ LOGGER.error("La configuration de la projection n'a pas de parametres");
+ return false;
+ } else {
+
+ if (typeof configuration.parameters !== "string") {
+ LOGGER.error("Les parametres de la projection ne sont pas une string");
+ return false;
+ } else {
+ LOGGER.debug("Projection parameters : " + configuration.parameters);
+ }
+
+ }
+
+ // On vérifie que l'id n'est pas déjà chargé
+ if (this._loadedProjectionId.length !== 0) {
+ for (let i = 0; i < this._loadedProjectionId.length; i++) {
+ if (configuration.id === this._loadedProjectionId[i]) {
+ LOGGER.error("Une projection contenant l'id " + configuration.id + " est deja chargee.");
+ return false;
+ }
+ }
+ }
+
+ // On vérifie que l'id n'est pas déjà pris par le check courant
+ if (this._checkedProjectionId.length !== 0) {
+ for (let i = 0; i < this._checkedProjectionId.length; i++) {
+ if (configuration.id === this._checkedProjectionId[i]) {
+ LOGGER.error("Une projection contenant l'id " + configuration.id + " est deja verifiee.");
+ return false;
+ }
+ }
+ }
+
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name flushCheckedProjection
+ * @description Vider la liste des projections déjà vérifiées
+ *
+ */
+ flushCheckedProjection() {
+
+ this._checkedProjectionId = new Array();
+
+ }
+
/**
*
* @function
@@ -137,7 +352,7 @@ module.exports = class ProjectionManager {
LOGGER.error("Pas de fichier");
return false;
} else {
- LOGGER.info(file);
+ LOGGER.debug(file);
}
let pathFile = file;
@@ -174,7 +389,7 @@ module.exports = class ProjectionManager {
}
for (let i = 0; i < fileContent.projectionsList.length; i++) {
- if (!this.loadProjection(fileContent.projectionsList[i])) {
+ if (!this.loadProjectionConfiguration(fileContent.projectionsList[i])) {
LOGGER.error("Erreur lors du chargement d'une projection du fichier.");
return false;
}
@@ -188,12 +403,12 @@ module.exports = class ProjectionManager {
/**
*
* @function
- * @name loadProjection
+ * @name loadProjectionConfiguration
* @description Charger la projection décrite via sa configuration
* @param {json} configuration - configuration de la projection
*
*/
- loadProjection (configuration) {
+ loadProjectionConfiguration (configuration) {
LOGGER.info("Chargement d'une projection");
@@ -208,7 +423,7 @@ module.exports = class ProjectionManager {
LOGGER.error("La configuration de la projection n'a pas d'id");
return false;
} else {
- LOGGER.info(configuration.id);
+ LOGGER.debug(configuration.id);
}
// Parametres de la projection
@@ -216,13 +431,14 @@ module.exports = class ProjectionManager {
LOGGER.error("La configuration de la projection n'a pas de parametres");
return false;
} else {
- // TODO: vérification des parametres ?
+ // On ne vérifie pas les paramètres car c'est fait dans le check
+ LOGGER.debug(configuration.parameters);
}
// On vérifie que l'id n'est pas déjà pris
- if (this._listOfProjectionId.length !== 0) {
- for (let i = 0; i < this._listOfProjectionId.length; i++) {
- if (configuration.id === this._listOfProjectionId[i]) {
+ if (this._loadedProjectionId.length !== 0) {
+ for (let i = 0; i < this._loadedProjectionId.length; i++) {
+ if (configuration.id === this._loadedProjectionId[i]) {
LOGGER.error("Une projection contenant l'id " + configuration.id + " est deja referencee.");
return false;
}
@@ -234,7 +450,7 @@ module.exports = class ProjectionManager {
proj4.defs(configuration.id, configuration.parameters);
// On stocke l'id
- this._listOfProjectionId.push(configuration.id);
+ this._loadedProjectionId.push(configuration.id);
} catch(error) {
LOGGER.error("Impossible de charger la projection dans proj4: ");
diff --git a/src/js/operations/operationManager.js b/src/js/operations/operationManager.js
index 2ba7873..919f1aa 100644
--- a/src/js/operations/operationManager.js
+++ b/src/js/operations/operationManager.js
@@ -1,7 +1,6 @@
'use strict';
const fs = require('fs');
-const path = require('path');
const log4js = require('log4js');
const ParameterManager = require('../parameters/parameterManager');
const Operation = require('../operations/operation');
@@ -30,8 +29,11 @@ module.exports = class operationManager {
*/
constructor() {
+ // Liste des ids appartenant aux opérations chargées par le manager
+ this._loadedOperationId = new Array();
+
// Liste des ids appartenant aux opérations vérifiées par le manager
- this._listOfVerifiedOperationId = new Array();
+ this._checkedOperationId = new Array();
// Parameter manager
this._parameterManager = new ParameterManager();
@@ -40,19 +42,27 @@ module.exports = class operationManager {
this._operationCatalog = {};
// Catalogue des configurations des opérations disponibles
- this._operationConfigurationCatalog = {};
+ this._checkedOperationConfiguration = {};
}
/**
*
* @function
- * @name get listOfVerifiedOperationId
- * @description Récupérer l'ensemble des ids appartenant aux opérations vérifiées par le manager
+ * @name verifyCheckedOperation
+ * @description Savoir si une opération est vérifiée sur le service
+ * @param {string} operationId - Id de l'opération
*
*/
- get listOfVerifiedOperationId() {
- return this._listOfVerifiedOperationId;
+ verifyCheckedOperation(operationId) {
+
+ for (let i = 0; i < this._checkedOperationId.length; i++) {
+ if (this._checkedOperationId[i] === operationId) {
+ return true;
+ }
+ }
+ return false;
+
}
/**
@@ -90,87 +100,72 @@ module.exports = class operationManager {
/**
*
* @function
- * @name loadOperationDirectory
- * @description Charger les opérations du dossier
- * @param {string} userOperationDirectory - Dossier contenant les opérations (chemin absolu)
- * @param {string} userParameterDirectory - Dossier contenant les paramètres (chemin absolu)
- * @return {boolean}
+ * @name get checkOperationDirectory
+ * @description Vérifier les configurations d'opération d'un dossier
+ * @param {string} directory - Dossier qui contient les configurations d'opération à vérifier
*
*/
- loadOperationDirectory(userOperationDirectory, userParameterDirectory) {
-
- LOGGER.info("Chargement des operations...");
-
- // Vérification de l'existence du dossier operations
- let operationsDirectory = userOperationDirectory;
- if (!fs.statSync(operationsDirectory).isDirectory()) {
- LOGGER.error("Le dossier contenant la configuration des operations n'existe pas: " + operationsDirectory);
- return false;
- }
+ checkOperationDirectory(directory) {
- // Vérification de l'existence du dossier parameters
- let parametersDirectory = userParameterDirectory;
- if (!fs.statSync(parametersDirectory).isDirectory()) {
- LOGGER.error("Le dossier contenant la configuration des parametres n'existe pas: " + parametersDirectory);
- return false;
- }
+ LOGGER.info("Vérification du dossier d'opération...");
- // Chargement des paramètres
- // C'est le parameterManager qui s'en charge
- if (!this._parameterManager.loadParameterDirectory(parametersDirectory)) {
- LOGGER.error("Erreur lors du chargement des parametres");
+ if (!fs.existsSync(directory)) {
+ LOGGER.error("Le dossier" + directory + "n'existe pas");
return false;
- } else {
- LOGGER.info("Chargement des parametres ok");
}
- // Chargement des opérations
- fs.readdirSync(operationsDirectory).forEach(operationConfFileName => {
-
- let operationConfFile = operationsDirectory + "/" + operationConfFileName;
+ // On vérifie que l'application peut lire les fichiers du dossier
+ if (!fs.readdirSync(directory).every(operation => {
- if (fs.statSync(operationConfFile).isFile()) {
-
- // on récupère le contenu du fichier puis on le vérifie
- let operationConf = JSON.parse(fs.readFileSync(operationConfFile));
+ let operationFile = "";
- if (this.checkOperationConf(operationConf)) {
- // on stocke l'id si tout va bien
- this._listOfVerifiedOperationId.push(operationConf.id);
- // on crée l'opération et on l'ajoute au catalogue
- // pour créer l'opération, il faut d'abord créer les paramètres
- let parametersTable = this._parameterManager.createParameters(operationConf);
- this._operationConfigurationCatalog[operationConf.id] = operationConf;
- this._operationCatalog[operationConf.id] = new Operation(operationConf.id, operationConf.name, operationConf.description, parametersTable);
+ try {
+ operationFile = directory + "/" + operation;
+ fs.accessSync(operationFile, fs.constants.R_OK);
+ } catch (err) {
+ LOGGER.error("Le fichier d'operation ne peut etre lu: " + operationFile);
+ }
- } else {
- LOGGER.error("La configuration d'une operation est incorrecte: " + operationConfFile);
- return false;
- }
+ let fileContent = {};
+ try {
+ // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard
+ fileContent = JSON.parse(fs.readFileSync(operationFile));
+ } catch (error) {
+ LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier d'operation: " + operationFile);
+ LOGGER.error(error);
+ return false;
+ }
+ if (!this.checkOperationConfiguration(fileContent)) {
+ LOGGER.error("Operation mal configurée");
+ return false;
} else {
- // On ne fait rien
+ this._checkedOperationId.push(fileContent.id);
+ this._checkedOperationConfiguration[fileContent.id] = fileContent;
+ LOGGER.info("Operation bien configurée");
+ return true;
}
- });
-
- LOGGER.info("Operations chargees.");
+ })
+ ) {
+ LOGGER.error("Une des opérations est mal configurée");
+ return false;
+ }
return true;
-
+
}
-
/**
*
* @function
- * @name checkOperationConf
+ * @name checkOperationConfiguration
* @description Vérifier la configuration d'une opération
* @param {json} operationConf - Configuration d'une opération de service
* @return {boolean}
*
*/
- checkOperationConf(operationConf) {
+ checkOperationConfiguration(operationConf) {
LOGGER.info("Verification de l'operation");
@@ -180,12 +175,28 @@ module.exports = class operationManager {
return false;
} else {
- // On vérifie que l'id n'est pas déjà pris.
- if (this._listOfVerifiedOperationId.length !== 0) {
+ // On vérifie que l'id n'est pas déjà chargé.
+ if (this._loadedOperationId.length !== 0) {
+
+ for (let i = 0; i < this._loadedOperationId.length; i++ ) {
+ if (this._loadedOperationId[i] === operationConf.id) {
+ LOGGER.info("L'operation contenant l'id " + operationConf.id + " est deja chargée.");
+ return false;
+ } else {
+ // on continue de vérifier
+ }
+ }
+
+ } else {
+ // C'est la première operation. On ne fait rien, on continue la vérification
+ }
+
+ // On vérifie que l'id n'est pas déjà vérifié.
+ if (this._checkedOperationId.length !== 0) {
- for (let i = 0; i < this._listOfVerifiedOperationId.length; i++ ) {
- if (this._listOfVerifiedOperationId[i] === operationConf.id) {
- LOGGER.info("L'operation contenant l'id " + operationConf.id + " est deja referencee.");
+ for (let i = 0; i < this._checkedOperationId.length; i++ ) {
+ if (this._checkedOperationId[i] === operationConf.id) {
+ LOGGER.info("L'operation contenant l'id " + operationConf.id + " est deja vérifié.");
return false;
} else {
// on continue de vérifier
@@ -224,7 +235,7 @@ module.exports = class operationManager {
if (operationConf.parameters.length !== 0) {
// on vérifie la validité des ids de paramètre fournis
for (let i = 0; i < operationConf.parameters.length; i++ ) {
- if (!this._parameterManager.isParameterAvailable(operationConf.parameters[i])) {
+ if (!this._parameterManager.isParameterChecked(operationConf.parameters[i])) {
LOGGER.error("L'operation précise un parametre qui n'est pas disponible: " + operationConf.parameters[i]);
return false;
} else {
@@ -245,15 +256,150 @@ module.exports = class operationManager {
/**
*
* @function
- * @name checkResourceOperationConf
+ * @name flushCheckedOperation
+ * @description Vider la liste des opérations et paramètres déjà vérifiés
+ *
+ */
+ flushCheckedOperation() {
+
+ this._checkedOperationId = new Array();
+ this._checkedOperationConfiguration = {};
+ this._parameterManager.flushCheckedParameter();
+
+ }
+
+ /**
+ *
+ * @function
+ * @name checkParameterDirectory
+ * @description Vérifier les configurations de paramètre d'un dossier
+ * @param {string} directory - Dossier qui contient les configurations de paramètre à vérifier
+ *
+ */
+ checkParameterDirectory(directory) {
+
+ return this._parameterManager.checkParameterDirectory(directory);
+
+ }
+
+ /**
+ *
+ * @function
+ * @name loadParameterDirectory
+ * @description Charger les configurations de paramètre d'un dossier
+ * @param {string} directory - Dossier qui contient les configurations de paramètre à charger
+ *
+ */
+ loadParameterDirectory(directory) {
+
+ return this._parameterManager.loadParameterDirectory(directory);
+
+ }
+
+ /**
+ *
+ * @function
+ * @name loadOperationDirectory
+ * @description Charger les opérations du dossier
+ * @param {string} operationsDirectory - Dossier contenant les opérations (chemin absolu)
+ * @return {boolean}
+ *
+ */
+ loadOperationDirectory(operationsDirectory) {
+
+ LOGGER.info("Chargement des operations d'un dossier...");
+
+ // Vérification de l'existence du dossier operations
+ if (!fs.statSync(operationsDirectory).isDirectory()) {
+ LOGGER.error("Le dossier contenant la configuration des operations n'existe pas: " + operationsDirectory);
+ return false;
+ }
+
+ // Chargement des opérations
+ if (!fs.readdirSync(operationsDirectory).every(operationConfFileName => {
+
+ let operationConfFile = operationsDirectory + "/" + operationConfFileName;
+
+ if (fs.statSync(operationConfFile).isFile()) {
+
+ // on récupère le contenu du fichier puis on le vérifie
+ let operationConf = {};
+ try {
+ operationConf = JSON.parse(fs.readFileSync(operationConfFile));
+ } catch(error) {
+ LOGGER.error("Impossible de lire la configuration de l'opération dans le fichier " + operationConfFile);
+ return false;
+ }
+
+ if (!this.loadOperationConfiguration(operationConf)) {
+ LOGGER.error("Impossible de charger l'opération configurée dans le fichier " + operationConfFile);
+ return false;
+ }
+
+ } else {
+ // On ne fait rien
+ }
+
+ return true;
+
+ })
+ ) {
+ LOGGER.error("Une des opérations n'a pas pu être chargée");
+ return false;
+ }
+
+ LOGGER.info("Operations chargees.");
+
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name loadOperationConfiguration
+ * @description Charger une opération à partir de sa configuration
+ * @param {object} operationConf - Configuration de l'opération
+ * @return {boolean}
+ *
+ */
+ loadOperationConfiguration(operationConf) {
+
+ // on crée l'opération et on l'ajoute au catalogue
+ // pour créer l'opération, il faut d'abord récupérer les paramètres
+ let parametersTable = this._parameterManager.getParameters(operationConf);
+
+ if (parametersTable === null) {
+ LOGGER.error("Impossible de récuperer l'ensemble des parametres pour créer l'opération");
+ return false;
+ } else {
+ if (parametersTable.length === 0) {
+ LOGGER.error("Impossible de récuperer les parametres pour créer l'opération");
+ return false;
+ } else {
+ this._operationCatalog[operationConf.id] = new Operation(operationConf.id, operationConf.name, operationConf.description, parametersTable);
+ }
+ }
+
+ // on stocke l'id si tout va bien
+ this._loadedOperationId.push(operationConf.id);
+
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name checkResourceOperationConfiguration
* @description Vérifier la configuration d'une opération de ressource
* @param {json} resourceOperationJsonObject - Configuration d'une opération de ressource
* @return {boolean}
*
*/
- checkResourceOperationConf(resourceOperationJsonObject) {
+ checkResourceOperationConfiguration(resourceOperationJsonObject) {
- LOGGER.info("Verification de l'operation de la ressource");
+ LOGGER.info("Verification de l'operation de la ressource...");
// on regarde d'abord la taille du tableau donné en entrée
if (resourceOperationJsonObject.length === 0) {
@@ -273,7 +419,7 @@ module.exports = class operationManager {
LOGGER.info(currentOperationConf.id);
// on vérifie qu'elle est bien disponible pour cette instance du service
- if (!this.verifyAvailabilityOperation(currentOperationConf.id)) {
+ if (!this.verifyCheckedOperation(currentOperationConf.id)) {
LOGGER.error("L'operation indiquee n'est pas disponible");
// TODO: remplacer ce return par un continue pour affiner le chargement des ressources
// par exemple, si la ressource indique une opération non disponible mais qu'on veuille quand même la charger pour les opérations disponibles
@@ -301,7 +447,7 @@ module.exports = class operationManager {
// On prend la liste des paramètres censé être là et on vérifie qu'ils sont bien présents et valides
// On compare le nombre de paramètres attendus au nombre de paramètres présents et on compare pour être certain qu'il n'y en ait pas trop
- let wantedParameters = this._operationConfigurationCatalog[currentOperationConf.id].parameters;
+ let wantedParameters = this._checkedOperationConfiguration[currentOperationConf.id].parameters;
if (wantedParameters.length !== currentOperationConf.parameters.length) {
LOGGER.error("Le nombre de parametres presents n'est pas celui attendu");
@@ -311,7 +457,7 @@ module.exports = class operationManager {
for(let j = 0; j < currentOperationConf.parameters.length; j++) {
let currentParameterConf = currentOperationConf.parameters[j];
- if (!this._parameterManager.checkResourceParameterConf(currentParameterConf)) {
+ if (!this._parameterManager.checkResourceParameterConfiguration(currentParameterConf)) {
LOGGER.error("L'objet representant un parametre est mal configure");
return false;
} else {
@@ -319,55 +465,7 @@ module.exports = class operationManager {
}
}
- }
-
- }
-
- }
-
- return true;
-
- }
-
- /**
- *
- * @function
- * @name getResourceOperationConf
- * @description Récupérer la liste des opérations disponibles sur une ressource
- * @param {json} resourceOperationJsonObject - Configuration d'une opération de ressource
- * @param {table} operationTable - Tableau contenant les ids d'opérations de ressource
- * @return {boolean}
- *
- */
- getResourceOperationConf(resourceOperationJsonObject, operationTable) {
-
- LOGGER.info("Recuperation des operations de la ressource");
-
- // on regarde d'abord la taille du tableau donné en entrée
- if (resourceOperationJsonObject.length === 0) {
- LOGGER.error("Il n'y aucune operation decrite");
- return false;
- } else {
-
- // on vérifie les opérations unes à une
- for (let i = 0; i < resourceOperationJsonObject.length; i++) {
- let currentOperationConf = resourceOperationJsonObject[i];
-
- if (!currentOperationConf.id) {
- LOGGER.error("L'objet representant l'operation n'a pas d'id");
- return false;
- } else {
-
- LOGGER.info(currentOperationConf.id);
-
- // on vérifie qu'elle est bien disponible pour cette instance du service
- if (!this.verifyAvailabilityOperation(currentOperationConf.id)) {
- LOGGER.error("L'operation indiquee n'est pas disponible");
- return false;
- } else {
- // on le stocke
- operationTable.push(currentOperationConf.id);
- }
+ LOGGER.info("Operation de ressource bien configurée");
}
@@ -382,53 +480,19 @@ module.exports = class operationManager {
/**
*
* @function
- * @name isAvailableInTable
- * @description Savoir si une opération est disponible dans une liste d'opérations de ressource
- * @param {string} operationId - Id de l'opération de ressource recherchée
- * @param {table} operationTable - Tableau contenant les ids d'opérations de ressource
- * @return {boolean}
- *
- */
-
- isAvailableInTable (operationId, resourceOperationTable) {
-
- if (resourceOperationTable.length === 0) {
- LOGGER.error("Le tableau d'operations est vide.")
- return false;
- } else {
-
- for (let i = 0; i < resourceOperationTable.length; i++) {
- LOGGER.info(resourceOperationTable[i]);
- if (operationId === resourceOperationTable[i]) {
- return true;
- }
- }
-
- }
-
- LOGGER.info("Operation non trouvee.");
- return false;
- }
-
- /**
- *
- * @function
- * @name createResourceOperation
+ * @name loadResourceOperationConfiguration
* @description Créer l'ensemble des opérations d'une ressource
* @param {object} resourceOperationHash - Objet contenant les opérations de ressource
* @param {json} resourceJsonObject - Configuration d'une opération de ressource
* @return {boolean}
*
*/
- createResourceOperation(resourceOperationHash, resourceJsonObject) {
+ loadResourceOperationConfiguration(resourceOperationHash, resourceJsonObject) {
LOGGER.info("Creation des operations de la ressource");
// on crée les opérations unes à une
for (let i = 0; i < resourceJsonObject.resource.availableOperations.length; i++) {
-
- // TODO: tester à nouveau si l'opération est bien disponible sur le service
- // cela permet de ne charger que les opérations disponibles
// on isole la conf de l'opération
let currentOperationConf = resourceJsonObject.resource.availableOperations[i];
@@ -437,7 +501,7 @@ module.exports = class operationManager {
// création des paramètres de l'opération de ressource
let resourceParameterHash = {};
- if (!this._parameterManager.createResourceParameter(resourceParameterHash, currentOperationConf)) {
+ if (!this._parameterManager.loadResourceParameterConfiguration(resourceParameterHash, currentOperationConf)) {
LOGGER.error("Erreur lors de la creation des parametres de l'operation");
return false;
}
diff --git a/src/js/parameters/parameterManager.js b/src/js/parameters/parameterManager.js
index 02c8def..11bf941 100644
--- a/src/js/parameters/parameterManager.js
+++ b/src/js/parameters/parameterManager.js
@@ -33,12 +33,18 @@ module.exports = class parameterManager {
*/
constructor() {
+ // Liste des ids appartenant aux paramètres chargés par le manager
+ this._loadedParameterId = new Array();
+
// Liste des ids appartenant aux paramètres vérifiés par le manager
- this._listOfVerifiedParameterId = new Array();
+ this._checkedParameterId = new Array();
// Stockage des configurations des paramètres de service
this._parametersConfiguration = {};
+ // Stockage des configurations des paramètres de service vérifiés par le manager
+ this._checkedParametersConfiguration = {};
+
// Stockage des paramètres de service
this._parameters = {};
@@ -47,55 +53,51 @@ module.exports = class parameterManager {
/**
*
* @function
- * @name get listOfVerifiedParameterId
+ * @name get loadedParameterId
* @description Récupérer l'ensemble des ids appartenant aux paramètres vérifiés par le manager
*
*/
- get listOfVerifiedParameterId() {
- return this._listOfVerifiedParameterId;
- }
-
- /**
- *
- * @function
- * @name get parametersConfiguration
- * @description Récupérer l'ensemble des configurations appartenant aux paramètres vérifiés par le manager
- *
- */
- get parametersConfiguration() {
- return this._parametersConfiguration;
+ get loadedParameterId() {
+ return this._loadedParameterId;
}
/**
*
* @function
- * @name getParameterConfigurationById
- * @description Récupérer la configuration d'un paramètre via son id
+ * @name isParameterLoaded
+ * @description Permet de savoir si un paramètre est disponible, via son id
* @param {string} id - Id du paramètre de service
- * @return {object} Instance de Parameter, paramètre de service
+ * @return {boolean}
*
*/
- getParameterConfigurationById(id) {
- if (this._parametersConfiguration[id]) {
- return this._parametersConfiguration[id];
+ isParameterLoaded(id) {
+ if (this._loadedParameterId.length !== 0) {
+ for (let i=0; i < this._loadedParameterId.length; i++) {
+ if (id === this._loadedParameterId[i]) {
+ return true;
+ } else {
+ // on continue
+ }
+ }
} else {
- return {};
+ return false;
}
+ return false;
}
/**
*
* @function
- * @name isParameterAvailable
- * @description Permet de savoir si un paramètre est disponible, via son id
+ * @name isParameterChecked
+ * @description Permet de savoir si un paramètre a été vérifié, via son id
* @param {string} id - Id du paramètre de service
* @return {boolean}
*
*/
- isParameterAvailable(id) {
- if (this._listOfVerifiedParameterId.length !== 0) {
- for (let i=0; i < this._listOfVerifiedParameterId.length; i++) {
- if (id === this._listOfVerifiedParameterId[i]) {
+ isParameterChecked(id) {
+ if (this._checkedParameterId.length !== 0) {
+ for (let i=0; i < this._checkedParameterId.length; i++) {
+ if (id === this._checkedParameterId[i]) {
return true;
} else {
// on continue
@@ -110,53 +112,55 @@ module.exports = class parameterManager {
/**
*
* @function
- * @name loadParameterDirectory
- * @description Charger les paramètres du dossier
- * @param {string} parametersDirectory - Dossier contenant la description des paramètres
- * @return {boolean}
+ * @name get checkParameterDirectory
+ * @description Vérifier les configurations de paramètre d'un dossier
+ * @param {string} directory - Dossier qui contient les configurations de paramètre à vérifier
*
*/
- loadParameterDirectory(parametersDirectory) {
-
- LOGGER.info("Chargement des parametres...");
+ checkParameterDirectory(directory) {
- // Vérification de l'existence du dossier /dir/parameters
- if (!fs.statSync(parametersDirectory).isDirectory()) {
- LOGGER.error("Le dossier contenant la configuration des parametres n'existe pas: " + parametersDirectory);
+ if (!fs.existsSync(directory)) {
+ LOGGER.fatal("Mauvaise configuration: Le dossier des parametres n'existe pas : " + directory);
return false;
- }
-
- // Chargement des paramètres
- // On les charge en premier pour qu'au moment du chargement des opérations, on connaisse déjà les identifiants des paramètres
- fs.readdirSync(parametersDirectory).forEach(parameterConfFileName => {
-
- let parameterConfFile = parametersDirectory + "/" + parameterConfFileName;
-
- if (fs.statSync(parameterConfFile).isFile()) {
+ }
- LOGGER.info("Chargement du parametre depuis " + parameterConfFile);
+ // On vérifie que l'application peut lire les fichiers du dossier
+ if (!fs.readdirSync(directory).every(parameter => {
- // on récupère le contenu du fichier puis on le vérifie et enfin on stocke l'id si tout va bien
- let parameterConf = JSON.parse(fs.readFileSync(parameterConfFile));
+ let parameterFile = "";
- if (this.checkParameterConf(parameterConf)) {
-
- this._listOfVerifiedParameterId.push(parameterConf.id);
- this._parametersConfiguration[parameterConf.id] = parameterConf;
+ try {
+ parameterFile = directory + "/" + parameter;
+ fs.accessSync(parameterFile, fs.constants.R_OK);
+ } catch (err) {
+ LOGGER.error("Le fichier de parametres ne peut etre lu: " + parameterFile);
+ }
- } else {
- // s'il y a une erreur dans le fichier on arrête
- LOGGER.error("La configuration d'un parametres est incorrecte: " + parameterConfFile);
- return false;
- }
+ let contentFile = {};
+ try {
+ // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard
+ contentFile = JSON.parse(fs.readFileSync(parameterFile));
+ } catch (error) {
+ LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de parametres: " + parameterFile);
+ LOGGER.error(error);
+ return false;
+ }
+ if (!this.checkParameterConfiguration(contentFile)) {
+ LOGGER.error("Parametre mal configuré");
+ return false;
} else {
- // On ne fait rien
+ this._checkedParameterId.push(contentFile.id);
+ this._checkedParametersConfiguration[contentFile.id] = contentFile;
+ LOGGER.info("Parametre bien configurée");
+ return true;
}
- });
-
- LOGGER.info("Parametres charges.");
+ })
+ ) {
+ LOGGER.error("Un des paramètres est mal configuré");
+ return false;
+ }
return true;
@@ -165,13 +169,13 @@ module.exports = class parameterManager {
/**
*
* @function
- * @name checkParameterConf
+ * @name checkParameterConfiguration
* @description Vérifier la configuration d'un paramètre
* @param {json} parametersConf - Configuration du paramètre de service
* @return {boolean}
*
*/
- checkParameterConf(parameterConf) {
+ checkParameterConfiguration(parameterConf) {
let tmpMin;
let tmpMax;
@@ -184,12 +188,28 @@ module.exports = class parameterManager {
return false;
} else {
LOGGER.info(parameterConf.id);
- // On vérifie que l'id n'est pas déjà pris.
- if (this._listOfVerifiedParameterId.length !== 0) {
+ // On vérifie que l'id n'est pas déjà chargé.
+ if (this._loadedParameterId.length !== 0) {
+
+ for (let i = 0; i < this._loadedParameterId.length; i++ ) {
+ if (this._loadedParameterId[i] === parameterConf.id) {
+ LOGGER.info("Le parametre contenant l'id " + parameterConf.id + " est deja chargé.");
+ return false;
+ } else {
+ // on continue de vérifier
+ }
+ }
+
+ } else {
+ // C'est le premier paramètre. On ne fait rien, on continue la vérification
+ }
+
+ // On vérifie que l'id n'est pas déjà vérifié.
+ if (this._checkedParameterId.length !== 0) {
- for (let i = 0; i < this._listOfVerifiedParameterId.length; i++ ) {
- if (this._listOfVerifiedParameterId[i] === parameterConf.id) {
- LOGGER.info("Le parametre contenant l'id " + parameterConf.id + " est deja reference.");
+ for (let i = 0; i < this._checkedParameterId.length; i++ ) {
+ if (this._checkedParameterId[i] === parameterConf.id) {
+ LOGGER.info("Le parametre contenant l'id " + parameterConf.id + " est deja vérifié.");
return false;
} else {
// on continue de vérifier
@@ -340,45 +360,157 @@ module.exports = class parameterManager {
/**
*
* @function
- * @name createParameters
- * @description Créer les objets paramètres à partir de la configuration d'une opération
- * @param {json} operationConf - Configuration d'une opération de service
- * @return {table} Tableau d'instance de Parameter, paramètre de service
+ * @name flushCheckedParameter
+ * @description Vider la liste des paramètres déjà vérifiés
*
*/
- createParameters(operationConf) {
+ flushCheckedParameter() {
- let parametersTable = {};
+ this._checkedParameterId = new Array();
+ this._checkedParametersConfiguration = {};
+
+ }
- for (let i = 0; i < operationConf.parameters.length; i++ ) {
+ /**
+ *
+ * @function
+ * @name loadParameterDirectory
+ * @description Charger les paramètres du dossier
+ * @param {string} parametersDirectory - Dossier contenant la description des paramètres
+ * @return {boolean}
+ *
+ */
+ loadParameterDirectory(parametersDirectory) {
- let parameterId = operationConf.parameters[i];
- let parameterConf = this._parametersConfiguration[parameterId];
+ LOGGER.info("Chargement des parametres du dossier...");
- parametersTable[parameterId] = new Parameter(parameterId, parameterConf.type, parameterConf.name, parameterConf.description, parameterConf.required, parameterConf.defaultValue);
+ // Vérification de l'existence du dossier /dir/parameters
+ if (!fs.statSync(parametersDirectory).isDirectory()) {
+ LOGGER.error("Le dossier contenant la configuration des parametres n'existe pas: " + parametersDirectory);
+ return false;
+ }
- if (parameterConf.example) {
- parametersTable[parameterId].example = parameterConf.example;
- }
+ // Chargement des paramètres
+ // On les charge en premier pour qu'au moment du chargement des opérations, on connaisse déjà les identifiants des paramètres
+ if (!fs.readdirSync(parametersDirectory).every(parameterConfFileName => {
- if (parameterConf.min) {
- parametersTable[parameterId].min = parameterConf.min;
- }
+ let parameterConfFile = parametersDirectory + "/" + parameterConfFileName;
- if (parameterConf.max) {
- parametersTable[parameterId].max = parameterConf.max;
- }
+ if (fs.statSync(parameterConfFile).isFile()) {
- if (parameterConf.explode) {
- parametersTable[parameterId].explode = parameterConf.explode;
- }
+ LOGGER.info("Chargement du parametre depuis " + parameterConfFile);
+
+ // on récupère le contenu du fichier puis on le vérifie et enfin on stocke l'id si tout va bien
+ let parameterConf = {};
+ try {
+ parameterConf = JSON.parse(fs.readFileSync(parameterConfFile));
+ } catch(error) {
+ LOGGER.error("Impossible de lire " + parameterConfFile);
+ LOGGER.error(error);
+ return false;
+ }
+
+ if (!this.loadParameterConfiguration(parameterConf)) {
+ LOGGER.error("Impossible de charger le parametre");
+ return false;
+ }
- if (parameterConf.style) {
- parametersTable[parameterId].style = parameterConf.style;
+ } else {
+ // On ne fait rien
}
- // Stocakge du paramètre
- this._parameters[parameterId] = parametersTable[parameterId];
+ return true;
+
+ })
+ ) {
+ LOGGER.error("Un des paramètres n'a pas pu être chargé");
+ return false;
+ }
+
+ LOGGER.info("Parametres charges.");
+
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name loadParameterConfiguration
+ * @description Créer un paramètre à partir de sa configuration
+ * @param {json} configuration - Configuration d'un parametre
+ * @return {boolean}
+ *
+ */
+ loadParameterConfiguration(configuration) {
+
+ LOGGER.info("Chargement d'un parametre à partir de sa configuration...");
+
+ let parameterId = configuration.id;
+ let parameterConf = configuration;
+
+ if (this._parameters[parameterId]) {
+ LOGGER.info("Le parametre existe déjà");
+ return true;
+ }
+
+ let parameter = new Parameter(parameterId, parameterConf.type, parameterConf.name, parameterConf.description, parameterConf.required, parameterConf.defaultValue);
+
+ if (parameterConf.example) {
+ parameter.example = parameterConf.example;
+ }
+
+ if (parameterConf.min) {
+ parameter.min = parameterConf.min;
+ }
+
+ if (parameterConf.max) {
+ parameter.max = parameterConf.max;
+ }
+
+ if (parameterConf.explode) {
+ parameter.explode = parameterConf.explode;
+ }
+
+ if (parameterConf.style) {
+ parameter.style = parameterConf.style;
+ }
+
+ // Stocakge du paramètre
+ this._parameters[parameterId] = parameter;
+ this._loadedParameterId.push(parameterId);
+ this._parametersConfiguration[parameterId] = parameterConf;
+
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name getParameters
+ * @description Créer les objets paramètres à partir de la configuration d'une opération
+ * @param {json} operationConf - Configuration d'une opération de service
+ * @return {table} Tableau d'instance de Parameter, paramètre de service
+ *
+ */
+ getParameters(operationConf) {
+
+ LOGGER.info("Récupération des parametres d'une operation...");
+
+ let parametersTable = {};
+
+ for (let i = 0; i < operationConf.parameters.length; i++ ) {
+
+ let parameterId = operationConf.parameters[i];
+
+ if (this._parameters[parameterId]) {
+ parametersTable[parameterId] = this._parameters[parameterId];
+ LOGGER.debug("Parametre " + parameterId + " récupéré");
+ } else {
+ LOGGER.error("Le parametre " + parameterId + " n'existe pas");
+ return null;
+ }
}
@@ -389,13 +521,13 @@ module.exports = class parameterManager {
/**
*
* @function
- * @name checkResourceParameterConf
+ * @name checkResourceParameterConfiguration
* @description Vérifier la configuration d'un paramètre de ressource
* @param {json} resourceParameterJsonObject - Configuration d'un paramètre de ressource
* @return {boolean}
*
*/
- checkResourceParameterConf(resourceParameterJsonObject) {
+ checkResourceParameterConfiguration(resourceParameterJsonObject) {
LOGGER.info("Verification du parametre de la ressource");
@@ -407,7 +539,7 @@ module.exports = class parameterManager {
}
// on vérifie qu'il est bien disponible pour cette instance du service
- if (!this.isParameterAvailable(resourceParameterJsonObject.id)) {
+ if (!this.isParameterChecked(resourceParameterJsonObject.id)) {
LOGGER.error("Le parametre indique n'est pas disponible");
return false;
} else {
@@ -415,7 +547,7 @@ module.exports = class parameterManager {
}
// on récupère la configuration du paramètre
- let serviceParameterConf = this._parametersConfiguration[resourceParameterJsonObject.id];
+ let serviceParameterConf = this._checkedParametersConfiguration[resourceParameterJsonObject.id];
if (!serviceParameterConf) {
LOGGER.fatal("La configuration du parametre de service est introuvable !");
return false;
@@ -776,14 +908,14 @@ module.exports = class parameterManager {
/**
*
* @function
- * @name createResourceParameter
+ * @name loadResourceParameterConfiguration
* @description Créer l'ensemble des opérations d'une ressource
* @param {object} resourceParameterHash - Objet contenant l'ensemble des paramètres de ressource pour une ressource
* @param {json} currentOperationConf - Configuraton de l'opération de ressource pour une ressource
* @return {boolean}
*
*/
- createResourceParameter(resourceParameterHash, currentOperationConf) {
+ loadResourceParameterConfiguration(resourceParameterHash, currentOperationConf) {
LOGGER.info("Creation des parametres de l'operation");
diff --git a/src/js/resources/osrmResource.js b/src/js/resources/osrmResource.js
index 5298a5d..d202ea5 100644
--- a/src/js/resources/osrmResource.js
+++ b/src/js/resources/osrmResource.js
@@ -140,30 +140,4 @@ module.exports = class osrmResource extends Resource {
}
- /**
- *
- * @function
- * @name removeSource
- * @description Supprimer les references à une source au sein de la ressource
- * @param {string} sourceId - Id de la source
- * @return {boolean}
- *
- */
- removeSource (sourceId) {
-
- let keysToDelete = new Array();
- for (let key in this._linkedSource) {
- if (this._linkedSource[key] === sourceId) {
- keysToDelete.push(key);
- }
- }
- if(keysToDelete.length !== 0) {
- for (let i = 0; i < keysToDelete.length; i++) {
- delete this._linkedSource[keysToDelete[i]];
- }
- }
-
- return true;
- }
-
}
diff --git a/src/js/resources/pgrResource.js b/src/js/resources/pgrResource.js
index 86aa58e..1a26e1b 100644
--- a/src/js/resources/pgrResource.js
+++ b/src/js/resources/pgrResource.js
@@ -127,30 +127,4 @@ module.exports = class pgrResource extends Resource {
}
- /**
- *
- * @function
- * @name removeSource
- * @description Supprimer les references à une source au sein de la ressource
- * @param {string} sourceId - Id de la source
- * @return {boolean}
- *
- */
- removeSource (sourceId) {
-
- let keysToDelete = new Array();
- for (const key in this._linkedSource) {
- if (this._linkedSource[key] === sourceId) {
- keysToDelete.push(key);
- }
- }
- if(keysToDelete.length !== 0) {
- for (let i = 0; i < keysToDelete.length; i++) {
- delete this._linkedSource[keysToDelete[i]];
- }
- }
-
- return true;
- }
-
}
diff --git a/src/js/resources/resource.js b/src/js/resources/resource.js
index 3439dbb..354ae65 100644
--- a/src/js/resources/resource.js
+++ b/src/js/resources/resource.js
@@ -98,22 +98,6 @@ module.exports = class Resource {
return sourceId;
}
- /**
- *
- * @function
- * @name removeSource
- * @description Supprimer les references à une source au sein de la ressource
- * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
- * Dans la classe actuelle, ce n'est que pour indiquer qu'il faut implémenter la fonction
- * dans chacune des classes filles.
- * @param {string} sourceId - Id de la source
- * @return {boolean}
- *
- */
- removeSource (sourceId) {
- return true;
- }
-
/**
*
* @function
diff --git a/src/js/resources/resourceManager.js b/src/js/resources/resourceManager.js
index 24a0e1d..6a20a39 100644
--- a/src/js/resources/resourceManager.js
+++ b/src/js/resources/resourceManager.js
@@ -1,5 +1,7 @@
'use strict';
+const fs = require('fs');
+const path = require('path');
const osrmResource = require('../resources/osrmResource');
const pgrResource = require('../resources/pgrResource');
const smartpgrResource = require('../resources/smartpgrResource');
@@ -17,74 +19,128 @@ module.exports = class resourceManager {
* @description Constructeur de la classe resourceManager
*
*/
- constructor() {
+ constructor(sourceManager, operationManager, topologyManager) {
+
+ // Liste des ids des ressources chargées par le manager
+ this._loadedResourceId = new Array();
// Liste des ids des ressources vérifiées par le manager
- this._listOfVerifiedResourceIds = new Array();
+ this._checkedResourceId = new Array();
+
+ // Liste des ressources chargées dans le manager
+ this._resource = {};
+
+ // Liste des types de ressource gérées par le manager
+ this._availableResourceTypes = ["pgr", "smartpgr","osrm"];
+
+ // Manager de topology
+ this._topologyManager = topologyManager;
+
+ // Manager de source
+ this._sourceManager = sourceManager;
- // Liste des ids des ressources gérées par le manager
- this._listOfResourceIds = new Array();
+ // Manager d'opération
+ this._operationManager = operationManager;
}
/**
*
* @function
- * @name get listOfResourceIds
- * @description Récupérer l'ensemble des ids de ressources
+ * @name get resource
+ * @description Récupérer les ressources
*
*/
- get listOfResourceIds() {
- return this._listOfResourceIds;
+ get resource() {
+ return this._resource;
}
/**
*
* @function
- * @name removeResource
- * @description Supprimer une ressource
- * @param {string} id - Id de la ressource
- * @return {boolean}
+ * @name checkResourceDirectory
+ * @description Fonction utilisée pour vérifier le contenu d'un dossier de description d'une ressource.
+ * @param {string} directory - Dossier qui contient les configurations des ressources
+ * @return {boolean}
*
*/
- removeResource(id) {
- let index = this._listOfVerifiedResourceIds.indexOf(id);
- if (index !== -1) {
- this._listOfVerifiedResourceIds.splice(index,1);
- } else {
- return false;
- }
- this._listOfVerifiedResourceIds.splice(index,1);
+ async checkResourceDirectory(directory) {
+
+ LOGGER.info("Vérification d'un dossier de ressources...");
+ LOGGER.info("Nom du dossier: " + directory);
+
+ if (fs.existsSync(directory)) {
+
+ let fileList = new Array();
+ try {
+ fileList = fs.readdirSync(directory);
+ } catch(error) {
+ LOGGER.error("Impossible de lire le dossier :");
+ LOGGER.error(error);
+ return false;
+ }
+
+ if (fileList.length === 0) {
+ LOGGER.warn("Le dossier " + directory + " est vide");
+ return false;
+ }
+
+ for (let i = 0; i < fileList.length; i++) {
+
+ let resource = fileList[i];
+ let resourceFile = "";
+ try {
+ resourceFile = directory + "/" + resource;
+ fs.accessSync(resourceFile, fs.constants.R_OK);
+ } catch (err) {
+ LOGGER.error("Le fichier de ressource ne peut etre lu: " + resourceFile);
+ }
+
+ let resourceConf = {};
+ try {
+ // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard
+ resourceConf = JSON.parse(fs.readFileSync(resourceFile));
+ } catch (error) {
+ LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de ressource: " + resourceFile);
+ LOGGER.error(error);
+ return false;
+ }
+
+ if (!(await this.checkResourceConfiguration(resourceConf))) {
+ LOGGER.error("La ressource décrite dans le fichier " + resourceFile + " est mal configuée");
+ return false;
+ } else {
+ this._checkedResourceId.push(resourceConf.resource.id);
+ }
+
+ }
+
+ LOGGER.info("Vérification du dossier de ressources terminée");
+ return true;
- index = this._listOfResourceIds.indexOf(id);
- if (index !== -1) {
- this._listOfResourceIds.splice(index,1);
} else {
+ LOGGER.error("Mauvaise configuration: Le dossier n'existe pas: " + directory );
return false;
}
- this._listOfResourceIds.splice(index,1);
- return true;
}
/**
*
* @function
- * @name checkResource
+ * @name checkResourceConfiguration
* @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une ressource.
- * @param {json} resourceJsonObject - Description JSON de la ressource
- * @param {object} sourceManager - Manager de source du service
- * @param {object} operationManager - Manager d'opération du service
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
+ * @param {object} resourceJsonObject - Configuration de la ressource
+ * @return {boolean}
*
*/
- async checkResource(resourceJsonObject, sourceManager, operationManager, topologyManager) {
+ async checkResourceConfiguration(resourceJsonObject) {
- LOGGER.info("Verification de la ressource...");
+ LOGGER.info("Verification de la configuration d'une ressource...");
- if (!resourceJsonObject.resource.id) {
+ if (!resourceJsonObject.resource) {
LOGGER.error("Le fichier ne contient pas d'objet resource");
return false;
}
@@ -95,17 +151,31 @@ module.exports = class resourceManager {
return false;
} else {
LOGGER.info("Ressource id: " + resourceJsonObject.resource.id);
- // On vérifie que l'id de la ressource n'est pas déjà pris par une autre ressource.
- if (this._listOfVerifiedResourceIds.length !== 0) {
- for (let i = 0; i < this._listOfVerifiedResourceIds.length; i++ ) {
- if (this._listOfVerifiedResourceIds[i] === resourceJsonObject.resource.id) {
- LOGGER.error("Une ressource contenant l'id " + resourceJsonObject.resource.id + " a deja ete verifiee. Cette ressource ne peut donc etre ajoutee.");
+
+ // On vérifie que l'id de la ressource n'est pas déjà pris par une autre ressource chargée
+ if (this._loadedResourceId.length !== 0) {
+ for (let i = 0; i < this._loadedResourceId.length; i++ ) {
+ if (this._loadedResourceId[i] === resourceJsonObject.resource.id) {
+ LOGGER.error("Une ressource contenant l'id " + resourceJsonObject.resource.id + " a deja ete chargée.");
return false;
}
}
} else {
- // C'est la première ressource.
+ // Il n'y a pas encore de ressource chargée.
}
+
+ // On vérifie que l'id de la ressource n'est pas déjà pris par une autre ressource vérifiée
+ if (this._checkedResourceId.length !== 0) {
+ for (let i = 0; i < this._checkedResourceId.length; i++ ) {
+ if (this._checkedResourceId[i] === resourceJsonObject.resource.id) {
+ LOGGER.error("Une ressource contenant l'id " + resourceJsonObject.resource.id + " a deja ete verifiee.");
+ return false;
+ }
+ }
+ } else {
+ // C'est la première ressource vérifiée.
+ }
+
}
// Version
@@ -125,74 +195,33 @@ module.exports = class resourceManager {
LOGGER.error("La ressource ne contient pas de type.");
return false;
} else {
- // Vérification que le type est valide puis vérification spécifique à chaque type
- let available = false;
- // La partie délimitée peut être copié-collée pour ajouter un nouveau type.
- // Il ne reste plus qu'à créer la fonction de vérification correspondante.
- //------ OSRM
- if (resourceJsonObject.resource.type === "osrm") {
- available = true;
- LOGGER.info("Ressource osrm.");
- if (!this.checkResourceOsrm(resourceJsonObject.resource)) {
- LOGGER.error("Erreur lors de la verification de la ressource osrm.");
- return false;
- } else {
- // il n'y a eu aucun problème, la ressource est correctement configurée.
- }
- } else {
- // On va voir si c'est un autre type.
- }
- //------ OSRM
- //------ PGR
- let pgrStyleResources = ["pgr", "smartpgr"];
- if (pgrStyleResources.includes(resourceJsonObject.resource.type)) {
- available = true;
- LOGGER.info("Ressource pgrouting.");
- if (!this.checkResourcePgr(resourceJsonObject.resource)) {
- LOGGER.error("Erreur lors de la verification de la ressource pgr.");
- return false;
- } else {
- // il n'y a eu aucun problème, la ressource est correctement configurée.
- }
- } else {
- // On va voir si c'est un autre type.
- }
- //------ PGR
- // Si ce n'est aucun type valide, on renvoie une erreur.
- if (!available) {
+ // Vérification que le type est valide
+ if (this._availableResourceTypes.includes(resourceJsonObject.resource.type)) {
+ LOGGER.info("Type de la ressource disponible: " + resourceJsonObject.resource.type);
+ } else {
LOGGER.error("La ressource indique un type invalide: " + resourceJsonObject.resource.type);
- return false;
+ return false;
}
+
}
+ // Description
+ if (!resourceJsonObject.resource.description) {
+ LOGGER.error("La ressource ne contient pas de description.");
+ return false;
+ }
+
// Topology
if (!resourceJsonObject.resource.topology) {
LOGGER.error("La ressource ne contient pas de topologie.");
return false;
} else {
- if (!(await topologyManager.checkTopology(resourceJsonObject.resource.topology))) {
+ if (!(await this._topologyManager.checkTopologyConfiguration(resourceJsonObject.resource.topology))) {
LOGGER.error("La ressource contient une topologie incorrecte.");
return false;
- }
- }
-
- let currentAvailableOp = new Array();
- // availableOperations
- if (!resourceJsonObject.resource.availableOperations) {
- LOGGER.error("La ressource ne contient pas de availableOperations.");
- return false;
- } else {
- // on fait la vérification via le operationManager
- if (!operationManager.checkResourceOperationConf(resourceJsonObject.resource.availableOperations)) {
- LOGGER.error("Mauvaise configuration des operations dans la ressource.");
- return false;
} else {
- // on récupère la liste des opérations validées pour cette ressource
- if (!operationManager.getResourceOperationConf(resourceJsonObject.resource.availableOperations, currentAvailableOp)) {
- LOGGER.error("Impossible de recuperer les operations de la ressource.");
- return false;
- }
+ this._topologyManager.saveCheckedTopology(resourceJsonObject.resource.topology);
}
}
@@ -207,146 +236,181 @@ module.exports = class resourceManager {
for (let i = 0; i < resourceJsonObject.resource.sources.length; i++ ) {
let sourceJsonObject = resourceJsonObject.resource.sources[i];
- if (!sourceManager.checkSource(sourceJsonObject, operationManager, currentAvailableOp)) {
+ if (!this._sourceManager.checkSourceConfiguration(sourceJsonObject)) {
LOGGER.error("La ressource contient une source invalide.");
return false;
} else {
// on stocke l'id de la ressource pour cette source donnée
- sourceManager.addUsage(sourceJsonObject.id, resourceJsonObject.resource.id);
+ this._sourceManager.saveCheckedSource(sourceJsonObject);
}
// Lien avec la topologie
// TODO: vérifier que le type de la topologie soit cohérent avec le type de la source
// On stocke la correspondance entre une source et la topologie dont elle dérive
- sourceManager.sourceTopology[sourceJsonObject.id] = resourceJsonObject.resource.topology.id;
+ this._sourceManager.sourceTopology[sourceJsonObject.id] = resourceJsonObject.resource.topology.id;
}
}
- // on sauvegarde l'id de la ressource pour savoir qu'elle a déjà été vérifiée et que sa description est valide
- this._listOfVerifiedResourceIds.push(resourceJsonObject.resource.id);
+ // availableOperations
+ if (!resourceJsonObject.resource.availableOperations) {
+ LOGGER.error("La ressource ne contient pas de availableOperations.");
+ return false;
+ } else {
+ // on fait la vérification via le operationManager
+ if (!this._operationManager.checkResourceOperationConfiguration(resourceJsonObject.resource.availableOperations)) {
+ LOGGER.error("Mauvaise configuration des operations dans la ressource.");
+ return false;
+ }
+ }
+
+ // On vérifie la cohérence entre les sources diponibles et les opérations configurées
+ // Pour le moment, on va seulement vérifier que pour chaque opération paramétrée, il y a au moins une source qui puisse répondre
+ for (let i = 0; i < resourceJsonObject.resource.availableOperations.length; i++) {
+
+ let operationId = resourceJsonObject.resource.availableOperations[i].id;
+ let found = false;
+
+ for (let j = 0; resourceJsonObject.resource.sources; j++) {
+ let sourceType = resourceJsonObject.resource.sources[j].type;
+ let operations = this._sourceManager.operationsByType[sourceType];
+ if (operations.includes(operationId)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ LOGGER.error("L'opération " + operationId + " n'a pas de source pour y répondre");
+ return false;
+ }
+
+ }
LOGGER.info("Fin de la verification de la ressource.");
return true;
}
-
/**
*
* @function
- * @name checkResourceOsrm
- * @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une ressource osrm.
- * @param {json} resourceJsonObject - Description JSON de la ressource
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
+ * @name flushCheckedResource
+ * @description Vider la liste des ressources déjà vérifiées
*
*/
- checkResourceOsrm(resourceJsonObject) {
-
- LOGGER.info("Verification de la ressource osrm...");
-
- // Description
- if (!resourceJsonObject.description) {
- LOGGER.error("La ressource ne contient pas de description.");
- return false;
- } else {
- // rien à faire
- }
-
- LOGGER.info("Fin de la verification de la ressource osrm.");
- return true;
+ flushCheckedResource() {
+ this._checkedResourceId = new Array();
+
}
/**
*
* @function
- * @name checkResourcePgr
- * @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une ressource pgr.
- * @param {json} resourceJsonObject - Description JSON de la ressource
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
- * TODO: c'est une copie conforme de checkResourceOsrm, c'est pas terrible (à factoriser ou spécialiser)
+ * @name loadResourceDirectory
+ * @description Fonction utilisée pour charger le contenu d'un dossier de description d'une ressource.
+ * @param {string} directory - Dossier qui contient les configurations des ressources
+ * @return {boolean}
+ *
*/
- checkResourcePgr(resourceJsonObject) {
+ loadResourceDirectory(resourceDirectory) {
- LOGGER.info("Verification de la ressource pgr...");
+ // Pour chaque fichier du dossier des ressources, on crée une ressource
+ let files = fs.readdirSync(resourceDirectory).filter( (file) => {
+ return path.extname(file).toLowerCase() === ".resource";
+ });
+
+ for (let fileName of files) {
+
+ let resourceFile = resourceDirectory + "/" + fileName;
+ LOGGER.info("Chargement de: " + resourceFile);
+
+ // Récupération du contenu en objet pour vérification puis création de la ressource
+ let resourceContent = {};
+ try {
+ resourceContent = JSON.parse(fs.readFileSync(resourceFile));
+ } catch (error) {
+ LOGGER.error(error);
+ LOGGER.error("Erreur lors de la lecture de la ressource: " + resourceFile);
+ }
+
+ // Création de la ressource
+ if (!this.loadResourceConfiguration(resourceContent)) {
+ LOGGER.error("La ressource configurée dans le fichier " + resourceFile + " n'a pas pu être chargée");
+ } else {
+ LOGGER.info("Ressource chargée : " + resourceFile);
+ }
- // Description
- if (!resourceJsonObject.description) {
- LOGGER.error("La ressource ne contient pas de description.");
- return false;
- } else {
- // rien à faire
}
- LOGGER.info("Fin de la verification de la ressource pgr.");
return true;
+
}
/**
*
* @function
- * @name createResource
- * @description Fonction utilisée pour créer une ressource.
+ * @name loadResourceConfiguration
+ * @description Fonction utilisée pour créer une ressource à partir de sa configuration
* @param {json} resourceJsonObject - Description JSON de la ressource
- * @param {object} operationManager - Manager d'opération du service
- * @return {Resource} Ressource créée
+ * @return {boolean}
*
*/
- createResource(resourceJsonObject, operationManager) {
+ loadResourceConfiguration(resourceJsonObject) {
let resource;
if (!resourceJsonObject.resource.id) {
LOGGER.error("La ressource ne contient pas d'id.");
- return null;
+ return false;
}
LOGGER.info("Creation de la ressource: " + resourceJsonObject.resource.id);
- // On vérifie que la ressource a bien été vérifiée et validée
- if (this._listOfVerifiedResourceIds.length !== 0) {
- for (let i = 0; i < this._listOfVerifiedResourceIds.length; i++ ) {
- if (this._listOfVerifiedResourceIds[i] === resourceJsonObject.resource.id) {
- LOGGER.info("La ressource contenant l'id " + resourceJsonObject.resource.id + " a deja ete verifiee.");
- break;
+ // On vérifie que la ressource n'existe pas déjà
+ if (this._loadedResourceId.length !== 0) {
+ for (let i = 0; i < this._loadedResourceId.length; i++ ) {
+ if (this._loadedResourceId[i] === resourceJsonObject.resource.id) {
+ LOGGER.info("La ressource contenant l'id " + resourceJsonObject.resource.id + " a déjà été chargée.");
+ return true;
}
}
} else {
- LOGGER.error("Tentative de creation d'une ressource sans verification prealable. Cette ressource ne peut donc etre creee.");
- return null;
+ // C'est la première ressource créée
}
- // On vérifie que la ressource n'a pas déjà été créée
- if (this._listOfResourceIds.length !== 0) {
- for (let i = 0; i < this._listOfResourceIds.length; i++ ) {
- if (this._listOfResourceIds[i] === resourceJsonObject.resource.id) {
- LOGGER.error("Une ressource contenant l'id " + resourceJsonObject.resource.id + " existe deja. Cette ressource ne peut donc etre creee.");
- return null;
- }
- }
+ // Création de la topology associée
+ LOGGER.info("Chargement de la topology associé...");
+ let currentTopology = {};
+ if (!this._topologyManager.loadTopologyConfiguration(resourceJsonObject.resource.topology)) {
+ LOGGER.error("Impossible de créer la topology associée à la ressource");
+ return false;
} else {
- // C'est la première ressource.
+ currentTopology = this._topologyManager.getTopology(resourceJsonObject.resource.topology.id);
}
- // Création des opérations
- // ---
+ // Création des sources associées
+ LOGGER.info("Chargement des sources associées...");
+ for (let i = 0; i < resourceJsonObject.resource.sources.length; i++) {
+ if (!this._sourceManager.loadSourceConfiguration(resourceJsonObject.resource.sources[i], currentTopology)) {
+ LOGGER.error("Impossible de créer la source associée à la ressource : " + resourceJsonObject.resource.sources[i].id);
+ return false;
+ }
+ }
+ // Création des opérations
let resourceOperationHash = {};
-
- if (!operationManager.createResourceOperation(resourceOperationHash, resourceJsonObject)) {
+ if (!this._operationManager.loadResourceOperationConfiguration(resourceOperationHash, resourceJsonObject)) {
LOGGER.error("Erreur lors de la creation des operations de la ressource");
- return null;
- } else {
- // on continue
- }
-
- // ---
+ return false;
+ }
+ // Création de la ressource
if (resourceJsonObject.resource.type === "osrm") {
resource = new osrmResource(resourceJsonObject, resourceOperationHash);
} else if (resourceJsonObject.resource.type === "pgr") {
@@ -354,13 +418,16 @@ module.exports = class resourceManager {
} else if (resourceJsonObject.resource.type === "smartpgr") {
resource = new smartpgrResource(resourceJsonObject, resourceOperationHash);
} else {
- // On va voir si c'est un autre type.
+ LOGGER.error("Type de la ressource inconnue");
+ return false;
}
- // on sauvegarde l'id de la ressource pour savoir qu'elle a déjà été créée
- this._listOfResourceIds.push(resourceJsonObject.resource.id);
+ // on sauvegarde l'id de la ressource pour savoir qu'elle a déjà été créée et la ressource elle-même
+ this._loadedResourceId.push(resourceJsonObject.resource.id);
+ this._resource[resourceJsonObject.resource.id] = resource;
- return resource;
+ return true;
+
}
diff --git a/src/js/resources/smartpgrResource.js b/src/js/resources/smartpgrResource.js
index 7f9ff42..c08a9e6 100644
--- a/src/js/resources/smartpgrResource.js
+++ b/src/js/resources/smartpgrResource.js
@@ -158,30 +158,4 @@ module.exports = class smartpgrResource extends Resource {
}
- /**
- *
- * @function
- * @name removeSource
- * @description Supprimer les references à une source au sein de la ressource
- * @param {string} sourceId - Id de la source
- * @return {boolean}
- *
- */
- removeSource (sourceId) {
-
- let keysToDelete = new Array();
- for (const key in this._linkedSource) {
- if (this._linkedSource[key] === sourceId) {
- keysToDelete.push(key);
- }
- }
- if(keysToDelete.length !== 0) {
- for (let i = 0; i < keysToDelete.length; i++) {
- delete this._linkedSource[keysToDelete[i]];
- }
- }
-
- return true;
- }
-
}
diff --git a/src/js/road2.js b/src/js/road2.js
index ca753dd..56a2f48 100644
--- a/src/js/road2.js
+++ b/src/js/road2.js
@@ -2,7 +2,7 @@
const log4js = require('log4js');
const nconf = require('nconf');
-const Service = require('./service/service');
+const Administrator = require('./administrator/administrator');
const path = require('path');
const fs = require('fs');
const pm = require('./utils/processManager.js');
@@ -21,7 +21,7 @@ var LOGGER;
async function start() {
console.log("===========================");
- console.log("ROAD2 - Calcul d'itineraire");
+ console.log("ROAD2 - Administrator");
console.log("===========================");
// Chargement de la configuration
@@ -32,61 +32,85 @@ async function start() {
let logConfiguration = getLoggerConfiguration(configuration, configurationPath);
checkAndInitLogger(logConfiguration);
- // Création du service
- let service = new Service();
+ LOGGER.info("Logger de l'administrateur initialisé");
- // Vérification de la configuration globale du service et sauvegarde
- if (!service.checkAndSaveGlobalConfiguration(configuration, configurationPath)) {
- pm.shutdown(1);
- }
+ // Création de l'administrateur car il sera utilisé dans tous les cas
+ let administrator = new Administrator();
- // Sauvegarde de la configuration des logs
- service.logConfiguration = logConfiguration;
+ if (!nconf.argv().get('configCheck')) {
- // Chargement des opérations rendues disponibles sur le service
- if (!service.loadOperations()) {
- pm.shutdown(1);
- }
+ // Cas général de l'utilisation de Road2
+ LOGGER.info("Lancement classique de Road2");
- // Chargement des projections
- if (!service.loadProjections()) {
- pm.shutdown(1);
- }
+ // Récupération de la configuration de l'administrateur
+ if (!administrator.checkAdminConfiguration(configuration, configurationPath)) {
+ LOGGER.fatal("La configuration de l'administrateur n'est pas validée");
+ pm.shutdown(11);
+ } else {
- // Chargement des ressources
- if (!(await service.loadResources())) {
- pm.shutdown(1);
- }
+ LOGGER.info("La configuration de l'administrateur est validée. On la sauvegarde.");
- // En mode check de configuration, fermeteure du serveur sans code d'erreur
- if (nconf.argv().get('configCheck')) {
+ // On aura besoin de cette configuration plus tard
+ administrator.saveAdminConfiguration(configuration, configurationPath, logConfiguration);
- LOGGER.info("La vérification de la configuration est terminée");
- pm.shutdown(0);
+ // Création du serveur d'administration
+ if (!administrator.createServer()) {
+ LOGGER.fatal("Le serveur de l'administrateur ne peut être créé");
+ pm.shutdown(12);
+ } else {
+
+ LOGGER.debug("Serveur administrateur créé");
- } else {
+ // Création des services au démarrage si demandé
+ LOGGER.info("Création des services demandés au démarrage...");
- // Chargement des topologies
- if (!service.loadTopologies()) {
- pm.shutdown(1);
- }
+ if (!(await administrator.createServicesOnStart())) {
+ LOGGER.error("Problèmes lors du démarrage des services demandés. Reconfigurez les et relancez leur démarrage.");
+ // On n'éteint pas le serveur d'administration car les services pourront être reconfiguré et démarrés par l'API
+ } else {
+ LOGGER.info("Les services concernés ont été démarré");
+ }
+
+ }
- // Chargement des sources uniques
- try {
- await service.loadSources();
- } catch (err) {
- LOGGER.fatal("Impossible de charger les sources", err);
- pm.shutdown(1);
}
- // Création du serveur web
- if (!service.createServer("../apis/", "")) {
- pm.shutdown(1);
+ } else {
+
+ // Cas particulier
+ LOGGER.info("Lancement de Road2 pour vérification des configurations");
+
+ // On commence par vérifier la configuration du service
+ if (!administrator.checkAdminConfiguration(configuration, configurationPath)) {
+
+ // La configuration de l'administrateur n'est pas validée
+ LOGGER.fatal("La configuration de l'administrateur n'est pas validée");
+ pm.shutdown(11);
+
+ } else {
+
+ LOGGER.info("La configuration de l'administrateur a été vérifiée et validée");
+
+ // On la sauvegarde pour la suite
+ administrator.saveAdminConfiguration(configuration, configurationPath, logConfiguration);
+
+ // On vérifie la configuration du service
+ if (!(await administrator.checkServicesConfiguration())) {
+
+ // La configuration du service n'est pas validée
+ LOGGER.fatal("La configuration des services n'est pas validée");
+ pm.shutdown(1);
+
+ } else {
+ LOGGER.info("La configuration des services est validée");
+ }
+
}
- }
+ LOGGER.info("La vérification des différentes configurations est terminée");
+ pm.shutdown(0);
-
+ }
}
@@ -120,31 +144,31 @@ function loadGlobalConfiguration() {
} catch (error) {
console.log("Impossible de recuperer le chemin absolu du fichier de configuration:");
console.log(error);
- process.exit(1);
+ process.exit(11);
}
// vérification de l'exitence du fichier
if (fs.existsSync(configurationPath)) {
- // chargement dans une variable pour la classe Service
+ // chargement dans une variable pour la classe Administrateur
try {
globalConfiguration = JSON.parse(fs.readFileSync(configurationPath));
} catch (error) {
console.log("Mauvaise configuration: impossible de lire ou de parser le fichier de configuration de Road2:");
console.log(error);
- process.exit(1);
+ process.exit(11);
}
} else {
console.log("Mauvaise configuration: fichier de configuration global inexistant: " + configurationPath);
console.log("Utilisez le paramètre ROAD2_CONF_FILE en ligne de commande ou en variable d'environnement pour le préciser.");
- process.exit(1);
+ process.exit(11);
}
} else {
//si aucun fichier n'a été précisé on renvoie une erreur
console.log("Aucun fichier de configuration. Utiliser la variable d'environnement $ROAD2_CONF_FILE ou l'option --ROAD2_CONF_FILE lors de l'initialisation du serveur.");
- process.exit(1);
+ process.exit(11);
}
console.log("Configuration chargee.")
@@ -156,9 +180,9 @@ function loadGlobalConfiguration() {
/**
*
* @function
-* @name initLogger
+* @name checkAndInitLogger
* @description Initialiser le logger
-* @param {json} userLogConfigurationFile - Configuration des logs de l'application
+* @param {json} userLogConfiguration - Configuration des logs de l'administrateur
*
*/
@@ -176,7 +200,7 @@ function checkAndInitLogger(userLogConfiguration) {
} catch (error) {
console.log("Mauvaise configuration des logs dans mainConf");
console.log(error);
- process.exit(1);
+ process.exit(11);
}
//Instanciation du logger
@@ -186,39 +210,39 @@ function checkAndInitLogger(userLogConfiguration) {
} else {
console.log("Mausvaise configuration pour les logs: 'mainConf' absent.");
- process.exit(1);
+ process.exit(11);
}
if (userLogConfiguration.httpConf) {
if (!userLogConfiguration.httpConf.level) {
console.log("Mausvaise configuration pour les logs: 'httpConf.level' absent.");
- process.exit(1);
+ process.exit(11);
} else {
if (typeof userLogConfiguration.httpConf.level !== "string") {
console.log("Mausvaise configuration pour les logs: 'httpConf.level' n'est pas une chaine de caracteres");
- process.exit(1);
+ process.exit(11);
}
}
if (!userLogConfiguration.httpConf.format) {
console.log("Mausvaise configuration pour les logs: 'httpConf.format' absent.");
- process.exit(1);
+ process.exit(11);
} else {
if (typeof userLogConfiguration.httpConf.format !== "string") {
console.log("Mausvaise configuration pour les logs: 'httpConf.format' n'est pas une chaine de caracteres");
- process.exit(1);
+ process.exit(11);
}
}
} else {
console.log("Mausvaise configuration pour les logs: 'httpConf' absent.");
- process.exit(1);
+ process.exit(11);
}
} else {
console.log("Aucune configuration pour les logs.");
- process.exit(1);
+ process.exit(11);
}
}
@@ -227,9 +251,9 @@ function checkAndInitLogger(userLogConfiguration) {
*
* @function
* @name getLoggerConfiguration
-* @description Récupérer la configuration des logs du serveur
-* @param {json} userConfiguration - Configuration de l'application
-* @param {string} userConfigurationPath - CHemin absolu du fichier de configuration
+* @description Récupérer la configuration des logs du serveur d'administration
+* @param {json} userConfiguration - Configuration de l'administrateur
+* @param {string} userConfigurationPath - Chemin absolu du fichier de configuration
* @return {json} Configuration des logs du serveur
*
*/
@@ -243,13 +267,13 @@ function getLoggerConfiguration(userConfiguration, userConfigurationPath) {
if (userConfiguration) {
- if (userConfiguration.application) {
+ if (userConfiguration.administration) {
- if (userConfiguration.application.logs) {
+ if (userConfiguration.administration.logs) {
- if (userConfiguration.application.logs.configuration) {
+ if (userConfiguration.administration.logs.configuration) {
- userLogConfigurationFile = userConfiguration.application.logs.configuration;
+ userLogConfigurationFile = userConfiguration.administration.logs.configuration;
// chemin absolu du fichier
let file = "";
@@ -262,7 +286,7 @@ function getLoggerConfiguration(userConfiguration, userConfigurationPath) {
console.log("Impossible de recuperer le chemin absolu du fichier de log:");
console.log(error);
- process.exit(1);
+ process.exit(11);
}
@@ -274,33 +298,33 @@ function getLoggerConfiguration(userConfiguration, userConfigurationPath) {
} catch (error) {
console.log("Mauvaise configuration: impossible de lire ou de parser le fichier de configuration des logs:");
console.log(error);
- process.exit(1);
+ process.exit(11);
}
} else {
console.log("Mauvaise configuration: fichier de configuration des logs inexistant:");
console.log(file);
- process.exit(1);
+ process.exit(11);
}
} else {
- console.log("Mauvais configuration: 'application.logs.configuration' absent.");
- process.exit(1);
+ console.log("Mauvaise configuration: 'administration.logs.configuration' absent.");
+ process.exit(11);
}
} else {
- console.log("Mauvais configuration: 'application.logs' absent.");
- process.exit(1);
+ console.log("Mauvaise configuration: 'administration.logs' absent.");
+ process.exit(11);
}
} else {
- console.log("Mauvais configuration: 'application' absent.");
- process.exit(1);
+ console.log("Mauvaise configuration: 'administration' absent.");
+ process.exit(11);
}
} else {
// cela ne doit arriver que si cette fonction est appelée sans paramètre
- console.log("Absence de configuration pour l'application.");
- process.exit(1);
+ console.log("Absence de configuration pour l'administration.");
+ process.exit(11);
}
return logsConf;
diff --git a/src/js/server/serverManager.js b/src/js/server/serverManager.js
index 3c26ff0..964d9b0 100644
--- a/src/js/server/serverManager.js
+++ b/src/js/server/serverManager.js
@@ -3,7 +3,6 @@
const Server = require('./server');
const log4js = require('log4js');
const fs = require('fs');
-const path = require('path');
const assert = require('assert');
// Création du LOGGER
@@ -29,22 +28,32 @@ module.exports = class serverManager {
*/
constructor() {
+ // Liste des serveurs chargés
+ this._loadedServerId = new Array();
+
+ // Liste des serveurs vérifiés
+ this._checkedServerId = new Array();
+
// Catalogue de serveurs
this._serverCatalog = {};
// Description des serveurs
- this._serverDescriptions = new Array();
+ this._loadedServerDescription = {};
+
+ // Description des serveurs
+ this._checkedServerDescription = {};
}
/**
*
* @function
- * @name checkConfiguration
+ * @name checkServerConfiguration
* @description Vérifier la configuration d'un serveur
+ * @param {object} config - Configuration à vérifier
*
*/
- checkConfiguration(config) {
+ checkServerConfiguration(config) {
if (!config) {
LOGGER.error("Aucune configuration n'a ete fournie");
@@ -57,7 +66,27 @@ module.exports = class serverManager {
LOGGER.error("La configuration du serveur n'indique aucun id");
return false;
} else {
- // TODO: Vérification
+
+ // On vérifie que l'id n'est pas déjà chargé
+ if (this._loadedServerId.length !== 0) {
+ for (let i = 0; i < this._loadedServerId.length; i++) {
+ if (config.id === this._loadedServerId[i]) {
+ LOGGER.error("Un serveur contenant l'id " + config.id + " est deja chargé.");
+ return false;
+ }
+ }
+ }
+
+ // On vérifie que l'id n'est pas déjà pris par le check courant
+ if (this._checkedServerId.length !== 0) {
+ for (let i = 0; i < this._checkedServerId.length; i++) {
+ if (config.id === this._checkedServerId[i]) {
+ LOGGER.error("Un serveur contenant l'id " + config.id + " est déjà verifié.");
+ return false;
+ }
+ }
+ }
+
}
if (!config.https) {
@@ -176,69 +205,79 @@ module.exports = class serverManager {
}
- // Stockage de la description
- this._serverDescriptions.push(config);
-
return true;
}
+ saveServerConfiguration(config) {
+
+ this._checkedServerId.push(config.id);
+ this._checkedServerDescription[config.id] = config;
+
+ }
+
/**
*
* @function
- * @name createServer
+ * @name loadServerConfiguration
* @description Créer un serveur
+ * @param {object} app - Instance d'ExpressJS
+ * @param {object} config - Configuration du serveur
*
*/
- createServer(app, config) {
+ loadServerConfiguration(app, config) {
+
+ LOGGER.info("Chargement du serveur : " + config.id);
+
+ // On vérifie que l'id n'est pas déjà chargé
+ if (this._loadedServerId.length !== 0) {
+ for (let i = 0; i < this._loadedServerId.length; i++) {
+ if (config.id === this._loadedServerId[i]) {
+ LOGGER.info("Un serveur contenant l'id " + config.id + " est deja chargé.");
+ return true;
+ }
+ }
+ }
if (config.https === "true") {
- return new Server(config.id, app, config.host, config.port, "true", config.options);
+ this._serverCatalog[config.id] = new Server(config.id, app, config.host, config.port, "true", config.options);
} else {
- return new Server(config.id, app, config.host, config.port, "false", config.options);
+ this._serverCatalog[config.id] = new Server(config.id, app, config.host, config.port, "false", config.options);
}
+ this._loadedServerId.push(config.id);
+ this._loadedServerDescription[config.id] = config;
+
+ return true;
+
}
/**
*
* @function
- * @name createAllServer
- * @description Créer l'ensemble des serveurs disponibles dans le manager
+ * @name flushCheckedServer
+ * @description Vider la liste des serveurs déjà vérifiées
*
*/
- createAllServer(app) {
+ flushCheckedServer() {
- if (this._serverDescriptions.length === 0) {
- LOGGER.error("Aucun serveur n'est disponible.");
- return false;
- }
-
- for(let i = 0; i < this._serverDescriptions.length; i++) {
- let configuration = this._serverDescriptions[i];
- try {
- this._serverCatalog[configuration.id] = this.createServer(app, configuration);
- } catch (err) {
- return false;
- }
- }
-
- return true;
+ this._checkedServerId = new Array();
+ this._checkedServerDescription = {};
}
/**
*
* @function
- * @name startAllServer
- * @description Démarer l'ensemble des serveurs disponibles dans le manager
+ * @name startAllServers
+ * @description Démarrer l'ensemble des serveurs disponibles dans le manager
*
*/
- startAllServer() {
+ startAllServers() {
LOGGER.info("Demarrage de l'ensemble des serveurs.");
- if (this._serverDescriptions.length === 0) {
+ if (this._loadedServerId.length === 0) {
LOGGER.error("Aucun serveur n'est disponible.");
return false;
}
@@ -276,7 +315,7 @@ module.exports = class serverManager {
LOGGER.info("Arret de l'ensemble des serveurs.");
- if (this._serverDescriptions.length === 0) {
+ if (this._loadedServerId.length === 0) {
LOGGER.warn("Aucun serveur n'est disponible.");
return true;
}
diff --git a/src/js/service/main.js b/src/js/service/main.js
new file mode 100644
index 0000000..4c0aec4
--- /dev/null
+++ b/src/js/service/main.js
@@ -0,0 +1,250 @@
+'use strict';
+
+const pm = require('../utils/processManager.js');
+const Service = require('./service');
+const log4js = require('log4js');
+const fs = require('fs');
+const path = require('path');
+
+var LOGGER;
+
+/**
+*
+* @function
+* @name startService
+* @description Fonction principale pour démarrer un service
+* @param {string} configurationLocation - Localisation de la configuration du service (localisation absolue du service.json)
+*
+*/
+
+async function startService() {
+
+ console.log("===========================");
+ console.log("ROAD2 - Service ");
+ console.log("===========================");
+
+ // Récupération des arguments
+ let configurationLocation = "";
+ if (process.argv[2] !== "") {
+ configurationLocation = process.argv[2];
+ } else {
+ console.log("Configuration du service absente, extinction du processus...");
+ process.exit(1);
+ }
+
+ // Récupération de la configuration
+ let configuration = "";
+ try {
+ configuration = JSON.parse(fs.readFileSync(configurationLocation));
+ } catch(error) {
+ console.log("Impossible de lire la configuration : " + configurationLocation);
+ console.log(error);
+ process.exit(1);
+ }
+
+ // Instanciation du logger
+ let logConfiguration = getLoggerConfiguration(configuration, configurationLocation);
+ checkAndInitLogger(logConfiguration);
+
+ LOGGER.info("Instanciation du logger pour le service terminee. Creation de la classe Service...");
+
+ // Création du service
+ let service = new Service();
+
+ // Vérification de la configuration globale du service
+ // TODO : Selon les erreurs, on lance ou pas le service
+
+ if (!(await service.checkServiceConfiguration(configuration, configurationLocation))) {
+ pm.shutdown(1);
+ } else {
+
+ LOGGER.debug("Configuration du service vérifiée et suffisamment validée pour lancer un service");
+
+ // On aura besoin de cette configuration juste après et peut-être plus tard
+ service.saveServiceConfiguration(configuration, configurationLocation, logConfiguration);
+
+ // On lance le chargement du service qui est normalement correctement configuré
+ if (!service.loadServiceConfiguration()) {
+ pm.shutdown(2);
+ } else {
+
+ LOGGER.debug("Service chargé");
+
+ // On connecte les sources
+ if (!(await service.connectSources())) {
+
+ LOGGER.fatal("Aucune source n'a pu être connectée");
+ pm.shutdown(4);
+
+ } else {
+
+ LOGGER.info("Les sources connectables ont été connectées");
+
+ // On démarre les serveurs associé à ce service
+ if (!service.startServers()) {
+ pm.shutdown(5);
+ }
+
+ }
+
+ }
+
+ }
+
+}
+
+/**
+*
+* @function
+* @name checkAndInitLogger
+* @description Initialiser le logger
+* @param {json} userLogConfiguration - Configuration des logs de l'administrateur
+*
+*/
+
+function checkAndInitLogger(userLogConfiguration) {
+
+ console.log("Instanciation du logger...");
+
+ if (userLogConfiguration) {
+
+ if (userLogConfiguration.mainConf) {
+
+ // Configuration du logger
+ try {
+ log4js.configure(userLogConfiguration.mainConf);
+ } catch (error) {
+ console.log("Mauvaise configuration des logs dans mainConf");
+ console.log(error);
+ process.exit(1);
+ }
+
+ //Instanciation du logger
+ LOGGER = log4js.getLogger('MAIN-SERVICE');
+
+ LOGGER.info("Logger charge.");
+
+ } else {
+ console.log("Mausvaise configuration pour les logs: 'mainConf' absent.");
+ process.exit(1);
+ }
+
+ if (userLogConfiguration.httpConf) {
+
+ if (!userLogConfiguration.httpConf.level) {
+ console.log("Mausvaise configuration pour les logs: 'httpConf.level' absent.");
+ process.exit(1);
+ } else {
+ if (typeof userLogConfiguration.httpConf.level !== "string") {
+ console.log("Mausvaise configuration pour les logs: 'httpConf.level' n'est pas une chaine de caracteres");
+ process.exit(1);
+ }
+ }
+
+ if (!userLogConfiguration.httpConf.format) {
+ console.log("Mausvaise configuration pour les logs: 'httpConf.format' absent.");
+ process.exit(1);
+ } else {
+ if (typeof userLogConfiguration.httpConf.format !== "string") {
+ console.log("Mausvaise configuration pour les logs: 'httpConf.format' n'est pas une chaine de caracteres");
+ process.exit(1);
+ }
+ }
+
+ } else {
+ console.log("Mausvaise configuration pour les logs: 'httpConf' absent.");
+ process.exit(1);
+ }
+
+ } else {
+ console.log("Aucune configuration pour les logs.");
+ process.exit(1);
+ }
+
+ }
+
+ /**
+ *
+ * @function
+ * @name getLoggerConfiguration
+ * @description Récupérer la configuration des logs du serveur d'administration
+ * @param {json} userConfiguration - Configuration de l'administrateur
+ * @param {string} userConfigurationPath - Chemin absolu du fichier de configuration
+ * @return {json} Configuration des logs du serveur
+ *
+ */
+
+ function getLoggerConfiguration(userConfiguration, userConfigurationPath) {
+
+ console.log("Recuperation de la configuration du logger...");
+
+ let logsConf;
+ let userLogConfigurationFile;
+
+ if (userConfiguration) {
+
+ if (userConfiguration.application) {
+
+ if (userConfiguration.application.logs) {
+
+ if (userConfiguration.application.logs.configuration) {
+
+ userLogConfigurationFile = userConfiguration.application.logs.configuration;
+
+ // chemin absolu du fichier
+ let file = "";
+
+ try {
+
+ file = path.resolve(path.dirname(userConfigurationPath), userLogConfigurationFile);
+
+ } catch (error) {
+
+ console.log("Impossible de recuperer le chemin absolu du fichier de log:");
+ console.log(error);
+ process.exit(1);
+
+ }
+
+ // vérification de l'exitence du fichier
+ if (fs.existsSync(file)) {
+ //Lecture du fichier de configuration des logs
+ try {
+ logsConf = JSON.parse(fs.readFileSync(file));
+ } catch (error) {
+ console.log("Mauvaise configuration: impossible de lire ou de parser le fichier de configuration des logs:");
+ console.log(error);
+ process.exit(1);
+ }
+ } else {
+ console.log("Mauvaise configuration: fichier de configuration des logs inexistant:");
+ console.log(file);
+ process.exit(1);
+ }
+
+ } else {
+ console.log("Mauvaise configuration: 'application.logs.configuration' absent.");
+ process.exit(1);
+ }
+
+ } else {
+ console.log("Mauvaise configuration: 'application.logs' absent.");
+ process.exit(1);
+ }
+
+ } else {
+ console.log("Mauvaise configuration: 'application' absent.");
+ process.exit(1);
+ }
+
+ } else {
+ // cela ne doit arriver que si cette fonction est appelée sans paramètre
+ console.log("Absence de configuration pour l'application.");
+ process.exit(1);
+ }
+
+ return logsConf;
+
+ }
+
+startService();
\ No newline at end of file
diff --git a/src/js/service/service.js b/src/js/service/service.js
index 244e6e7..899ca66 100644
--- a/src/js/service/service.js
+++ b/src/js/service/service.js
@@ -3,18 +3,17 @@
const fs = require('fs');
const path = require('path');
const express = require('express');
-const assert = require('assert').strict;
const cors = require('cors');
const helmet = require('helmet');
const ApisManager = require('../apis/apisManager');
const ResourceManager = require('../resources/resourceManager');
-const errorManager = require('../utils/errorManager');
const SourceManager = require('../sources/sourceManager');
const OperationManager = require('../operations/operationManager');
const BaseManager = require('../base/baseManager');
const TopologyManager = require('../topology/topologyManager');
const ProjectionManager = require('../geography/projectionManager');
const ServerManager = require('../server/serverManager');
+const LogManager = require('../utils/logManager');
const log4js = require('log4js');
// Création du LOGGER
@@ -52,17 +51,11 @@ module.exports = class Service {
// Manager des topologies du service
this._topologyManager = new TopologyManager(this._baseManager, this._projectionManager);
- // Manager des ressources du service.
- this._resourceManager = new ResourceManager();
-
- // catalogue des ressources du service.
- this._resourceCatalog = {};
-
// Manager des sources du service.
this._sourceManager = new SourceManager();
- // catalogue des sources du service.
- this._sourceCatalog = {};
+ // Manager des ressources du service.
+ this._resourceManager = new ResourceManager(this._sourceManager, this._operationManager, this._topologyManager);
// Manager des apis du service
this._apisManager = new ApisManager();
@@ -84,8 +77,8 @@ module.exports = class Service {
/**
*
* @function
- * @name get resourceCatalog
- * @description Récupérer l'ensemble des ressources
+ * @name get configuration
+ * @description Récupérer la configuration du service
*
*/
get configuration() {
@@ -124,17 +117,6 @@ module.exports = class Service {
}
}
- /**
- *
- * @function
- * @name get resourceCatalog
- * @description Récupérer l'ensemble des ressources
- *
- */
- get resourceCatalog() {
- return this._resourceCatalog;
- }
-
/**
*
* @function
@@ -167,7 +149,18 @@ module.exports = class Service {
*
*/
getResourceById(id) {
- return this._resourceCatalog[id];
+ return this._resourceManager.resource[id];
+ }
+
+ /**
+ *
+ * @function
+ * @name getResources
+ * @description Récupérer l'ensemble des ressources
+ *
+ */
+ getResources() {
+ return this._resourceManager.resource;
}
/**
@@ -179,24 +172,13 @@ module.exports = class Service {
*
*/
verifyResourceExistenceById(id) {
- if (this._resourceCatalog[id]) {
+ if (this._resourceManager.resource[id]) {
return true;
} else {
return false;
}
}
- /**
- *
- * @function
- * @name get sourceCatalog
- * @description Récupérer l'ensemble des sources
- *
- */
- get sourceCatalog() {
- return this._sourceCatalog;
- }
-
/**
*
* @function
@@ -206,7 +188,7 @@ module.exports = class Service {
*
*/
getSourceById(id) {
- return this._sourceCatalog[id];
+ return this._sourceManager.source[id];
}
/**
@@ -218,7 +200,7 @@ module.exports = class Service {
*
*/
verifySourceExistenceById(id) {
- if (this._sourceCatalog[id]) {
+ if (this._sourceManager.source[id]) {
return true;
} else {
return false;
@@ -239,39 +221,49 @@ module.exports = class Service {
/**
*
* @function
- * @name checkAndSaveGlobalConfiguration
+ * @name checkServiceConfiguration
* @description Vérification de la configuration globale du serveur
* @param {json} userConfiguration - JSON décrivant la configuration du service
* @param {string} userConfigurationPath - Chemin absolu du fichier de configuration
*
*/
- checkAndSaveGlobalConfiguration(userConfiguration, userConfigurationPath) {
+ async checkServiceConfiguration(userConfiguration, userConfigurationPath) {
+
+ LOGGER.info("Verification de la configuration globale du service...");
- LOGGER.info("Verification de la configuration globale de l'application...");
+ LOGGER.debug("Vérification des informations générales");
// Configuration de l'application
if (!userConfiguration.application) {
LOGGER.fatal("Mauvaise configuration: Objet 'application' manquant !");
return false;
}
+
// Nom de l'application
if (!userConfiguration.application.name) {
LOGGER.fatal("Mauvaise configuration: Champ 'application:name' manquant !");
return false;
}
+
// Titre de l'application
if (!userConfiguration.application.title) {
LOGGER.fatal("Mauvaise configuration: Champ 'application:title' manquant !");
return false;
}
+
// Description de l'application
if (!userConfiguration.application.description) {
LOGGER.fatal("Mauvaise configuration: Champ 'application:description' manquant !");
return false;
}
+
// Information sur le fournisseur du service
+
+ LOGGER.debug("Vérification des informations du provider");
+
if (userConfiguration.application.provider) {
+
// Nom
if (!userConfiguration.application.provider.name) {
LOGGER.fatal("Mauvaise configuration: Champ 'application:provider:name' manquant !");
@@ -286,121 +278,162 @@ module.exports = class Service {
LOGGER.fatal("Mauvaise configuration: Champ 'application:provider:mail' manquant !");
return false;
}
+
} else {
LOGGER.warn("Configuration incomplete: Objet 'application:provider' manquant !");
}
+
+ // Information sur le logger
+
+ // On le test ici aussi pour avoir un check le plus complet quand il est lancé en dehors d'un démarrage de Road2
+ LOGGER.debug("Vérification des informations sur les logs");
+
+ if (!userConfiguration.application.logs) {
+ LOGGER.error("Mauvaise configuration: Objet 'application.logs' manquant !");
+ return false;
+ } else {
+
+ if (!userConfiguration.application.logs.configuration) {
+ LOGGER.error("Mauvaise configuration: Objet 'application.logs.configuration' manquant !");
+ return false;
+ } else {
+
+ let logConfPath = "";
+
+ try {
+ logConfPath = path.resolve(path.dirname(userConfigurationPath), userConfiguration.application.logs.configuration);
+ } catch (error) {
+ LOGGER.error("Impossible d'avoir le chemin absolu du fichier de configuration des logs: " + userConfiguration.application.logs.configuration);
+ LOGGER.error(error);
+ return false;
+ }
+
+ if (fs.existsSync(logConfPath)) {
+
+ let logConf = {};
+
+ try {
+ // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard
+ logConf = JSON.parse(fs.readFileSync(logConfPath));
+ } catch (error) {
+ LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de conf des logs du service de Road2: " + logConfPath);
+ LOGGER.error(error);
+ return false;
+ }
+
+ if (!LogManager.checkLogConfiguration(logConf, logConfPath)) {
+ LOGGER.error("Le logger est mal configuré");
+ return false;
+ }
+
+ } else {
+ LOGGER.fatal("Mauvaise configuration: Fichier de conf des logs inexistant : " + logConfPath);
+ return false;
+ }
+
+ }
+ }
+
// Information sur les opérations
- if (userConfiguration.application.operations) {
+
+ LOGGER.debug("Vérification des informations sur les opérations");
+
+ if (!userConfiguration.application.operations) {
+ LOGGER.fatal("Mauvaise configuration: Objet 'application:operations' manquant !");
+ return false;
+ } else {
+
// Dossier contenant les fichiers d'opérations
if (!userConfiguration.application.operations.directory) {
LOGGER.fatal("Mauvaise configuration: Champ 'application:operations:directory' manquant !");
return false;
} else {
- // On vérifie que le dossier existe et qu'il contient des fichiers de description des opérations
- let directory = "";
-
- try {
- directory = path.resolve(path.dirname(userConfigurationPath), userConfiguration.application.operations.directory);
- } catch (error) {
- LOGGER.fatal("Can't get absolute path of operations directory: " + userConfiguration.application.operations.directory);
- LOGGER.fatal(error);
+ // On vérifie d'abord les paramètres car ils sont référencés dans les opérations
+ if (!userConfiguration.application.operations.parameters) {
+ LOGGER.fatal("Mauvaise configuration: Objet 'application:operations:parameters' manquant !");
return false;
- }
-
- if (fs.existsSync(directory)) {
- // On vérifie que l'application peut lire les fichiers du dossier
- fs.readdirSync(directory).forEach(operation => {
+ } else {
- let operationFile = "";
+ if (!userConfiguration.application.operations.parameters.directory) {
+ LOGGER.fatal("Mauvaise configuration: Champ 'application:operations:parameters:directory' manquant !");
+ return false;
+ } else {
- try {
- operationFile = directory + "/" + operation;
- fs.accessSync(operationFile, fs.constants.R_OK);
- } catch (err) {
- LOGGER.error("Le fichier d'operation ne peut etre lu: " + operationFile);
- }
+ // On vérifie que le dossier existe et qu'il contient des fichiers de description des paramètres
+ let parameterDirectory = "";
try {
- // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard
- JSON.parse(fs.readFileSync(operationFile));
+ parameterDirectory = path.resolve(path.dirname(userConfigurationPath), userConfiguration.application.operations.parameters.directory);
} catch (error) {
- LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier d'operation: " + operationFile);
- LOGGER.error(error);
+ LOGGER.fatal("Can't get absolute path of parameters directory: " + userConfiguration.application.operations.parameters.directory);
+ LOGGER.fatal(error);
return false;
}
- });
+ if (!this._operationManager.checkParameterDirectory(parameterDirectory)) {
+ LOGGER.error("Le dossier des parametres est mal configuré");
+ return false;
+ }
- // On vérifie que la partie concernant les paramètres est bien renseignée
- if (!userConfiguration.application.operations.parameters) {
- LOGGER.fatal("Mauvaise configuration: Objet 'application:operations:parameters' manquant !");
- return false;
- } else {
+ // On vérifie que le dossier existe et qu'il contient des fichiers de description des opérations
+ let operationDirectory = "";
- if (!userConfiguration.application.operations.parameters.directory) {
- LOGGER.fatal("Mauvaise configuration: Champ 'application:operations:parameters:directory' manquant !");
+ try {
+ operationDirectory = path.resolve(path.dirname(userConfigurationPath), userConfiguration.application.operations.directory);
+ } catch (error) {
+ LOGGER.fatal("Can't get absolute path of operations directory: " + userConfiguration.application.operations.directory);
+ LOGGER.fatal(error);
return false;
- } else {
-
- // On vérifie que le dossier existe et qu'il contient des fichiers de description des paramètres
- let directory = "";
-
- try {
- directory = path.resolve(path.dirname(userConfigurationPath), userConfiguration.application.operations.parameters.directory);
- } catch (error) {
- LOGGER.fatal("Can't get absolute path of parameters directory: " + userConfiguration.application.operations.parameters.directory);
- LOGGER.fatal(error);
- return false;
- }
-
- if (fs.existsSync(directory)) {
- // On vérifie que l'application peut lire les fichiers du dossier
- fs.readdirSync(directory).forEach(parameter => {
-
- let parameterFile = "";
-
- try {
- parameterFile = directory + "/" + parameter;
- fs.accessSync(parameterFile, fs.constants.R_OK);
- } catch (err) {
- LOGGER.error("Le fichier de parametres ne peut etre lu: " + parameterFile);
- }
-
- try {
- // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard
- JSON.parse(fs.readFileSync(parameterFile));
- } catch (error) {
- LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de parametres: " + parameterFile);
- LOGGER.error(error);
- return false;
- }
-
- });
-
- } else {
- LOGGER.fatal("Mauvaise configuration: Le dossier des parametres n'existe pas : " + directory);
- return false;
- }
+ }
+ if (!this._operationManager.checkOperationDirectory(operationDirectory)) {
+ LOGGER.error("Le dossier des operations est mal configuré");
+ return false;
}
}
- } else {
- LOGGER.fatal("Mauvaise configuration: Le dossier des operations n'existe pas: " + directory);
- return false;
}
}
- } else {
- LOGGER.fatal("Mauvaise configuration: Objet 'application:operations' manquant !");
+ }
+
+ // Projections
+
+ LOGGER.debug("Vérification des informations sur les projections");
+
+ if (!userConfiguration.application.projections) {
+ LOGGER.fatal("Mauvaise configuration: Objet 'application:projections' manquant !");
return false;
+ } else {
+
+ if (!userConfiguration.application.projections.directory) {
+ LOGGER.fatal("Mauvaise configuration: Champ 'application:projections:directory' manquant !");
+ return false;
+ } else {
+
+
+ let directory = path.resolve(path.dirname(userConfigurationPath), userConfiguration.application.projections.directory);
+
+ if (!this._projectionManager.checkProjectionDirectory(directory)) {
+ LOGGER.fatal("La configuration des projections du dossier est incorrecte");
+ return false;
+ }
+
+ }
+
}
// Information sur les ressources
- if (userConfiguration.application.resources) {
+
+ LOGGER.debug("Vérification des informations sur les ressources");
+
+ if (!userConfiguration.application.resources) {
+ LOGGER.fatal("Mauvaise configuration: Objet 'application:resources' manquant !");
+ return false;
+ } else {
// Dossier contenant les fichiers de ressources
if (!userConfiguration.application.resources.directories) {
LOGGER.fatal("Mauvaise configuration: Champ 'application:resources:directories' manquant !");
@@ -418,7 +451,8 @@ module.exports = class Service {
return false;
}
- let resourceCount = 0;
+ let oneValidDir = false;
+
for (let i = 0; i < resourcesDirectories.length; i++) {
// On vérifie que le dossier existe et qu'il contient des fichiers de description des ressources
@@ -428,49 +462,32 @@ module.exports = class Service {
} else {
let directory = path.resolve(path.dirname(userConfigurationPath), resourcesDirectories[i]);
- if (fs.existsSync(directory)) {
- // On vérifie que l'application peut lire les fichiers du dossier
- fs.readdirSync(directory).forEach(resource => {
-
- let resourceFile = "";
- try {
- resourceFile = directory + "/" + resource;
- fs.accessSync(resourceFile, fs.constants.R_OK);
- resourceCount++;
- } catch (err) {
- LOGGER.error("Le fichier de ressource ne peut etre lu: " + resourceFile);
- }
-
- try {
- // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard
- JSON.parse(fs.readFileSync(resourceFile));
- } catch (error) {
- LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de ressource: " + resourceFile);
- LOGGER.error(error);
- return false;
- }
-
- });
+
+ if (!(await this._resourceManager.checkResourceDirectory(directory))) {
+ LOGGER.error("Le dossier " + directory + " contient des ressources dont la vérification a échoué");
+ return false;
} else {
- LOGGER.error("Mauvaise configuration: Le dossier n'existe pas: " + directory );
+ LOGGER.info("Le dossier " + directory + " est vérifié et suffisamment validé pour continuer");
+ oneValidDir = true;
}
}
}
- if (resourceCount === 0) {
- LOGGER.fatal("Mauvaise configuration: Champ 'application:resources:directories' ne pointe vers aucune ressource disponible !");
+ if (!oneValidDir) {
+ LOGGER.error("Aucun dossier de ressource n'a été validé");
return false;
}
}
- } else {
- LOGGER.fatal("Mauvaise configuration: Objet 'application:resources' manquant !");
- return false;
- }
+ }
+
// Information sur le reseau
+
+ LOGGER.debug("Vérification des informations sur le réseau");
+
if (!userConfiguration.application.network) {
LOGGER.fatal("Mauvaise configuration: Objet 'application:network' manquant !");
return false;
@@ -492,9 +509,11 @@ module.exports = class Service {
}
for (let i = 0; i < userConfiguration.application.network.servers.length; i++) {
- if (!this._serverManager.checkConfiguration(userConfiguration.application.network.servers[i])) {
+ if (!this._serverManager.checkServerConfiguration(userConfiguration.application.network.servers[i])) {
LOGGER.fatal("Mauvaise configuration d'un serveur !");
return false;
+ } else {
+ this._serverManager.saveServerConfiguration(userConfiguration.application.network.servers[i]);
}
}
@@ -539,351 +558,163 @@ module.exports = class Service {
}
- if (!userConfiguration.application.projections) {
- LOGGER.fatal("Mauvaise configuration: Objet 'application:projections' manquant !");
+ // Les APIs
+
+ LOGGER.debug("Vérification des informations sur les APIs");
+
+ if (!userConfiguration.application.apis) {
+ LOGGER.fatal("Mauvaise configuration: Objet 'application:apis' manquant !");
return false;
} else {
- if (!userConfiguration.application.projections.directory) {
- LOGGER.fatal("Mauvaise configuration: Champ 'application:projections:directory' manquant !");
- return false;
+ if (!Array.isArray(userConfiguration.application.apis)) {
+ LOGGER.fatal("Mauvaise configuration: Objet 'application:apis' n'est pas un tableau !");
+ return false;
+ }
+
+ if (userConfiguration.application.apis.length === 0) {
+ LOGGER.fatal("Mauvaise configuration: Objet 'application:apis' est un tableau vide !");
+ return false;
} else {
- let projDir = "";
-
- try {
- projDir = path.resolve(path.dirname(userConfigurationPath), userConfiguration.application.projections.directory);
- } catch (error) {
- LOGGER.error("Impossible d'avoir le chemin aboslu du dossier de projection: " + projDir);
- LOGGER.error(error);
- return false;
+ for (let i = 0; i < userConfiguration.application.apis.length; i++) {
+ if (!this._apisManager.checkApiConfiguration(userConfiguration.application.apis[i])) {
+ LOGGER.fatal("Mauvaise configuration: Objet 'application:apis' contient un objet invalide");
+ return false;
+ }
}
- if (fs.existsSync(projDir)) {
-
- // On vérifie que l'application peut lire les fichiers du dossier
- fs.readdirSync(projDir).forEach(projection => {
-
- let projectionFile = "";
-
- try {
- projectionFile = projDir + "/" + projection;
- fs.accessSync(projectionFile, fs.constants.R_OK);
- } catch (err) {
- LOGGER.error("Le fichier de projection ne peut etre lu: " + projectionFile);
- }
+ }
- try {
- // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard
- JSON.parse(fs.readFileSync(projectionFile));
- } catch (error) {
- LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de projection: " + projectionFile);
- LOGGER.error(error);
- return false;
- }
- });
+ }
- } else {
- LOGGER.fatal("Mauvaise configuration: Dossier de projections inexistant : " + projDir);
- return false;
- }
+ // Nettoyage de tous les managers
- }
+ LOGGER.debug("Nettoyage des managers");
- }
+ this._projectionManager.flushCheckedProjection();
+ this._baseManager.flushCheckedBaseConfiguration();
+ this._operationManager.flushCheckedOperation();
+ this._resourceManager.flushCheckedResource();
+ this._sourceManager.flushCheckedSource();
+ this._topologyManager.flushCheckedTopology();
+ this._serverManager.flushCheckedServer();
LOGGER.info("Verification terminee.");
- this._configuration = userConfiguration;
- // On stocke le chemin absolu car c'est utile pour la suite, notamment pour les chemins relatifs que l'on aura
- this._configurationPath = userConfigurationPath;
+
return true;
}
-
/**
*
* @function
- * @name loadOperations
- * @description Chargement des opérations
- * @param {string} operationsDirectory - Dossier contenant les opérations à charger (chemin absolu)
- * @param {string} parametersDirectory - Dossier contenant les paramètres à charger (chemin absolu)
+ * @name saveServiceConfiguration
+ * @description Sauvegarde de la configuration du service
+ * @param {json} configuration - Configuration du service (contenu du service.json)
+ * @param {string} configurationPath - Chemin de la configuration du service (chemin du service.json)
+ * @param {json} logConfiguration - Configuration des logs du service (contenu du log4js.json)
*
*/
+ saveServiceConfiguration(configuration, configurationPath, logConfiguration) {
- loadOperations(operationsDirectory, parametersDirectory) {
-
- LOGGER.info("Chargement des operations...");
-
- if (!operationsDirectory) {
- try {
- operationsDirectory = path.resolve(path.dirname(this._configurationPath), this._configuration.application.operations.directory);
- } catch (error) {
- LOGGER.error("Impossible d'avoir le chemin aboslu du dossier des operations: " + this._configuration.application.operations.directory);
- LOGGER.error(error);
- return false;
- }
- }
-
- if (!parametersDirectory) {
- try {
- parametersDirectory = path.resolve(path.dirname(this._configurationPath), this._configuration.application.operations.parameters.directory);
- } catch (error) {
- LOGGER.error("Impossible d'avoir le chemin aboslu du dossier des parametres: " + this._configuration.application.operations.parameters.directory);
- LOGGER.error(error);
- return false;
- }
- }
-
- if (!this._operationManager.loadOperationDirectory(operationsDirectory, parametersDirectory)) {
- LOGGER.error("Erreur lors du chargement des operations.");
- return false;
- }
-
- return true;
+ this._configuration = configuration;
+ this._configurationPath = configurationPath;
+ this._logConfiguration = logConfiguration;
}
/**
*
* @function
- * @name loadProjections
- * @description Chargement des opérations
- * @param {string} projectionsDirectory - Dossier contenant les projections à charger (chemin absolu)
+ * @name loadServiceConfiguration
+ * @description Chargement de la configuration du service
*
*/
+ loadServiceConfiguration() {
- loadProjections(projectionsDirectory) {
+ LOGGER.info("Chargement de la configuration du service...");
- LOGGER.info("Chargement des projections...");
-
- if (!projectionsDirectory) {
- try {
- projectionsDirectory = path.resolve(path.dirname(this._configurationPath), this._configuration.application.projections.directory);
- } catch (error) {
- LOGGER.error("Impossible d'avoir le chemin aboslu du dossier des projections: " + this._configuration.application.projections.directory);
- LOGGER.error(error);
- return false;
- }
+ // Chargement des opérations
+ LOGGER.info("Chargement des operations...");
+
+ let parametersDirectory = "";
+ try {
+ parametersDirectory = path.resolve(path.dirname(this._configurationPath), this._configuration.application.operations.parameters.directory);
+ } catch (error) {
+ LOGGER.error("Impossible d'avoir le chemin aboslu du dossier des parametres: " + this._configuration.application.operations.parameters.directory);
+ LOGGER.error(error);
+ return false;
}
- if (!this._projectionManager.loadProjectionDirectory(projectionsDirectory)) {
- LOGGER.error("Erreur lors du chargement des projections.");
+ if (!this._operationManager.loadParameterDirectory(parametersDirectory)) {
+ LOGGER.error("Erreur lors du chargement des operations.");
return false;
}
- return true;
-
- }
-
- /**
- *
- * @function
- * @name loadResources
- * @description Chargement des ressources
- * @param {table} userResourceDirectories - Tableau de dossiers contenant les ressources à charger (chemins absolus)
- *
- */
-
- async loadResources(userResourceDirectories) {
-
- LOGGER.info("Chargement des ressources...");
-
- // Nombre de ressources chargées
- let loadedResources = 0;
-
- if (!userResourceDirectories) {
- userResourceDirectories = this._configuration.application.resources.directories;
+ let operationsDirectory = "";
+ try {
+ operationsDirectory = path.resolve(path.dirname(this._configurationPath), this._configuration.application.operations.directory);
+ } catch (error) {
+ LOGGER.error("Impossible d'avoir le chemin aboslu du dossier des operations: " + this._configuration.application.operations.directory);
+ LOGGER.error(error);
+ return false;
}
- if (!Array.isArray(userResourceDirectories)) {
- LOGGER.error("La variable contenant les dossiers de ressources n'est pas un tableau");
+ if (!this._operationManager.loadOperationDirectory(operationsDirectory)) {
+ LOGGER.error("Erreur lors du chargement des operations.");
return false;
}
- if (userResourceDirectories.length === 0) {
- LOGGER.error("Le tableau contenant les dossiers de ressources est vide");
+ // Chargement des projections
+ LOGGER.info("Chargement des projections...");
+
+ let projectionsDirectory = "";
+ try {
+ projectionsDirectory = path.resolve(path.dirname(this._configurationPath), this._configuration.application.projections.directory);
+ } catch (error) {
+ LOGGER.error("Impossible d'avoir le chemin aboslu du dossier des projections: " + this._configuration.application.projections.directory);
+ LOGGER.error(error);
+ return false;
+ }
+
+ if (!this._projectionManager.loadProjectionDirectory(projectionsDirectory)) {
+ LOGGER.error("Erreur lors du chargement des projections.");
return false;
}
- for (let i = 0; i < userResourceDirectories.length; i++) {
+ // Chargement des ressources
+ LOGGER.info("Chargement des ressources...");
+
+ for (let i = 0; i < this._configuration.application.resources.directories.length; i++) {
let resourceDirectory = "";
try {
- resourceDirectory = path.resolve(path.dirname(this._configurationPath), userResourceDirectories[i]);
+ resourceDirectory = path.resolve(path.dirname(this._configurationPath), this._configuration.application.resources.directories[i]);
+ LOGGER.info("Dossier de ressources : " + resourceDirectory);
} catch (error) {
- LOGGER.error("Impossible d'obtenir le chemin absolu du dossier de ressources: " + userResourceDirectories[i]);
+ LOGGER.error("Impossible d'obtenir le chemin absolu du dossier de ressources: " + this._configuration.application.resources.directories[i]);
LOGGER.error(error);
- return false;
+ continue;
}
- // Pour chaque fichier du dossier des ressources, on crée une ressource
- const files = fs.readdirSync(resourceDirectory).filter( (file) => {
- return path.extname(file).toLowerCase() === ".resource";
- })
- for (let fileName of files){
-
- let resourceFile = resourceDirectory + "/" + fileName;
- LOGGER.info("Chargement de: " + resourceFile);
-
- // Récupération du contenu en objet pour vérification puis création de la ressource
- try {
-
- let resourceContent = JSON.parse(fs.readFileSync(resourceFile));
- // Vérification du contenu
- let resourceChecked = await this._resourceManager.checkResource(resourceContent, this._sourceManager, this._operationManager, this._topologyManager)
- if (!resourceChecked) {
- LOGGER.error("Erreur lors du chargement de la ressource: " + resourceFile);
- } else {
- // Création de la ressource
- this._resourceCatalog[resourceContent.resource.id] = this._resourceManager.createResource(resourceContent, this._operationManager);
- loadedResources++;
- }
-
- } catch (error) {
- LOGGER.error(error);
- LOGGER.error("Erreur lors de la lecture de la ressource: " + resourceFile);
- }
-
- };
+ if (!this._resourceManager.loadResourceDirectory(resourceDirectory)) {
+ LOGGER.error("Impossible de charger correctement le dossier de ressources " + resourceDirectory);
+ } else {
+ // On va continuer
+ LOGGER.info("Les ressources du dossier " + resourceDirectory + " sont chargées dans la mesure du possible")
+ }
}
- if (loadedResources === 0) {
+ if (this._resourceManager.resource.length === 0) {
LOGGER.fatal("Aucune ressource n'a pu etre chargee");
return false;
}
- return true;
-
- }
-
- /**
- *
- * @function
- * @name loadTopologies
- * @description Chargement des topologies
- *
- */
-
- loadTopologies() {
-
- LOGGER.info("Chargement des topologies...");
-
- if (!this._topologyManager.loadAllTopologies()) {
- LOGGER.error("Echec lors du chargement des topologies.");
- return false;
- }
-
- LOGGER.info("Topologies chargees.");
- return true;
- }
-
- /**
- *
- * @function
- * @name loadSources
- * @description Chargement des sources
- *
- */
-
- async loadSources() {
-
- LOGGER.info("Chargement des sources...");
-
- let loadedSources = 0;
-
- // On récupère les informations du resourceManager pour les intégrer au sourceManager du service
- let listOfSourceIds = this._sourceManager.listOfSourceIds;
- let sourceDescriptions = this._sourceManager.sourceDescriptions;
-
- // On va créer chaque source
- if (listOfSourceIds.length !== 0) {
- // On va charger chaque source identifiée
- let sourceToRemove = new Array();
- for (let i = 0; i < listOfSourceIds.length; i++) {
-
- let sourceId = listOfSourceIds[i];
- LOGGER.info("Chargement de la source: " + sourceId);
-
- // On récupère la bonne topologie
- let topologyId = this._sourceManager.getSourceTopology(sourceId);
- if (topologyId === "") {
- LOGGER.error("Erreur lors de la recuperation de l'id de la topologie associee a la source");
- throw errorManager.createError("Topology Id not found");
- }
-
- let topology = this._topologyManager.getTopologyById(topologyId);
-
- try {
- assert.notDeepStrictEqual(topology, {});
- } catch(err) {
- LOGGER.error("Erreur lors de la recuperation de la topologie associee a la source");
- LOGGER.error(err);
- throw errorManager.createError("Topology not found");
- }
-
- // On crée la source
- // TODO: a revoir -> cas ou plusieurs datasources utilisant des topologies différentes
- let currentSource = this._sourceManager.createSource(sourceDescriptions[sourceId], topology);
-
- // On vérifie que le source peut bien être chargée ou connectée
- try {
- await this._sourceManager.connectSource(currentSource);
- this._sourceCatalog[sourceId] = currentSource;
- loadedSources++;
- } catch (err) {
- // on n'a pas pu se connecter à la source
- // si une source ne peut être chargée alors on la supprime
- LOGGER.error("Impossible de se connecter a la source: " + sourceId);
- LOGGER.debug("Erreur : " + err);
- LOGGER.warn("Suppression des references a la source dans les ressources qui l'utilisent...");
- let resourceList = this._sourceManager.listOfUsage(sourceId);
- if (resourceList.length !== 0) {
- for (let k = 0; k < resourceList.length; k++) {
- LOGGER.warn("Suppression au sein de la ressource " + resourceList[k]);
- let resource = this.resourceCatalog[resourceList[k]];
- resource.removeSource(sourceId);
- }
- }
- sourceToRemove.push(sourceId);
-
- }
- }
-
- // On supprime les sources qui n'ont pas pu être chargées
- if (sourceToRemove.length !== 0) {
- for (let k= 0; k < sourceToRemove.length; k++) {
- LOGGER.warn("Suppression de la source " + sourceToRemove[k]);
- this._sourceManager.removeSource(sourceToRemove[k]);
- }
- }
-
- } else {
- LOGGER.fatal("Il n'y a aucune source a charger.");
- throw errorManager.createError("No source found");
- }
-
- if (loadedSources === 0) {
- LOGGER.fatal("Aucune source n'a pu etre chargee");
- throw errorManager.createError("No source loaded");
- }
- }
-
- /**
- *
- * @function
- * @name createServer
- * @description Création du serveur
- * @param {string} userApiDirectory - Dossier contenant les apis à charger sur ce serveur
- * @param {string} userServerPrefix - Prefixe à utiliser sur le serveur créer
- *
- */
-
- createServer(userApiDirectory, userServerPrefix) {
-
- LOGGER.info("Creation de l'application web...");
+ // Chargement des serveurs
+ LOGGER.info("Creation de l'application ExpressJS...");
// Application Express
let road2 = express();
@@ -892,6 +723,8 @@ module.exports = class Service {
road2.set("service", this);
// Initialisation des CORS
+ LOGGER.info("Initialisation des cors...");
+
let corsConfiguration = {};
if (this._configuration.application.network.cors) {
try {
@@ -934,44 +767,94 @@ module.exports = class Service {
return false;
}
+ // Chargement des APIs indiquées dans la conf
+ LOGGER.info("Chargement des APIs indiquées dans la configuration...");
-
-
- // Chargement des APIs
- if (!this._apisManager.loadAPISDirectory(road2, userApiDirectory, userServerPrefix)) {
- LOGGER.error("Erreur lors du chargement des apis.");
- return false;
+ for (let i = 0; i < this._configuration.application.apis.length; i++) {
+ let apiConfiguration = this._configuration.application.apis[i];
+ if (!this._apisManager.loadApiConfiguration(road2, apiConfiguration)) {
+ LOGGER.fatal("Impossible de créer l'API " + apiConfiguration.name + "/" + apiConfiguration.version);
+ return false;
+ }
}
road2.all('/', (req, res) => {
res.send('Road2');
});
- // Création des serveurs
- if (!this._serverManager.createAllServer(road2)) {
- LOGGER.fatal("Impossible de creer les serveurs.");
+ // Création des serveurs indiqués dans la conf
+ LOGGER.info("Chargement des serveurs...");
+
+ for (let i = 0; i < this._configuration.application.network.servers.length; i++) {
+
+ let serverConf = this._configuration.application.network.servers[i];
+ LOGGER.info("Chargement du serveur : " + serverConf.id);
+
+ if (!this._serverManager.loadServerConfiguration(road2, serverConf)) {
+ LOGGER.fatal("Impossible de creer le serveur");
+ return false;
+ } else {
+ LOGGER.info("Serveur chargé");
+ }
+ }
+
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name connectSources
+ * @description Connecter toutes les sources du service
+ *
+ */
+ async connectSources() {
+
+ LOGGER.info("Connexion des sources du service...");
+
+ // Connexion des sources
+ if (!(await this._sourceManager.connectAllSources())) {
+ LOGGER.fatal("Impossible de connecter toutes les sources du service");
return false;
+ } else {
+ LOGGER.info("Les sources du service potentiellement connectables ont été connectées");
+ return true;
}
+ }
+
+ /**
+ *
+ * @function
+ * @name startServers
+ * @description Démarrage des serveurs du service
+ *
+ */
+ startServers() {
+
+ LOGGER.info("Démarrage des serveurs du service...");
+
// Démarrage des serveurs
- if (!this._serverManager.startAllServer()) {
- LOGGER.fatal("Impossible de demarer les serveurs.");
+ if (!this._serverManager.startAllServers()) {
+ LOGGER.fatal("Impossible de démarrer tous les serveurs.");
return false;
+ } else {
+ LOGGER.info("Les serveurs du service ont été démarrés");
+ return true;
}
- return true;
-
}
/**
*
* @function
- * @name stopServer
+ * @name stopServers
* @description Arrêt du serveur
*
*/
- stopServer() {
+ stopServers() {
// Extinction des serveurs
if (!this._serverManager.stopAllServer()) {
@@ -1000,8 +883,8 @@ module.exports = class Service {
// ---
// L'id est dans la requête
let resourceId = request.resource;
- // La ressource est dans le catalogue du service
- let resource = this._resourceCatalog[resourceId];
+ // La ressource est dans le catalogue du resourceManager
+ let resource = this._resourceManager.resource[resourceId];
// ---
// Récupération de la source concernée par la requête
@@ -1009,9 +892,8 @@ module.exports = class Service {
// L'id est donné par le ressource
let sourceId = resource.getSourceIdFromRequest(request);
- // La source est dans le catalogue du service
- // TODO : vérifier que la source existe toujours
- let source = this._sourceCatalog[sourceId];
+ // La source est dans le catalogue du sourceManager
+ let source = this._sourceManager.source[sourceId];
// ---
//On renvoie la requête vers le moteur
@@ -1026,24 +908,4 @@ module.exports = class Service {
}
- /**
- *
- * @function
- * @name disconnectAllSources
- * @description Fonction utilisée pour déconnecter toutes les sources.
- * @param {Source} source - Objet Source ou hérité de la classe Source
- *
- */
- async disconnectAllSources() {
- LOGGER.info("Déconnection de toutes les sources");
- try {
- for (let source_id in this._sourceCatalog) {
- await this._sourceManager.disconnectSource(this._sourceCatalog[source_id]);
- }
- } catch (err) {
- LOGGER.error("Impossible de déconnecter la source.", err);
- }
- }
-
-
}
diff --git a/src/js/service/serviceAdministered.js b/src/js/service/serviceAdministered.js
new file mode 100644
index 0000000..fdeac44
--- /dev/null
+++ b/src/js/service/serviceAdministered.js
@@ -0,0 +1,55 @@
+'use strict';
+
+/**
+*
+* @class
+* @name ServiceAdministered
+* @description Classe modélisant une service administré par l'administrateur.
+* @param {string} id - Identifiant du service administré
+* @param {string} type - Type de service administré
+*
+*/
+
+module.exports = class ServiceAdministered {
+
+
+ /**
+ *
+ * @function
+ * @name constructor
+ * @description Constructeur de la classe ServiceAdministered
+ *
+ */
+ constructor(id, type) {
+
+ // Id d'une ressource. Il doit être unique.
+ this._id = id;
+
+ // Type de la ressource
+ this._type = type;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name get id
+ * @description Récupérer l'id du service administré
+ *
+ */
+ get id () {
+ return this._id;
+ }
+
+ /**
+ *
+ * @function
+ * @name get type
+ * @description Récupérer le type du service administré
+ *
+ */
+ get type () {
+ return this._type;
+ }
+
+}
diff --git a/src/js/service/serviceManager.js b/src/js/service/serviceManager.js
new file mode 100644
index 0000000..7a93be4
--- /dev/null
+++ b/src/js/service/serviceManager.js
@@ -0,0 +1,130 @@
+'use strict';
+
+const log4js = require('log4js');
+const Service = require('./service');
+const ServiceProcess = require('./serviceProcess');
+
+// Création du LOGGER
+const LOGGER = log4js.getLogger("SERVICEMANAGER");
+
+/**
+*
+* @class
+* @name serviceManager
+* @description Gestionnaire des services gérés par un administrateur
+*
+*/
+
+module.exports = class serviceManager {
+
+ /**
+ *
+ * @function
+ * @name constructor
+ * @description Constructeur de la classe serviceManager
+ *
+ */
+ constructor() {
+
+ // Catalogue de services chargés (objets de la classe ServiceAdministered)
+ this._loadedServiceAdministeredCatalog = {};
+
+ // Contenu de la configuration des services chargés (contenu du service.json)
+ this._loadedServiceConfigurations = {};
+
+ // Emplacement de la configuration des services chargés (chemin du service.json)
+ this._loadedServiceConfLocations = {};
+
+ }
+
+ /**
+ *
+ * @function
+ * @name checkServiceConfiguration
+ * @description Vérification du contenu de la configuration d'un service (contenu du service.json)
+ * @param {object} configuration - Configuration du service (contenu du service.json)
+ * @param {string} configurationLocation - Chemin de la configuration du service (chemin du service.json)
+ *
+ */
+ async checkServiceConfiguration(configuration, configurationLocation) {
+
+ LOGGER.info("Vérification du contenu de la configuration du service...");
+
+ // Création d'un service pour vérifier la configuration
+ // On procède ainsi pour ne pas dupliquer du code déjà présent dans la classe Service
+ // De plus, on souhaite que la classe Service soit indépendante, donc ait le code de vérification de sa conf
+ let service = new Service();
+
+ if (!(await service.checkServiceConfiguration(configuration, configurationLocation))) {
+ LOGGER.error("La configuration du service n'est pas correcte");
+ return false;
+ } else {
+ LOGGER.info("La configuration du service est correcte");
+ return true;
+ }
+
+ }
+
+ /**
+ *
+ * @function
+ * @name loadService
+ * @description Création et lancement d'un service à partir de sa configuration
+ * @param {string} creationType - Type de création pour le service. Permet d'indiquer si on est dans le même process ou pas, voir sur une autre machine en théorie.
+ * @param {string} id - Id du service pour l'administrateur
+ * @param {string} configurationLocation - Emplacement de la configuration du service à charger
+ * @param {object} serviceConfiguration - Contenu de la configuration du service à charger
+ *
+ */
+ loadService(creationType, id, configurationLocation, serviceConfiguration) {
+
+ LOGGER.info("Création et lancement du service " + id);
+
+ // TODO : voir s'il n'existe pas déjà ?
+
+ let serviceAdministered = {};
+
+ // En fonction du type demandé, on va créer différemment le service
+ // Dans la configuration, on a "sameProcess", "newProcess" et "findByURI"
+ if (creationType === "sameProcess") {
+
+ // Instanciation du service directement sur le même process que l'administrateur
+ LOGGER.error("Type de création non implémentée. Impossible de créer le service.");
+ return false;
+
+ } else if (creationType === "newProcess") {
+
+ LOGGER.debug("newProcess : Création d'un service dans un autre processus");
+
+ serviceAdministered = new ServiceProcess(id, configurationLocation);
+
+ } else if (creationType === "findByURI") {
+
+ LOGGER.error("Type de création non implémentée. Impossible de créer le service.");
+ return false;
+
+ } else {
+
+ // Cela ne devrait pas arriver
+ LOGGER.error("Le type de creation du service n'est pas valide. Impossible de créer un service");
+ return false;
+
+ }
+
+ LOGGER.info("Service créé " + id);
+
+ // On le démarre par le même appel, qu'importe son type de création
+ LOGGER.info("Démarrage du service " + id);
+ serviceAdministered.loadService();
+
+ // Sauvegarde du service dans le manager
+ LOGGER.info("Service démarré. Sauvegarde dans le serviceManager...");
+ this._loadedServiceAdministeredCatalog[id] = serviceAdministered;
+ this._loadedServiceConfigurations[id] = serviceConfiguration;
+ this._loadedServiceConfLocations[id] = configurationLocation;
+
+ return true;
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/js/service/serviceProcess.js b/src/js/service/serviceProcess.js
new file mode 100644
index 0000000..64d4e79
--- /dev/null
+++ b/src/js/service/serviceProcess.js
@@ -0,0 +1,118 @@
+'use strict';
+
+const log4js = require('log4js');
+const { fork } = require('child_process');
+
+const ServiceAdministered = require('./serviceAdministered');
+
+// Création du LOGGER
+const LOGGER = log4js.getLogger("SERVICEPRO");
+
+/**
+*
+* @class
+* @name ServiceProcess
+* @description Classe modélisant un service administré mais qui se situe dans un autre processus que celui de l'administrateur qui le gère.
+*
+*/
+
+module.exports = class ServiceProcess extends ServiceAdministered {
+
+
+ /**
+ *
+ * @function
+ * @name constructor
+ * @description Constructeur de la classe ServiceProcess
+ * @param {string} id - Identifiant du service pour l'administrateur
+ * @param {string} location - Localisation de la configuration du service
+ *
+ */
+ constructor(id, location) {
+
+ // Constructeur parent
+ super(id, "newProcess");
+
+ // Emplacement de la configuration
+ this._configurationLocation = location;
+
+ // Stockage de la configuration
+ this._configuration = {};
+
+ // Instance de childProcess quand le processus est lancé
+ this._serviceAdministered;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name get configurationLocation
+ * @description Récupérer la configurationLocation du service
+ *
+ */
+ get configurationLocation () {
+ return this._configurationLocation;
+ }
+
+ /**
+ *
+ * @function
+ * @name get configuration
+ * @description Récupérer la configuration du service
+ *
+ */
+ get configuration () {
+ return this._configuration;
+ }
+
+ /**
+ *
+ * @function
+ * @name loadService
+ * @description Créer un service administré via un fork de processus
+ *
+ */
+ loadService() {
+
+ LOGGER.info("Création et lancement d'un service dans un autre processus");
+
+ // Un minimum de vérifications au cas où
+ if (typeof(this._configurationLocation) !== "string") {
+ LOGGER.error("Le chemin fourni n'est pas une string");
+ return null;
+ } else {
+ LOGGER.debug("Le chemin fourni est bien une string");
+ }
+
+ if (this._configurationLocation === "") {
+ LOGGER.error("Le chemin fourni est vide");
+ return null;
+ } else {
+ LOGGER.debug("Le chemin est renseigné : " + this._configurationLocation);
+ }
+
+ // On prépare les options
+ let serviceOptions = {};
+
+ if (process.env.NODE_ENV === "debug") {
+ serviceOptions.execArgv = new Array();
+ serviceOptions.execArgv.push("--inspect=0.0.0.0:9230");
+ LOGGER.debug("Options du service : ");
+ LOGGER.debug(serviceOptions);
+ } else {
+ LOGGER.info("Pas d'options liées au debug");
+ }
+
+ // Création du service via un fork : on lance simplement service/main.js
+ LOGGER.info("Fork du processus pour créer le service...");
+
+ this._serviceAdministered = fork("./src/js/service/main.js", [this._configurationLocation], serviceOptions);
+
+ LOGGER.info("Processus enfant créé");
+
+ return true;
+
+ }
+
+}
diff --git a/src/js/sources/osrmSource.js b/src/js/sources/osrmSource.js
index bd9ae26..ea39ec5 100644
--- a/src/js/sources/osrmSource.js
+++ b/src/js/sources/osrmSource.js
@@ -39,7 +39,7 @@ module.exports = class osrmSource extends Source {
* @name constructor
* @description Constructeur de la classe osrmSource
* @param {json} sourceJsonObject - Description de la source en json
- * @param{topology} topology - Instance de la classe Topology
+ * @param {topology} topology - Instance de la classe Topology
*
*/
constructor(sourceJsonObject, topology) {
@@ -47,9 +47,6 @@ module.exports = class osrmSource extends Source {
// Constructeur parent
super(sourceJsonObject.id,sourceJsonObject.type, topology);
- // Ajout des opérations possibles sur ce type de source
- this.availableOperations.push("route");
-
// Stockage de la configuration
this._configuration = sourceJsonObject;
diff --git a/src/js/sources/pgrSource.js b/src/js/sources/pgrSource.js
index 08a7aae..1f1a68e 100644
--- a/src/js/sources/pgrSource.js
+++ b/src/js/sources/pgrSource.js
@@ -43,11 +43,7 @@ module.exports = class pgrSource extends Source {
// Constructeur parent
super(sourceJsonObject.id, "pgr", topology);
-
- // Ajout des opérations possibles sur ce type de source
- this.availableOperations.push("route");
- this.availableOperations.push("isochrone");
-
+
// Stockage de la configuration
this._configuration = sourceJsonObject;
diff --git a/src/js/sources/smartroutingSource.js b/src/js/sources/smartroutingSource.js
index 8d6d9d6..1fd701f 100644
--- a/src/js/sources/smartroutingSource.js
+++ b/src/js/sources/smartroutingSource.js
@@ -44,10 +44,6 @@ module.exports = class smartroutingSource extends Source {
// Constructeur parent
super(sourceJsonObject.id,sourceJsonObject.type, undefined);
- // Ajout des opérations possibles sur ce type de source
- this.availableOperations.push("route");
- this.availableOperations.push("isochrone");
-
// Stockage de la configuration
this._configuration = sourceJsonObject;
diff --git a/src/js/sources/source.js b/src/js/sources/source.js
index 72fa2e9..79c22ad 100644
--- a/src/js/sources/source.js
+++ b/src/js/sources/source.js
@@ -32,9 +32,6 @@ module.exports = class Source {
// État de la connexion de la source
this._connected = false;
- // Liste d'opérations possibles sur la source
- this._availableOperations = new Array();
-
// Topologie dont dérive la source
this._topology = topology;
@@ -113,17 +110,6 @@ module.exports = class Source {
this._state = st;
}
- /**
- *
- * @function
- * @name get availableOperations
- * @description Récupérer la liste des opérations possibles sur la source
- *
- */
- get availableOperations () {
- return this._availableOperations;
- }
-
/**
*
* @function
@@ -135,23 +121,6 @@ module.exports = class Source {
return this._topology;
}
- /**
- *
- * @function
- * @name isOperationAvailable
- * @description Savoir si une opération est disponible sur la source
- * @param {string} operationId - Id de l'opération
- *
- */
- isOperationAvailable (operationId) {
- for (let i = 0; i < this._availableOperations.length; i++ ) {
- if (this._availableOperations[i] === operationId) {
- return true;
- }
- }
- return false;
- }
-
/**
*
* @function
diff --git a/src/js/sources/sourceManager.js b/src/js/sources/sourceManager.js
index 10337b2..83fe2a2 100644
--- a/src/js/sources/sourceManager.js
+++ b/src/js/sources/sourceManager.js
@@ -22,203 +22,100 @@ module.exports = class sourceManager {
*/
constructor() {
- // Liste des ids des sources gérées par le manager
- this._listOfSourceIds = new Array();
+ // Liste des ids des sources chargées par le manager
+ this._loadedSourceId = new Array();
- // Description des sources conservées de manière unique dans _listOfSourceIds
- this._sourceDescriptions = {};
+ // Liste des ids des sources vérifiées par le manager
+ this._checkedSourceId = new Array();
- // Correspondance entre l'id d'une source et l'id de la topologie dont elle dérive
- this._sourceTopology = {};
+ // Catalogue des sources du manager
+ this._source = {};
- // Correspondance entre l'id d'une source et l'id des ressources où elle est utilisée
- this._sourceUsage = {};
+ // Descriptions des sources chargées par le manager
+ this._loadedSourceConfiguration = {};
- }
+ // Descriptions des sources vérifiées par le manager
+ this._checkedSourceConfiguration = {};
- /**
- *
- * @function
- * @name get listOfSourceIds
- * @description Récupérer l'ensemble des ids de sources
- *
- */
- get listOfSourceIds() {
- return this._listOfSourceIds;
- }
+ // Correspondance entre l'id d'une source et l'id de la topologie dont elle dérive
+ this._sourceTopology = {};
- /**
- *
- * @function
- * @name get sourceTopology
- * @description Récupérer la correspondance source/topologie
- *
- */
- get sourceTopology() {
- return this._sourceTopology;
- }
+ // Correspondance entre les sources et les opérations possibles
+ this._operationsByType = {
+ "osrm": ["nearest", "route"],
+ "pgr": ["route", "isochrone"],
+ "smartrouting": ["route", "isochrone"]
+ };
- /**
- *
- * @function
- * @name get sourceDescriptions
- * @description Récupérer l'ensemble des descriptions des sources conservées
- *
- */
- get sourceDescriptions() {
- return this._sourceDescriptions;
}
/**
*
* @function
- * @name get sourceUsage
- * @description Récupérer l'ensemble des correspondances de sources
+ * @name get loadedSourceId
+ * @description Récupérer l'ensemble des ids de sources chargées
*
*/
- get sourceUsage() {
- return this._sourceUsage;
+ get loadedSourceId() {
+ return this._loadedSourceId;
}
/**
*
* @function
- * @name listOfUsage
- * @description Récupérer l'ensemble des id de ressources utilisant une source
- * @param {string} id - Id de la source
- * @return {table} Liste des id de ressource
+ * @name get source
+ * @description Récupérer l'ensemble des ids de sources chargées
*
*/
- listOfUsage(id) {
- return this._sourceUsage[id];
+ get source() {
+ return this._source;
}
/**
*
* @function
- * @name removeSource
- * @description Supprimer une source
- * @param {string} id - Id de la source
- * @return {boolean}
+ * @name get sourceTopology
+ * @description Récupérer la correspondance source/topologie
*
*/
- removeSource(id) {
-
- let index = this._listOfSourceIds.indexOf(id);
- if (index !== -1) {
- this._listOfSourceIds.splice(index,1);
- } else {
- return false;
- }
-
- if (!delete this._sourceDescriptions[id]) {
- return false;
- }
- if (!delete this._sourceTopology[id]) {
- return false;
- }
- if (!delete this._sourceUsage[id]) {
- return false;
- }
-
- return true;
+ get sourceTopology() {
+ return this._sourceTopology;
}
- /**
+ /**
*
* @function
- * @name addUsage
- * @description Ajouter l'usage, via l'id, d'une ressource pour une source
- * @param {string} sourceId - Id de la source
- * @param {string} resourceId - Id de la ressource
- * @return {boolean}
+ * @name get operationsByType
+ * @description Récupérer l'ensemble des opérations possibles par type de source
*
*/
- addUsage(sourceId, resourceId) {
- if (!this._sourceUsage[sourceId]) {
- this._sourceUsage[sourceId] = new Array();
- }
- if (!Array.isArray(this._sourceUsage[sourceId])) {
- return false;
- }
- this._sourceUsage[sourceId].push(resourceId);
- return true;
+ get operationsByType() {
+ return this._operationsByType;
}
/**
*
* @function
- * @name set listOfSourceIds
+ * @name set loadedSourceId
* @description Attribuer l'ensemble des ids de sources
* @param {table} list - État de la connexion
*
*/
- set listOfSourceIds(list) {
- this._listOfSourceIds = list;
- }
-
- /**
- *
- * @function
- * @name set sourceDescriptions
- * @description Attribuer l'ensemble des descriptions des sources conservées
- * @param {object} descriptions - Objet contenant les descriptions
- *
- */
- set sourceDescriptions(descriptions) {
- this._sourceDescriptions = descriptions;
- }
-
- /**
- *
- * @function
- * @name getSourceDescriptionById
- * @description Récupérer la description de la source indiquée par son id
- * @param {string} id - Id de la source
- *
- */
- getSourceDescriptionById(id) {
- if (this._sourceDescriptions[id]) {
- return this._sourceDescriptions[id];
- } else {
- return {};
- }
-
- }
-
- /**
- *
- * @function
- * @name getSourceTopology
- * @description Récupérer l'id de la topologie dont dérive une source
- * @param {string} sourceId - Id de la source
- * @return {string} Id d'une topologie
- *
- */
-
- getSourceTopology(sourceId) {
-
- if(this._sourceTopology[sourceId]) {
- return this._sourceTopology[sourceId];
- } else {
- return "";
- }
-
+ set loadedSourceId(list) {
+ this._loadedSourceId = list;
}
/**
*
* @function
- * @name checkSource
+ * @name checkSourceConfiguration
* @description Fonction utilisée pour vérifier la partie source d'un fichier de description d'une ressource.
* @param {json} sourceJsonObject - Description JSON de la source
- * @param {object} operationManager - Le manager des opérations du service
- * @param {table} resourceOperationTable - Tableau contenant l'ensemble des id d'opérations disponibles pour cette ressource
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
+ * @return {boolean}
*
*/
- checkSource(sourceJsonObject, operationManager, resourceOperationTable) {
+ checkSourceConfiguration(sourceJsonObject) {
LOGGER.info("Verification de la source...");
@@ -227,17 +124,37 @@ module.exports = class sourceManager {
LOGGER.error("La ressource contient une source sans id.");
return false;
} else {
- // On vérifie que l'id n'est pas déjà pris.
- if (this._listOfSourceIds.length !== 0) {
+ // On vérifie que l'id n'est pas déjà chargé.
+ if (this._loadedSourceId.length !== 0) {
- let present = false;
+ for (let i = 0; i < this._loadedSourceId.length; i++ ) {
+ if (this._loadedSourceId[i] === sourceJsonObject.id) {
+ LOGGER.info("La source contenant l'id " + sourceJsonObject.id + " est deja chargée.");
+ // On vérifie que la source décrite et celle déjà identifiée soient exactement les mêmes
+ if (this.checkDuplicationLoadedSource(sourceJsonObject)) {
+ break;
+ } else {
+ LOGGER.error("La source contenant l'id " + sourceJsonObject.id + " n'est pas identique à la source deja identifiee.");
+ return false;
+ }
+
+ } else {
+ // on continue la boucle de vérification
+ }
+ }
- for (let i = 0; i < this._listOfSourceIds.length; i++ ) {
- if (this._listOfSourceIds[i] === sourceJsonObject.id) {
- LOGGER.info("La source contenant l'id " + sourceJsonObject.id + " est deja referencee.");
+ } else {
+ // C'est la première source.
+ }
+
+ // On vérifie que l'id n'est pas déjà vérifié.
+ if (this._checkedSourceId.length !== 0) {
+
+ for (let i = 0; i < this._checkedSourceId.length; i++ ) {
+ if (this._checkedSourceId[i] === sourceJsonObject.id) {
+ LOGGER.info("La source contenant l'id " + sourceJsonObject.id + " est deja vérifiée.");
// On vérifie que la source décrite et celle déjà identifiée soient exactement les mêmes
- if (this.checkDuplicationSource(sourceJsonObject)) {
- present = true;
+ if (this.checkDuplicationCheckedSource(sourceJsonObject)) {
break;
} else {
LOGGER.error("La source contenant l'id " + sourceJsonObject.id + " n'est pas identique à la source deja identifiee.");
@@ -252,6 +169,7 @@ module.exports = class sourceManager {
} else {
// C'est la première source.
}
+
}
// Type
@@ -268,8 +186,6 @@ module.exports = class sourceManager {
available = true;
LOGGER.info("Source osrm.");
- let operationFound = false;
-
// On vérifie que le module osrm est disponible
try {
let osrmTest = require('osrm');
@@ -278,28 +194,11 @@ module.exports = class sourceManager {
return false;
}
- // On vérifie que les opérations possibles sur ce type de source soient disponibles dans l'instance du service
- if (operationManager.verifyAvailabilityOperation("route")) {
- // On vérifie que les opérations possibles sur ce type de source soient disponibles pour la ressource
- if (operationManager.isAvailableInTable("route", resourceOperationTable)) {
- operationFound = true;
- } else {
- // on continue pour voir la suite
- }
- } else {
- // on continue pour voir la suite
- }
-
- if (!operationFound) {
- LOGGER.error("Le service ne propose pas d'operations disponibles pour ce type de source (ex. route), il n'est donc pas possible de charger cette source.");
- return false;
- }
-
if (!this.checkSourceOsrm(sourceJsonObject)) {
LOGGER.error("Erreur lors de la verification de la source osrm.");
return false;
} else {
- // il n'y a eu aucun problème, la ressource est correctement configurée.
+ // il n'y a eu aucun problème, la source est correctement configurée.
}
} else {
// On va voir si c'est un autre type.
@@ -318,37 +217,6 @@ module.exports = class sourceManager {
return false;
}
- let operationFound = false;
-
- // On vérifie que les opérations possibles sur ce type de source soient disponibles dans l'instance du service
- if (operationManager.verifyAvailabilityOperation("route")) {
- // On vérifie que les opérations possibles sur ce type de source soient disponibles pour la ressource
- if (operationManager.isAvailableInTable("route", resourceOperationTable)) {
- operationFound = true;
- } else {
- // on continue pour voir la suite
- }
- } else {
- // on continue pour voir la suite
- }
-
- // On vérifie que les opérations possibles sur ce type de source soient disponibles dans l'instance du service
- if (operationManager.verifyAvailabilityOperation("isochrone")) {
- // On vérifie que les opérations possibles sur ce type de source soient disponibles pour la ressource
- if (operationManager.isAvailableInTable("isochrone", resourceOperationTable)) {
- operationFound = true;
- } else {
- // on continue pour voir la suite
- }
- } else {
- // on continue pour voir la suite
- }
-
- if (!operationFound) {
- LOGGER.error("Le service ne propose pas d'operations disponibles pour ce type de source (ex. route, isochrone), il n'est donc pas possible de charger cette source.");
- return false;
- }
-
if (!this.checkSourcePgr(sourceJsonObject)) {
LOGGER.error("Erreur lors de la verification de la source pgr.");
return false;
@@ -364,37 +232,6 @@ module.exports = class sourceManager {
available = true;
LOGGER.info("Source smartrouting.");
- let operationFound = false;
-
- // On vérifie que les opérations possibles sur ce type de source soient disponibles dans l'instance du service
- if (operationManager.verifyAvailabilityOperation("route")) {
- // On vérifie que les opérations possibles sur ce type de source soient disponibles pour la ressource
- if (operationManager.isAvailableInTable("route", resourceOperationTable)) {
- operationFound = true;
- } else {
- // on continue pour voir la suite
- }
- } else {
- // on continue pour voir la suite
- }
-
- // On vérifie que les opérations possibles sur ce type de source soient disponibles dans l'instance du service
- if (operationManager.verifyAvailabilityOperation("isochrone")) {
- // On vérifie que les opérations possibles sur ce type de source soient disponibles pour la ressource
- if (operationManager.isAvailableInTable("isochrone", resourceOperationTable)) {
- operationFound = true;
- } else {
- // on continue pour voir la suite
- }
- } else {
- // on continue pour voir la suite
- }
-
- if (!operationFound) {
- LOGGER.error("Le service ne propose pas d'operations disponibles pour ce type de source (ex. route, isochrone), il n'est donc pas possible de charger cette source.");
- return false;
- }
-
if (!this.checkSourceSmartrouting(sourceJsonObject)) {
LOGGER.error("Erreur lors de la verification de la source smartrouting.");
return false;
@@ -413,9 +250,6 @@ module.exports = class sourceManager {
}
}
- this._listOfSourceIds.push(sourceJsonObject.id);
- this._sourceDescriptions[sourceJsonObject.id] = sourceJsonObject;
-
LOGGER.info("Fin de la verification de la source.");
return true;
@@ -592,19 +426,50 @@ module.exports = class sourceManager {
/**
*
* @function
- * @name checkDuplicationSource
+ * @name checkDuplicationLoadedSource
* @description Fonction utilisée pour vérifier que le contenu d'un fichier de description d'une source est bien le même qu'un autre.
* @param {json} sourceJsonObject - Description JSON de la source
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
+ * @return {boolean}
+ *
+ */
+
+ checkDuplicationLoadedSource(sourceJsonObject) {
+
+ LOGGER.info("Comparaison des deux sources identifiees et devant etre identiques...");
+
+ // On récupère la description de la source faisant office de référence car lue la première.
+ let referenceSource = this._loadedSourceConfiguration[sourceJsonObject.id];
+
+ // On compare les deux objets
+ try {
+ assert.deepStrictEqual(sourceJsonObject, referenceSource);
+ } catch (err) {
+ LOGGER.error("Les deux sources ne sont pas identiques.");
+ LOGGER.debug(err);
+ return false;
+ }
+
+ LOGGER.info("Les deux sources sont identiques.");
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name checkDuplicationCheckedSource
+ * @description Fonction utilisée pour vérifier que le contenu d'un fichier de description d'une source est bien le même qu'un autre.
+ * @param {json} sourceJsonObject - Description JSON de la source
+ * @return {boolean}
*
*/
- checkDuplicationSource(sourceJsonObject) {
+ checkDuplicationCheckedSource(sourceJsonObject) {
LOGGER.info("Comparaison des deux sources identifiees et devant etre identiques...");
// On récupère la description de la source faisant office de référence car lue la première.
- let referenceSource = this._sourceDescriptions[sourceJsonObject.id];
+ let referenceSource = this._checkedSourceConfiguration[sourceJsonObject.id];
// On compare les deux objets
try {
@@ -623,20 +488,54 @@ module.exports = class sourceManager {
/**
*
* @function
- * @name createSource
+ * @name saveCheckedSource
+ * @description Sauvegarder l'id de la source vérifié
+ * @param {object} configuration - Id de la source que l'on veut sauvegarder
+ *
+ */
+ saveCheckedSource(configuration) {
+
+ this._checkedSourceId.push(configuration.id);
+ this._checkedSourceConfiguration[configuration.id] = configuration;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name flushCheckedSource
+ * @description Vider la liste des source déjà vérifiées
+ *
+ */
+ flushCheckedSource() {
+
+ this._checkedSourceId = new Array();
+ this._checkedSourceConfiguration = {};
+
+ }
+
+ /**
+ *
+ * @function
+ * @name loadSourceConfiguration
* @description Fonction utilisée pour créer une source.
* @param {json} sourceJsonObject - Description JSON de la source
* @param {Topology} topology - Instance de la classe Topology
- * @return {Source} Source créée
+ * @return {boolean}
*
*/
- createSource(sourceJsonObject, topology) {
+ loadSourceConfiguration(sourceJsonObject, topology) {
LOGGER.info("Creation de la source: " + sourceJsonObject.id);
let source;
+ if (this._source[sourceJsonObject.id]) {
+ LOGGER.info("La source " + sourceJsonObject.id + " existe déjà");
+ return true;
+ }
+
if (sourceJsonObject.type === "osrm") {
source = new osrmSource(sourceJsonObject, topology);
} else if (sourceJsonObject.type === "pgr") {
@@ -646,47 +545,102 @@ module.exports = class sourceManager {
source = new smartroutingSource(sourceJsonObject);
} else {
// On va voir si c'est un autre type.
+ LOGGER.error("Le type de la source est inconnu");
+ return false;
}
- return source;
+
+ this._loadedSourceId.push(sourceJsonObject.id);
+ this._loadedSourceConfiguration[sourceJsonObject.id] = sourceJsonObject;
+ this._source[sourceJsonObject.id] = source;
+
+ return true;
+
}
/**
*
* @function
* @name connectSource
- * @description Fonction utilisée pour connecter une source.
- * @param {Source} source - Objet Source ou hérité de la classe Source
+ * @description Fonction utilisée pour connecter une source.
+ * On la sépare volontairement du load de la source car on veut pouvoir gérer ces actions de manière indépendante.
+ * @param {string} sourceId - Id de la source que l'on veut connecter
*
*/
- async connectSource(source) {
+ async connectSource(sourceId) {
+
+ LOGGER.info("Connexion a la source: " + sourceId);
- LOGGER.info("Connexion a la source: " + source.id);
try {
- await source.connect();
+
+ await this._source[sourceId].connect();
LOGGER.info("Source connectee.");
+ return true;
+
} catch (err) {
+
LOGGER.error("Impossible de connecter la source.", err);
- throw errorManager.createError("Impossible de connecter la source.");
+ return false;
+
}
+
}
/**
*
* @function
- * @name disconnectSource
- * @description Fonction utilisée pour déconnecter une source.
- * @param {Source} source - Objet Source ou hérité de la classe Source
+ * @name connectAllSources
+ * @description Connecter l'ensemble des sources disponibles dans le manager
*
*/
- async disconnectSource(source) {
- LOGGER.info("Déconnection de la source: " + source.id);
+ async connectAllSources() {
+
+ LOGGER.info("Connexion de l'ensemble des sources...");
+
+ if (this._loadedSourceId.length === 0) {
+ LOGGER.error("Aucune source n'est disponible");
+ return false;
+ }
+
try {
- await source.disconnect();
- LOGGER.info("Source déconnectee.");
+ assert.deepStrictEqual(this._loadedSourceConfiguration, {});
+ LOGGER.error("Aucune source n'a été préalablement chargée");
+ return false;
} catch (err) {
- LOGGER.error("Impossible de déconnecter la source.", err);
- throw errorManager.createError("Impossible de déconnecter la source.");
+ // tout va bien
}
+
+ let nbSourceConnected = 0;
+
+ for (let i = 0; i < this._loadedSourceId.length; i++) {
+
+ LOGGER.info("Source : " + this._loadedSourceId[i]);
+
+ if (!(await this.connectSource(this._loadedSourceId[i]))) {
+
+ LOGGER.error("Source " + this._loadedSourceId[i] + " non connectée");
+ // TODO : on continue de connecter les autres sources et on gère après coup la MAJ des ressources, du getcap, etc...
+ // Pour le moment, s'il y a une source qui ne fonctionne pas, on arrête le serveur
+ return false;
+
+ } else {
+
+ LOGGER.info("Source " + this._loadedSourceId[i] + " connectée");
+ nbSourceConnected++;
+
+ }
+
+ }
+
+ LOGGER.info("Les démarrages se sont bien déroulés.");
+
+ if (nbSourceConnected === 0) {
+ LOGGER.error("Aucune source n'a pu être connectée");
+ return false;
+ } else {
+ LOGGER.info("Au moins une source a été connectée");
+ return true;
+ }
+
}
}
diff --git a/src/js/topology/topologyManager.js b/src/js/topology/topologyManager.js
index 77faeb5..0f0a5df 100644
--- a/src/js/topology/topologyManager.js
+++ b/src/js/topology/topologyManager.js
@@ -28,14 +28,20 @@ module.exports = class topologyManager {
*/
constructor(baseManager, projectionManager) {
+ // Liste des descriptions de topologies chargées par le manager
+ this._loadedTopologyId = new Array();
+
// Liste des descriptions de topologies vérifiées et validées par le manager
- this._listOfTopologyIds = new Array();
+ this._checkedTopologyId = new Array();
+
+ // Descriptions des topologies chargées par le manager
+ this._loadedTopologyConfiguration = {};
- // Descriptions des topologies vérifiées et validées par le manager
- this._topologyDescriptions = {};
+ // Descriptions des topologies vérifiées par le manager
+ this._checkedTopologyConfiguration = {};
// Le catalogue des topologies créées par le manager
- this._topologiesCatalog = {};
+ this._topologyCatalog = {};
// Manager de bases
this._baseManager = baseManager;
@@ -48,25 +54,25 @@ module.exports = class topologyManager {
/**
*
* @function
- * @name get topologiesCatalog
+ * @name get topologyCatalog
* @description Récupérer le catalogue des topologies
*
*/
- get topologiesCatalog() {
- return this._topologiesCatalog;
+ get topologyCatalog() {
+ return this._topologyCatalog;
}
/**
*
* @function
- * @name getTopologyById
+ * @name getTopology
* @description Récupérer une topologie via son id
- * @param{string} id - Id de la topologie
+ * @param {string} id - Id de la topologie
*
*/
- getTopologyById(id) {
- if (this._topologiesCatalog[id]) {
- return this._topologiesCatalog[id];
+ getTopology(id) {
+ if (this._topologyCatalog[id]) {
+ return this._topologyCatalog[id];
} else {
return {};
}
@@ -76,26 +82,28 @@ module.exports = class topologyManager {
/**
*
* @function
- * @name checkTopology
+ * @name checkTopologyConfiguration
* @description Vérification de la description d'une topologie
* @param{json} topologyJsonDescription - JSON décrivant une topologie
*
*/
- async checkTopology(topologyJsonDescription) {
+ async checkTopologyConfiguration(topologyJsonDescription) {
// Id de la topologie
if (!topologyJsonDescription.id) {
LOGGER.error("La topologie ne contient pas d'id.");
return false;
} else {
- // On vérifie que l'id n'est pas déjà pris.
- if (this._listOfTopologyIds.length !== 0) {
-
- for (let i = 0; i < this._listOfTopologyIds.length; i++ ) {
- if (this._listOfTopologyIds[i] === topologyJsonDescription.id) {
- LOGGER.info("La topologie contenant l'id " + topologyJsonDescription.id + " est deja referencee.");
- // On vérifie que la source décrite et celle déjà identifiée soient exactement les mêmes
- if (this.checkDuplicationTopology(topologyJsonDescription)) {
+
+ // On vérifie que l'id n'est pas déjà chargés.
+ if (this._loadedTopologyId.length !== 0) {
+
+ for (let i = 0; i < this._loadedTopologyId.length; i++ ) {
+ if (this._loadedTopologyId[i] === topologyJsonDescription.id) {
+
+ LOGGER.info("La topologie contenant l'id " + topologyJsonDescription.id + " est deja chargée.");
+ // On vérifie que la topology décrite et celle déjà identifiée soient exactement les mêmes
+ if (this.checkDuplicationLoadedTopology(topologyJsonDescription)) {
LOGGER.info("La topologie contenant l'id " + topologyJsonDescription.id + " est identique à la topologie deja identifiee.");
return true;
} else {
@@ -103,14 +111,29 @@ module.exports = class topologyManager {
return false;
}
- } else {
- // on continue de vérifier
}
}
-
- } else {
- // C'est la première source, on continue la vérification
}
+
+ // On vérifie que l'id n'est pas déjà vérifiés.
+ if (this._checkedTopologyId.length !== 0) {
+
+ for (let i = 0; i < this._checkedTopologyId.length; i++ ) {
+ if (this._checkedTopologyId[i] === topologyJsonDescription.id) {
+
+ LOGGER.info("La topologie contenant l'id " + topologyJsonDescription.id + " est deja vérifiée.");
+ // On vérifie que la topology décrite et celle déjà identifiée soient exactement les mêmes
+ if (this.checkDuplicationCheckedTopology(topologyJsonDescription)) {
+ LOGGER.info("La topologie contenant l'id " + topologyJsonDescription.id + " est identique à la topologie deja identifiee.");
+ return true;
+ } else {
+ LOGGER.error("La topologie contenant l'id " + topologyJsonDescription.id + " n'est pas identique à la topologie deja identifiee.");
+ return false;
+ }
+
+ }
+ }
+ }
}
// Description de la topologie
@@ -127,7 +150,7 @@ module.exports = class topologyManager {
return false;
} else {
// Vérification de la projection
- if (!this._projectionManager.isAvailableById(topologyJsonDescription.projection)) {
+ if (!this._projectionManager.isChecked(topologyJsonDescription.projection)) {
LOGGER.error("La topologie indique une projection non disponible sur le service: " + topologyJsonDescription.projection);
return false;
}
@@ -163,10 +186,6 @@ module.exports = class topologyManager {
}
- // on sauvegarde l'id de la topologie pour savoir qu'elle a déjà été vérifiée et que sa description est valide
- this._listOfTopologyIds.push(topologyJsonDescription.id);
- this._topologyDescriptions[topologyJsonDescription.id] = topologyJsonDescription;
-
return true;
}
@@ -224,9 +243,11 @@ module.exports = class topologyManager {
LOGGER.error("La ressource ne contient pas de parametre 'topology.storage.dbConfig'.");
return false;
} else {
- if (!(await this._baseManager.checkBase(topologyJsonDescription.storage.base.dbConfig))) {
+ if (!(await this._baseManager.checkBaseConfiguration(topologyJsonDescription.storage.base.dbConfig))) {
LOGGER.error("La ressource contient un parametre 'topology.storage.dbConfig' incorrect.");
return false;
+ } else {
+ this._baseManager.saveCheckedBaseConfiguration(topologyJsonDescription.storage.base.dbConfig);
}
}
@@ -322,19 +343,19 @@ module.exports = class topologyManager {
/**
*
* @function
- * @name checkDuplicationTopology
+ * @name checkDuplicationLoadedTopology
* @description Fonction utilisée pour vérifier que le contenu d'un fichier de description d'une source est bien le même qu'un autre.
* @param {json} topologyJsonDescription - Description JSON de la topologie
* @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
*
*/
- checkDuplicationTopology(topologyJsonDescription) {
+ checkDuplicationLoadedTopology(topologyJsonDescription) {
LOGGER.info("Comparaison des deux topologies identifiees et devant etre identiques...");
// On récupère la description de la topologie faisant office de référence car lue la première.
- let referenceTopology = this._topologyDescriptions[topologyJsonDescription.id];
+ let referenceTopology = this._loadedTopologyConfiguration[topologyJsonDescription.id];
// On compare les deux objets
try {
@@ -353,22 +374,83 @@ module.exports = class topologyManager {
/**
*
* @function
- * @name createTopology
+ * @name checkDuplicationCheckedTopology
+ * @description Fonction utilisée pour vérifier que le contenu d'un fichier de description d'une source est bien le même qu'un autre.
+ * @param {json} topologyJsonDescription - Description JSON de la topologie
+ * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
+ *
+ */
+
+ checkDuplicationCheckedTopology(topologyJsonDescription) {
+
+ LOGGER.info("Comparaison des deux topologies identifiees et devant etre identiques...");
+
+ // On récupère la description de la topologie faisant office de référence car lue la première.
+ let referenceTopology = this._checkedTopologyConfiguration[topologyJsonDescription.id];
+
+ // On compare les deux objets
+ try {
+ assert.deepStrictEqual(topologyJsonDescription, referenceTopology);
+ } catch (err) {
+ LOGGER.error("Les deux topologies ne sont pas identiques.");
+ LOGGER.error(err);
+ return false;
+ }
+
+ LOGGER.info("Les deux topologies sont identiques.");
+ return true;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name saveCheckedTopology
+ * @description Sauvegarder l'id de la topology vérifié
+ * @param {object} configuration - Id de la topology que l'on veut sauvegarder
+ *
+ */
+ saveCheckedTopology(configuration) {
+
+ this._checkedTopologyId.push(configuration.id);
+ this._checkedTopologyConfiguration[configuration.id] = configuration;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name flushCheckedTopology
+ * @description Vider la liste des topology déjà vérifiées
+ *
+ */
+ flushCheckedTopology() {
+
+ this._checkedTopologyId = new Array();
+ this._checkedTopologyConfiguration = {};
+
+ }
+
+ /**
+ *
+ * @function
+ * @name loadTopologyConfiguration
* @description Fonction utilisée pour créer une source.
* @param {json} topologyJsonObject - Description JSON de la topologie
* @return {Topology} Topologie créée - Instance d'une classe fille de Topology
*
*/
- createTopology(topologyJsonObject) {
+ loadTopologyConfiguration(topologyJsonObject) {
LOGGER.info("Creation de la topologie: " + topologyJsonObject.id);
let topology;
// on vérifie d'abord que la topologie n'a pas déjà été créée
- if (this._topologiesCatalog[topologyJsonObject.id]) {
- return this._topologiesCatalog[topologyJsonObject.id];
+ if (this._topologyCatalog[topologyJsonObject.id]) {
+ LOGGER.info("La topologie " + topologyJsonObject.id + " existe déjà");
+ return true;
} else {
// la topologie n'existe pas, on continue
}
@@ -388,7 +470,14 @@ module.exports = class topologyManager {
} else if (topologyJsonObject.type === "db") {
// récupération de la base
- let base = this._baseManager.createBase(topologyJsonObject.storage.base.dbConfig);
+ let base = {};
+ if (!this._baseManager.loadBaseConfiguration(topologyJsonObject.storage.base.dbConfig)) {
+ LOGGER.error("Impossible de charger la base configurée dans " + topologyJsonObject.storage.base.dbConfig);
+ return false;
+ } else {
+ base = this._baseManager.getBase(topologyJsonObject.storage.base.dbConfig);
+ }
+
// création des tableaux d'attributs
let defaultAttributes = new Array();
let otherAttributes = new Array();
@@ -402,6 +491,7 @@ module.exports = class topologyManager {
// cela ne doit pas arriver
}
}
+
// création de la topologie
topology = new DbTopology(topologyJsonObject.id, topologyJsonObject.description,
topologyJsonObject.projection, topologyJsonObject.bbox, base, topologyJsonObject.storage.base.schema,
@@ -409,38 +499,14 @@ module.exports = class topologyManager {
} else {
// On va voir si c'est un autre type.
- }
-
- this._topologiesCatalog[topologyJsonObject.id] = topology;
-
- return topology;
- }
-
- /**
- *
- * @function
- * @name loadAllTopologies
- * @description Fonction utilisée pour créer une source.
- *
- */
-
- loadAllTopologies() {
-
- if (this._listOfTopologyIds.length === 0) {
- LOGGER.error("Aucune topologie a charger.");
+ LOGGER.error("Type de la topology inconnu");
return false;
- } else {
- // on continue
}
- for (let i = 0; i < this._listOfTopologyIds.length; i++) {
-
- let id = this._listOfTopologyIds[i];
- let configuration = this._topologyDescriptions[id];
-
- this._topologiesCatalog[id] = this.createTopology(configuration);
-
- }
+ // on sauvegarde l'id de la topologie pour savoir qu'elle a déjà été vérifiée et que sa description est valide
+ this._loadedTopologyId.push(topologyJsonObject.id);
+ this._loadedTopologyConfiguration[topologyJsonObject.id] = topologyJsonObject;
+ this._topologyCatalog[topologyJsonObject.id] = topology;
return true;
diff --git a/src/js/utils/logManager.js b/src/js/utils/logManager.js
new file mode 100644
index 0000000..c9bc972
--- /dev/null
+++ b/src/js/utils/logManager.js
@@ -0,0 +1,91 @@
+'use strict';
+
+const log4js = require('log4js');
+
+// Création du LOGGER
+const LOGGER = log4js.getLogger("LOGMANAGER");
+
+module.exports = {
+
+ /**
+ *
+ * @function
+ * @name checkLogConfiguration
+ * @description Vérification de la configuration d'un logger
+ * @param {object} userLogConfiguration - Configuration du logger
+ * @param {string} userLogConfPath - Chemin absolu de la configuration du logger
+ * @return {boolean}
+ *
+ */
+
+ checkLogConfiguration: function(userLogConfiguration, userLogConfPath) {
+
+ LOGGER.info("Vérification de la configuration du logger...");
+
+ if (!userLogConfiguration) {
+
+ LOGGER.error("Aucune configuration pour les logs.");
+ return false;
+
+ } else {
+
+ if (!userLogConfiguration.mainConf) {
+ LOGGER.error("Mausvaise configuration pour les logs: 'mainConf' absent.");
+ return false;
+ } else {
+
+ if (!userLogConfiguration.mainConf.appenders) {
+ LOGGER.error("Mausvaise configuration pour les logs: 'mainConf.appenders' absent.");
+ return false;
+ }
+
+ if (!userLogConfiguration.mainConf.categories) {
+ LOGGER.error("Mausvaise configuration pour les logs: 'mainConf.categories' absent.");
+ return false;
+ }
+
+ }
+
+ if (!userLogConfiguration.httpConf) {
+
+ LOGGER.error("Mausvaise configuration pour les logs: 'httpConf' absent.");
+ return false;
+
+ } else {
+
+ if (!userLogConfiguration.httpConf.level) {
+ LOGGER.error("Mausvaise configuration pour les logs: 'httpConf.level' absent.");
+ return false;
+ } else {
+
+ if (typeof userLogConfiguration.httpConf.level !== "string") {
+ LOGGER.error("Mausvaise configuration pour les logs: 'httpConf.level' n'est pas une chaine de caracteres");
+ return false;
+ }
+
+ }
+
+ if (!userLogConfiguration.httpConf.format) {
+
+ LOGGER.error("Mausvaise configuration pour les logs: 'httpConf.format' absent.");
+ return false;
+
+ } else {
+
+ if (typeof userLogConfiguration.httpConf.format !== "string") {
+ LOGGER.error("Mausvaise configuration pour les logs: 'httpConf.format' n'est pas une chaine de caracteres");
+ return false;
+ }
+
+ }
+
+ }
+
+ }
+
+ LOGGER.info("Vérification des logs terminée");
+ return true;
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/js/utils/processManager.js b/src/js/utils/processManager.js
index c7a5332..1141caf 100644
--- a/src/js/utils/processManager.js
+++ b/src/js/utils/processManager.js
@@ -18,11 +18,11 @@ module.exports = {
shutdown: function(error) {
- LOGGER.info("Extinction du serveur.")
-
- log4js.shutdown(function(){
- process.exit(error);
- });
+ LOGGER.info("Extinction du processus");
+ // TODO : à voir si on en a besoin
+ // log4js.shutdown(() => {});
+ // setTimeout(() => {process.exit(error);},"1000");
+ process.exit(error);
}
diff --git a/test/functional/configuration/cucumber/features/conf-admin.feature b/test/functional/configuration/cucumber/features/conf-admin.feature
new file mode 100644
index 0000000..5f885ab
--- /dev/null
+++ b/test/functional/configuration/cucumber/features/conf-admin.feature
@@ -0,0 +1,351 @@
+# Tests fonctionnels de Road2 sur la configuration du serveur admin
+Feature: Road2 Admin configuration
+ Tests fonctionnels de Road2 sur la configuration du serveur admin
+
+ Background:
+ Given I have loaded all my test configuration
+
+ Scenario: [server.json] administration différent
+ Given a valid configuration
+ And with parameter "test" for attribute "administration" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.logs' absent"
+
+ Scenario: [server.json] administration vide
+ Given a valid configuration
+ And with parameter "" for attribute "administration" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration' absent"
+
+ Scenario: [server.json] administration absent
+ Given a valid configuration
+ And without attribute "administration" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration' absent"
+
+ Scenario: [server.json] administration.logs différent
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.logs" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.logs.configuration' absent"
+
+ Scenario: [server.json] administration.logs vide
+ Given a valid configuration
+ And with parameter "" for attribute "administration.logs" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.logs' absent"
+
+ Scenario: [server.json] administration.logs absent
+ Given a valid configuration
+ And without attribute "administration.logs" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.logs' absent"
+
+ Scenario: [server.json] administration.logs.configuration avec un fichier qui n'existe pas
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.logs.configuration" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: fichier de configuration des logs inexistant"
+
+ Scenario: [server.json] administration.logs.configuration sur un fichier non lisible
+ Given a valid configuration
+ And a file "file.json" non readable
+ And with parameter "file.json" for attribute "administration.logs.configuration" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de configuration des logs"
+
+ Scenario: [server.json] administration.logs.configuration sur un fichier vide
+ Given a valid configuration
+ And a file "file.json"
+ And with parameter "file.json" for attribute "administration.logs.configuration" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de configuration des logs"
+
+ Scenario: [server.json] administration.logs.configuration sur un fichier incorrect
+ Given a valid configuration
+ And a wrong JSON file "file.json"
+ And with parameter "file.json" for attribute "administration.logs.configuration" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de configuration des logs"
+
+ Scenario: [server.json] administration.logs.configuration vide
+ Given a valid configuration
+ And with parameter "" for attribute "administration.logs.configuration" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.logs.configuration' absent"
+
+ Scenario: [server.json] administration.logs.configuration absent
+ Given a valid configuration
+ And without attribute "administration.logs.configuration" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.logs.configuration' absent"
+
+ Scenario: [server.json] network different
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.network" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.network.server' absent"
+
+ Scenario: [server.json] network vide
+ Given a valid configuration
+ And with parameter "" for attribute "administration.network" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.network' absent"
+
+ Scenario: [server.json] network absent
+ Given a valid configuration
+ And without attribute "administration.network" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.network' absent"
+
+ Scenario: [server.json] network.server different
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.network.server" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "La configuration du serveur n'indique aucun id"
+
+ Scenario: [server.json] network.server vide
+ Given a valid configuration
+ And with parameter "" for attribute "administration.network.server" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.network.server' absent"
+
+ Scenario: [server.json] network.server absent
+ Given a valid configuration
+ And without attribute "administration.network.server" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.network.server' absent"
+
+ Scenario: [server.json] serveur http avec id different
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.network.server.id" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+
+ Scenario: [server.json] serveur http sans id
+ Given a valid configuration
+ And without attribute "administration.network.server.id" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "La configuration du serveur n'indique aucun id"
+
+ Scenario: [server.json] serveur http avec un mauvais https
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.network.server.https" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Le parametre https est mal renseigné. Valeurs disponibles: 'true' ou 'false'."
+
+ Scenario: [server.json] serveur http sans https
+ Given a valid configuration
+ And without attribute "administration.network.server.https" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "La configuration du serveur n'indique pas la securisation du serveur"
+
+ Scenario: [server.json] serveur http avec un mauvais host
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.network.server.host" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "L'host du serveur est mal renseigne."
+
+ Scenario: [server.json] serveur http avec un autre host
+ Given a valid configuration
+ And with parameter "127.0.0.1" for attribute "administration.network.server.host" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [server.json] serveur http sans host
+ Given a valid configuration
+ And without attribute "administration.network.server.host" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "La configuration du serveur n'indique aucun host"
+
+ Scenario: [server.json] serveur http avec un mauvais port
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.network.server.port" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Le port est mal renseigne."
+
+ Scenario: [server.json] serveur http avec un port trop eleve
+ Given a valid configuration
+ And with parameter "65537" for attribute "administration.network.server.port" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Le port est mal renseigne: Numero de port invalide"
+
+ Scenario: [server.json] serveur http avec un autre port
+ Given a valid configuration
+ And with parameter "8888" for attribute "administration.network.server.port" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [server.json] serveur http sans port
+ Given a valid configuration
+ And without attribute "administration.network.server.port" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "La configuration du serveur n'indique aucun port"
+
+ Scenario: [server.json] serveur https bien configuré
+ Given a valid configuration
+ And with parameter "true" for attribute "administration.network.server.https" in server configuration
+ And with parameter "/run/secrets/key" for attribute "administration.network.server.options.key" in server configuration
+ And with parameter "/run/secrets/cert" for attribute "administration.network.server.options.cert" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [server.json] serveur https avec un port different
+ Given a valid configuration
+ And with parameter "true" for attribute "administration.network.server.https" in server configuration
+ And with parameter "/run/secrets/cert" for attribute "administration.network.server.options.cert" in server configuration
+ And with parameter "/run/secrets/key" for attribute "administration.network.server.options.key" in server configuration
+ And with parameter "445" for attribute "administration.network.server.port" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [server.json] serveur https sans options
+ Given a valid configuration
+ And with parameter "true" for attribute "administration.network.server.https" in server configuration
+ And without attribute "administration.network.server.options" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Serveur https sans options."
+
+ Scenario: [server.json] serveur https avec options vide
+ Given a valid configuration
+ And with parameter "true" for attribute "administration.network.server.https" in server configuration
+ And with parameter "" for attribute "administration.network.server.options" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Serveur https sans options."
+
+ Scenario: [server.json] serveur https avec un mauvais options
+ Given a valid configuration
+ And with parameter "true" for attribute "administration.network.server.https" in server configuration
+ And with parameter "test" for attribute "administration.network.server.options" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "L'objet options doit contenir un key pour le HTTPS."
+
+ Scenario: [server.json] serveur https avec options.key vide
+ Given a valid configuration
+ And with parameter "true" for attribute "administration.network.server.https" in server configuration
+ And with parameter "" for attribute "administration.network.server.options.key" in server configuration
+ And with parameter "/run/secrets/cert" for attribute "administration.network.server.options.cert" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "L'objet options doit contenir un key pour le HTTPS."
+
+ Scenario: [server.json] serveur https avec un mauvais options.key
+ Given a valid configuration
+ And with parameter "true" for attribute "administration.network.server.https" in server configuration
+ And with parameter "test.key" for attribute "administration.network.server.options.key" in server configuration
+ And with parameter "/run/secrets/cert" for attribute "administration.network.server.options.cert" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Le fichier ne peut etre lu"
+
+ Scenario: [server.json] serveur https avec options.cert vide
+ Given a valid configuration
+ And with parameter "true" for attribute "administration.network.server.https" in server configuration
+ And with parameter "" for attribute "administration.network.server.options.cert" in server configuration
+ And with parameter "/run/secrets/key" for attribute "administration.network.server.options.key" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "L'objet options doit contenir un cert pour le HTTPS"
+
+ Scenario: [server.json] serveur https avec un mauvais options.cert
+ Given a valid configuration
+ And with parameter "true" for attribute "administration.network.server.https" in server configuration
+ And with parameter "/run/secrets/key" for attribute "administration.network.server.options.key" in server configuration
+ And with parameter "test.cert" for attribute "administration.network.server.options.cert" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Le fichier ne peut etre lu"
+
+
+ Scenario: [server.json] administration.api différent
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.api" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration de l'api: 'name' absent"
+
+ Scenario: [server.json] administration.api vide
+ Given a valid configuration
+ And with parameter "" for attribute "administration.api" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.api' absent"
+
+ Scenario: [server.json] administration.api absent
+ Given a valid configuration
+ And without attribute "administration.api" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'administration.api' absent"
+
+ Scenario: [server.json] administration.api.name différent
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.api.name" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: 'name' ne peut être évalué"
+
+ Scenario: [server.json] administration.api.name vide
+ Given a valid configuration
+ And with parameter "" for attribute "administration.api.name" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration de l'api: 'name' absent"
+
+ Scenario: [server.json] administration.api.name absent
+ Given a valid configuration
+ And without attribute "administration.api.name" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration de l'api: 'name' absent"
+
+ Scenario: [server.json] administration.api.version différent
+ Given a valid configuration
+ And with parameter "test" for attribute "administration.api.version" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration de l'api: 'version' ne peut être évalué"
+
+ Scenario: [server.json] administration.api.version vide
+ Given a valid configuration
+ And with parameter "" for attribute "administration.api.version" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration de l'api: 'version' absent"
+
+ Scenario: [server.json] administration.api.version absent
+ Given a valid configuration
+ And without attribute "administration.api.version" in server configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration de l'api: 'version' absent"
diff --git a/test/functional/configuration/cucumber/features/conf-common.feature b/test/functional/configuration/cucumber/features/conf-common.feature
new file mode 100644
index 0000000..710f27d
--- /dev/null
+++ b/test/functional/configuration/cucumber/features/conf-common.feature
@@ -0,0 +1,51 @@
+# Tests fonctionnels de Road2 sur la configuration du serveur
+Feature: Road2 configuration
+ Tests fonctionnels de Road2 sur la configuration du serveur
+
+ Background:
+ Given I have loaded all my test configuration
+
+ Scenario: Configuration correcte
+ Given a valid configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+ Then the server log should contain "La vérification des différentes configurations est terminée"
+ Then the server log should not contain "[ERROR]"
+
+ Scenario: Mauvais argument de la ligne de commande (valeur vide)
+ Given a valid configuration
+ And with "" for command line parameter "ROAD2_CONF_FILE"
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Impossible de recuperer le chemin absolu du fichier de configuration"
+
+ Scenario: Mauvais argument de la ligne de commande (fichier qui n'existe pas)
+ Given a valid configuration
+ And with "test1" for command line parameter "ROAD2_CONF_FILE"
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Mauvaise configuration: fichier de configuration global inexistant"
+
+ #TODO Fix: root peut toujours lire un fichier même si chmod 000
+ #Scenario: Mauvais argument de la ligne de commande (fichier qui ne peut être lu)
+ # Given a valid configuration
+ # And a server configuration non readable
+ # When I test the configuration
+ # Then the configuration analysis should give an exit code 1
+ # Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de configuration de Road2"
+
+ Scenario: Pas d'argument ROAD2_CONF_FILE dans la ligne de commande
+ Given a valid configuration
+ And without parameter "ROAD2_CONF_FILE" in command line
+ When I test the configuration
+ Then the configuration analysis should give an exit code 11
+ Then the server log should contain "Aucun fichier de configuration. Utiliser la variable d'environnement $ROAD2_CONF_FILE ou l'option --ROAD2_CONF_FILE lors de l'initialisation du serveur."
+
+ Scenario: Argument inutile dans la ligne de commande
+ Given a valid configuration
+ And with "test" for command line parameter "ROAD2_TEST"
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+ Then the server log should contain "La vérification des différentes configurations est terminée"
diff --git a/test/functional/configuration/cucumber/features/conf-cors.feature b/test/functional/configuration/cucumber/features/conf-cors.feature
new file mode 100644
index 0000000..fdfd023
--- /dev/null
+++ b/test/functional/configuration/cucumber/features/conf-cors.feature
@@ -0,0 +1,21 @@
+# Tests fonctionnels de Road2 sur la configuration du serveur
+Feature: Road2 configuration
+ Tests fonctionnels de Road2 sur la configuration du serveur
+
+ Background:
+ Given I have loaded all my test configuration
+
+ Scenario: [cors.json] Contenu different
+ Given a valid configuration
+ And with parameter "127.0.0.1" for attribute "origin" in cors configuration
+ And with parameter "GET,POST" for attribute "methods" in cors configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ And the command log should not contain error
+
+ Scenario: [cors.json] Contenu mauvais
+ Given a valid configuration
+ And with parameter "TEST" for attribute "methods" in cors configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ And the command log should not contain error
diff --git a/test/functional/configuration/cucumber/features/conf-log.feature b/test/functional/configuration/cucumber/features/conf-log.feature
new file mode 100644
index 0000000..9b9e40a
--- /dev/null
+++ b/test/functional/configuration/cucumber/features/conf-log.feature
@@ -0,0 +1,88 @@
+# Tests fonctionnels de Road2 sur la configuration du serveur
+Feature: Road2 configuration
+ Tests fonctionnels de Road2 sur la configuration du serveur
+
+ Background:
+ Given I have loaded all my test configuration
+
+ Scenario: [log.json] (mainConf different)
+ Given a valid configuration
+ And with parameter "test" for attribute "mainConf" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mausvaise configuration pour les logs: 'mainConf.appenders' absent"
+
+ Scenario: [log.json] (mainConf vide)
+ Given a valid configuration
+ And with parameter "" for attribute "mainConf" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mausvaise configuration pour les logs: 'mainConf' absent"
+
+ Scenario: [log.json] (mainConf absent)
+ Given a valid configuration
+ And without attribute "mainConf" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mausvaise configuration pour les logs: 'mainConf' absent"
+
+ Scenario: [log.json] (httpConf different)
+ Given a valid configuration
+ And with parameter "test" for attribute "httpConf" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf.level' absent"
+
+ Scenario: [log.json] (httpConf vide)
+ Given a valid configuration
+ And with parameter "" for attribute "httpConf" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf' absent"
+
+ Scenario: [log.json] (httpConf absent)
+ Given a valid configuration
+ And without attribute "httpConf" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf' absent"
+
+ Scenario: [log.json] (httpConf.level different)
+ Given a valid configuration
+ And with parameter "test" for attribute "httpConf.level" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [log.json] (httpConf.level vide)
+ Given a valid configuration
+ And with parameter "" for attribute "httpConf.level" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf.level' absent"
+
+ Scenario: [log.json] (httpConf.level absent)
+ Given a valid configuration
+ And without attribute "httpConf.level" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf.level' absent"
+
+ Scenario: [log.json] (httpConf.format different)
+ Given a valid configuration
+ And with parameter "test" for attribute "httpConf.format" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [log.json] (httpConf.format vide)
+ Given a valid configuration
+ And with parameter "" for attribute "httpConf.format" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf.format' absent"
+
+ Scenario: [log.json] (httpConf.format absent)
+ Given a valid configuration
+ And without attribute "httpConf.format" in service log configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf.format' absent"
diff --git a/test/functional/configuration/cucumber/features/conf-operation.feature b/test/functional/configuration/cucumber/features/conf-operation.feature
new file mode 100644
index 0000000..0c194b0
--- /dev/null
+++ b/test/functional/configuration/cucumber/features/conf-operation.feature
@@ -0,0 +1,122 @@
+# Tests fonctionnels de Road2 sur la configuration du serveur
+Feature: Road2 configuration
+ Tests fonctionnels de Road2 sur la configuration du serveur
+
+ Background:
+ Given I have loaded all my test configuration
+
+ Scenario: [operations] id différent
+ Given a valid configuration
+ And with parameter "test" for attribute "id" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation indiquee n'est pas disponible"
+
+ Scenario: [operations] id vide
+ Given a valid configuration
+ And with parameter "" for attribute "id" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation ne contient pas d'id"
+
+ Scenario: [operations] id absent
+ Given a valid configuration
+ And without attribute "id" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation ne contient pas d'id"
+
+ Scenario: [operations] name différent
+ Given a valid configuration
+ And with parameter "test" for attribute "name" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [operations] name vide
+ Given a valid configuration
+ And with parameter "" for attribute "name" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation ne contient pas d'attribut name"
+
+ Scenario: [operations] name absent
+ Given a valid configuration
+ And without attribute "name" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation ne contient pas d'attribut name"
+
+ Scenario: [operations] description différent
+ Given a valid configuration
+ And with parameter "test" for attribute "description" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [operations] description vide
+ Given a valid configuration
+ And with parameter "" for attribute "description" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation ne contient pas d'attribut description"
+
+ Scenario: [operations] description absent
+ Given a valid configuration
+ And without attribute "description" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation ne contient pas d'attribut description"
+
+ Scenario: [operations] parameters différent
+ Given a valid configuration
+ And with parameter "test" for attribute "parameters" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Les parametres de l'operation ne sont pas dans un tableau"
+
+ Scenario: [operations] parameters vide
+ Given a valid configuration
+ And with parameter "" for attribute "parameters" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation ne contient pas d'attribut parameters"
+
+ Scenario: [operations] parameters absent
+ Given a valid configuration
+ And without attribute "parameters" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation ne contient pas d'attribut parameters"
+
+ Scenario: [operations] parameters est un tableau vide
+ Given a valid configuration
+ And without attribute "parameters.[13]" in "route.json" operation
+ And without attribute "parameters.[12]" in "route.json" operation
+ And without attribute "parameters.[11]" in "route.json" operation
+ And without attribute "parameters.[10]" in "route.json" operation
+ And without attribute "parameters.[9]" in "route.json" operation
+ And without attribute "parameters.[8]" in "route.json" operation
+ And without attribute "parameters.[7]" in "route.json" operation
+ And without attribute "parameters.[6]" in "route.json" operation
+ And without attribute "parameters.[5]" in "route.json" operation
+ And without attribute "parameters.[4]" in "route.json" operation
+ And without attribute "parameters.[3]" in "route.json" operation
+ And without attribute "parameters.[2]" in "route.json" operation
+ And without attribute "parameters.[1]" in "route.json" operation
+ And without attribute "parameters.[0]" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le tableau des parametres est vide"
+
+ Scenario: [operations] parameters est incomplet
+ Given a valid configuration
+ And without attribute "parameters.[0]" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le nombre de parametres presents n'est pas celui attendu"
+
+ Scenario: [operations] parameters contient un element different
+ Given a valid configuration
+ And with parameter "test" for attribute "parameters.[0]" in "route.json" operation
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation précise un parametre qui n'est pas disponible"
diff --git a/test/functional/configuration/cucumber/features/conf-osrm-ressource.feature b/test/functional/configuration/cucumber/features/conf-osrm-ressource.feature
new file mode 100644
index 0000000..cae5bb7
--- /dev/null
+++ b/test/functional/configuration/cucumber/features/conf-osrm-ressource.feature
@@ -0,0 +1,21 @@
+# Tests fonctionnels de Road2 sur la configuration du serveur
+Feature: Road2 configuration
+ Tests fonctionnels de Road2 sur la configuration du serveur
+
+ Background:
+ Given I have loaded all my test configuration
+
+ Scenario: [osrm resource] resource absent
+ Given a valid configuration
+ And without attribute "resource" in "data-osm.resource" resource
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ # TODO : avoir plusieurs ressources dans le dossier pour qu'une d'entre elles marche
+ # Then the configuration analysis should give an exit code 0
+ # Then the server log should contain "Erreur lors de la lecture de la ressource"
+
+ Scenario: [osrm resource] id different
+ Given a valid configuration
+ And with parameter "test" for attribute "resource.id" in "data-osm.resource" resource
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
diff --git a/test/functional/configuration/cucumber/features/conf-parameter.feature b/test/functional/configuration/cucumber/features/conf-parameter.feature
new file mode 100644
index 0000000..b5ebba4
--- /dev/null
+++ b/test/functional/configuration/cucumber/features/conf-parameter.feature
@@ -0,0 +1,307 @@
+# Tests fonctionnels de Road2 sur la configuration du serveur
+Feature: Road2 configuration
+ Tests fonctionnels de Road2 sur la configuration du serveur
+
+ Background:
+ Given I have loaded all my test configuration
+
+ Scenario: [parameters] id différent
+ Given a valid configuration
+ And with parameter "test" for attribute "id" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'operation précise un parametre qui n'est pas disponible: intermediates"
+
+ Scenario: [parameters] id vide
+ Given a valid configuration
+ And with parameter "" for attribute "id" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'id"
+
+ Scenario: [parameters] id absent
+ Given a valid configuration
+ And without attribute "id" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'id"
+
+ Scenario: [parameters] id deja utilise
+ Given a valid configuration
+ And with parameter "test" for attribute "id" in "start.json" parameter
+ And with parameter "test" for attribute "id" in "end.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre contenant l'id test est deja vérifié"
+
+ Scenario: [parameters] name différent
+ Given a valid configuration
+ And with parameter "test" for attribute "name" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] name vide
+ Given a valid configuration
+ And with parameter "" for attribute "name" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'attribut name"
+
+ Scenario: [parameters] name absent
+ Given a valid configuration
+ And without attribute "name" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'attribut name"
+
+ Scenario: [parameters] description différent
+ Given a valid configuration
+ And with parameter "test" for attribute "description" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] description vide
+ Given a valid configuration
+ And with parameter "" for attribute "description" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'attribut description"
+
+ Scenario: [parameters] description absent
+ Given a valid configuration
+ And without attribute "description" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'attribut description"
+
+ Scenario: [parameters] required différent
+ Given a valid configuration
+ And with parameter "true" for attribute "required" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] required invalide
+ Given a valid configuration
+ And with parameter "test" for attribute "required" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre contient un attribut required mal configure"
+
+ Scenario: [parameters] required vide
+ Given a valid configuration
+ And with parameter "" for attribute "required" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'attribut required"
+
+ Scenario: [parameters] required absent
+ Given a valid configuration
+ And without attribute "required" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'attribut required"
+
+ Scenario: [parameters] defaultValue différent (true donc probleme apres)
+ Given a valid configuration
+ And with parameter "true" for attribute "defaultValue" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas de valeur par defaut alors qu'il doit en avoir un"
+
+ Scenario: [parameters] defaultValue invalide
+ Given a valid configuration
+ And with parameter "test" for attribute "defaultValue" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre contient un attribut defaultValue mal configure"
+
+ Scenario: [parameters] defaultValue vide
+ Given a valid configuration
+ And with parameter "" for attribute "defaultValue" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'attribut defaultValue"
+
+ Scenario: [parameters] defaultValue absent
+ Given a valid configuration
+ And without attribute "defaultValue" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'attribut defaultValue"
+
+ Scenario: [parameters] example différent
+ Given a valid configuration
+ And with parameter "test" for attribute "example" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] example vide
+ Given a valid configuration
+ And with parameter "" for attribute "example" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the server log should contain "Le parametre ne contient pas d'exemple"
+
+ Scenario: [parameters] example absent
+ Given a valid configuration
+ And without attribute "example" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the server log should contain "Le parametre ne contient pas d'exemple"
+
+ Scenario: [parameters] type différent
+ Given a valid configuration
+ And with parameter "boolean" for attribute "type" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La valeur du parametre est incorrecte par rapport à son type: boolean"
+
+ Scenario: [parameters] type invalide
+ Given a valid configuration
+ And with parameter "test" for attribute "type" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le type du parametre est incorrect"
+
+ Scenario: [parameters] type vide
+ Given a valid configuration
+ And with parameter "" for attribute "type" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'attribut type"
+
+ Scenario: [parameters] type absent
+ Given a valid configuration
+ And without attribute "type" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre ne contient pas d'attribut type"
+
+ Scenario: [parameters] min différent et required true
+ Given a valid configuration
+ And with parameter "1" for attribute "min" in "intermediates.json" parameter
+ And with parameter "true" for attribute "required" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] min différent et required false
+ Given a valid configuration
+ And with parameter "1" for attribute "min" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre min est incorrect: valeur superieure a 0"
+
+ Scenario: [parameters] min a 0 et required true
+ Given a valid configuration
+ And with parameter "0" for attribute "min" in "intermediates.json" parameter
+ And with parameter "true" for attribute "required" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre min est incorrect: valeur inferieure a 1"
+
+ Scenario: [parameters] min invalide
+ Given a valid configuration
+ And with parameter "test" for attribute "min" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre min est incorrect: valeur non entiere"
+
+ Scenario: [parameters] min vide
+ Given a valid configuration
+ And with parameter "" for attribute "min" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] min absent
+ Given a valid configuration
+ And without attribute "min" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] max différent
+ Given a valid configuration
+ And with parameter "1" for attribute "max" in "intermediates.json" parameter
+ And with parameter "true" for attribute "required" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] max a 0
+ Given a valid configuration
+ And with parameter "0" for attribute "max" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre max est incorrect: valeur inferieure a 1"
+
+ Scenario: [parameters] max invalide
+ Given a valid configuration
+ And with parameter "test" for attribute "max" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre max est incorrect: valeur non entiere"
+
+ Scenario: [parameters] max vide
+ Given a valid configuration
+ And with parameter "" for attribute "max" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] max absent
+ Given a valid configuration
+ And without attribute "max" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] max plus petit que min
+ Given a valid configuration
+ And with parameter "1" for attribute "max" in "intermediates.json" parameter
+ And with parameter "2" for attribute "min" in "intermediates.json" parameter
+ And with parameter "true" for attribute "required" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre max est incorrect: valeur inferieure au parametre min"
+
+ Scenario: [parameters] explode différent (true)
+ Given a valid configuration
+ And with parameter "true" for attribute "explode" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] explode invalide
+ Given a valid configuration
+ And with parameter "test" for attribute "explode" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre explode est incorrect"
+
+ Scenario: [parameters] explode vide
+ Given a valid configuration
+ And with parameter "" for attribute "explode" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] explode absent
+ Given a valid configuration
+ And without attribute "explode" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [parameters] style invalide alors que explode false
+ Given a valid configuration
+ And with parameter "test" for attribute "style" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre style est incorrect"
+
+ Scenario: [parameters] style vide alors que explode false
+ Given a valid configuration
+ And with parameter "" for attribute "style" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre style n'est pas present alors que explode=false"
+
+ Scenario: [parameters] style vide alors que explode false
+ Given a valid configuration
+ And without attribute "style" in "intermediates.json" parameter
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre style n'est pas present alors que explode=false"
diff --git a/test/functional/configuration/cucumber/features/conf-projection.feature b/test/functional/configuration/cucumber/features/conf-projection.feature
new file mode 100644
index 0000000..89f4376
--- /dev/null
+++ b/test/functional/configuration/cucumber/features/conf-projection.feature
@@ -0,0 +1,110 @@
+# Tests fonctionnels de Road2 sur la configuration du serveur
+Feature: Road2 configuration
+ Tests fonctionnels de Road2 sur la configuration du serveur
+
+ Background:
+ Given I have loaded all my test configuration
+
+ Scenario: [projection.json] JSON invalide
+ Given a valid configuration
+ And a wrong JSON file "./projections/test.json"
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de projection"
+
+ Scenario: [projection.json] JSON vide
+ Given a valid configuration
+ And without attribute "projectionsList" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La fichier des projections ne contient pas de liste"
+
+ Scenario: [projection.json] projectionsList absent
+ Given a valid configuration
+ And without attribute "projectionsList" in "projection.json" projection
+ And with parameter "test" for attribute "projections" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La fichier des projections ne contient pas de liste"
+
+ Scenario: [projection.json] projectionsList different
+ Given a valid configuration
+ And with parameter "test" for attribute "projectionsList" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'attribut projectionsList de la configuration n'est pas un tableau"
+
+ Scenario: [projection.json] projectionsList est un tableau vide
+ Given a valid configuration
+ And without attribute "projectionsList.[6]" in "projection.json" projection
+ And without attribute "projectionsList.[5]" in "projection.json" projection
+ And without attribute "projectionsList.[4]" in "projection.json" projection
+ And without attribute "projectionsList.[3]" in "projection.json" projection
+ And without attribute "projectionsList.[2]" in "projection.json" projection
+ And without attribute "projectionsList.[1]" in "projection.json" projection
+ And without attribute "projectionsList.[0]" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'attribut projectionsList de la configuration est un tableau vide"
+
+ Scenario: [projection.json] une configuration de projection vide
+ Given a valid configuration
+ And without attribute "projectionsList.[0].id" in "projection.json" projection
+ And without attribute "projectionsList.[0].parameters" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La configuration de la projection n'a pas d'id"
+
+ Scenario: [projection.json] une configuration de projection sans id
+ Given a valid configuration
+ And without attribute "projectionsList.[0].id" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La configuration de la projection n'a pas d'id"
+
+ Scenario: [projection.json] une configuration de projection sans parametre
+ Given a valid configuration
+ And without attribute "projectionsList.[0].parameters" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La configuration de la projection n'a pas de parametres"
+
+ Scenario: [projection.json] une configuration de projection différentes
+ Given a valid configuration
+ And with parameter "test" for attribute "projectionsList.[0]" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La configuration de la projection n'a pas d'id"
+
+ Scenario: [projection.json] projection.id différent pour une projection inutilisée dans les topologies
+ Given a valid configuration
+ And with parameter "test" for attribute "projectionsList.[2].id" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [projection.json] projection.id différent pour une projection utilisée dans les topologies
+ Given a valid configuration
+ And with parameter "test" for attribute "projectionsList.[0].id" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+
+ Scenario: [projection.json] projection.id vide
+ Given a valid configuration
+ And with parameter "" for attribute "projectionsList.[2].id" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La configuration de la projection n'a pas d'id"
+
+ #TODO : Voir si on peut mieux vérifier
+ Scenario: [projection.json] projection.parameters différent
+ Given a valid configuration
+ And with parameter "test" for attribute "projectionsList.[0].parameters" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [projection.json] projection.parameters vide
+ Given a valid configuration
+ And with parameter "" for attribute "projectionsList.[0].parameters" in "projection.json" projection
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La configuration de la projection n'a pas de parametres"
diff --git a/test/functional/configuration/cucumber/features/conf-service.feature b/test/functional/configuration/cucumber/features/conf-service.feature
new file mode 100644
index 0000000..91f70fe
--- /dev/null
+++ b/test/functional/configuration/cucumber/features/conf-service.feature
@@ -0,0 +1,677 @@
+# Tests fonctionnels de Road2 sur la configuration du service
+Feature: Road2 service configuration
+ Tests fonctionnels de Road2 sur la configuration du service
+
+ Background:
+ Given I have loaded all my test configuration
+
+ Scenario: [service.json] (application different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:name' manquant"
+
+ Scenario: [service.json] (application vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application' manquant"
+
+ Scenario: [service.json] (application absent)
+ Given a valid configuration
+ And without attribute "application" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application' manquant"
+
+ Scenario: [service.json] (application.logs different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.logs" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application.logs.configuration' manquant"
+
+ Scenario: [service.json] (application.logs vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.logs" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application.logs' manquant"
+
+ Scenario: [service.json] (application.logs absent)
+ Given a valid configuration
+ And without attribute "application.logs" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application.logs' manquant"
+
+ Scenario: [service.json] (application.logs.configuration different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.logs.configuration" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Fichier de conf des logs inexistant"
+
+ Scenario: [service.json] (application.logs.configuration vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.logs.configuration" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application.logs.configuration' manquant"
+
+ Scenario: [service.json] (application.logs.configuration absent)
+ Given a valid configuration
+ And without attribute "application.logs.configuration" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application.logs.configuration' manquant"
+
+ Scenario: [service.json] (application.logs.configuration sur un fichier non lisible)
+ Given a valid configuration
+ And a file "file.json" non readable
+ And with parameter "file.json" for attribute "application.logs.configuration" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de conf des logs du service"
+
+ Scenario: [service.json] (application.logs.configuration sur un fichier vide)
+ Given a valid configuration
+ And a file "file.json"
+ And with parameter "file.json" for attribute "application.logs.configuration" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de conf des logs du service"
+
+ Scenario: [service.json] (application.logs.configuration sur un fichier incorrect)
+ Given a valid configuration
+ And a wrong JSON file "file.json"
+ And with parameter "file.json" for attribute "application.logs.configuration" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de conf des logs du service"
+
+ Scenario: [service.json] (name different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.name" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [service.json] (name vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.name" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+
+ Scenario: [service.json] (name absent)
+ Given a valid configuration
+ And without attribute "application.name" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+
+ Scenario: [service.json] (title different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.title" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+
+ Scenario: [service.json] (title vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.title" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:title' manquant !"
+
+ Scenario: [service.json] (title absent)
+ Given a valid configuration
+ And without attribute "application.title" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:title' manquant !"
+
+ Scenario: [service.json] (description different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.description" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+
+ Scenario: [service.json] (description vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.description" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:description' manquant !"
+
+ Scenario: [service.json] (description absent)
+ Given a valid configuration
+ And without attribute "application.description" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:description' manquant !"
+
+ Scenario: [service.json] (provider different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.provider" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:provider:name' manquant !"
+
+ Scenario: [service.json] (provider vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.provider" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+ Then the server log should contain "Configuration incomplete: Objet 'application:provider' manquant !"
+
+ Scenario: [service.json] (provider absent)
+ Given a valid configuration
+ And without attribute "application.provider" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+ Then the server log should contain "Configuration incomplete: Objet 'application:provider' manquant !"
+
+ Scenario: [service.json] (provider.name different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.provider.name" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+
+ Scenario: [service.json] (provider.name vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.provider.name" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:provider:name' manquant !"
+
+ Scenario: [service.json] (provider.name absent)
+ Given a valid configuration
+ And without attribute "application.provider.name" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:provider:name' manquant !"
+
+ Scenario: [service.json] (provider.site different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.provider.site" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+
+ Scenario: [service.json] (provider.site vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.provider.site" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the server log should contain "Le champ 'application:provider:site' n'est pas renseigne."
+
+ Scenario: [service.json] (provider.site absent)
+ Given a valid configuration
+ And without attribute "application.provider.site" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the server log should contain "Le champ 'application:provider:site' n'est pas renseigne."
+
+ Scenario: [service.json] (provider.mail different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.provider.mail" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+
+ Scenario: [service.json] (provider.mail vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.provider.mail" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:provider:mail' manquant !"
+
+ Scenario: [service.json] (provider.mail absent)
+ Given a valid configuration
+ And without attribute "application.provider.mail" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:provider:mail' manquant !"
+
+ Scenario: [service.json] (operations different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.operations" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:operations:directory' manquant !"
+
+ Scenario: [service.json] (operations vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.operations" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:operations' manquant !"
+
+ Scenario: [service.json] (operations absent)
+ Given a valid configuration
+ And without attribute "application.operations" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:operations' manquant !"
+
+ Scenario: [service.json] (operations.directory sur un dossier qui n'existe pas)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.operations.directory" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le dossier des operations est mal configuré"
+
+ Scenario: [service.json] (operations.directory vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.operations.directory" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:operations:directory' manquant !"
+
+ Scenario: [service.json] (operations.directory absent)
+ Given a valid configuration
+ And without attribute "application.operations.directory" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:operations:directory' manquant !"
+
+ # TODO
+ # Faire un scénario qui teste si les fichiers de operations.directory ne sont pas lisibles
+
+ Scenario: [service.json] (operations.parameters different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.operations.parameters" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:operations:parameters:directory' manquant !"
+
+ Scenario: [service.json] (operations.parameters vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.operations.parameters" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:operations:parameters' manquant !"
+
+ Scenario: [service.json] (operations.parameters absent)
+ Given a valid configuration
+ And without attribute "application.operations.parameters" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:operations:parameters' manquant !"
+
+ Scenario: [service.json] (operations.parameters.directory sur un dossier qui n'existe pas)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.operations.parameters.directory" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Le dossier des parametres n'existe pas"
+
+ Scenario: [service.json] (operations.parameters.directory vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.operations.parameters.directory" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:operations:parameters:directory' manquant !"
+
+ Scenario: [service.json] (operations.parameters.directory absent)
+ Given a valid configuration
+ And without attribute "application.operations.parameters.directory" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:operations:parameters:directory' manquant !"
+
+ # TODO
+ # Faire un scénario qui teste si les fichiers de operations.parameters.directory ne sont pas lisibles
+
+ Scenario: [service.json] (resources different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.resources" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:resources:directories' manquant !"
+
+ Scenario: [service.json] (resources vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.resources" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:resources' manquant !"
+
+ Scenario: [service.json] (resources absent)
+ Given a valid configuration
+ And without attribute "application.resources" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:resources' manquant !"
+
+ Scenario: [service.json] (resources.directories est une chaine de caracteres)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.resources.directories" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:resources:directories' n'est pas un tableau !"
+
+ # TODO
+ # Tester le paramètre resources.directories sur un tableau vide
+
+ Scenario: [service.json] (resources.directories sur un dossier qui n'existe pas et en chemin relatif)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.resources.directories.[1]" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the server log should contain "Mauvaise configuration: Le dossier n'existe pas:"
+
+ Scenario: [service.json] (resources.directories sur deux dossiers qui n'existent pas et en chemins relatifs)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.resources.directories.[0]" in service configuration
+ And with parameter "test1" for attribute "application.resources.directories.[1]" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Le dossier n'existe pas"
+
+ Scenario: [service.json] (resources.directories contient un élément vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.resources.directories.[1]" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the server log should contain "Mauvaise configuration: Champ 'application:resources:directories' contient un élément vide"
+
+ Scenario: [service.json] (resources.directories contient que des éléments vides)
+ Given a valid configuration
+ And with parameter "" for attribute "application.resources.directories.[0]" in service configuration
+ And with parameter "" for attribute "application.resources.directories.[1]" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Aucun dossier de ressource n'a été validé"
+
+ Scenario: [service.json] (resources.directories absent)
+ Given a valid configuration
+ And without attribute "application.resources.directories" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:resources:directories' manquant !"
+
+ # TODO
+ # Tester un dossier de ressources dont une des ressources ne peut être lues
+
+ Scenario: [service.json] (network different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.network" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:network:servers' manquant !"
+
+ Scenario: [service.json] (network vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.network" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:network' manquant !"
+
+ Scenario: [service.json] (network absent)
+ Given a valid configuration
+ And without attribute "application.network" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:network' manquant !"
+
+ Scenario: [service.json] (network.servers different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.network.servers" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:network:servers' n'est pas un tableau !"
+
+ Scenario: [service.json] (network.servers vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.network.servers" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:network:servers' manquant !"
+
+ Scenario: [service.json] (network.servers absent)
+ Given a valid configuration
+ And without attribute "application.network.servers" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:network:servers' manquant !"
+
+ # TODO: tester le tableau vide pour network.servers
+
+ Scenario: [service.json] (network.servers contient une chaîne de caractères)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.network.servers.[0]" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration d'un serveur !"
+
+ Scenario: [service.json] (network.servers contient que des chaînes de caractères)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.network.servers.[0]" in service configuration
+ And with parameter "test" for attribute "application.network.servers.[1]" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration d'un serveur !"
+
+ Scenario: [service.json] (serveur http avec id different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.network.servers.[0].id" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the command log should not contain error
+
+ Scenario: [service.json] (serveur http sans id)
+ Given a valid configuration
+ And without attribute "application.network.servers.[0].id" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La configuration du serveur n'indique aucun id"
+
+ Scenario: [service.json] (serveur http avec un mauvais https)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.network.servers.[0].https" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le parametre https est mal renseigné. Valeurs disponibles: 'true' ou 'false'."
+
+ Scenario: [service.json] (serveur http sans https)
+ Given a valid configuration
+ And without attribute "application.network.servers.[0].https" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La configuration du serveur n'indique pas la securisation du serveur"
+
+ Scenario: [service.json] (serveur http avec un mauvais host)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.network.servers.[0].host" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'host du serveur est mal renseigne."
+
+ Scenario: [service.json] (serveur http avec un autre host)
+ Given a valid configuration
+ And with parameter "127.0.0.1" for attribute "application.network.servers.[0].host" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [service.json] (serveur http sans host)
+ Given a valid configuration
+ And without attribute "application.network.servers.[0].host" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La configuration du serveur n'indique aucun host"
+
+ Scenario: [service.json] (serveur http avec un mauvais port)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.network.servers.[0].port" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le port est mal renseigne."
+
+ Scenario: [service.json] (serveur http avec un port trop eleve)
+ Given a valid configuration
+ And with parameter "65537" for attribute "application.network.servers.[0].port" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le port est mal renseigne: Numero de port invalide"
+
+ Scenario: [service.json] (serveur http avec un autre port)
+ Given a valid configuration
+ And with parameter "8888" for attribute "application.network.servers.[0].port" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [service.json] (serveur http sans port)
+ Given a valid configuration
+ And without attribute "application.network.servers.[0].port" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "La configuration du serveur n'indique aucun port"
+
+ Scenario: [service.json] (serveur https avec un port different)
+ Given a valid configuration
+ And with parameter "445" for attribute "application.network.servers.[1].port" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+
+ Scenario: [service.json] (serveur https sans options)
+ Given a valid configuration
+ And without attribute "application.network.servers.[1].options" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Serveur https sans options."
+
+ Scenario: [service.json] (server https avec options vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.network.servers.[1].options" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Serveur https sans options."
+
+ Scenario: [service.json] (serveur https avec un mauvais options)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.network.servers.[1].options" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'objet options doit contenir un key pour le HTTPS."
+
+ Scenario: [service.json] (server https avec options.key vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.network.servers.[1].options.key" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'objet options doit contenir un key pour le HTTPS."
+
+ Scenario: [service.json] (serveur https avec un mauvais options.key)
+ Given a valid configuration
+ And with parameter "test.key" for attribute "application.network.servers.[1].options.key" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le fichier ne peut etre lu"
+
+ Scenario: [service.json] (server https avec options.cert vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.network.servers.[1].options.cert" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "L'objet options doit contenir un cert pour le HTTPS."
+
+ Scenario: [service.json] (serveur https avec un mauvais options.cert)
+ Given a valid configuration
+ And with parameter "test.cert" for attribute "application.network.servers.[1].options.cert" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Le fichier ne peut etre lu"
+
+ Scenario: [service.json] (network.cors absent)
+ Given a valid configuration
+ And without attribute "application.network.cors" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the server log should contain "Configuration incomplete: Objet 'application:network:cors' manquant !"
+
+ Scenario: [service.json] (network.cors vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.network.cors" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the server log should contain "Configuration incomplete: Objet 'application:network:cors' manquant !"
+
+ Scenario: [service.json] (network.cors mauvais)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.network.cors" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:network:cors:configuration' manquant !"
+
+ Scenario: [service.json] (network.cors.configuration vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.network.cors.configuration" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:network:cors:configuration' manquant !"
+
+ Scenario: [service.json] (network.cors.configuration mauvais)
+ Given a valid configuration
+ And with parameter "test.json" for attribute "application.network.cors.configuration" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Fichier de cors inexistant"
+
+ Scenario: [service.json] (application.network.cors.configuration sur un fichier incorrect)
+ Given a valid configuration
+ And a wrong JSON file "file.json"
+ And with parameter "file.json" for attribute "application.network.cors.configuration" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de cors de Road2"
+
+ Scenario: [service.json] (projections different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.projections" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:projections:directory' manquant !"
+
+ Scenario: [service.json] (projections vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.projections" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:projections' manquant !"
+
+ Scenario: [service.json] (projections absent)
+ Given a valid configuration
+ And without attribute "application.projections" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:projections' manquant !"
+
+ Scenario: [service.json] (projections.directory sur un dossier qui n'existe pas)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.projections.directory" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Dossier de projections inexistant"
+
+ Scenario: [service.json] (projections.directory vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.projections.directory" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:projections:directory' manquant !"
+
+ Scenario: [service.json] (projections.directory absent)
+ Given a valid configuration
+ And without attribute "application.projections.directory" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:projections:directory' manquant !"
+
+ # TODO
+ # Faire un scénario qui teste si les fichiers de projections.directory ne sont pas lisibles
diff --git a/test/functional/configuration/cucumber/features/configurationTest.feature b/test/functional/configuration/cucumber/features/configurationTest.feature
deleted file mode 100644
index 1daf995..0000000
--- a/test/functional/configuration/cucumber/features/configurationTest.feature
+++ /dev/null
@@ -1,1354 +0,0 @@
-# Tests fonctionnels de Road2 sur la configuration du serveur
-Feature: Road2 configuration
- Tests fonctionnels de Road2 sur la configuration du serveur
-
- Background:
- Given I have loaded all my test configuration
-
- Scenario: Configuration correcte
- Given a valid configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "La vérification de la configuration est terminée"
- Then the server log should not contain error
-
- Scenario: Mauvais argument de la ligne de commande (valeur vide)
- Given a valid configuration
- And with "" for command line parameter "ROAD2_CONF_FILE"
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Impossible de recuperer le chemin absolu du fichier de configuration"
-
- Scenario: Mauvais argument de la ligne de commande (fichier qui n'existe pas)
- Given a valid configuration
- And with "test1" for command line parameter "ROAD2_CONF_FILE"
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: fichier de configuration global inexistant"
-
- #TODO Fix: root peut toujours lire un fichier même si chmod 000
- #Scenario: Mauvais argument de la ligne de commande (fichier qui ne peut être lu)
- # Given a valid configuration
- # And a server configuration non readable
- # When I test the configuration
- # Then the configuration analysis should give an exit code 1
- # Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de configuration de Road2"
-
- Scenario: Pas d'argument ROAD2_CONF_FILE dans la ligne de commande
- Given a valid configuration
- And without parameter "ROAD2_CONF_FILE" in command line
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Aucun fichier de configuration. Utiliser la variable d'environnement $ROAD2_CONF_FILE ou l'option --ROAD2_CONF_FILE lors de l'initialisation du serveur."
-
- Scenario: Argument inutile dans la ligne de commande
- Given a valid configuration
- And with "test" for command line parameter "ROAD2_TEST"
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "La vérification de la configuration est terminée"
- Then the server log should not contain error
-
- Scenario: [server.json] (application different)
- Given a valid configuration
- And with parameter "test" for attribute "application" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvais configuration: 'application.logs' absent"
-
- Scenario: [server.json] (application vide)
- Given a valid configuration
- And with parameter "" for attribute "application" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvais configuration: 'application' absent"
-
- Scenario: [server.json] (application absent)
- Given a valid configuration
- And without attribute "application" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvais configuration: 'application' absent"
-
- Scenario: [server.json] (application.logs different)
- Given a valid configuration
- And with parameter "test" for attribute "application.logs" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvais configuration: 'application.logs.configuration' absent"
-
- Scenario: [server.json] (application.logs vide)
- Given a valid configuration
- And with parameter "" for attribute "application.logs" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvais configuration: 'application.logs' absent"
-
- Scenario: [server.json] (application.logs absent)
- Given a valid configuration
- And without attribute "application.logs" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvais configuration: 'application.logs' absent"
-
- Scenario: [server.json] (application.logs.configuration different)
- Given a valid configuration
- And with parameter "test" for attribute "application.logs.configuration" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: fichier de configuration des logs inexistant"
-
- Scenario: [server.json] (application.logs.configuration vide)
- Given a valid configuration
- And with parameter "" for attribute "application.logs.configuration" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvais configuration: 'application.logs.configuration' absent"
-
- Scenario: [server.json] (application.logs.configuration absent)
- Given a valid configuration
- And without attribute "application.logs.configuration" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvais configuration: 'application.logs.configuration' absent"
-
- Scenario: [server.json] (application.logs.configuration sur un fichier non lisible)
- Given a valid configuration
- And a file "file.json" non readable
- And with parameter "file.json" for attribute "application.logs.configuration" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de configuration des logs"
-
- Scenario: [server.json] (application.logs.configuration sur un fichier vide)
- Given a valid configuration
- And a file "file.json"
- And with parameter "file.json" for attribute "application.logs.configuration" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de configuration des logs"
-
- Scenario: [server.json] (application.logs.configuration sur un fichier incorrect)
- Given a valid configuration
- And a wrong JSON file "file.json"
- And with parameter "file.json" for attribute "application.logs.configuration" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de configuration des logs"
-
- Scenario: [server.json] (name different)
- Given a valid configuration
- And with parameter "test" for attribute "application.name" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [server.json] (name vide)
- Given a valid configuration
- And with parameter "" for attribute "application.name" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
-
- Scenario: [server.json] (name absent)
- Given a valid configuration
- And without attribute "application.name" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
-
- Scenario: [server.json] (title different)
- Given a valid configuration
- And with parameter "test" for attribute "application.title" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should not contain error
-
- Scenario: [server.json] (title vide)
- Given a valid configuration
- And with parameter "" for attribute "application.title" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:title' manquant !"
-
- Scenario: [server.json] (title absent)
- Given a valid configuration
- And without attribute "application.title" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:title' manquant !"
-
- Scenario: [server.json] (description different)
- Given a valid configuration
- And with parameter "test" for attribute "application.description" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should not contain error
-
- Scenario: [server.json] (description vide)
- Given a valid configuration
- And with parameter "" for attribute "application.description" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:description' manquant !"
-
- Scenario: [server.json] (description absent)
- Given a valid configuration
- And without attribute "application.description" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:description' manquant !"
-
- Scenario: [server.json] (provider different)
- Given a valid configuration
- And with parameter "test" for attribute "application.provider" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:provider:name' manquant !"
-
- Scenario: [server.json] (provider vide)
- Given a valid configuration
- And with parameter "" for attribute "application.provider" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should not contain error
- Then the server log should contain "Configuration incomplete: Objet 'application:provider' manquant !"
-
- Scenario: [server.json] (provider absent)
- Given a valid configuration
- And without attribute "application.provider" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should not contain error
- Then the server log should contain "Configuration incomplete: Objet 'application:provider' manquant !"
-
- Scenario: [server.json] (provider.name different)
- Given a valid configuration
- And with parameter "test" for attribute "application.provider.name" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should not contain error
-
- Scenario: [server.json] (provider.name vide)
- Given a valid configuration
- And with parameter "" for attribute "application.provider.name" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:provider:name' manquant !"
-
- Scenario: [server.json] (provider.name absent)
- Given a valid configuration
- And without attribute "application.provider.name" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:provider:name' manquant !"
-
- Scenario: [server.json] (provider.site different)
- Given a valid configuration
- And with parameter "test" for attribute "application.provider.site" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should not contain error
-
- Scenario: [server.json] (provider.site vide)
- Given a valid configuration
- And with parameter "" for attribute "application.provider.site" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "Le champ 'application:provider:site' n'est pas renseigne."
-
- Scenario: [server.json] (provider.site absent)
- Given a valid configuration
- And without attribute "application.provider.site" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "Le champ 'application:provider:site' n'est pas renseigne."
-
- Scenario: [server.json] (provider.mail different)
- Given a valid configuration
- And with parameter "test" for attribute "application.provider.mail" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should not contain error
-
- Scenario: [server.json] (provider.mail vide)
- Given a valid configuration
- And with parameter "" for attribute "application.provider.mail" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:provider:mail' manquant !"
-
- Scenario: [server.json] (provider.mail absent)
- Given a valid configuration
- And without attribute "application.provider.mail" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:provider:mail' manquant !"
-
- Scenario: [server.json] (operations different)
- Given a valid configuration
- And with parameter "test" for attribute "application.operations" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:operations:directory' manquant !"
-
- Scenario: [server.json] (operations vide)
- Given a valid configuration
- And with parameter "" for attribute "application.operations" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:operations' manquant !"
-
- Scenario: [server.json] (operations absent)
- Given a valid configuration
- And without attribute "application.operations" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:operations' manquant !"
-
- Scenario: [server.json] (operations.directory sur un dossier qui n'existe pas)
- Given a valid configuration
- And with parameter "test" for attribute "application.operations.directory" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Le dossier des operations n'existe pas"
-
- Scenario: [server.json] (operations.directory vide)
- Given a valid configuration
- And with parameter "" for attribute "application.operations.directory" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:operations:directory' manquant !"
-
- Scenario: [server.json] (operations.directory absent)
- Given a valid configuration
- And without attribute "application.operations.directory" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:operations:directory' manquant !"
-
- # TODO
- # Faire un scénario qui teste si les fichiers de operations.directory ne sont pas lisibles
-
- Scenario: [server.json] (operations.parameters different)
- Given a valid configuration
- And with parameter "test" for attribute "application.operations.parameters" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:operations:parameters:directory' manquant !"
-
- Scenario: [server.json] (operations.parameters vide)
- Given a valid configuration
- And with parameter "" for attribute "application.operations.parameters" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:operations:parameters' manquant !"
-
- Scenario: [server.json] (operations.parameters absent)
- Given a valid configuration
- And without attribute "application.operations.parameters" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:operations:parameters' manquant !"
-
- Scenario: [server.json] (operations.parameters.directory sur un dossier qui n'existe pas)
- Given a valid configuration
- And with parameter "test" for attribute "application.operations.parameters.directory" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Le dossier des parametres n'existe pas"
-
- Scenario: [server.json] (operations.parameters.directory vide)
- Given a valid configuration
- And with parameter "" for attribute "application.operations.parameters.directory" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:operations:parameters:directory' manquant !"
-
- Scenario: [server.json] (operations.parameters.directory absent)
- Given a valid configuration
- And without attribute "application.operations.parameters.directory" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:operations:parameters:directory' manquant !"
-
- # TODO
- # Faire un scénario qui teste si les fichiers de operations.parameters.directory ne sont pas lisibles
-
- Scenario: [server.json] (resources different)
- Given a valid configuration
- And with parameter "test" for attribute "application.resources" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:resources:directories' manquant !"
-
- Scenario: [server.json] (resources vide)
- Given a valid configuration
- And with parameter "" for attribute "application.resources" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:resources' manquant !"
-
- Scenario: [server.json] (resources absent)
- Given a valid configuration
- And without attribute "application.resources" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:resources' manquant !"
-
- Scenario: [server.json] (resources.directories est une chaine de caracteres)
- Given a valid configuration
- And with parameter "test" for attribute "application.resources.directories" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:resources:directories' n'est pas un tableau !"
-
- # TODO
- # Tester le paramètre resources.directories sur un tableau vide
-
- Scenario: [server.json] (resources.directories sur un dossier qui n'existe pas et en chemin relatif)
- Given a valid configuration
- And with parameter "test" for attribute "application.resources.directories.[1]" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "Mauvaise configuration: Le dossier n'existe pas:"
-
- Scenario: [server.json] (resources.directories sur deux dossiers qui n'existent pas et en chemins relatifs)
- Given a valid configuration
- And with parameter "test" for attribute "application.resources.directories.[0]" in server configuration
- And with parameter "test1" for attribute "application.resources.directories.[1]" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:resources:directories' ne pointe vers aucune ressource disponible !"
-
- Scenario: [server.json] (resources.directories contient un élément vide)
- Given a valid configuration
- And with parameter "" for attribute "application.resources.directories.[1]" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "Mauvaise configuration: Champ 'application:resources:directories' contient un élément vide"
-
- Scenario: [server.json] (resources.directories contient que des éléments vides)
- Given a valid configuration
- And with parameter "" for attribute "application.resources.directories.[0]" in server configuration
- And with parameter "" for attribute "application.resources.directories.[1]" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:resources:directories' ne pointe vers aucune ressource disponible !"
-
- Scenario: [server.json] (resources.directories absent)
- Given a valid configuration
- And without attribute "application.resources.directories" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:resources:directories' manquant !"
-
- # TODO
- # Tester un dossier de ressources dont une des ressources ne peut être lues
-
- Scenario: [server.json] (network different)
- Given a valid configuration
- And with parameter "test" for attribute "application.network" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:network:servers' manquant !"
-
- Scenario: [server.json] (network vide)
- Given a valid configuration
- And with parameter "" for attribute "application.network" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:network' manquant !"
-
- Scenario: [server.json] (network absent)
- Given a valid configuration
- And without attribute "application.network" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:network' manquant !"
-
- Scenario: [server.json] (network.servers different)
- Given a valid configuration
- And with parameter "test" for attribute "application.network.servers" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:network:servers' n'est pas un tableau !"
-
- Scenario: [server.json] (network.servers vide)
- Given a valid configuration
- And with parameter "" for attribute "application.network.servers" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:network:servers' manquant !"
-
- Scenario: [server.json] (network.servers absent)
- Given a valid configuration
- And without attribute "application.network.servers" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:network:servers' manquant !"
-
- # TODO: tester le tableau vide pour network.servers
-
- Scenario: [server.json] (network.servers contient une chaîne de caractères)
- Given a valid configuration
- And with parameter "test" for attribute "application.network.servers.[0]" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration d'un serveur !"
-
- Scenario: [server.json] (network.servers contient que des chaînes de caractères)
- Given a valid configuration
- And with parameter "test" for attribute "application.network.servers.[0]" in server configuration
- And with parameter "test" for attribute "application.network.servers.[1]" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration d'un serveur !"
-
- Scenario: [server.json] (serveur http avec id different)
- Given a valid configuration
- And with parameter "test" for attribute "application.network.servers.[0].id" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should not contain error
-
- Scenario: [server.json] (serveur http sans id)
- Given a valid configuration
- And without attribute "application.network.servers.[0].id" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration du serveur n'indique aucun id"
-
- Scenario: [server.json] (serveur http avec un mauvais https)
- Given a valid configuration
- And with parameter "test" for attribute "application.network.servers.[0].https" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre https est mal renseigné. Valeurs disponibles: 'true' ou 'false'."
-
- Scenario: [server.json] (serveur http sans https)
- Given a valid configuration
- And without attribute "application.network.servers.[0].https" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration du serveur n'indique pas la securisation du serveur"
-
- Scenario: [server.json] (serveur http avec un mauvais host)
- Given a valid configuration
- And with parameter "test" for attribute "application.network.servers.[0].host" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'host du serveur est mal renseigne."
-
- Scenario: [server.json] (serveur http avec un autre host)
- Given a valid configuration
- And with parameter "127.0.0.1" for attribute "application.network.servers.[0].host" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [server.json] (serveur http sans host)
- Given a valid configuration
- And without attribute "application.network.servers.[0].host" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration du serveur n'indique aucun host"
-
- Scenario: [server.json] (serveur http avec un mauvais port)
- Given a valid configuration
- And with parameter "test" for attribute "application.network.servers.[0].port" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le port est mal renseigne."
-
- Scenario: [server.json] (serveur http avec un port trop eleve)
- Given a valid configuration
- And with parameter "65537" for attribute "application.network.servers.[0].port" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le port est mal renseigne: Numero de port invalide"
-
- Scenario: [server.json] (serveur http avec un autre port)
- Given a valid configuration
- And with parameter "8888" for attribute "application.network.servers.[0].port" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [server.json] (serveur http sans port)
- Given a valid configuration
- And without attribute "application.network.servers.[0].port" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration du serveur n'indique aucun port"
-
- Scenario: [server.json] (serveur https avec un port different)
- Given a valid configuration
- And with parameter "445" for attribute "application.network.servers.[1].port" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [server.json] (serveur https sans options)
- Given a valid configuration
- And without attribute "application.network.servers.[1].options" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Serveur https sans options."
-
- Scenario: [server.json] (server https avec options vide)
- Given a valid configuration
- And with parameter "" for attribute "application.network.servers.[1].options" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Serveur https sans options."
-
- Scenario: [server.json] (serveur https avec un mauvais options)
- Given a valid configuration
- And with parameter "test" for attribute "application.network.servers.[1].options" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'objet options doit contenir un key pour le HTTPS."
-
- Scenario: [server.json] (server https avec options.key vide)
- Given a valid configuration
- And with parameter "" for attribute "application.network.servers.[1].options.key" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'objet options doit contenir un key pour le HTTPS."
-
- Scenario: [server.json] (serveur https avec un mauvais options.key)
- Given a valid configuration
- And with parameter "test.key" for attribute "application.network.servers.[1].options.key" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le fichier ne peut etre lu"
-
- Scenario: [server.json] (server https avec options.cert vide)
- Given a valid configuration
- And with parameter "" for attribute "application.network.servers.[1].options.cert" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'objet options doit contenir un cert pour le HTTPS."
-
- Scenario: [server.json] (serveur https avec un mauvais options.cert)
- Given a valid configuration
- And with parameter "test.cert" for attribute "application.network.servers.[1].options.cert" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le fichier ne peut etre lu"
-
- Scenario: [server.json] (network.cors absent)
- Given a valid configuration
- And without attribute "application.network.cors" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "Configuration incomplete: Objet 'application:network:cors' manquant !"
-
- Scenario: [server.json] (network.cors vide)
- Given a valid configuration
- And with parameter "" for attribute "application.network.cors" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "Configuration incomplete: Objet 'application:network:cors' manquant !"
-
- Scenario: [server.json] (network.cors mauvais)
- Given a valid configuration
- And with parameter "test" for attribute "application.network.cors" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:network:cors:configuration' manquant !"
-
- Scenario: [server.json] (network.cors.configuration vide)
- Given a valid configuration
- And with parameter "" for attribute "application.network.cors.configuration" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:network:cors:configuration' manquant !"
-
- Scenario: [server.json] (network.cors.configuration mauvais)
- Given a valid configuration
- And with parameter "test.json" for attribute "application.network.cors.configuration" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Fichier de cors inexistant"
-
- Scenario: [server.json] (application.network.cors.configuration sur un fichier incorrect)
- Given a valid configuration
- And a wrong JSON file "file.json"
- And with parameter "file.json" for attribute "application.network.cors.configuration" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de cors de Road2"
-
- Scenario: [server.json] (projections different)
- Given a valid configuration
- And with parameter "test" for attribute "application.projections" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:projections:directory' manquant !"
-
- Scenario: [server.json] (projections vide)
- Given a valid configuration
- And with parameter "" for attribute "application.projections" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:projections' manquant !"
-
- Scenario: [server.json] (projections absent)
- Given a valid configuration
- And without attribute "application.projections" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Objet 'application:projections' manquant !"
-
- Scenario: [server.json] (projections.directory sur un dossier qui n'existe pas)
- Given a valid configuration
- And with parameter "test" for attribute "application.projections.directory" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Dossier de projections inexistant"
-
- Scenario: [server.json] (projections.directory vide)
- Given a valid configuration
- And with parameter "" for attribute "application.projections.directory" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:projections:directory' manquant !"
-
- Scenario: [server.json] (projections.directory absent)
- Given a valid configuration
- And without attribute "application.projections.directory" in server configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: Champ 'application:projections:directory' manquant !"
-
- # TODO
- # Faire un scénario qui teste si les fichiers de projections.directory ne sont pas lisibles
-
- Scenario: [log.json] (mainConf different)
- Given a valid configuration
- And with parameter "test" for attribute "mainConf" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration des logs dans mainConf"
-
- Scenario: [log.json] (mainConf vide)
- Given a valid configuration
- And with parameter "" for attribute "mainConf" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mausvaise configuration pour les logs: 'mainConf' absent"
-
- Scenario: [log.json] (mainConf absent)
- Given a valid configuration
- And without attribute "mainConf" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mausvaise configuration pour les logs: 'mainConf' absent"
-
- Scenario: [log.json] (httpConf different)
- Given a valid configuration
- And with parameter "test" for attribute "httpConf" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf.level' absent"
-
- Scenario: [log.json] (httpConf vide)
- Given a valid configuration
- And with parameter "" for attribute "httpConf" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf' absent"
-
- Scenario: [log.json] (httpConf absent)
- Given a valid configuration
- And without attribute "httpConf" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf' absent"
-
- Scenario: [log.json] (httpConf.level different)
- Given a valid configuration
- And with parameter "test" for attribute "httpConf.level" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [log.json] (httpConf.level vide)
- Given a valid configuration
- And with parameter "" for attribute "httpConf.level" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf.level' absent"
-
- Scenario: [log.json] (httpConf.level absent)
- Given a valid configuration
- And without attribute "httpConf.level" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf.level' absent"
-
- Scenario: [log.json] (httpConf.format different)
- Given a valid configuration
- And with parameter "test" for attribute "httpConf.format" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [log.json] (httpConf.format vide)
- Given a valid configuration
- And with parameter "" for attribute "httpConf.format" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf.format' absent"
-
- Scenario: [log.json] (httpConf.format absent)
- Given a valid configuration
- And without attribute "httpConf.format" in log configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mausvaise configuration pour les logs: 'httpConf.format' absent"
-
- Scenario: [cors.json] Contenu different
- Given a valid configuration
- And with parameter "127.0.0.1" for attribute "origin" in cors configuration
- And with parameter "GET,POST" for attribute "methods" in cors configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- And the server log should not contain error
-
- Scenario: [cors.json] Contenu mauvais
- Given a valid configuration
- And with parameter "TEST" for attribute "methods" in cors configuration
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- And the server log should not contain error
-
- Scenario: [projection.json] JSON invalide
- Given a valid configuration
- And a wrong JSON file "./projections/test.json"
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Mauvaise configuration: impossible de lire ou de parser le fichier de projection"
-
- Scenario: [projection.json] JSON vide
- Given a valid configuration
- And without attribute "projectionsList" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration des projections ne contient pas de liste"
-
- Scenario: [projection.json] projectionsList absent
- Given a valid configuration
- And without attribute "projectionsList" in "projection.json" projection
- And with parameter "test" for attribute "projections" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration des projections ne contient pas de liste"
-
- Scenario: [projection.json] projectionsList different
- Given a valid configuration
- And with parameter "test" for attribute "projectionsList" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'attribut projectionsList de la configuration n'est pas un tableau"
-
- Scenario: [projection.json] projectionsList est un tableau vide
- Given a valid configuration
- And without attribute "projectionsList.[6]" in "projection.json" projection
- And without attribute "projectionsList.[5]" in "projection.json" projection
- And without attribute "projectionsList.[4]" in "projection.json" projection
- And without attribute "projectionsList.[3]" in "projection.json" projection
- And without attribute "projectionsList.[2]" in "projection.json" projection
- And without attribute "projectionsList.[1]" in "projection.json" projection
- And without attribute "projectionsList.[0]" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'attribut projectionsList de la configuration est un tableau vide"
-
- Scenario: [projection.json] une configuration de projection vide
- Given a valid configuration
- And without attribute "projectionsList.[0].id" in "projection.json" projection
- And without attribute "projectionsList.[0].parameters" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration de la projection n'a pas d'id"
-
- Scenario: [projection.json] une configuration de projection sans id
- Given a valid configuration
- And without attribute "projectionsList.[0].id" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration de la projection n'a pas d'id"
-
- Scenario: [projection.json] une configuration de projection sans parametre
- Given a valid configuration
- And without attribute "projectionsList.[0].parameters" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration de la projection n'a pas de parametres"
-
- Scenario: [projection.json] une configuration de projection différentes
- Given a valid configuration
- And with parameter "test" for attribute "projectionsList.[0]" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration de la projection n'a pas d'id"
-
- Scenario: [projection.json] projection.id différent pour une projection inutilisée dans les topologies
- Given a valid configuration
- And with parameter "test" for attribute "projectionsList.[2].id" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [projection.json] projection.id différent pour une projection utilisée dans les topologies
- Given a valid configuration
- And with parameter "test" for attribute "projectionsList.[0].id" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
-
- Scenario: [projection.json] projection.id vide
- Given a valid configuration
- And with parameter "" for attribute "projectionsList.[2].id" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration de la projection n'a pas d'id"
-
- Scenario: [projection.json] projection.parameters différent
- Given a valid configuration
- And with parameter "test" for attribute "projectionsList.[0].parameters" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Impossible de charger la projection dans proj4"
-
- Scenario: [projection.json] projection.parameters vide
- Given a valid configuration
- And with parameter "" for attribute "projectionsList.[0].parameters" in "projection.json" projection
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La configuration de la projection n'a pas de parametres"
-
- Scenario: [operations] id différent
- Given a valid configuration
- And with parameter "test" for attribute "id" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation indiquee n'est pas disponible"
-
- Scenario: [operations] id vide
- Given a valid configuration
- And with parameter "" for attribute "id" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation ne contient pas d'id"
-
- Scenario: [operations] id absent
- Given a valid configuration
- And without attribute "id" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation ne contient pas d'id"
-
- Scenario: [operations] name différent
- Given a valid configuration
- And with parameter "test" for attribute "name" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [operations] name vide
- Given a valid configuration
- And with parameter "" for attribute "name" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation ne contient pas d'attribut name"
-
- Scenario: [operations] name absent
- Given a valid configuration
- And without attribute "name" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation ne contient pas d'attribut name"
-
- Scenario: [operations] description différent
- Given a valid configuration
- And with parameter "test" for attribute "description" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [operations] description vide
- Given a valid configuration
- And with parameter "" for attribute "description" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation ne contient pas d'attribut description"
-
- Scenario: [operations] description absent
- Given a valid configuration
- And without attribute "description" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation ne contient pas d'attribut description"
-
- Scenario: [operations] parameters différent
- Given a valid configuration
- And with parameter "test" for attribute "parameters" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Les parametres de l'operation ne sont pas dans un tableau"
-
- Scenario: [operations] parameters vide
- Given a valid configuration
- And with parameter "" for attribute "parameters" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation ne contient pas d'attribut parameters"
-
- Scenario: [operations] parameters absent
- Given a valid configuration
- And without attribute "parameters" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation ne contient pas d'attribut parameters"
-
- Scenario: [operations] parameters est un tableau vide
- Given a valid configuration
- And without attribute "parameters.[13]" in "route.json" operation
- And without attribute "parameters.[12]" in "route.json" operation
- And without attribute "parameters.[11]" in "route.json" operation
- And without attribute "parameters.[10]" in "route.json" operation
- And without attribute "parameters.[9]" in "route.json" operation
- And without attribute "parameters.[8]" in "route.json" operation
- And without attribute "parameters.[7]" in "route.json" operation
- And without attribute "parameters.[6]" in "route.json" operation
- And without attribute "parameters.[5]" in "route.json" operation
- And without attribute "parameters.[4]" in "route.json" operation
- And without attribute "parameters.[3]" in "route.json" operation
- And without attribute "parameters.[2]" in "route.json" operation
- And without attribute "parameters.[1]" in "route.json" operation
- And without attribute "parameters.[0]" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le tableau des parametres est vide"
-
- Scenario: [operations] parameters est incomplet
- Given a valid configuration
- And without attribute "parameters.[0]" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le nombre de parametres presents n'est pas celui attendu"
-
- Scenario: [operations] parameters contient un element different
- Given a valid configuration
- And with parameter "test" for attribute "parameters.[0]" in "route.json" operation
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation précise un parametre qui n'est pas disponible"
-
- Scenario: [parameters] id différent
- Given a valid configuration
- And with parameter "test" for attribute "id" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "L'operation précise un parametre qui n'est pas disponible: intermediates"
-
- Scenario: [parameters] id vide
- Given a valid configuration
- And with parameter "" for attribute "id" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'id"
-
- Scenario: [parameters] id absent
- Given a valid configuration
- And without attribute "id" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'id"
-
- Scenario: [parameters] id deja utilise
- Given a valid configuration
- And with parameter "test" for attribute "id" in "start.json" parameter
- And with parameter "test" for attribute "id" in "end.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre contenant l'id test est deja reference"
-
- Scenario: [parameters] name différent
- Given a valid configuration
- And with parameter "test" for attribute "name" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] name vide
- Given a valid configuration
- And with parameter "" for attribute "name" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'attribut name"
-
- Scenario: [parameters] name absent
- Given a valid configuration
- And without attribute "name" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'attribut name"
-
- Scenario: [parameters] description différent
- Given a valid configuration
- And with parameter "test" for attribute "description" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] description vide
- Given a valid configuration
- And with parameter "" for attribute "description" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'attribut description"
-
- Scenario: [parameters] description absent
- Given a valid configuration
- And without attribute "description" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'attribut description"
-
- Scenario: [parameters] required différent
- Given a valid configuration
- And with parameter "true" for attribute "required" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] required invalide
- Given a valid configuration
- And with parameter "test" for attribute "required" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre contient un attribut required mal configure"
-
- Scenario: [parameters] required vide
- Given a valid configuration
- And with parameter "" for attribute "required" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'attribut required"
-
- Scenario: [parameters] required absent
- Given a valid configuration
- And without attribute "required" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'attribut required"
-
- Scenario: [parameters] defaultValue différent (true donc probleme apres)
- Given a valid configuration
- And with parameter "true" for attribute "defaultValue" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas de valeur par defaut alors qu'il doit en avoir un"
-
- Scenario: [parameters] defaultValue invalide
- Given a valid configuration
- And with parameter "test" for attribute "defaultValue" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre contient un attribut defaultValue mal configure"
-
- Scenario: [parameters] defaultValue vide
- Given a valid configuration
- And with parameter "" for attribute "defaultValue" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'attribut defaultValue"
-
- Scenario: [parameters] defaultValue absent
- Given a valid configuration
- And without attribute "defaultValue" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'attribut defaultValue"
-
- Scenario: [parameters] example différent
- Given a valid configuration
- And with parameter "test" for attribute "example" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] example vide
- Given a valid configuration
- And with parameter "" for attribute "example" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "Le parametre ne contient pas d'exemple"
-
- Scenario: [parameters] example absent
- Given a valid configuration
- And without attribute "example" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
- Then the server log should contain "Le parametre ne contient pas d'exemple"
-
- Scenario: [parameters] type différent
- Given a valid configuration
- And with parameter "boolean" for attribute "type" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "La valeur du parametre est incorrecte par rapport à son type: boolean"
-
- Scenario: [parameters] type invalide
- Given a valid configuration
- And with parameter "test" for attribute "type" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le type du parametre est incorrect"
-
- Scenario: [parameters] type vide
- Given a valid configuration
- And with parameter "" for attribute "type" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'attribut type"
-
- Scenario: [parameters] type absent
- Given a valid configuration
- And without attribute "type" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre ne contient pas d'attribut type"
-
- Scenario: [parameters] min différent et required true
- Given a valid configuration
- And with parameter "1" for attribute "min" in "intermediates.json" parameter
- And with parameter "true" for attribute "required" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] min différent et required false
- Given a valid configuration
- And with parameter "1" for attribute "min" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre min est incorrect: valeur superieure a 0"
-
- Scenario: [parameters] min a 0 et required true
- Given a valid configuration
- And with parameter "0" for attribute "min" in "intermediates.json" parameter
- And with parameter "true" for attribute "required" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre min est incorrect: valeur inferieure a 1"
-
- Scenario: [parameters] min invalide
- Given a valid configuration
- And with parameter "test" for attribute "min" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre min est incorrect: valeur non entiere"
-
- Scenario: [parameters] min vide
- Given a valid configuration
- And with parameter "" for attribute "min" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] min absent
- Given a valid configuration
- And without attribute "min" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] max différent
- Given a valid configuration
- And with parameter "1" for attribute "max" in "intermediates.json" parameter
- And with parameter "true" for attribute "required" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] max a 0
- Given a valid configuration
- And with parameter "0" for attribute "max" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre max est incorrect: valeur inferieure a 1"
-
- Scenario: [parameters] max invalide
- Given a valid configuration
- And with parameter "test" for attribute "max" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre max est incorrect: valeur non entiere"
-
- Scenario: [parameters] max vide
- Given a valid configuration
- And with parameter "" for attribute "max" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] max absent
- Given a valid configuration
- And without attribute "max" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] max plus petit que min
- Given a valid configuration
- And with parameter "1" for attribute "max" in "intermediates.json" parameter
- And with parameter "2" for attribute "min" in "intermediates.json" parameter
- And with parameter "true" for attribute "required" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre max est incorrect: valeur inferieure au parametre min"
-
- Scenario: [parameters] explode différent (true)
- Given a valid configuration
- And with parameter "true" for attribute "explode" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] explode invalide
- Given a valid configuration
- And with parameter "test" for attribute "explode" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre explode est incorrect"
-
- Scenario: [parameters] explode vide
- Given a valid configuration
- And with parameter "" for attribute "explode" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] explode absent
- Given a valid configuration
- And without attribute "explode" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 0
-
- Scenario: [parameters] style invalide alors que explode false
- Given a valid configuration
- And with parameter "test" for attribute "style" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre style est incorrect"
-
- Scenario: [parameters] style vide alors que explode false
- Given a valid configuration
- And with parameter "" for attribute "style" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre style n'est pas present alors que explode=false"
-
- Scenario: [parameters] style vide alors que explode false
- Given a valid configuration
- And without attribute "style" in "intermediates.json" parameter
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- Then the server log should contain "Le parametre style n'est pas present alors que explode=false"
-
- Scenario: [osrm resource] resource absent
- Given a valid configuration
- And without attribute "resource" in "data-osm.resource" resource
- When I test the configuration
- Then the configuration analysis should give an exit code 1
- # TODO : avoir plusieurs ressources dans le dossier pour qu'une d'entre elles marche
- # Then the configuration analysis should give an exit code 0
- # Then the server log should contain "Erreur lors de la lecture de la ressource"
-
- Scenario: [osrm resource] id different
- Given a valid configuration
- And with parameter "test" for attribute "resource.id" in "data-osm.resource" resource
- When I test the configuration
- Then the configuration analysis should give an exit code 0
diff --git a/test/functional/configuration/cucumber/features/support/steps.js b/test/functional/configuration/cucumber/features/support/steps.js
index a72869a..ab6a7f8 100644
--- a/test/functional/configuration/cucumber/features/support/steps.js
+++ b/test/functional/configuration/cucumber/features/support/steps.js
@@ -3,6 +3,7 @@ const assert = require('assert');
After( function () {
this.cleanTmpDirectory();
+ // this.killChildProcess();
});
Given("I have loaded all my test configuration", function() {
@@ -29,6 +30,14 @@ Given("with parameter {string} for attribute {string} in server configuration",
this.modifyServerConfiguration(value, attribute, "", "server", "modify");
});
+Given("with parameter {string} for attribute {string} in service configuration", function(value, attribute) {
+ this.modifyServerConfiguration(value, attribute, "", "service", "modify");
+});
+
+Given("without attribute {string} in service configuration", function(attribute) {
+ this.modifyServerConfiguration("", attribute, "", "service", "delete");
+});
+
Given("without attribute {string} in server configuration", function(attribute) {
this.modifyServerConfiguration("", attribute, "", "server", "delete");
});
@@ -49,12 +58,12 @@ Given("a wrong JSON file {string}", function(relativeFilePath) {
this.createWrongJSONFile(relativeFilePath);
});
-Given("with parameter {string} for attribute {string} in log configuration", function(value, attribute) {
- this.modifyServerConfiguration(value, attribute, "", "log", "modify");
+Given("with parameter {string} for attribute {string} in service log configuration", function(value, attribute) {
+ this.modifyServerConfiguration(value, attribute, "", "log-service", "modify");
});
-Given("without attribute {string} in log configuration", function(attribute) {
- this.modifyServerConfiguration("", attribute, "", "log", "delete");
+Given("without attribute {string} in service log configuration", function(attribute) {
+ this.modifyServerConfiguration("", attribute, "", "log-service", "delete");
});
Given("with parameter {string} for attribute {string} in cors configuration", function(value, attribute) {
@@ -131,7 +140,7 @@ Then("the server log should not contain {string}", function(message) {
assert.equal(this.findInServerLog(message), false);
});
-Then("the server log should not contain error", function() {
+Then("the command log should not contain error", function() {
assert.equal(this._stderr, "");
});
diff --git a/test/functional/configuration/cucumber/features/support/world.js b/test/functional/configuration/cucumber/features/support/world.js
index eb8cf2f..50a8c30 100644
--- a/test/functional/configuration/cucumber/features/support/world.js
+++ b/test/functional/configuration/cucumber/features/support/world.js
@@ -44,11 +44,17 @@ class road2World {
// Contenu du server.json pour le test en cours
this._serverConf = {};
+ // Contenu du service.json pour le test en cours
+ this._serviceConf = {};
+
// Boolean pour savoir si le fichier de conf sera lisible ou pas
this._serverReadable = true;
- // Contenu du log4js.json pour le test en cours
- this._logConf = {};
+ // Contenu du log4js-administration.json pour le test en cours
+ this._logAdminConf = {};
+
+ // Contenu du log4js-service.json pour le test en cours
+ this._logServiceConf = {};
// Contenu du cors.json pour le test en cours
this._corsConf = {};
@@ -68,6 +74,9 @@ class road2World {
// Dossier temporaire pour le test en cours
this._tmpDirConf = "";
+ // Instance de childProcess pour le test en cours
+ this._childProcess;
+
// Code de retour de Road2 pour le test en cours
this._code;
@@ -152,22 +161,36 @@ class road2World {
throw "Can't parse server conf: " + error;
}
- // Lecture du log4js.json
+ // Lecture du log4js-administration.json
+ try {
+ this._logAdminConf = JSON.parse(fs.readFileSync(this._serverConf.administration.logs.configuration));
+ } catch(error) {
+ throw "Can't parse log4js admin conf: " + error;
+ }
+
+ // Lecture du service.json
try {
- this._logConf = JSON.parse(fs.readFileSync(this._serverConf.application.logs.configuration));
+ this._serviceConf = JSON.parse(fs.readFileSync(this._serverConf.administration.services[0].configuration));
+ } catch(error) {
+ throw "Can't parse log conf: " + error;
+ }
+
+ // Lecture du log4js-service.json
+ try {
+ this._logServiceConf = JSON.parse(fs.readFileSync(this._serviceConf.application.logs.configuration));
} catch(error) {
throw "Can't parse log conf: " + error;
}
// Lecture du cors.json
try {
- this._corsConf = JSON.parse(fs.readFileSync(this._serverConf.application.network.cors.configuration));
+ this._corsConf = JSON.parse(fs.readFileSync(this._serviceConf.application.network.cors.configuration));
} catch(error) {
throw "Can't parse cors conf: " + error;
}
// Lecture des projections
- let projDir = this._serverConf.application.projections.directory;
+ let projDir = this._serviceConf.application.projections.directory;
try {
projDirFiles = fs.readdirSync(projDir);
@@ -184,7 +207,7 @@ class road2World {
}
// Lecture des operations
- let operationsDir = this._serverConf.application.operations.directory;
+ let operationsDir = this._serviceConf.application.operations.directory;
try {
operationsDirFiles = fs.readdirSync(operationsDir);
@@ -201,7 +224,7 @@ class road2World {
}
// Lecture des parametres
- let parametersDir = this._serverConf.application.operations.parameters.directory;
+ let parametersDir = this._serviceConf.application.operations.parameters.directory;
try {
parametersDirFiles = fs.readdirSync(parametersDir);
@@ -218,7 +241,7 @@ class road2World {
}
// Lecture des ressources
- let resourceDir = this._serverConf.application.resources.directories;
+ let resourceDir = this._serviceConf.application.resources.directories;
// Pour chaque dossier, on récupère l'ensemble des fichiers
for (let i = 0; i < resourceDir.length; i++) {
@@ -248,29 +271,35 @@ class road2World {
// 3. On modifie la configuration pour qu'elle puisse être copiée dans l'espace temporaire
// mais elle pourra de nouveau être modifiée dans la suite du scénario
- // Emplacement du log4js.json
- this._serverConf.application.logs.configuration = path.join(this._tmpDirConf, "log4js.json");
+ // Emplacement du service.json
+ this._serverConf.administration.services[0].configuration = path.join(this._tmpDirConf, "service.json");
+
+ // Emplacement du log4js-administration.json
+ this._serverConf.administration.logs.configuration = path.join(this._tmpDirConf, "log4js-administration.json");
+
+ // Emplacement du log4js-service.json
+ this._serviceConf.application.logs.configuration = path.join(this._tmpDirConf, "log4js-service.json");
// Emplacement des ressources
- this._serverConf.application.resources.directories = newResourcesDirectories;
+ this._serviceConf.application.resources.directories = newResourcesDirectories;
// Emplacement des projections
let curProjDir = path.join(this._tmpDirConf, "projections");
- this._serverConf.application.projections.directory = curProjDir;
+ this._serviceConf.application.projections.directory = curProjDir;
if (!fs.existsSync(curProjDir)) {
fs.mkdirSync(curProjDir, {recursive: true, mode: "766"});
}
// Emplacement des operations
let curOperationsDir = path.join(this._tmpDirConf, "operations");
- this._serverConf.application.operations.directory = curOperationsDir;
+ this._serviceConf.application.operations.directory = curOperationsDir;
if (!fs.existsSync(curOperationsDir)) {
fs.mkdirSync(curOperationsDir, {recursive: true, mode: "766"});
}
// Emplacement des parameters
let curParametersDir = path.join(this._tmpDirConf, "parameters");
- this._serverConf.application.operations.parameters.directory = curParametersDir;
+ this._serviceConf.application.operations.parameters.directory = curParametersDir;
if (!fs.existsSync(curParametersDir)) {
fs.mkdirSync(curParametersDir, {recursive: true, mode: "766"});
}
@@ -292,8 +321,12 @@ class road2World {
// 1. On commence par déterminer sur quelle élément de la configuration on va faire des modifications
if (configurationType === "server") {
modification = this._serverConf;
- } else if (configurationType === "log") {
- modification = this._logConf;
+ } else if (configurationType === "log-admin") {
+ modification = this._logAdminConf;
+ } else if (configurationType === "service") {
+ modification = this._serviceConf;
+ } else if (configurationType === "log-service") {
+ modification = this._logServiceConf;
} else if (configurationType === "cors") {
modification = this._corsConf;
} else if (configurationType === "projection") {
@@ -489,9 +522,21 @@ class road2World {
}
try {
- fs.writeFileSync(path.join(this._tmpDirConf, "log4js.json"), JSON.stringify(this._logConf));
+ fs.writeFileSync(path.join(this._tmpDirConf, "log4js-administration.json"), JSON.stringify(this._logAdminConf));
} catch(error) {
- throw "Can't write log4js.json : " + error;
+ throw "Can't write log4js-administration.json : " + error;
+ }
+
+ try {
+ fs.writeFileSync(path.join(this._tmpDirConf, "service.json"), JSON.stringify(this._serviceConf));
+ } catch(error) {
+ throw "Can't write service.json : " + error;
+ }
+
+ try {
+ fs.writeFileSync(path.join(this._tmpDirConf, "log4js-service.json"), JSON.stringify(this._logServiceConf));
+ } catch(error) {
+ throw "Can't write log4js-service.json : " + error;
}
try {
@@ -562,21 +607,21 @@ class road2World {
// On lance l'analyse de la conf par Road2
return new Promise ( (resolve, reject) => {
- const command = spawn("node", options);
+ this._childProcess = spawn("node", options);
- command.stdout.on("data", (data) => {
+ this._childProcess.stdout.on("data", (data) => {
this._stdout += data.toString();
});
- command.stderr.on("data", (data) => {
+ this._childProcess.stderr.on("data", (data) => {
this._stderr += data.toString();
});
- command.on("error", (err) => {
+ this._childProcess.on("error", (err) => {
reject(err);
});
- command.on("close", (code) => {
+ this._childProcess.on("close", (code) => {
this._code = code;
resolve();
});
@@ -592,7 +637,7 @@ class road2World {
if (code === this._code) {
return true;
} else {
- return false;
+ return this._code;
}
}
@@ -626,6 +671,18 @@ class road2World {
}
}
+
+ // Gestion du processus enfant
+ // killChildProcess() {
+
+ // if (this._childProcess.exitCode === null) {
+ // // On va killer le process pour passer au test suivant
+ // this._childProcess.kill(9);
+ // } else {
+ // // Le processus est déjà mort, donc il n'y a rien à faire
+ // }
+
+ // }
}
diff --git a/test/functional/request/cucumber/configurations/local-admin.json b/test/functional/request/cucumber/configurations/local-admin.json
new file mode 100644
index 0000000..ed251b6
--- /dev/null
+++ b/test/functional/request/cucumber/configurations/local-admin.json
@@ -0,0 +1,17 @@
+{
+ "url": "localhost",
+ "port": 8079,
+ "protocol": "http",
+ "apisUrl": {
+ "admin": {
+ "1.0.0": {
+ "health": "/admin/1.0.0/health",
+ "version": "/admin/1.0.0/version"
+ }
+ }
+ },
+ "defaultParameters": [],
+ "alternativeParameters" : {
+ "url" : "127.0.0.1"
+ }
+}
\ No newline at end of file
diff --git a/test/functional/request/cucumber/configurations/local.json b/test/functional/request/cucumber/configurations/local-service.json
similarity index 90%
rename from test/functional/request/cucumber/configurations/local.json
rename to test/functional/request/cucumber/configurations/local-service.json
index 024b120..9ebb29b 100644
--- a/test/functional/request/cucumber/configurations/local.json
+++ b/test/functional/request/cucumber/configurations/local-service.json
@@ -10,12 +10,6 @@
"nearest": "/simple/1.0.0/nearest",
"getcapabilities": "/simple/1.0.0/getcapabilities"
}
- },
- "admin": {
- "1.0.0": {
- "health": "/admin/1.0.0/health",
- "version": "/admin/1.0.0/version"
- }
}
},
"defaultParameters": [
diff --git a/test/functional/request/cucumber/features/req-admin-1.0.0.feature b/test/functional/request/cucumber/features/req-admin-1.0.0.feature
index 6c5a8fb..209c80d 100644
--- a/test/functional/request/cucumber/features/req-admin-1.0.0.feature
+++ b/test/functional/request/cucumber/features/req-admin-1.0.0.feature
@@ -3,7 +3,7 @@ Feature: Road2 with data
Tests fonctionnels de Road2 prenant en compte la donnée
Background:
- Given I have loaded all my test configuration in "../../configurations/local.json"
+ Given I have loaded all my test configuration in "../../configurations/local-admin.json"
Scenario Outline: [admin/1.0.0] Une route qui n'existe pas
Given an "" request on "/admin/1.0.0/test"
diff --git a/test/functional/request/cucumber/features/req-data-bduni-osrm.feature b/test/functional/request/cucumber/features/req-data-bduni-osrm.feature
index f43685e..02f178b 100644
--- a/test/functional/request/cucumber/features/req-data-bduni-osrm.feature
+++ b/test/functional/request/cucumber/features/req-data-bduni-osrm.feature
@@ -2,7 +2,7 @@ Feature: Road2 with Bduni data via OSRM
Tests fonctionnels de Road2 prenant en compte la donnée Bduni via le moteur OSRM
Background:
- Given I have loaded all my test configuration in "../../configurations/local.json"
+ Given I have loaded all my test configuration in "../../configurations/local-service.json"
Scenario Outline: [] [simple/1.0.0] Route normale
Given an "" request on operation "route" in api "simple" "1.0.0"
diff --git a/test/functional/request/cucumber/features/req-data-bduni-pgr.feature b/test/functional/request/cucumber/features/req-data-bduni-pgr.feature
index 4b87879..53ac3e1 100644
--- a/test/functional/request/cucumber/features/req-data-bduni-pgr.feature
+++ b/test/functional/request/cucumber/features/req-data-bduni-pgr.feature
@@ -2,7 +2,7 @@ Feature: Road2 with Bduni data via PGR
Tests fonctionnels de Road2 prenant en compte la donnée Bduni via PGR
Background:
- Given I have loaded all my test configuration in "../../configurations/local.json"
+ Given I have loaded all my test configuration in "../../configurations/local-service.json"
Scenario Outline: [] [simple/1.0.0] Route normale
Given an "" request on operation "route" in api "simple" "1.0.0"
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-common.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-common.feature
index 870b1d9..6c2dbf5 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-common.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-common.feature
@@ -2,7 +2,7 @@ Feature: Road2
Tests fonctionnels de Road2 sur les requêtes de l'API simple 1.0.0
Background:
- Given I have loaded all my test configuration in "../../configurations/local.json"
+ Given I have loaded all my test configuration in "../../configurations/local-service.json"
Scenario Outline: [] Route principale
Given an "" request on "/"
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
index 41d1d95..225bdbb 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
@@ -2,7 +2,7 @@ Feature: Road2-OSRM
Tests fonctionnels complémentaires de Road2 sur OSRM
Background:
- Given I have loaded all my test configuration in "../../configurations/local.json"
+ Given I have loaded all my test configuration in "../../configurations/local-service.json"
Scenario Outline: [] Route sur l'API simple 1.0.0
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
index aa73d59..c2c06a3 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
@@ -2,7 +2,7 @@ Feature: Road2-PGR
Tests fonctionnels complémentaires de Road2 via PGRouting
Background:
- Given I have loaded all my test configuration in "../../configurations/local.json"
+ Given I have loaded all my test configuration in "../../configurations/local-service.json"
Scenario Outline: [] Route sur l'API simple 1.0.0
Given an "" request on operation "route" in api "simple" "1.0.0"
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
index 9197368..fb704ae 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
@@ -2,7 +2,7 @@ Feature: Road2-SMARTROUTING
Tests fonctionnels complémentaires de Road2 via SmartRouting
Background:
- Given I have loaded all my test configuration in "../../configurations/local.json"
+ Given I have loaded all my test configuration in "../../configurations/local-service.json"
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource smartpgr avec appel à la source smartrouting
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
diff --git a/test/integration/mocha/apis/integrationApiManager.js b/test/integration/mocha/apis/integrationApiManager.js
index 18de119..3df128f 100644
--- a/test/integration/mocha/apis/integrationApiManager.js
+++ b/test/integration/mocha/apis/integrationApiManager.js
@@ -31,10 +31,10 @@ describe('Test de la classe ApisManager', function() {
});
- describe('Test de la fonction loadAPISDirectory()', function() {
+ describe('Test de la fonction loadApiDirectory()', function() {
- it('loadAPISDirectory() avec les bons parametres', function() {
- assert.equal(apisManager.loadAPISDirectory(app, "../../../test/integration/mocha/config/apis/", ""), true);
+ it('loadApiDirectory() avec les bons parametres', function() {
+ assert.equal(apisManager.loadApiDirectory(app, "../../../test/integration/mocha/config/apis/", ""), true);
});
});
diff --git a/test/integration/mocha/base/integrationBaseManager.js b/test/integration/mocha/base/integrationBaseManager.js
index 73e2943..53fcd01 100644
--- a/test/integration/mocha/base/integrationBaseManager.js
+++ b/test/integration/mocha/base/integrationBaseManager.js
@@ -18,8 +18,8 @@ describe('Test de la classe BaseManager', function() {
describe('Test du constructeur et des getters/setters', function() {
- it('Get listOfVerifiedDbConfig', function() {
- assert.deepEqual(baseManager.listOfVerifiedDbConfig, new Array());
+ it('Get loadedBaseConfiguration', function() {
+ assert.deepEqual(baseManager.loadedBaseConfiguration, new Array());
});
it('Get baseCatalog', function() {
@@ -30,17 +30,22 @@ describe('Test de la classe BaseManager', function() {
describe('Verifications des configurations', function() {
- it('checkBase()', function() {
- assert.equal(baseManager.checkBase(configuration), true);
- assert.deepEqual(baseManager.listOfVerifiedDbConfig, [configuration]);
+ it('checkBaseConfiguration()', async function() {
+ let response = await baseManager.checkBaseConfiguration(configuration);
+ assert.equal(response, true);
+ });
+
+ it('saveCheckedBaseConfiguration()', function() {
+ baseManager.saveCheckedBaseConfiguration(configuration);
+ assert.deepEqual(baseManager._checkedBaseConfiguration, [configuration]);
});
});
describe('Creation d\'une base', function() {
- it('createBase()', function() {
- let newBase = baseManager.createBase(configuration);
+ it('loadBaseConfiguration()', function() {
+ let newBase = baseManager.loadBaseConfiguration(configuration);
// TODO: comprendre pourquoi le assert qui suit ne marche pas
// assert.deepEqual(baseManager.baseCatalog[configuration], referenceBase);
assert.equal(newBase.connected, false);
diff --git a/test/integration/mocha/service/integrationService.js b/test/integration/mocha/service/integrationService.js
index ca8aebd..bd4a7e3 100644
--- a/test/integration/mocha/service/integrationService.js
+++ b/test/integration/mocha/service/integrationService.js
@@ -82,7 +82,7 @@ describe('Test de la classe Service', function() {
describe('Test de createServer() et stopServer()', function() {
const apisManager = sinon.mock(ApisManager);
- apisManager.loadAPISDirectory = sinon.stub().returns(true);
+ apisManager.loadApiDirectory = sinon.stub().returns(true);
service._apisManager = apisManager;
const serverManager = sinon.mock(ServerManager);
diff --git a/test/integration/readme.md b/test/integration/readme.md
index e732e12..b60d3b8 100644
--- a/test/integration/readme.md
+++ b/test/integration/readme.md
@@ -9,7 +9,7 @@ docker-compose exec road2 npm run itest
C'est l'approche bottom-up qui a été choisie pour ces tests. On va tester les classes qui dépendent d'une autre pour fonctionner. On testera donc les classes suivantes dans l'ordre indiqué:
- Premier niveau:
- - apiManager (ExpressJS, api, log4js)
+ - apisManager (ExpressJS, api, log4js)
- baseManager (base, log4js)
- looseConstraint (constraint)
- line (geometry, proj4, polyline)
@@ -60,7 +60,7 @@ Huitième niveau:
- resourceManager (osrmResource, pgrResource, sourceManager, operationManager, log4js)
Neuvième niveau:
- - service (apiManager, resourceManager, sourceManager, operationManager, baseManager, topologyManager, projectionManager, serverManager, errorManager, ExpressJS, log4js)
+ - service (apisManager, resourceManager, sourceManager, operationManager, baseManager, topologyManager, projectionManager, serverManager, errorManager, ExpressJS, log4js)
Autres:
- road2.js
diff --git a/test/unit/mocha/geography/testsProjectionManager.js b/test/unit/mocha/geography/testsProjectionManager.js
index 5343721..1173859 100644
--- a/test/unit/mocha/geography/testsProjectionManager.js
+++ b/test/unit/mocha/geography/testsProjectionManager.js
@@ -13,8 +13,64 @@ describe('Test de la classe ProjectionManager', function() {
let projManager = new ProjectionManager();
- it('Get listOfProjectionId', function() {
- assert.deepEqual(projManager.listOfProjectionId, new Array());
+ it('Get loadedProjectionId', function() {
+ assert.deepEqual(projManager.loadedProjectionId, new Array());
+ });
+
+ });
+
+ describe('Vérification d\'une configuration de projection', function() {
+
+ let projManager = new ProjectionManager();
+ let configuration = {
+ "id": "EPSG:4326",
+ "parameters": "+proj=longlat +datum=WGS84 +no_defs"
+ };
+
+ it('checkProjectionConfiguration()', function() {
+ assert.equal(projManager.checkProjectionConfiguration(configuration), true);
+ });
+
+ });
+
+ describe('Vérification d\'un fichier de projections', function() {
+
+ let projManager = new ProjectionManager();
+ let file = "/home/docker/app/test/unit/mocha/config/projections/projection.json";
+
+ it('checkProjectionFile()', function() {
+ assert.equal(projManager.checkProjectionFile(file), true);
+ assert.equal(projManager.isChecked("EPSG:4326"), true);
+ assert.equal(projManager.isChecked("EPSG:2154"), true);
+ assert.equal(projManager.isChecked("EPSG:2155"), false);
+ });
+
+ });
+
+ describe('Vérification d\'un dossier de projections', function() {
+
+ let projManager = new ProjectionManager();
+ let directory = "/home/docker/app/test/unit/mocha/config/projections/";
+
+ it('checkProjectionDirectory()', function() {
+ assert.equal(projManager.checkProjectionDirectory(directory), true);
+ assert.equal(projManager.isChecked("EPSG:4326"), true);
+ assert.equal(projManager.isChecked("EPSG:2154"), true);
+ assert.equal(projManager.isChecked("EPSG:2155"), false);
+ });
+
+ });
+
+ describe('Test de isChecked', function() {
+
+ let projManager = new ProjectionManager();
+ let directory = "/home/docker/app/test/unit/mocha/config/projections/";
+
+ it('isChecked()', function() {
+ projManager.checkProjectionDirectory(directory);
+ assert.equal(projManager.isChecked("EPSG:4326"), true);
+ assert.equal(projManager.isChecked("EPSG:2154"), true);
+ assert.equal(projManager.isChecked("EPSG:2155"), false);
});
});
@@ -27,9 +83,9 @@ describe('Test de la classe ProjectionManager', function() {
"parameters": "+proj=longlat +datum=WGS84 +no_defs"
};
- it('loadProjection()', function() {
- assert.equal(projManager.loadProjection(configuration), true);
- assert.deepEqual(projManager.listOfProjectionId, ["EPSG:4326"]);
+ it('loadProjectionConfiguration()', function() {
+ assert.equal(projManager.loadProjectionConfiguration(configuration), true);
+ assert.deepEqual(projManager.loadedProjectionId, ["EPSG:4326"]);
});
});
@@ -41,9 +97,9 @@ describe('Test de la classe ProjectionManager', function() {
it('loadProjectionFile()', function() {
assert.equal(projManager.loadProjectionFile(file), true);
- assert.equal(projManager.isAvailableById("EPSG:4326"), true);
- assert.equal(projManager.isAvailableById("EPSG:2154"), true);
- assert.equal(projManager.isAvailableById("EPSG:2155"), false);
+ assert.equal(projManager.isAvailable("EPSG:4326"), true);
+ assert.equal(projManager.isAvailable("EPSG:2154"), true);
+ assert.equal(projManager.isAvailable("EPSG:2155"), false);
});
});
@@ -55,23 +111,23 @@ describe('Test de la classe ProjectionManager', function() {
it('loadProjectionDirectory()', function() {
assert.equal(projManager.loadProjectionDirectory(directory), true);
- assert.equal(projManager.isAvailableById("EPSG:4326"), true);
- assert.equal(projManager.isAvailableById("EPSG:2154"), true);
- assert.equal(projManager.isAvailableById("EPSG:2155"), false);
+ assert.equal(projManager.isAvailable("EPSG:4326"), true);
+ assert.equal(projManager.isAvailable("EPSG:2154"), true);
+ assert.equal(projManager.isAvailable("EPSG:2155"), false);
});
});
- describe('Test de isAvailableById', function() {
+ describe('Test de isAvailable', function() {
let projManager = new ProjectionManager();
let directory = "/home/docker/app/test/unit/mocha/config/projections/";
- it('isAvailableById()', function() {
+ it('isAvailable()', function() {
projManager.loadProjectionDirectory(directory);
- assert.equal(projManager.isAvailableById("EPSG:4326"), true);
- assert.equal(projManager.isAvailableById("EPSG:2154"), true);
- assert.equal(projManager.isAvailableById("EPSG:2155"), false);
+ assert.equal(projManager.isAvailable("EPSG:4326"), true);
+ assert.equal(projManager.isAvailable("EPSG:2154"), true);
+ assert.equal(projManager.isAvailable("EPSG:2155"), false);
});
});
From 980987d956f35d9f3efd775073cdf59722034edc Mon Sep 17 00:00:00 2001
From: "amaury.zarzelli"
Date: Fri, 21 Oct 2022 15:09:38 +0200
Subject: [PATCH 08/93] feature(valhalla): Add support for Valhalla for routes
and isochrones
---
src/js/geometry/line.js | 12 +-
src/js/resources/resourceManager.js | 5 +-
src/js/resources/valhallaResource.js | 151 +++++
src/js/sources/sourceManager.js | 88 ++-
src/js/sources/valhallaSource.js | 580 ++++++++++++++++++
src/js/utils/storageManager.js | 29 +-
.../configurations/local-service.json | 17 +-
.../features/req-simple-1.0.0-pgr.feature | 208 +++----
.../req-simple-1.0.0-valhalla.feature | 52 ++
.../resources/integrationValhallaResource.js | 104 ++++
.../sources/integrationValhallaSource.js | 135 ++++
11 files changed, 1266 insertions(+), 115 deletions(-)
create mode 100644 src/js/resources/valhallaResource.js
create mode 100644 src/js/sources/valhallaSource.js
create mode 100644 test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
create mode 100644 test/integration/mocha/resources/integrationValhallaResource.js
create mode 100644 test/integration/mocha/sources/integrationValhallaSource.js
diff --git a/src/js/geometry/line.js b/src/js/geometry/line.js
index 87fb1ca..a2076dd 100644
--- a/src/js/geometry/line.js
+++ b/src/js/geometry/line.js
@@ -25,9 +25,10 @@ module.exports = class Line extends Geometry {
* @param {object} geom - Géométrie
* @param {string} format - Format de la geom (geojson, polyline)
* @param {string} projection - Id de la projection utilisée (EPSG:4326)
+ * @param {integer} polylinePrecision - Précision de l'encodage en polyline en entrée (défaut : 5)
*
*/
- constructor(geom, format, projection) {
+ constructor(geom, format, projection, polylinePrecision = 5) {
super("polyline", projection);
@@ -37,6 +38,9 @@ module.exports = class Line extends Geometry {
// Format de géométrie (geojson, polyline...)
this._format = format;
+ if (polylinePrecision != 5) {
+ this._geom = polyline.encode(polyline.decode(geom, polylinePrecision));
+ }
}
/**
@@ -131,11 +135,11 @@ module.exports = class Line extends Geometry {
this._geom = tmpGeom;
this.projection = projection;
-
+
return true;
}
-
+
} else {
// il n'y a rien à faire
return true;
@@ -167,7 +171,7 @@ module.exports = class Line extends Geometry {
return {};
}
- // reprojection
+ // reprojection
let reprojectedCoordinates = new Array();
for (let i = 0; i < geojson.coordinates.length; i++) {
diff --git a/src/js/resources/resourceManager.js b/src/js/resources/resourceManager.js
index 6a20a39..b6a685d 100644
--- a/src/js/resources/resourceManager.js
+++ b/src/js/resources/resourceManager.js
@@ -5,6 +5,7 @@ const path = require('path');
const osrmResource = require('../resources/osrmResource');
const pgrResource = require('../resources/pgrResource');
const smartpgrResource = require('../resources/smartpgrResource');
+const valhallaResource = require('../resources/valhallaResource');
const log4js = require('log4js');
// Création du LOGGER
@@ -31,7 +32,7 @@ module.exports = class resourceManager {
this._resource = {};
// Liste des types de ressource gérées par le manager
- this._availableResourceTypes = ["pgr", "smartpgr","osrm"];
+ this._availableResourceTypes = ["pgr", "smartpgr","osrm","valhalla"];
// Manager de topology
this._topologyManager = topologyManager;
@@ -417,6 +418,8 @@ module.exports = class resourceManager {
resource = new pgrResource(resourceJsonObject, resourceOperationHash);
} else if (resourceJsonObject.resource.type === "smartpgr") {
resource = new smartpgrResource(resourceJsonObject, resourceOperationHash);
+ } else if (resourceJsonObject.resource.type === "valhalla") {
+ resource = new valhallaResource(resourceJsonObject, resourceOperationHash);
} else {
LOGGER.error("Type de la ressource inconnue");
return false;
diff --git a/src/js/resources/valhallaResource.js b/src/js/resources/valhallaResource.js
new file mode 100644
index 0000000..f470787
--- /dev/null
+++ b/src/js/resources/valhallaResource.js
@@ -0,0 +1,151 @@
+'use strict';
+
+const Resource = require('./resource');
+
+/**
+*
+* @class
+* @name valhallaResource
+* @description Classe modélisant une ressource Valhalla.
+*
+*/
+
+module.exports = class valhallaResource extends Resource {
+
+
+ /**
+ *
+ * @function
+ * @name constructor
+ * @description Constructeur de la classe valhallaResource
+ * @param {json} resourceJsonObject - Description JSON de la ressource
+ * @param {object} operations - Objet contenant des instances de classes filles de ResourceOperation
+ *
+ */
+ constructor(resourceJsonObject, operations) {
+
+ // Constructeur parent
+ super(resourceJsonObject.resource.id,resourceJsonObject.resource.type, resourceJsonObject.resource.resourceVersion, operations);
+
+ // Stockage de la configuration
+ this._configuration = resourceJsonObject.resource;
+
+ // Correspondance entre profile/optimization et sourceId
+ this._linkedSource = {};
+
+ // Instanciation de la correspondance entre profile/optimization et sourceId
+ // et instanciation du profile et de l'optimisation par défaut
+ for (let i=0; i < this._configuration.sources.length; i++) {
+
+ /* TODO: Il serait mieux, dans le futur, d'avoir un nouveau type de ressource, dédiée à l'isochrone. */
+ const currentSourceOptimization = this._configuration.sources[i].cost.optimization;
+ let linkedId = '';
+ if (operations["isochrone"]) {
+ if (currentSourceOptimization === "fastest") {
+ linkedId = this._configuration.sources[i].cost.profile + "time";
+ } else if (currentSourceOptimization === "shortest") {
+ linkedId = this._configuration.sources[i].cost.profile + "distance";
+ } else {
+ /* TODO: À repenser. */
+ }
+ this._linkedSource[linkedId] = this._configuration.sources[i].id;
+ }
+ if (operations["route"]) {
+ linkedId = this._configuration.sources[i].cost.profile + this._configuration.sources[i].cost.optimization;
+ this._linkedSource[linkedId] = this._configuration.sources[i].id;
+ }
+ }
+
+ // Attribut des voies
+ // Par défaut, OSRM ne renvoit que le nom des voies empruntées.
+ this._waysAttributes = new Array();
+ this._waysAttributes.push("name");
+
+ }
+
+ /**
+ *
+ * @function
+ * @name get configuration
+ * @description Récupérer la configuration de la ressource
+ *
+ */
+ get configuration () {
+ return this._configuration;
+ }
+
+ /**
+ *
+ * @function
+ * @name get linkedSource
+ * @description Récupérer la correspondance entre profile/optimization et sourceId de la ressource
+ *
+ */
+ get linkedSource () {
+ return this._linkedSource;
+ }
+
+ /**
+ *
+ * @function
+ * @name get waysAttributes
+ * @description Récupérer la liste des attributs disponibles pour les voies empruntées.
+ *
+ */
+ get waysAttributes () {
+ return this._waysAttributes;
+ }
+
+ /**
+ *
+ * @function
+ * @name isWayAttributeAvailable
+ * @description Permet de savoir si un attribut est disponible pour cette ressource.
+ * @param {string} attr - Attribut à vérifier
+ *
+ */
+ isWayAttributeAvailable (attr) {
+
+ if (this._waysAttributes.length !== 0) {
+ for (let i=0; i < this._waysAttributes.length; i++) {
+ if (this._waysAttributes[i] === attr) {
+ return true;
+ } else {
+ // on continue
+ }
+ }
+ } else {
+ return false;
+ }
+
+ return false;
+ }
+
+ /**
+ *
+ * @function
+ * @name getSourceIdFromRequest
+ * @description Récupérer l'id de la source concernée par la requête.
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * @param {Request} request - Objet Request ou ou dérivant de la classe Request
+ * @return {string} Id de la source concernée par la requête
+ *
+ */
+ getSourceIdFromRequest (request) {
+
+ const currentOperation = request.operation;
+ let source = "";
+ /* TODO: Pour le moment, c'est un contrôle en dur sur le type de l'opération. Il serait mieux de revoir cette façon de voir (avoir peut-être un catalogue de correspondance ? Maybe..). */
+ if (currentOperation === "isochrone") {
+ source = request.profile + request.costType;
+ } else {
+ source = request.profile + request.optimization;
+ }
+ if (this._linkedSource[source]) {
+ return this._linkedSource[source];
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/src/js/sources/sourceManager.js b/src/js/sources/sourceManager.js
index 83fe2a2..86d365d 100644
--- a/src/js/sources/sourceManager.js
+++ b/src/js/sources/sourceManager.js
@@ -6,6 +6,7 @@ const errorManager = require('../utils/errorManager');
const osrmSource = require('../sources/osrmSource');
const pgrSource = require('../sources/pgrSource');
const smartroutingSource = require('../sources/smartroutingSource');
+const valhallaSource = require('../sources/valhallaSource');
const log4js = require('log4js');
// Création du LOGGER
@@ -209,7 +210,7 @@ module.exports = class sourceManager {
available = true;
LOGGER.info("Source pgrouting.");
- // On vérifie que le module pg est disponible
+ // On vérifie que le module pg est disponible
try {
let { poolTest } = require('pg');
} catch(error) {
@@ -242,6 +243,52 @@ module.exports = class sourceManager {
// On va voir si c'est un autre type.
}
//------ SMARTROUTING
+ //------ VALHALLA
+ if (sourceJsonObject.type === "valhalla") {
+ available = true;
+ LOGGER.info("Source valhalla.");
+
+ let operationFound = false;
+
+ // On vérifie que les opérations possibles sur ce type de source soient disponibles dans l'instance du service
+ if (operationManager.verifyAvailabilityOperation("route")) {
+ // On vérifie que les opérations possibles sur ce type de source soient disponibles pour la ressource
+ if (operationManager.isAvailableInTable("route", resourceOperationTable)) {
+ operationFound = true;
+ } else {
+ // on continue pour voir la suite
+ }
+ } else {
+ // on continue pour voir la suite
+ }
+
+ // On vérifie que les opérations possibles sur ce type de source soient disponibles dans l'instance du service
+ if (operationManager.verifyAvailabilityOperation("isochrone")) {
+ // On vérifie que les opérations possibles sur ce type de source soient disponibles pour la ressource
+ if (operationManager.isAvailableInTable("isochrone", resourceOperationTable)) {
+ operationFound = true;
+ } else {
+ // on continue pour voir la suite
+ }
+ } else {
+ // on continue pour voir la suite
+ }
+
+ if (!operationFound) {
+ LOGGER.error("Le service ne propose pas d'operations disponibles pour ce type de source (ex. route, isochrone), il n'est donc pas possible de charger cette source.");
+ return false;
+ }
+
+ if (!this.checkSourceValhalla(sourceJsonObject)) {
+ LOGGER.error("Erreur lors de la verification de la source valhalla.");
+ return false;
+ } else {
+ // il n'y a eu aucun problème, la ressource est correctement configurée.
+ }
+ } else {
+ // On va voir si c'est un autre type.
+ }
+ //------ VALHALLA
// Si ce n'est aucun type valide, on renvoie une erreur.
if (!available) {
@@ -396,7 +443,7 @@ module.exports = class sourceManager {
*
* @function
* @name checkSourceSmartrouting
- * @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source pgr.
+ * @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source smartrouting.
* @param {json} sourceJsonObject - Description JSON de la source
* @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
*
@@ -405,7 +452,38 @@ module.exports = class sourceManager {
checkSourceSmartrouting(sourceJsonObject) {
LOGGER.info("Verification de la source smartrouting...");
-
+
+ // Storage
+ if (!sourceJsonObject.storage) {
+ LOGGER.error("La ressource contient une source sans stockage.");
+ return false;
+ } else {
+ if (!storageManager.checkJsonStorage(sourceJsonObject.storage)) {
+ LOGGER.error("Stockage de la source incorrect.");
+ return false;
+ } else {
+ // Normalement, il n'y a plus rien à faire car la fonction checkDuplicationSource() vérifie déjà que la source n'est pas dupliquée
+ }
+ }
+
+ LOGGER.info("Fin de la verification de la source smartrouting.");
+ return true;
+ }
+
+ /**
+ *
+ * @function
+ * @name checkSourceValhalla
+ * @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source valhalla.
+ * @param {json} sourceJsonObject - Description JSON de la source
+ * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
+ *
+ */
+
+ checkSourceValhalla(sourceJsonObject) {
+
+ LOGGER.info("Verification de la source smartrouting...");
+
// Storage
if (!sourceJsonObject.storage) {
LOGGER.error("La ressource contient une source sans stockage.");
@@ -418,7 +496,7 @@ module.exports = class sourceManager {
// Normalement, il n'y a plus rien à faire car la fonction checkDuplicationSource() vérifie déjà que la source n'est pas dupliquée
}
}
-
+
LOGGER.info("Fin de la verification de la source smartrouting.");
return true;
}
@@ -543,6 +621,8 @@ module.exports = class sourceManager {
} else if (sourceJsonObject.type === "smartrouting") {
// smartrouting n'utilise pas la topologie définie dans la conf
source = new smartroutingSource(sourceJsonObject);
+ } else if (sourceJsonObject.type === "valhalla") {
+ source = new valhallaSource(sourceJsonObject, topology);
} else {
// On va voir si c'est un autre type.
LOGGER.error("Le type de la source est inconnu");
diff --git a/src/js/sources/valhallaSource.js b/src/js/sources/valhallaSource.js
new file mode 100644
index 0000000..dd86535
--- /dev/null
+++ b/src/js/sources/valhallaSource.js
@@ -0,0 +1,580 @@
+'use strict';
+
+const Source = require('./source');
+const RouteResponse = require('../responses/routeResponse');
+const IsochroneResponse = require('../responses/isochroneResponse');
+const Route = require('../responses/route');
+const Portion = require('../responses/portion');
+const Line = require('../geometry/line');
+const Point = require('../geometry/point');
+const Polygon = require('../geometry/polygon');
+const Step = require('../responses/step');
+const Distance = require('../geography/distance');
+const Duration = require('../time/duration');
+const errorManager = require('../utils/errorManager');
+const { exec } = require('child_process');
+
+// Création du LOGGER
+const log4js = require('log4js');
+const LOGGER = log4js.getLogger("VALHALLASOURCE");
+
+/**
+*
+* @class
+* @name valhallaSource
+* @description Classe modélisant une source pgRouting.
+*
+*/
+module.exports = class valhallaSource extends Source {
+ /**
+ *
+ * @function
+ * @name constructor
+ * @description Constructeur de la classe valhallaSource
+ * @param{json} sourceJsonObject - Description de la source
+ * @param{topology} topology - Instance de la classe Topology
+ *
+ */
+ constructor(sourceJsonObject, topology) {
+
+ // Constructeur parent
+ super(sourceJsonObject.id, "valhalla", topology);
+
+ // Stockage de la configuration
+ this._configuration = sourceJsonObject;
+
+ }
+
+ /**
+ *
+ * @function
+ * @name get configuration
+ * @description Récupérer la configuration de la source
+ *
+ */
+ get configuration () {
+ return this._configuration;
+ }
+
+ /**
+ *
+ * @function
+ * @name set configuration
+ * @description Attribuer la configuration de la source
+ * @param {json} conf - Description de la source en json
+ *
+ */
+ set configuration (conf) {
+ this._configuration = conf;
+ }
+
+ /**
+ *
+ * @function
+ * @name connect
+ * @description Connection
+ *
+ */
+ async connect() {
+ this._connected = true;
+ }
+
+ /**
+ *
+ * @function
+ * @name disconnect
+ * @description Déconnection
+ *
+ */
+ async disconnect() {
+ this._connected = false;
+ }
+
+ /**
+ *
+ * @function
+ * @name computeRequest
+ * @description Traiter une requête.
+ * Ce traitement est placé ici car c'est la source qui sait quel moteur est concernée par la requête.
+ * @param {Request} request - Objet Request ou dérivant de la classe Request
+ * @return {Promise}
+ *
+ */
+ computeRequest (request) {
+
+ LOGGER.debug("computeRequest()");
+
+ let valhallaRequest = {};
+
+ if (request.operation === "route") {
+
+ LOGGER.debug("operation request is route");
+
+ const coordinatesTable = new Array();
+ let constraints = new Array();
+
+ if (request.type === "routeRequest") {
+
+ LOGGER.debug("type of request is routeRequest");
+
+ // Coordonnées
+ // start
+ coordinatesTable.push(request.start.getCoordinatesIn(this.topology.projection));
+ // intermediates
+ if (request.intermediates.length !== 0) {
+ for (let i = 0; i < request.intermediates.length; i++) {
+ coordinatesTable.push(request.intermediates[i].getCoordinatesIn(this.topology.projection));
+ }
+ }
+ // end
+ coordinatesTable.push(request.end.getCoordinatesIn(this.topology.projection));
+
+ LOGGER.debug("coordinates:");
+ LOGGER.debug(coordinatesTable);
+
+ valhallaRequest.coordinates = coordinatesTable;
+
+ // Gestion des contraintes d'exclusion.
+ if (request.constraints && Array.isArray(request.constraints) && request.constraints.length > 0) {
+
+ valhallaRequest.exclude = [];
+ for (let i = 0; i < request.constraints.length; i++) {
+ let constraint = request.constraints[i];
+
+ if (constraint.type === "banned") {
+ constraints.push(constraint.field);
+ } else {
+ // ce sont des contraintes non gérées donc il n'y a rien à faire
+ LOGGER.debug("no banned contraints");
+ }
+
+ }
+
+ } else {
+ // il n'y rien à faire car pas de contraintes
+ LOGGER.debug("no contraints");
+ }
+
+ } else {
+
+ // TODO: qu'est-ce qui se passe si on arrive là, doit-on retourner une erreur ou une promesse
+ LOGGER.error("type of request not found");
+
+ }
+ // ---
+ let locationsString = `"locations":[`;
+ valhallaRequest.coordinates.forEach(location => {
+ locationsString += `{"lat": ${location[1]}, "lon": ${location[0]}},`;
+ });
+ locationsString = locationsString.slice(0, -1);
+ locationsString += "]";
+
+ const costingString = `"costing":"${this._configuration.cost.compute.configuration.costing}"`;
+ // Permet de grandement se simplifier le parsing !!
+ const optionsString = `"directions_options":{"format":"osrm"}`;
+ const commandString = `valhalla_service ${this._configuration.storage.config} route '{${locationsString},${costingString},${optionsString}}' `;
+ LOGGER.info(commandString);
+
+ return new Promise( (resolve, reject) => {
+
+ try {
+ exec(commandString, (err, stdout, stderr) => {
+
+ // Du moment qu'OSRM a répondu, on considère que la source est joignable
+ this.state = "green";
+
+ if (err) {
+ // mais on ne renvoie pas l'erreur à l'utilisateur
+ reject(errorManager.createError(" No path found ", 404));
+ LOGGER.error("valhalla error for route :");
+ LOGGER.error(err);
+
+ } else {
+
+ LOGGER.debug("valhalla response for route :");
+ LOGGER.debug(stdout);
+
+ try {
+ resolve(this.writeRouteResponse(request, stdout));
+ } catch (error) {
+ reject(error);
+ }
+
+ }
+
+ });
+
+ } catch (error) {
+ // Pour une raison que l'on ignore, la source n'est plus joignable
+ this.state = "red";
+ LOGGER.error(error);
+ reject("Internal VALHALLA error");
+ }
+ });
+
+ } else if (request.operation === "isochrone") {
+
+ LOGGER.debug("operation request is isochrone");
+
+ if (request.type === "isochroneRequest") {
+
+ LOGGER.debug("type of request is isochroneRequest");
+ let constraints = new Array();
+
+ // Gestion des contraintes d'exclusion.
+ if (request.constraints && Array.isArray(request.constraints) && request.constraints.length > 0) {
+
+ valhallaRequest.exclude = [];
+ for (let i = 0; i < request.constraints.length; i++) {
+ let constraint = request.constraints[i];
+
+ if (constraint.type === "banned") {
+ constraints.push(constraint.field);
+ } else {
+ // ce sont des contraintes non gérées donc il n'y a rien à faire
+ LOGGER.debug("no banned contraints");
+ }
+
+ }
+
+ } else {
+ // il n'y rien à faire car pas de contraintes
+ LOGGER.debug("no contraints");
+ }
+
+ // ---
+ // Conversion en unités valhalla : minutes et kilomètres...
+ let costValue;
+ if (request.costType === "time") {
+ costValue = request.costValue / 60;
+ }
+ if (request.costType === "distance") {
+ costValue = request.costValue / 1000;
+ }
+
+ let reverse = "false";
+ if (request.direction === "arrival") {
+ reverse = "true";
+ }
+
+ const locationsString = `"locations":[{"lat":${request.point.lat},"lon":${request.point.lon}}]`;
+ const costingString = `"costing":"${this._configuration.cost.compute.configuration.costing}"`;
+ const contoursString = `"contours":[{"${request.costType}":${costValue}}]`;
+ const reverseString = `"reverse":${reverse}`;
+ const commandString = `valhalla_service ${this._configuration.storage.config} isochrone '{${locationsString},${costingString},${contoursString},${reverseString}}' `;
+ LOGGER.info(commandString);
+
+ return new Promise( (resolve, reject) => {
+
+ try {
+ exec(commandString, (err, stdout, stderr) => {
+
+ // Du moment qu'OSRM a répondu, on considère que la source est joignable
+ this.state = "green";
+
+ if (err) {
+ // mais on ne renvoie pas l'erreur à l'utilisateur
+ LOGGER.error("valhalla error for route :");
+ LOGGER.error(err);
+ reject(errorManager.createError(" No path found ", 404));
+
+ } else {
+
+ LOGGER.debug("valhalla response for iso :");
+ LOGGER.debug(stdout);
+
+ try {
+ resolve(this.writeIsochroneResponse(request, stdout));
+ } catch (error) {
+ reject(error);
+ }
+
+ }
+
+ });
+
+ } catch (error) {
+ // Pour une raison que l'on ignore, la source n'est plus joignable
+ this.state = "red";
+ LOGGER.error(error);
+ reject("Internal VALHALLA error");
+ }
+ });
+
+ } else {
+ // TODO: qu'est-ce qui se passe si on arrive là, doit-on retourner une erreur ou une promesse
+ LOGGER.error("type of request not found");
+ }
+
+ } else {
+
+ // TODO: qu'est-ce qui se passe si on arrive là, doit-on retourner une erreur ou une promesse ?
+ LOGGER.error("request operation not found");
+
+ }
+
+ }
+
+ /**
+ *
+ * @function
+ * @name writeRouteResponse
+ * @description Pour traiter la réponse du moteur et la ré-écrire pour le proxy.
+ * Ce traitement est placé ici car c'est à la source de renvoyer une réponse adaptée au proxy.
+ * C'est cette fonction qui doit vérifier le contenu de la réponse. Une fois la réponse envoyée
+ * au proxy, on considère qu'elle est correcte.
+ * @param {Request} request - Objet Request ou dérivant de la classe Request
+ * @param {string} valhallaResponseStr - Réponse de valhalla
+ *
+ */
+ writeRouteResponse (routeRequest, valhallaResponseStr) {
+
+ LOGGER.debug("writeRouteResponse()");
+
+ let resource;
+ let start;
+ let end;
+ let profile;
+ let optimization;
+ let valhallaResponse;
+ let routes = new Array();
+
+ // Récupération des paramètres de la requête que l'on veut transmettre dans la réponse
+ // ---
+ // resource
+ resource = routeRequest.resource;
+
+ // profile
+ profile = routeRequest.profile;
+
+ // optimization
+ optimization = routeRequest.optimization;
+ // ---
+
+ // Lecture de la réponse Valhalla
+ // ---
+ try {
+ valhallaResponse = JSON.parse(valhallaResponseStr);
+ } catch (error) {
+ LOGGER.error("unable to parse valhalla response")
+ LOGGER.error(valhallaResponseStr)
+ LOGGER.error(error)
+ }
+
+ if (valhallaResponse.waypoints.length < 2) {
+ // Cela veut dire que l'on n'a pas un start et un end dans la réponse OSRM
+ throw errorManager.createError(" OSRM response is invalid: the number of waypoints is lower than 2. ");
+ } else {
+ LOGGER.debug("osrm response has 2 or more waypoints");
+ }
+
+ // projection demandée dans la requête
+ let askedProjection = routeRequest.start.projection;
+ LOGGER.debug("asked projection: " + askedProjection);
+
+ LOGGER.debug("topology projection: " + this.topology.projection);
+
+ // start
+ start = new Point(valhallaResponse.waypoints[0].location[0], valhallaResponse.waypoints[0].location[1], this.topology.projection);
+ if (!start.transform(askedProjection)) {
+ throw errorManager.createError(" Error during reprojection of start in OSRM response. ");
+ } else {
+ LOGGER.debug("start in asked projection:");
+ LOGGER.debug(start);
+ }
+
+ // end
+ end = new Point(valhallaResponse.waypoints[valhallaResponse.waypoints.length-1].location[0], valhallaResponse.waypoints[valhallaResponse.waypoints.length-1].location[1], this.topology.projection);
+ if (!end.transform(askedProjection)) {
+ throw errorManager.createError(" Error during reprojection of end in OSRM response. ");
+ } else {
+ LOGGER.debug("end in asked projection:");
+ LOGGER.debug(end);
+ }
+
+ let routeResponse = new RouteResponse(resource, start, end, profile, optimization);
+
+ if (valhallaResponse.routes.length === 0) {
+ // Cela veut dire que l'on n'a pas un start et un end dans la réponse OSRM
+ throw errorManager.createError(" No route found ", 404);
+ } else {
+ LOGGER.debug("osrm response has 1 or more routes");
+ }
+
+ // routes
+ // Il peut y avoir plusieurs itinéraires
+ for (let i = 0; i < valhallaResponse.routes.length; i++) {
+
+ LOGGER.debug("osrm route number " + i);
+
+ let portions = new Array();
+ let currentOsrmRoute = valhallaResponse.routes[i];
+
+ // On commence par créer l'itinéraire avec les attributs obligatoires
+ routes[i] = new Route( new Line(currentOsrmRoute.geometry, "polyline", this._topology.projection, 6) );
+ if (!routes[i].geometry.transform(askedProjection)) {
+ throw errorManager.createError(" Error during reprojection of geometry in OSRM response. ");
+ } else {
+ LOGGER.debug("route geometry is converted");
+ }
+
+ // On récupère la distance et la durée
+ routes[i].distance = new Distance(currentOsrmRoute.distance,"meter");
+ routes[i].duration = new Duration(currentOsrmRoute.duration,"second");
+
+ // On doit avoir une égalité entre ces deux valeurs pour la suite
+ // Si ce n'est pas le cas, c'est qu'OSRM n'a pas le comportement attendu...
+ if (currentOsrmRoute.legs.length !== valhallaResponse.waypoints.length-1) {
+ throw errorManager.createError(" OSRM response is invalid: the number of legs is not proportionnal to the number of waypoints. ");
+ } else {
+ LOGGER.debug("number of osrm legs et asked waypoints are compatible");
+ }
+
+ // On va gérer les portions qui sont des parties de l'itinéraire entre deux points intermédiaires
+ for (let j = 0; j < currentOsrmRoute.legs.length; j++) {
+
+ LOGGER.debug("Portion (osrm legs) number " + j + " for route number " + i);
+
+ let currentOsrmRouteLeg = currentOsrmRoute.legs[j];
+
+ let legStart = new Point(valhallaResponse.waypoints[j].location[0], valhallaResponse.waypoints[j].location[1], this.topology.projection);
+ if (!legStart.transform(askedProjection)) {
+ throw errorManager.createError(" Error during reprojection of leg start in OSRM response. ");
+ } else {
+ LOGGER.debug("portion start in asked projection:");
+ LOGGER.debug(legStart);
+ }
+
+ let legEnd = new Point(valhallaResponse.waypoints[j+1].location[0], valhallaResponse.waypoints[j+1].location[1], this.topology.projection);
+ if (!legEnd.transform(askedProjection)) {
+ throw errorManager.createError(" Error during reprojection of leg end in OSRM response. ");
+ } else {
+ LOGGER.debug("portion end in asked projection:");
+ LOGGER.debug(legEnd);
+ }
+
+ portions[j] = new Portion(legStart, legEnd);
+
+ // On récupère la distance et la durée
+ portions[j].distance = new Distance(currentOsrmRouteLeg.distance,"meter");
+ portions[j].duration = new Duration(currentOsrmRouteLeg.duration,"second");
+
+ // Steps
+ let steps = new Array();
+
+ // On va associer les étapes à la portion concernée
+ for (let k=0; k < currentOsrmRouteLeg.steps.length; k++) {
+
+ LOGGER.debug("Step number " + k + " of portion number " + j + " for route number " + i);
+
+ let currentOsrmRouteStep = currentOsrmRouteLeg.steps[k];
+ steps[k] = new Step( new Line(currentOsrmRouteStep.geometry, "polyline", this._topology.projection, 6) );
+ if (!steps[k].geometry.transform(askedProjection)) {
+ throw errorManager.createError(" Error during reprojection of step's geometry in OSRM response. ");
+ } else {
+ LOGGER.debug("step geometry is converted");
+ }
+
+ // Ajout de l'attribut name
+ let nameAttributs;
+ try {
+ nameAttributs = JSON.parse(currentOsrmRouteStep.name);
+ } catch(error) {
+ // Ce doit être une chaîne de caractère
+ nameAttributs = currentOsrmRouteStep.name;
+ }
+ steps[k].setAttributById("name", nameAttributs);
+
+ // On récupère la distance et la durée
+ steps[k].distance = new Distance(currentOsrmRouteStep.distance,"meter");
+ steps[k].duration = new Duration(currentOsrmRouteStep.duration,"second");
+
+ steps[k].instruction = {};
+ steps[k].instruction.type = currentOsrmRouteStep.maneuver.type;
+ if (currentOsrmRouteStep.maneuver.modifier) {
+ steps[k].instruction.modifier = currentOsrmRouteStep.maneuver.modifier;
+ }
+ if (currentOsrmRouteStep.maneuver.exit) {
+ steps[k].instruction.exit = currentOsrmRouteStep.maneuver.exit;
+ }
+ }
+
+ portions[j].steps = steps;
+
+ }
+
+ routes[i].portions = portions;
+
+ }
+
+ routeResponse.routes = routes;
+
+ return routeResponse;
+ }
+
+ /**
+ *
+ * @function
+ * @name writeIsochroneResponse
+ * @description Pour traiter la réponse du moteur et la ré-écrire pour le proxy.
+ * Ce traitement est placé ici car c'est à la source de renvoyer une réponse adaptée au proxy.
+ * C'est cette fonction qui doit vérifier le contenu de la réponse. Une fois la réponse envoyée
+ * au proxy, on considère qu'elle est correcte.
+ * @param {Request} request - Objet Request ou dérivant de la classe Request
+ * @param {string} valhallaResponseStr - Réponse de valhalla
+ *
+ */
+ writeIsochroneResponse(isochroneRequest, valhallaResponseStr) {
+ let point = {};
+ let geometry = {};
+ let valhallaResponse;
+
+ // Lecture de la réponse Valhalla
+ // ---
+ try {
+ valhallaResponse = JSON.parse(valhallaResponseStr);
+ } catch (error) {
+ LOGGER.error("unable to parse valhalla response")
+ LOGGER.error(valhallaResponseStr)
+ LOGGER.error(error)
+ }
+
+ // Si pgrResponse est vide
+ if (valhallaResponse.features.length === 0) {
+ throw errorManager.createError(" No data found ", 404);
+ }
+
+ // Création d'un objet Point (utile plus tard).
+ point = new Point(isochroneRequest.point.lon, isochroneRequest.point.lat, this.topology.projection);
+
+ let rawGeometry = valhallaResponse.features[0].geometry;
+
+ // Cas où il n'y a pas d'isochrone car costValue trop faible
+ if (rawGeometry === null) {
+ rawGeometry = {
+ type: 'Point',
+ coordinates: [
+ isochroneRequest.point.lon,
+ isochroneRequest.point.lat
+ ]
+ };
+ }
+
+ // Création d'un objet Polygon à partir du GeoJSON reçu.
+ geometry = new Polygon(rawGeometry, "geojson", this._topology.projection);
+
+ /* Envoi de la réponse au proxy. */
+ return new IsochroneResponse(
+ point,
+ isochroneRequest.resource,
+ isochroneRequest.costType,
+ isochroneRequest.costValue,
+ geometry,
+ isochroneRequest.profile,
+ isochroneRequest.direction,
+ isochroneRequest.askedProjection,
+ isochroneRequest.timeUnit,
+ isochroneRequest.distanceUnit
+ );
+ }
+}
diff --git a/src/js/utils/storageManager.js b/src/js/utils/storageManager.js
index 0732f62..1c533e9 100644
--- a/src/js/utils/storageManager.js
+++ b/src/js/utils/storageManager.js
@@ -37,7 +37,34 @@ module.exports = {
LOGGER.error("Le fichier " + jsonStorage.file + " n'existe pas.");
return false;
}
-
+ } else if (jsonStorage.tar || jsonStorage.config) {
+ // Vérification que le fichier existe et peut être lu.
+ if (fs.existsSync(jsonStorage.tar)) {
+ try {
+ fs.accessSync(jsonStorage.tar, fs.constants.R_OK);
+ } catch (err) {
+ LOGGER.error("Le fichier " + jsonStorage.tar + " ne peut etre lu.");
+ return false;
+ }
+ storageFound = true;
+ } else {
+ LOGGER.error("Le fichier " + jsonStorage.tar + " n'existe pas.");
+ return false;
+ }
+ } else if (jsonStorage.config) {
+ // Vérification que le fichier existe et peut être lu.
+ if (fs.existsSync(jsonStorage.config)) {
+ try {
+ fs.accessSync(jsonStorage.config, fs.constants.R_OK);
+ } catch (err) {
+ LOGGER.error("Le fichier " + jsonStorage.config + " ne peut etre lu.");
+ return false;
+ }
+ storageFound = true;
+ } else {
+ LOGGER.error("Le fichier " + jsonStorage.config + " n'existe pas.");
+ return false;
+ }
} else if (jsonStorage.costColumn) {
// TODO: Pas trop possible de vérifier sans requête
storageFound = true;
diff --git a/test/functional/request/cucumber/configurations/local-service.json b/test/functional/request/cucumber/configurations/local-service.json
index 9ebb29b..2bbd40c 100644
--- a/test/functional/request/cucumber/configurations/local-service.json
+++ b/test/functional/request/cucumber/configurations/local-service.json
@@ -51,9 +51,24 @@
"resource": "bduni-idf-osrm",
"coordinates": "2.333865,48.881989"
}
+ },
+ {
+ "id": "isochrone-valhalla",
+ "parameters": {
+ "resource": "bduni-idf-valhalla",
+ "point": "2.333865,48.881989"
+ }
+ },
+ {
+ "id": "route-valhalla",
+ "parameters": {
+ "resource": "bduni-idf-valhalla",
+ "start": "2.333865,48.881989",
+ "end": "2.344851,48.872393"
+ }
}
],
"alternativeParameters" : {
"url" : "127.0.0.1"
}
-}
\ No newline at end of file
+}
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
index c2c06a3..490f667 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
@@ -7,7 +7,7 @@ Feature: Road2-PGR
Scenario Outline: [] Route sur l'API simple 1.0.0
Given an "" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -15,61 +15,61 @@ Feature: Road2-PGR
Examples:
| method |
| GET |
- | POST |
+ | POST |
- Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes sur une ressource pgr
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes sur une ressource pgr
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
| key | value |
| constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
And the response should contain an attribute "constraints.[1].key"
- Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes dont une invalide sur une ressource pgr
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes dont une invalide sur une ressource pgr
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
| key | value |
| constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"test"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
- Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes sur une ressource pgr
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes sur une ressource pgr
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
| key | value |
| constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
And the response should contain an attribute "constraints.[1].key"
- Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes dont une invalide sur une ressource pgr
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes dont une invalide sur une ressource pgr
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
| key | value |
| constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"test"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
- Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes dont deux invalides sur une ressource pgr
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec trois contraintes dont deux invalides sur une ressource pgr
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
| key | value |
| constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"test1"}\|{"constraintType":"test2","key":"waytype","operator":"=","value":"tunnel"}\|{"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -81,7 +81,7 @@ Feature: Road2-PGR
| value |
| {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
| {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -94,7 +94,7 @@ Feature: Road2-PGR
| value |
| {"constraintType":"banned","key":"waytype","operator":"=","value":"test"} |
| {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -107,7 +107,7 @@ Feature: Road2-PGR
| {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
| {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
| {"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -121,7 +121,7 @@ Feature: Road2-PGR
| {"constraintType":"banned","key":"waytype","operator":"=","value":"test"} |
| {"constraintType":"banned","key":"waytype","operator":"=","value":"tunnel"} |
| {"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -134,53 +134,53 @@ Feature: Road2-PGR
| {"constraintType":"banned","key":"waytype","operator":"=","value":"test1"} |
| {"constraintType":"test2","key":"waytype","operator":"=","value":"tunnel"} |
| {"constraintType":"banned","key":"waytype","operator":"=","value":"pont"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
- Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
| key | value |
| constraints | {"constraintType":"banned","key":"importance","operator":">=","value":4} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
And the response should contain an attribute "constraints.[0].key"
- Scenario: [GET] Route sur l'API simple 1.0.0 avec une mauvaise contrainte spécifique pgr
+ Scenario: [GET] Route sur l'API simple 1.0.0 avec une mauvaise contrainte spécifique pgr
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with query parameters:
| key | value |
| constraints | {"constraintType":"banned","key":"importance","operator":">=","value":"4"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
- Scenario: [POST] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
+ Scenario: [POST] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
Given an "POST" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with table parameters of object for "constraints":
| value |
| {"constraintType":"banned","key":"importance","operator":">=","value":4} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
And the response should contain an attribute "constraints.[0].key"
- Scenario: [POST] Route sur l'API simple 1.0.0 avec une mauvaise contrainte spécifique pgr
+ Scenario: [POST] Route sur l'API simple 1.0.0 avec une mauvaise contrainte spécifique pgr
Given an "POST" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
And with table parameters of object for "constraints":
| value |
| {"constraintType":"banned","key":"importance","operator":">=","value":"4"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -191,7 +191,7 @@ Feature: Road2-PGR
And with query parameters:
| key | value |
| constraints | {"constraintType":"prefer","key":"cpx_classement_administratif","operator":"=","value":"autoroute"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -203,7 +203,7 @@ Feature: Road2-PGR
And with query parameters:
| key | value |
| constraints | {"constraintType":"prefer","key":"cpx_classement_administratif","operator":"=","value":"test"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -214,7 +214,7 @@ Feature: Road2-PGR
And with table parameters of object for "constraints":
| value |
| {"constraintType":"prefer","key":"cpx_classement_administratif","operator":"=","value":"autoroute"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -226,7 +226,7 @@ Feature: Road2-PGR
And with table parameters of object for "constraints":
| value |
| {"constraintType":"prefer","key":"cpx_classement_administratif","operator":"=","value":"test"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -237,7 +237,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with query parameters:
| key | value |
| constraints | {"constraintType":"avoid","key":"cpx_classement_administratif","operator":"=","value":"autoroute"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -249,7 +249,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with query parameters:
| key | value |
| constraints | {"constraintType":"avoid","key":"cpx_classement_administratif","operator":"=","value":"test"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -260,7 +260,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with table parameters of object for "constraints":
| value |
| {"constraintType":"avoid","key":"cpx_classement_administratif","operator":"=","value":"autoroute"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -272,7 +272,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with table parameters of object for "constraints":
| value |
| {"constraintType":"avoid","key":"cpx_classement_administratif","operator":"=","value":"test"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -283,7 +283,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with query parameters:
| key | value |
| constraints | {"constraintType":"banned","key":"importance","operator":"<=","value":1} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -295,7 +295,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with table parameters of object for "constraints":
| value |
| {"constraintType":"banned","key":"importance","operator":"<=","value":1} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -307,7 +307,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with query parameters:
| key | value |
| constraints | {"constraintType":"banned","key":"importance","operator":"=","value":1} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -319,7 +319,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with table parameters of object for "constraints":
| value |
| {"constraintType":"banned","key":"importance","operator":"=","value":1} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -331,7 +331,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with query parameters:
| key | value |
| constraints | {"constraintType":"prefer","key":"importance","operator":">=","value":5} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -343,7 +343,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with table parameters of object for "constraints":
| value |
| {"constraintType":"prefer","key":"importance","operator":">=","value":5} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -355,7 +355,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with query parameters:
| key | value |
| constraints | {"constraintType":"prefer","key":"importance","operator":">","value":5} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -367,7 +367,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with table parameters of object for "constraints":
| value |
| {"constraintType":"prefer","key":"importance","operator":">","value":5} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -379,7 +379,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with query parameters:
| key | value |
| constraints | {"constraintType":"prefer","key":"importance","operator":"!=","value":6} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -391,7 +391,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with table parameters of object for "constraints":
| value |
| {"constraintType":"prefer","key":"importance","operator":"!=","value":6} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -403,7 +403,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with query parameters:
| key | value |
| constraints | {"constraintType":"avoid","key":"importance","operator":"<","value":2} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -415,7 +415,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with table parameters of object for "constraints":
| value |
| {"constraintType":"avoid","key":"importance","operator":"<","value":2} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid road
@@ -427,7 +427,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with query parameters:
| key | value |
| constraints | {"constraintType":"avoid","key":"importance","operator":"<","value":"2"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -438,7 +438,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with table parameters of object for "constraints":
| value |
| {"constraintType":"avoid","key":"importance","operator":"<","value":"2"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -449,7 +449,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with query parameters:
| key | value |
| constraints | {"constraintType":"avoid","key":"importance","operator":"<","value":"test"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -460,7 +460,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
And with table parameters of object for "constraints":
| value |
| {"constraintType":"avoid","key":"importance","operator":"<","value":"test"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain "Parameter 'constraints' is invalid"
@@ -468,7 +468,7 @@ Scenario: [GET] Route sur l'API simple 1.0.0 avec une contrainte spécifique pgr
Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid iso
@@ -476,15 +476,15 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
- Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sans ressource
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sans ressource
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
And without query parameters:
- | key |
+ | key |
| resource |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'resource' not found"
@@ -492,15 +492,15 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
- Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec une mauvaise ressource
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec une mauvaise ressource
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
And with query parameters:
| key | value |
| resource | bduni-idf-osrm-2 |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'resource' is invalid"
@@ -508,15 +508,15 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
- Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sans point
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sans point
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
And without query parameters:
- | key |
+ | key |
| point |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'point' not found"
@@ -524,15 +524,15 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
- Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais point
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais point
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
And with query parameters:
| key | value |
| point | -9,-410 |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'point' is invalid"
@@ -540,15 +540,15 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
- Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sans costValue
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sans costValue
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
And without query parameters:
- | key |
+ | key |
| costValue |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'costValue' not found"
@@ -556,7 +556,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais costValue (1)
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -564,7 +564,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| costValue | -9,-410 |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'costValue' is invalid"
@@ -572,7 +572,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais costValue (2)
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -580,7 +580,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| costValue | Infinity |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'costValue' is invalid"
@@ -588,7 +588,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais costValue (3)
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -596,7 +596,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| costValue | NaN |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'costValue' is invalid"
@@ -604,7 +604,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais costValue (4)
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -612,7 +612,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| costValue | test |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'costValue' is invalid"
@@ -620,7 +620,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un costValue trop petit
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -628,7 +628,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| costValue | 5 |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'costValue' is invalid"
@@ -636,7 +636,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un costValue trop grand
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -644,7 +644,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| costValue | 30000 |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'costValue' is invalid"
@@ -652,15 +652,15 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
- Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sans costType
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sans costType
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
And without query parameters:
- | key |
+ | key |
| costType |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'costType' not found"
@@ -668,7 +668,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais costType
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -676,7 +676,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| costType | test |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'costType' is invalid"
@@ -684,7 +684,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais profile
@@ -693,7 +693,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| profile | test |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'profile' is invalid"
@@ -701,7 +701,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais direction
@@ -710,7 +710,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| direction | test |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'direction' is invalid"
@@ -718,7 +718,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais geometryFormat
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -726,7 +726,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| geometryFormat | test |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'geometryFormat' is invalid"
@@ -734,7 +734,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un geometryFormat polyline
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -742,14 +742,14 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| geometryFormat | polyline |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais distanceUnit
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -758,7 +758,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
| key | value |
| distanceUnit | test |
| costType | distance |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'distanceUnit' is invalid"
@@ -766,7 +766,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais timeUnit
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -774,7 +774,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| timeUnit | test |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'timeUnit' is invalid"
@@ -782,7 +782,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais crs
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
@@ -790,7 +790,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with query parameters:
| key | value |
| crs | test |
- When I send the request
+ When I send the request
Then the server should send a response with status 400
And the response should have an header "content-type" with value "application/json"
And the response should contain an attribute "error.message" with value "Parameter 'crs' is invalid"
@@ -798,15 +798,15 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
Examples:
| method |
| GET |
- | POST |
+ | POST |
- Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource pgr
+ Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource pgr
Given an "GET" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
And with query parameters:
| key | value |
| constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid iso
@@ -818,7 +818,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
And with table parameters of object for "constraints":
| value |
| {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} |
- When I send the request
+ When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
And the response should contain a complete and valid iso
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
new file mode 100644
index 0000000..562fced
--- /dev/null
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
@@ -0,0 +1,52 @@
+Feature: Road2-Valhalla
+ Tests fonctionnels complémentaires de Road2 via Valhalla
+
+ Background:
+ Given I have loaded all my test configuration in "../../configurations/local-service.json"
+
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource valhalla
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone-valhalla"
+ And with query parameters:
+ | key | value |
+ | costType | distance |
+ | costValue | 31000 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource valhalla
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone-valhalla"
+ And with query parameters:
+ | key | value |
+ | costType | distance |
+ | costValue | 1000 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+Scenario Outline: [] Route sur l'API simple 1.0.0 avec valhalla
+ Given an "" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-valhalla"
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
diff --git a/test/integration/mocha/resources/integrationValhallaResource.js b/test/integration/mocha/resources/integrationValhallaResource.js
new file mode 100644
index 0000000..56a2267
--- /dev/null
+++ b/test/integration/mocha/resources/integrationValhallaResource.js
@@ -0,0 +1,104 @@
+const assert = require('assert');
+const ValhallaResource = require('../../../../src/js/resources/valhallaResource');
+const RouteRequest = require('../../../../src/js/requests/routeRequest');
+const logManager = require('../../../unit/mocha/logManager');
+
+const sinon = require('sinon');
+
+describe('Test de la classe ValhallaResource', function() {
+
+ before(function() {
+ // runs before all tests in this block
+ logManager.manageLogs();
+ });
+
+ let resourceConfiguration = {
+ "resource": {
+ "id": "test-valhalla",
+ "type": "valhalla",
+ "description": "Exemple d'une ressource Valhalla",
+ "topology": {
+ "description": "Données OSM",
+ "storage": {
+ "file": "/home/docker/data/corse-latest.osm.pbf"
+ },
+ "projection": "EPSG:4326"
+ },
+ "sources": [
+ {
+ "id": "corse-auto-valhalla",
+ "type": "valhalla",
+ "storage": {
+ "tar": "/home/docker/data/corse-latest-valhalla-tiles.tar",
+ "dir": "/home/docker/data/corse-latest-valhalla-tiles/",
+ "config": "/home/docker/data/valhalla.json"
+ },
+ "cost": {
+ "profile": "car",
+ "optimization": "fastest",
+ "compute": {
+ "storage": {
+ "file": "/home/docker/config/graph_bdtopo.lua"
+ },
+ "configuration": {
+ "costing": "auto",
+ "storage": {
+ "file": "/home/docker/config/costs_calculation.json"
+ }
+ }
+ }
+ }
+ }
+ ],
+ "availableOperations":[
+
+ ],
+ "defaultSourceId": "corse-auto-valhalla",
+ "boundingBox": "-90,-180,90,180",
+ "defaultProjection": "EPSG:4326",
+ "availableProjections": ["EPSG:4326","EPSG:2154"]
+ }
+ };
+
+ let resource = new ValhallaResource(resourceConfiguration);
+
+ describe('Test du constructeur et des getters', function() {
+
+ it('Get Id', function() {
+ assert.equal(resource.id, "corse-osm");
+ });
+
+ it('Get Type', function() {
+ assert.equal(resource.type, "osrm");
+ });
+
+ it('Get Configuration', function() {
+ assert.deepEqual(resource.configuration, resourceConfiguration.resource);
+ });
+
+ it('Get waysAttributes', function() {
+ assert.deepEqual(resource.waysAttributes, ["name"]);
+ });
+
+ it('Get LinkedSource', function() {
+ let reference = {};
+ reference["carfastest"] = "corse-auto-valhalla";
+ assert.deepEqual(resource.linkedSource, reference);
+ });
+
+ });
+
+ describe('Test de getSourceIdFromRequest', function() {
+
+ // Pour ne pas dépendre de la classe RouteRequest
+ let request = sinon.mock(RouteRequest);
+ request.profile = "car";
+ request.optimization = "fastest";
+
+ it('getSourceIdFromRequest()', function() {
+ assert.equal(resource.getSourceIdFromRequest(request), "corse-auto-valhalla");
+ });
+
+ });
+
+});
diff --git a/test/integration/mocha/sources/integrationValhallaSource.js b/test/integration/mocha/sources/integrationValhallaSource.js
new file mode 100644
index 0000000..39d0d6a
--- /dev/null
+++ b/test/integration/mocha/sources/integrationValhallaSource.js
@@ -0,0 +1,135 @@
+const assert = require('assert');
+const valhallaSource = require('../../../../src/js/sources/valhallaSource');
+const RouteRequest = require('../../../../src/js/requests/routeRequest');
+const logManager = require('../logManager');
+const OSRM = require("osrm");
+
+const sinon = require('sinon');
+const mockfs = require('mock-fs');
+
+describe('Test de la classe valhallaSource', function() {
+
+ before(function() {
+ // runs before all tests in this block
+ logManager.manageLogs();
+
+ mockfs({
+ "/home/docker/data": {
+ "corse-latest.osm.pbf": "",
+ "corse-latest-valhalla-tiles.tar": "",
+ },
+ "/home/docker/config": {
+ "graph_bdtopo.lua": "",
+ "costs_calculation.json": "",
+ },
+ "/home/docker/data/corse-latest-valhalla-tiles": {
+ }
+ });
+ });
+
+ after(() => {
+ mockfs.restore();
+ });
+
+ let sourceDescription = {
+ "id": "corse-auto-valhalla",
+ "type": "valhalla",
+ "storage": {
+ "tar": "/home/docker/data/corse-latest-valhalla-tiles.tar",
+ "dir": "/home/docker/data/corse-latest-valhalla-tiles/",
+ "config": "/home/docker/data/valhalla.json"
+ },
+ "cost": {
+ "profile": "car",
+ "optimization": "fastest",
+ "compute": {
+ "storage": {
+ "file": "/home/docker/config/graph_bdtopo.lua"
+ },
+ "configuration": {
+ "costing": "auto",
+ "storage": {
+ "file": "/home/docker/config/costs_calculation.json"
+ }
+ }
+ }
+ }
+ };
+
+ let topology = {
+ "id": "corse-osm",
+ "type": "osm",
+ "description": "Données OSM sur la Corse.",
+ "storage": {
+ "file": "/home/docker/data/corse-latest.osm.pbf"
+ },
+ "projection": "EPSG:4326",
+ "bbox": "-90,-180,90,180",
+
+ };
+
+ let source = new valhallaSource(sourceDescription, topology);
+
+ describe('Test du constructeur et des getters', function() {
+
+ it('Get Source id', function() {
+ assert.equal(source.id, "corse-car-fastest");
+ });
+
+ it('Get Source type', function() {
+ assert.equal(source.type, "osrm");
+ });
+
+ it('Get Source connected', function() {
+ assert.equal(source.connected, false);
+ });
+
+ it('Get Source configuration', function() {
+ assert.deepEqual(source.configuration, sourceDescription);
+ });
+
+ });
+
+ // describe('Test de connect()', function() {
+
+ // // Impossible à tester sans les fichiers : connect() appelle le constructeur OSRM qui a besoin
+ // // d'un fichier, et qui visiblement le check (cf. mockfs dans le script before() )
+ // it('Connect()', async function() {
+ // const sourceConnected = await source.connect();
+ // assert.equal(sourceConnected, true);
+ // });
+
+ // });
+
+ describe('Test de disconnect()', function() {
+
+ it('Disconnect()', async function() {
+ await source.disconnect();
+ });
+
+ });
+
+ describe('Test de computeRequest() et writeRouteResponse()', function() {
+
+ let resource = "resource-test";
+ let start = {lon: 8.732901, lat: 41.928821, getCoordinatesIn(toto) { return [8.732901, 41.928821];} };
+ let end = {lon: 8.76385, lat: 41.953932, getCoordinatesIn(toto) { return [8.76385, 41.953932];}};
+ let profile = "car-test";
+ let optimization = "fastest-test";
+ let routeRequest = new RouteRequest(resource, start, end, profile, optimization);
+
+ // TODO: better fake osrm response
+ const fakeOsrmResponse = {"routes":[{"geometry":"cf|~Fssht@tAgLFiNqJTaEuFiEpEgIxCsLdDwDw@oIac@mAg@cKkTBiBeAaByCqSkHc[mGaQHiGgB_@wL{[_FvBsDmEuEeB{RjGk@e@Z{B","legs":[{"summary":"Avenue Colonel Colonna d'Ornano, Route de Mezzavia","weight":449.7,"duration":449.7,"steps":[{"intersections":[{"out":0,"entry":[true],"bearings":[204],"location":[8.732901,41.928821]}],"driving_side":"right","geometry":"cf|~Fssht@B@","mode":"driving","maneuver":{"bearing_after":204,"bearing_before":0,"location":[8.732901,41.928821],"type":"depart"},"weight":5.3,"duration":5.3,"name":"Avenue du Maréchal Moncey","distance":2.4},{"intersections":[{"out":1,"in":0,"entry":[false,true,true],"bearings":[15,120,300],"location":[8.732889,41.928801]},{"out":0,"in":1,"entry":[true,false,true],"bearings":[105,285,315],"location":[8.734336,41.92853]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[105,135,285],"location":[8.734622,41.92846]}],"driving_side":"right","geometry":"_f|~Fqsht@Rw@Hq@HwBL_ALw@LoAIuCG{BA]AY@SZkC","mode":"driving","maneuver":{"bearing_after":113,"bearing_before":199,"location":[8.732889,41.928801],"modifier":"left","type":"turn"},"ref":"D 11","weight":53.3,"duration":53.3,"name":"Avenue Colonel Colonna d'Ornano","distance":388.2},{"intersections":[{"out":0,"in":3,"entry":[true,false,true,false],"bearings":[15,105,180,285],"location":[8.737468,41.928353]},{"out":3,"in":1,"entry":[true,false,true,true],"bearings":[105,165,285,345],"location":[8.737421,41.928889]},{"out":0,"in":1,"entry":[true,false,false],"bearings":[15,180,345],"location":[8.737359,41.930203]}],"driving_side":"right","geometry":"ec|~Fepit@MC_@Gg@LUFm@PwEEe@Qc@Y","mode":"driving","maneuver":{"bearing_after":9,"bearing_before":104,"location":[8.737468,41.928353],"modifier":"left","type":"turn"},"weight":22.8,"duration":22.8,"name":"Boulevard Dominique Paoli","distance":253.1},{"intersections":[{"out":0,"in":1,"entry":[true,false,true],"bearings":[60,210,270],"location":[8.737582,41.930566]},{"out":0,"in":1,"entry":[true,false,true],"bearings":[60,240,315],"location":[8.737632,41.930591]},{"out":0,"in":2,"entry":[true,false,false],"bearings":[45,105,240],"location":[8.737712,41.93063]},{"out":0,"in":1,"entry":[true,false,true],"bearings":[45,225,330],"location":[8.737925,41.930761]}],"driving_side":"right","geometry":"aq|~F{pit@CIGOYk@g@aAi@aA","mode":"driving","maneuver":{"bearing_after":54,"bearing_before":28,"location":[8.737582,41.930566],"modifier":"slight right","type":"new name"},"weight":14.5,"duration":14.5,"name":"Avenue du Président Kennedy","distance":107.6},{"intersections":[{"out":2,"in":1,"entry":[true,false,true],"bearings":[120,225,330],"location":[8.738593,41.931173]},{"out":2,"in":1,"entry":[true,false,true],"bearings":[45,150,315],"location":[8.738491,41.931273]},{"out":2,"in":1,"entry":[true,false,true],"bearings":[45,135,315],"location":[8.738055,41.931646]},{"out":2,"in":1,"entry":[true,false,true],"bearings":[75,165,345],"location":[8.737414,41.932566]},{"out":0,"in":2,"entry":[true,true,false,true],"bearings":[15,60,165,300],"location":[8.737348,41.932831]},{"out":2,"in":1,"entry":[true,false,true],"bearings":[30,195,345],"location":[8.737389,41.932923]}],"driving_side":"right","geometry":"yt|~Fewit@SRkAtAa@b@gAbAMF_APs@JQGI@aA\\o@d@Y^]Tc@HuBJ","mode":"driving","maneuver":{"bearing_after":322,"bearing_before":49,"location":[8.738593,41.931173],"modifier":"left","type":"end of road"},"weight":28.2,"duration":28.2,"name":"Montée Saint-Jean","distance":426.4},{"intersections":[{"out":2,"in":1,"entry":[false,false,true],"bearings":[135,180,345],"location":[8.736664,41.934585]},{"out":2,"in":1,"entry":[true,false,true],"bearings":[75,165,330],"location":[8.736303,41.935359]}],"driving_side":"right","geometry":"ej}~Fckit@e@PKDIB}Aj@_CfAu@Fu@@e@Q","mode":"driving","maneuver":{"bearing_after":337,"bearing_before":355,"location":[8.736664,41.934585],"modifier":"straight","type":"new name"},"weight":17.5,"duration":17.5,"name":"Route d'Alata","distance":251.1},{"intersections":[{"out":0,"in":1,"entry":[true,false,false],"bearings":[90,195,285],"location":[8.735976,41.936731]}],"driving_side":"right","geometry":"qw}~F{fit@?KAKCIEGGEGAI@","mode":"driving","maneuver":{"exit":1,"bearing_after":95,"bearing_before":16,"location":[8.735976,41.936731],"modifier":"right","type":"roundabout"},"weight":3.3,"duration":3.3,"name":"Boulevard de l'Abbé Recco","distance":34.7},{"intersections":[{"out":0,"in":1,"entry":[true,false,true],"bearings":[75,180,330],"location":[8.736216,41.936918]}],"driving_side":"right","geometry":"wx}~Fkhit@e@aDm@kDs@uDc@_COq@_BgGm@cBOe@","mode":"driving","maneuver":{"exit":1,"bearing_after":71,"bearing_before":351,"location":[8.736216,41.936918],"modifier":"right","type":"exit roundabout"},"weight":28.1,"duration":28.1,"name":"Boulevard de l'Abbé Recco","distance":494.6},{"intersections":[{"out":0,"in":1,"entry":[true,false,false],"bearings":[135,240,330],"location":[8.7417,41.938654]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[60,150,255],"location":[8.74199,41.938595]}],"driving_side":"right","geometry":"qc~~Fsjjt@JS@SCQCKGEMCK?OH","mode":"driving","maneuver":{"exit":2,"bearing_after":130,"bearing_before":57,"location":[8.7417,41.938654],"modifier":"right","type":"roundabout"},"weight":3.8,"duration":3.8,"name":"","distance":61.3},{"intersections":[{"out":0,"in":1,"entry":[true,false,true],"bearings":[45,150,300],"location":[8.742045,41.938866]}],"driving_side":"right","geometry":"}d~~Fyljt@W[[u@uAiCm@gAcDcH[o@Uq@M]Mk@","mode":"driving","maneuver":{"exit":2,"bearing_after":39,"bearing_before":336,"location":[8.742045,41.938866],"modifier":"right","type":"exit roundabout"},"weight":23,"duration":23,"name":"","distance":394.8},{"intersections":[{"out":0,"in":1,"entry":[true,false,false],"bearings":[150,240,345],"location":[8.745834,41.941003]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[75,165,285],"location":[8.746049,41.940898]}],"driving_side":"right","geometry":"gr~~Fmdkt@HKFM@QAQGMIIKEMB","mode":"driving","maneuver":{"exit":2,"bearing_after":146,"bearing_before":66,"location":[8.745834,41.941003],"modifier":"right","type":"roundabout"},"weight":3.9000000000000004,"duration":3.9000000000000004,"name":"","distance":59.2},{"intersections":[{"out":0,"in":1,"entry":[true,false,true],"bearings":[60,180,330],"location":[8.746274,41.941128]},{"out":0,"in":1,"entry":[true,false,true],"bearings":[75,240,285],"location":[8.746626,41.94126]},{"out":1,"in":2,"entry":[false,true,false],"bearings":[30,75,255],"location":[8.747412,41.941483]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[70,82,250],"location":[8.747665,41.941553]},{"out":0,"in":2,"entry":[true,false,false,true],"bearings":[75,240,255,270],"location":[8.749168,41.94197]}],"driving_side":"right","geometry":"as~~Fegkt@YgAG[WsAKk@Ms@_@qBs@yDG]SgA","mode":"driving","maneuver":{"exit":2,"bearing_after":61,"bearing_before":351,"location":[8.746274,41.941128],"modifier":"right","type":"exit roundabout"},"weight":17.6,"duration":17.6,"name":"","distance":302.1},{"intersections":[{"out":1,"in":2,"entry":[false,true,false],"bearings":[0,150,255],"location":[8.749676,41.942111]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[75,180,285],"location":[8.749846,41.942021]},{"out":0,"in":2,"entry":[true,false,false],"bearings":[15,180,225],"location":[8.75,41.942081]}],"driving_side":"right","geometry":"ey~~Fo|kt@JIDWAMIOSE","mode":"driving","maneuver":{"exit":2,"bearing_after":146,"bearing_before":68,"location":[8.749676,41.942111],"modifier":"right","type":"roundabout"},"weight":3.1,"duration":3.1,"name":"Boulevard Louis Campi","distance":44.2},{"intersections":[{"out":0,"in":1,"entry":[true,false,true],"bearings":[75,195,330],"location":[8.750029,41.94218]}],"driving_side":"right","geometry":"sy~~Fu~kt@_AaGYkA_C}I_@iAW_A","mode":"driving","maneuver":{"exit":2,"bearing_after":70,"bearing_before":11,"location":[8.750029,41.94218],"modifier":"right","type":"exit roundabout"},"weight":21.4,"duration":21.4,"name":"Boulevard Louis Campi","distance":373.6},{"intersections":[{"out":0,"in":1,"entry":[true,false,false],"bearings":[135,240,345],"location":[8.754141,41.94355]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[75,135,255],"location":[8.754363,41.943511]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[30,90,210],"location":[8.754453,41.943572]}],"driving_side":"right","geometry":"eb__Gkxlt@FMBOCMCKGECCO@","mode":"driving","maneuver":{"exit":1,"bearing_after":135,"bearing_before":61,"location":[8.754141,41.94355],"modifier":"right","type":"roundabout"},"weight":2.6999999999999997,"duration":2.6999999999999997,"name":"Rue Louis Campi","distance":43.2},{"intersections":[{"out":0,"in":1,"entry":[true,false,true],"bearings":[60,180,330],"location":[8.754461,41.943674]}],"driving_side":"right","geometry":"}b__Gkzlt@oC}Hg@iBy@qCG_AEm@C}@","mode":"driving","maneuver":{"exit":1,"bearing_after":57,"bearing_before":357,"location":[8.754461,41.943674],"modifier":"right","type":"exit roundabout"},"weight":19.9,"duration":19.9,"name":"Rue Louis Campi","distance":343.5},{"intersections":[{"out":1,"in":2,"entry":[false,true,false],"bearings":[0,165,270],"location":[8.758172,41.944968]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[120,195,315],"location":[8.758272,41.944843]},{"out":0,"in":2,"entry":[true,false,false],"bearings":[90,195,285],"location":[8.758437,41.944791]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[30,75,225],"location":[8.758702,41.944872]},{"out":0,"in":2,"entry":[true,false,false],"bearings":[0,105,195],"location":[8.75877,41.94501]}],"driving_side":"right","geometry":"ak__Gqqmt@LGJKDOBQ?IAKEQGKMIMCK@KDIHEL","mode":"driving","maneuver":{"exit":3,"bearing_after":160,"bearing_before":85,"location":[8.758172,41.944968],"modifier":"right","type":"roundabout"},"ref":"T 22","weight":8.8,"duration":8.8,"name":"Route de Mezzavia","distance":100.3},{"intersections":[{"out":0,"in":1,"entry":[true,false,true],"bearings":[45,135,285],"location":[8.758609,41.945214]}],"driving_side":"right","geometry":"ql__Gitmt@[e@Uu@s@_D{@oCiB_CkBmE{@iCM_@Q}@","mode":"driving","maneuver":{"exit":3,"bearing_after":45,"bearing_before":306,"location":[8.758609,41.945214],"modifier":"right","type":"exit roundabout"},"ref":"T 22","weight":49.4,"duration":49.4,"name":"Route de Mezzavia","distance":480.3},{"intersections":[{"out":2,"in":1,"entry":[true,false,true],"bearings":[60,255,330],"location":[8.763419,41.947548]}],"driving_side":"right","geometry":"e{__Gkrnt@u@h@g@\\k@\\m@Pg@?aAe@i@cAgAcB{Ac@yBaA","mode":"driving","maneuver":{"bearing_after":330,"bearing_before":67,"location":[8.763419,41.947548],"modifier":"left","type":"turn"},"weight":57.4,"duration":57.4,"name":"","distance":397.2},{"intersections":[{"out":2,"in":1,"entry":[true,false,true],"bearings":[45,195,345],"location":[8.764357,41.950639]},{"out":2,"in":1,"entry":[true,false,true],"bearings":[60,150,345],"location":[8.763892,41.951919]}],"driving_side":"right","geometry":"on`_Ggxnt@iBXyA`@{@`@c@RkAn@s@VaCf@uAh@","mode":"driving","maneuver":{"bearing_after":348,"bearing_before":21,"location":[8.764357,41.950639],"modifier":"slight left","type":"fork"},"weight":53.5,"duration":53.5,"name":"","distance":372},{"intersections":[{"out":0,"in":1,"entry":[true,false,true],"bearings":[15,165,315],"location":[8.763022,41.953818]}],"driving_side":"right","geometry":"kba_G{ont@QIQIGQA]DUH[Lk@","mode":"driving","maneuver":{"bearing_after":18,"bearing_before":338,"location":[8.763022,41.953818],"modifier":"slight right","type":"fork"},"weight":12.2,"duration":12.2,"name":"","distance":85.1},{"intersections":[{"in":0,"entry":[true],"bearings":[294],"location":[8.763831,41.953897]}],"driving_side":"right","geometry":"{ba_G}tnt@","mode":"driving","maneuver":{"bearing_after":0,"bearing_before":114,"location":[8.763831,41.953897],"type":"arrive"},"weight":0,"duration":0,"name":"","distance":0}],"distance":5015}],"weight_name":"routability","weight":449.7,"duration":449.7,"distance":5015}],"waypoints":[{"hint":"dQ0AgO8zAIAPAAAABAAAAIIAAAAAAAAAoawtQWjKG0D0ELRCAAAAAA8AAAAEAAAAggAAAAAAAAAMAAAA5UCFAHXIfwLlQIUAdch_AgMAvwy-YJX8","name":"Avenue du Maréchal Moncey","location":[8.732901,41.928821]},{"hint":"8iwAgCEtAIAAAAAAFwAAAHoAAAAiAAAApgWzPh9jf0E3v6lCdn-wQQAAAAAXAAAAegAAACIAAAAMAAAAt7mFAGkqgALKuYUAjCqAAgcA_wa-YJX8","name":"","location":[8.763831,41.953897]}]};
+
+ const fakeClient = sinon.mock(OSRM);
+ fakeClient.route = sinon.stub().callsArgOnWith(1, source, null, fakeOsrmResponse);
+ source._osrm = fakeClient;
+
+ it('computeRequest() should return a routeResponse', async function() {
+ const routeResponse = await source.computeRequest(routeRequest);
+ assert.equal(routeResponse.resource, "resource-test");
+ });
+
+ });
+
+});
From d2d6c557a572c665cef9de07ce3aa769ac4405de Mon Sep 17 00:00:00 2001
From: Loic
Date: Fri, 21 Oct 2022 15:44:33 +0200
Subject: [PATCH 09/93] maj du changelog.md
---
changelog.md | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/changelog.md b/changelog.md
index 49dcf98..7659939 100644
--- a/changelog.md
+++ b/changelog.md
@@ -3,11 +3,27 @@
ADDED:
- La classe Administrator permet de gérer le service via une API. Notamment la création, la suppression et la modification d'un service seront possible.
- Cette classe est configurée par un nouveau fichier de configuration.
+ - Ajout du moteur Valhalla pour les itinéraires et les isochrones
CHANGED:
- L'option --configCheck au démarrage de Road2 n'a plus exactement le même comportement.
- Le fichier server.json permet maintenant de configurer l'administrateur et donc n'a plus le même contenu. Ce dernier est dans service.json.
+# 1.1.2
+
+FIXED:
+ - Géométries reprojetées pour les requêtes sur PGRouting
+
+# 1.1.1
+
+FIXED:
+ - Géométrie étrange quand on est dans une raquette
+
+# 1.1.0
+
+ADDED:
+ - Ajout de la fonctionnalité nearest via OSRM
+
# 1.O.14
FIXED:
- Mauvaise ligne pour un log
From ad99de3f7965b14b200cd85528d85f71c7d316db Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 24 Oct 2022 11:44:25 +0200
Subject: [PATCH 10/93] fix: commande du docker-compose de road2
---
docker/dev/docker-compose.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml
index d4756d8..b0edc31 100644
--- a/docker/dev/docker-compose.yml
+++ b/docker/dev/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- pgrouting
environment:
- NODE_ENV=debug
- command : "sleep 60000"
+ command : "npm run debug -- --ROAD2_CONF_FILE=../config/road2.json"
ports:
- 8080:8080
- 9229:9229
From a63f430fc630fec96fa20972ee5150cd4d38d3ed Mon Sep 17 00:00:00 2001
From: Loic
Date: Wed, 26 Oct 2022 11:33:08 +0200
Subject: [PATCH 11/93] =?UTF-8?q?WIP:=20s=C3=A9paration=20des=20sources?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docker/config/service.json | 5 +
docker/dev/docker-compose.yml | 2 +-
src/js/geography/projectionManager.js | 63 ++++-
src/js/resources/resourceManager.js | 21 +-
src/js/service/service.js | 89 ++++++-
src/js/sources/sourceManager.js | 349 ++++++++++++++++----------
src/js/topology/topologyManager.js | 2 +-
7 files changed, 380 insertions(+), 151 deletions(-)
diff --git a/docker/config/service.json b/docker/config/service.json
index b9c0620..265db84 100644
--- a/docker/config/service.json
+++ b/docker/config/service.json
@@ -23,6 +23,11 @@
"/home/docker/data/resources/"
]
},
+ "sources": {
+ "directories": [
+ "/home/docker/data/sources/"
+ ]
+ },
"network": {
"servers": [
{
diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml
index b0edc31..d4756d8 100644
--- a/docker/dev/docker-compose.yml
+++ b/docker/dev/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- pgrouting
environment:
- NODE_ENV=debug
- command : "npm run debug -- --ROAD2_CONF_FILE=../config/road2.json"
+ command : "sleep 60000"
ports:
- 8080:8080
- 9229:9229
diff --git a/src/js/geography/projectionManager.js b/src/js/geography/projectionManager.js
index fb1d755..a58c178 100644
--- a/src/js/geography/projectionManager.js
+++ b/src/js/geography/projectionManager.js
@@ -50,12 +50,12 @@ module.exports = class ProjectionManager {
/**
*
* @function
- * @name isAvailable
+ * @name isProjectionLoaded
* @description Savoir si une projection est disponible dans l'instance de proj4
* @param {string} id - ID de la projection
*
*/
- isAvailable (id) {
+ isProjectionLoaded (id) {
if (!id) {
return false;
@@ -77,12 +77,12 @@ module.exports = class ProjectionManager {
/**
*
* @function
- * @name isChecked
+ * @name isProjectionChecked
* @description Savoir si une projection a été validé durant l'étape de vérification
* @param {string} id - ID de la projection
*
*/
- isChecked (id) {
+ isProjectionChecked (id) {
if (!id) {
return false;
@@ -101,6 +101,61 @@ module.exports = class ProjectionManager {
}
+ /**
+ *
+ * @function
+ * @name checkBboxConfiguration
+ * @description Savoir si une bbox est valide dans une projection donnée
+ * @param {string} bbox - Bbox à vérifier
+ * @param {string} projectionId - ID de la projection
+ *
+ */
+ checkBboxConfiguration (bbox, projectionId) {
+
+ LOGGER.info("Vérification d'une bbox...");
+
+ if (!bbox) {
+ LOGGER.error("Aucune bbox fournie");
+ return false;
+ }
+
+ if (typeof(bbox) !== "string") {
+ LOGGER.error("La bbox fournie n'est pas une chaine de caracteres");
+ return false;
+ }
+
+ let regex = new RegExp("^(-?\d+\.?\d*),(-?\d+\.?\d*),(-?\d+\.?\d*),(-?\d+\.?\d*)$");
+ if (!regex.test(bbox)) {
+ LOGGER.error("La bbox n'est pas correctement formattée");
+ return false;
+ }
+
+ let bboxArray = new Array(4);
+ try {
+ bboxArray = regex.exec(bbox);
+ } catch(error) {
+ LOGGER.error("Impossible d'analyser la bbox");
+ LOGGER.error(error);
+ return false;
+ }
+
+ if (bboxArray[0] >= bboxArray[2]) {
+ LOGGER.error("Mauvaise configuration : Xmin est supérieur ou égal à Xmax");
+ return false;
+ }
+
+ if (bboxArray[1] >= bboxArray[3]) {
+ LOGGER.error("Mauvaise configuration : Ymin est supérieur ou égal à Ymax");
+ return false;
+ }
+
+ // TODO : vérifier la cohérence avec la projection indiquée
+
+ LOGGER.info("Vérification de la bbox terminée");
+ return true;
+
+ }
+
/**
*
* @function
diff --git a/src/js/resources/resourceManager.js b/src/js/resources/resourceManager.js
index b6a685d..897e3f5 100644
--- a/src/js/resources/resourceManager.js
+++ b/src/js/resources/resourceManager.js
@@ -236,21 +236,14 @@ module.exports = class resourceManager {
for (let i = 0; i < resourceJsonObject.resource.sources.length; i++ ) {
- let sourceJsonObject = resourceJsonObject.resource.sources[i];
- if (!this._sourceManager.checkSourceConfiguration(sourceJsonObject)) {
- LOGGER.error("La ressource contient une source invalide.");
+ let sourceId = resourceJsonObject.resource.sources[i];
+ if (!this._sourceManager.isCheckedSourceAvailable(sourceId)) {
+ LOGGER.error("La ressource contient une source non disponible.");
return false;
} else {
- // on stocke l'id de la ressource pour cette source donnée
- this._sourceManager.saveCheckedSource(sourceJsonObject);
+ // TODO : on stocke l'id de la ressource pour cette source donnée
}
- // Lien avec la topologie
- // TODO: vérifier que le type de la topologie soit cohérent avec le type de la source
-
- // On stocke la correspondance entre une source et la topologie dont elle dérive
- this._sourceManager.sourceTopology[sourceJsonObject.id] = resourceJsonObject.resource.topology.id;
-
}
}
@@ -396,10 +389,10 @@ module.exports = class resourceManager {
}
// Création des sources associées
- LOGGER.info("Chargement des sources associées...");
+ LOGGER.info("Vérification du chargement des sources associées...");
for (let i = 0; i < resourceJsonObject.resource.sources.length; i++) {
- if (!this._sourceManager.loadSourceConfiguration(resourceJsonObject.resource.sources[i], currentTopology)) {
- LOGGER.error("Impossible de créer la source associée à la ressource : " + resourceJsonObject.resource.sources[i].id);
+ if (!this._sourceManager.isLoadedSourceAvailable(resourceJsonObject.resource.sources[i])) {
+ LOGGER.error("La source associée à la ressource n'est pas chargée : " + resourceJsonObject.resource.sources[i].id);
return false;
}
}
diff --git a/src/js/service/service.js b/src/js/service/service.js
index 899ca66..66344c3 100644
--- a/src/js/service/service.js
+++ b/src/js/service/service.js
@@ -52,7 +52,7 @@ module.exports = class Service {
this._topologyManager = new TopologyManager(this._baseManager, this._projectionManager);
// Manager des sources du service.
- this._sourceManager = new SourceManager();
+ this._sourceManager = new SourceManager(this._projectionManager);
// Manager des ressources du service.
this._resourceManager = new ResourceManager(this._sourceManager, this._operationManager, this._topologyManager);
@@ -426,6 +426,63 @@ module.exports = class Service {
}
+ // Information sur les sources
+ LOGGER.debug("Vérification des informations sur les sources");
+
+ if (!userConfiguration.application.sources) {
+ LOGGER.fatal("Mauvaise configuration: Objet 'application:sources' manquant !");
+ return false;
+ } else {
+ // Dossier contenant les fichiers de sources
+ if (!userConfiguration.application.sources.directories) {
+ LOGGER.fatal("Mauvaise configuration: Champ 'application:sources:directories' manquant !");
+ return false;
+ } else {
+
+ let sourcesDirectories = userConfiguration.application.sources.directories;
+ // On vérifie que c'est un tableau non vide
+ if (!Array.isArray(sourcesDirectories)) {
+ LOGGER.error("Mauvaise configuration: Champ 'application:sources:directories' n'est pas un tableau !");
+ return false;
+ }
+ if (sourcesDirectories.length === 0) {
+ LOGGER.error("Mauvaise configuration: Champ 'application:sources:directories' est un tableau vide !");
+ return false;
+ }
+
+ let oneValidDir = false;
+
+ for (let i = 0; i < sourcesDirectories.length; i++) {
+
+ // On vérifie que le dossier existe et qu'il contient des fichiers de description des ressources
+ if (sourcesDirectories[i] === "") {
+ LOGGER.warn("Mauvaise configuration: Champ 'application:sources:directories' contient un élément vide");
+ continue;
+ } else {
+
+ let directory = path.resolve(path.dirname(userConfigurationPath), sourcesDirectories[i]);
+
+ if (!(await this._sourceManager.checkSourceDirectory(directory))) {
+ LOGGER.error("Le dossier " + directory + " contient des sources dont la vérification a échoué");
+ return false;
+ } else {
+ LOGGER.info("Le dossier " + directory + " est vérifié et suffisamment validé pour continuer");
+ oneValidDir = true;
+ }
+
+ }
+
+ }
+
+ if (!oneValidDir) {
+ LOGGER.error("Aucun dossier de source n'a été validé");
+ return false;
+ }
+
+ }
+
+ }
+
// Information sur les ressources
LOGGER.debug("Vérification des informations sur les ressources");
@@ -683,6 +740,36 @@ module.exports = class Service {
return false;
}
+ // Chargement des sources
+ LOGGER.info("Chargement des sources...");
+
+ for (let i = 0; i < this._configuration.application.sources.directories.length; i++) {
+
+ let sourceDirectory = "";
+
+ try {
+ sourceDirectory = path.resolve(path.dirname(this._configurationPath), this._configuration.application.sources.directories[i]);
+ LOGGER.info("Dossier de sources : " + sourceDirectory);
+ } catch (error) {
+ LOGGER.error("Impossible d'obtenir le chemin absolu du dossier de sources: " + this._configuration.application.sources.directories[i]);
+ LOGGER.error(error);
+ continue;
+ }
+
+ if (!this._sourceManager.loadSourceDirectory(sourceDirectory)) {
+ LOGGER.error("Impossible de charger correctement le dossier de sources " + sourceDirectory);
+ } else {
+ // On va continuer
+ LOGGER.info("Les sources du dossier " + sourceDirectory + " sont chargées dans la mesure du possible")
+ }
+
+ }
+
+ if (this._sourceManager.source.length === 0) {
+ LOGGER.fatal("Aucune ressource n'a pu etre chargee");
+ return false;
+ }
+
// Chargement des ressources
LOGGER.info("Chargement des ressources...");
diff --git a/src/js/sources/sourceManager.js b/src/js/sources/sourceManager.js
index 86d365d..7c7ac7b 100644
--- a/src/js/sources/sourceManager.js
+++ b/src/js/sources/sourceManager.js
@@ -21,7 +21,7 @@ module.exports = class sourceManager {
* @description Constructeur de la classe sourceManager
*
*/
- constructor() {
+ constructor(projectionManager) {
// Liste des ids des sources chargées par le manager
this._loadedSourceId = new Array();
@@ -38,14 +38,15 @@ module.exports = class sourceManager {
// Descriptions des sources vérifiées par le manager
this._checkedSourceConfiguration = {};
- // Correspondance entre l'id d'une source et l'id de la topologie dont elle dérive
- this._sourceTopology = {};
+ // Manager des projections
+ this._projectionManager = projectionManager;
// Correspondance entre les sources et les opérations possibles
this._operationsByType = {
"osrm": ["nearest", "route"],
"pgr": ["route", "isochrone"],
- "smartrouting": ["route", "isochrone"]
+ "smartrouting": ["route", "isochrone"],
+ "valhalla": ["route", "isochrone"]
};
}
@@ -53,64 +54,151 @@ module.exports = class sourceManager {
/**
*
* @function
- * @name get loadedSourceId
+ * @name get source
* @description Récupérer l'ensemble des ids de sources chargées
*
*/
- get loadedSourceId() {
- return this._loadedSourceId;
+ get source() {
+ return this._source;
}
/**
*
* @function
- * @name get source
- * @description Récupérer l'ensemble des ids de sources chargées
+ * @name get operationsByType
+ * @description Récupérer l'ensemble des opérations possibles par type de source
*
*/
- get source() {
- return this._source;
+ get operationsByType() {
+ return this._operationsByType;
}
/**
*
* @function
- * @name get sourceTopology
- * @description Récupérer la correspondance source/topologie
+ * @name isCheckedSourceAvailable
+ * @description Fonction utilisée pour vérifier si une source a été vérifiée
+ * @param {string} id - Id de la source
+ * @return {boolean}
*
*/
- get sourceTopology() {
- return this._sourceTopology;
+
+ isCheckedSourceAvailable(id) {
+
+ if (this._checkedSourceId.length === 0) {
+ return false;
+ }
+
+ for (let i = 0; i < this._checkedSourceId.length; i++) {
+ if (this._checkedSourceId[i] === id) {
+ return true;
+ }
+ }
+ return false;
+
}
/**
*
* @function
- * @name get operationsByType
- * @description Récupérer l'ensemble des opérations possibles par type de source
+ * @name isLoadedSourceAvailable
+ * @description Fonction utilisée pour vérifier si une source a été chargée
+ * @param {string} id - Id de la source
+ * @return {boolean}
*
*/
- get operationsByType() {
- return this._operationsByType;
+
+ isLoadedSourceAvailable(id) {
+
+ if (this._loadedSourceId.length === 0) {
+ return false;
+ }
+
+ for (let i = 0; i < this._loadedSourceId.length; i++) {
+ if (this._loadedSourceId[i] === id) {
+ return true;
+ }
+ }
+ return false;
+
}
/**
*
* @function
- * @name set loadedSourceId
- * @description Attribuer l'ensemble des ids de sources
- * @param {table} list - État de la connexion
+ * @name checkSourceDirectory
+ * @description Fonction utilisée pour vérifier un dossier contenant des sources.
+ * @param {string} directory - Dossier qui contient les configurations des ressources
+ * @return {boolean}
*
*/
- set loadedSourceId(list) {
- this._loadedSourceId = list;
+
+ checkSourceDirectory(directory) {
+
+ LOGGER.info("Vérification d'un dossier de sources...");
+ LOGGER.info("Nom du dossier: " + directory);
+
+ if (fs.existsSync(directory)) {
+
+ let fileList = new Array();
+ try {
+ fileList = fs.readdirSync(directory);
+ } catch(error) {
+ LOGGER.error("Impossible de lire le dossier :");
+ LOGGER.error(error);
+ return false;
+ }
+
+ if (fileList.length === 0) {
+ LOGGER.warn("Le dossier " + directory + " est vide");
+ return false;
+ }
+
+ for (let i = 0; i < fileList.length; i++) {
+
+ let source = fileList[i];
+ let sourceFile = "";
+ try {
+ sourceFile = directory + "/" + source;
+ fs.accessSync(sourceFile, fs.constants.R_OK);
+ } catch (err) {
+ LOGGER.error("Le fichier de source ne peut etre lu: " + sourceFile);
+ }
+
+ let sourceConf = {};
+ try {
+ // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard
+ sourceConf = JSON.parse(fs.readFileSync(sourceFile));
+ } catch (error) {
+ LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de source: " + sourceFile);
+ LOGGER.error(error);
+ return false;
+ }
+
+ if (!(await this.checkSourceConfiguration(sourceConf))) {
+ LOGGER.error("La source décrite dans le fichier " + sourceFile + " est mal configuée");
+ return false;
+ } else {
+ this._checkedSourceId.push(sourceConf.source.id);
+ }
+
+ }
+
+ LOGGER.info("Vérification du dossier de sources terminée");
+ return true;
+
+ } else {
+ LOGGER.error("Mauvaise configuration: Le dossier n'existe pas: " + directory );
+ return false;
+ }
+
}
/**
*
* @function
* @name checkSourceConfiguration
- * @description Fonction utilisée pour vérifier la partie source d'un fichier de description d'une ressource.
+ * @description Fonction utilisée pour vérifier la configuration d'une source.
* @param {json} sourceJsonObject - Description JSON de la source
* @return {boolean}
*
@@ -122,7 +210,7 @@ module.exports = class sourceManager {
// ID
if (!sourceJsonObject.id) {
- LOGGER.error("La ressource contient une source sans id.");
+ LOGGER.error("Mauvaise configuration: source.id absent");
return false;
} else {
// On vérifie que l'id n'est pas déjà chargé.
@@ -175,128 +263,70 @@ module.exports = class sourceManager {
// Type
if (!sourceJsonObject.type) {
- LOGGER.error("La ressource contient une source sans type.");
+ LOGGER.error("Mauvaise configuration: source.type absent");
return false;
} else {
- // Vérification que le type est valide puis vérification spécifique à chaque type
- let available = false;
- // La partie délimitée peut être copié-collée pour ajouter un nouveau type.
- // Il ne reste plus qu'à créer la fonction de vérification correspondante.
- //------ OSRM
- if (sourceJsonObject.type === "osrm") {
- available = true;
- LOGGER.info("Source osrm.");
- // On vérifie que le module osrm est disponible
- try {
- let osrmTest = require('osrm');
- } catch(error) {
- LOGGER.error("Le module osrm n'est pas disponible mais une source osrm est proposée dans la configuration.");
- return false;
- }
+ LOGGER.debug("Type présent");
- if (!this.checkSourceOsrm(sourceJsonObject)) {
- LOGGER.error("Erreur lors de la verification de la source osrm.");
- return false;
- } else {
- // il n'y a eu aucun problème, la source est correctement configurée.
- }
+ // Vérification que le type est valide puis vérification spécifique à chaque type
+
+ if (!Object.keys(this._operationsByType).includes(sourceJsonObject.type)) {
+ LOGGER.error("La source indique un type non disponible : " + sourceJsonObject.type);
+ return false;
} else {
- // On va voir si c'est un autre type.
+ LOGGER.debug("Le type présent est disponible : " + sourceJsonObject.type);
}
- //------ OSRM
- //------ PGR
- if (sourceJsonObject.type === "pgr") {
- available = true;
- LOGGER.info("Source pgrouting.");
- // On vérifie que le module pg est disponible
- try {
- let { poolTest } = require('pg');
- } catch(error) {
- LOGGER.error("Le module pg n'est pas disponible mais une source pgrouting est proposée dans la configuration.");
- return false;
- }
+ let validation = false;
- if (!this.checkSourcePgr(sourceJsonObject)) {
- LOGGER.error("Erreur lors de la verification de la source pgr.");
- return false;
- } else {
- // il n'y a eu aucun problème, la ressource est correctement configurée.
- }
+ if (sourceJsonObject.type === "osrm") {
+ validation = this.checkSourceOsrm(sourceJsonObject);
+ } else if (sourceJsonObject.type === "pgr") {
+ validation = this.checkSourcePgr(sourceJsonObject);
+ } else if (sourceJsonObject.type === "valhalla") {
+ validation = this.checkSourceValhalla(sourceJsonObject);
+ } else if (sourceJsonObject.type === "smartrouting") {
+ validation = this.checkSourceSmartrouting(sourceJsonObject);
} else {
- // On va voir si c'est un autre type.
+ LOGGER.error("La source indique un type invalide : " + sourceJsonObject.type);
+ return false;
}
- //------ PGR
- //------ SMARTROUTING
- if (sourceJsonObject.type === "smartrouting") {
- available = true;
- LOGGER.info("Source smartrouting.");
-
- if (!this.checkSourceSmartrouting(sourceJsonObject)) {
- LOGGER.error("Erreur lors de la verification de la source smartrouting.");
- return false;
- } else {
- // il n'y a eu aucun problème, la ressource est correctement configurée.
- }
+
+ if (!validation) {
+ LOGGER.error("Erreur lors de la verification de la source");
+ return false;
} else {
- // On va voir si c'est un autre type.
+ LOGGER.debug("Aucune erreur lors de la vérification de la source");
}
- //------ SMARTROUTING
- //------ VALHALLA
- if (sourceJsonObject.type === "valhalla") {
- available = true;
- LOGGER.info("Source valhalla.");
-
- let operationFound = false;
-
- // On vérifie que les opérations possibles sur ce type de source soient disponibles dans l'instance du service
- if (operationManager.verifyAvailabilityOperation("route")) {
- // On vérifie que les opérations possibles sur ce type de source soient disponibles pour la ressource
- if (operationManager.isAvailableInTable("route", resourceOperationTable)) {
- operationFound = true;
- } else {
- // on continue pour voir la suite
- }
- } else {
- // on continue pour voir la suite
- }
-
- // On vérifie que les opérations possibles sur ce type de source soient disponibles dans l'instance du service
- if (operationManager.verifyAvailabilityOperation("isochrone")) {
- // On vérifie que les opérations possibles sur ce type de source soient disponibles pour la ressource
- if (operationManager.isAvailableInTable("isochrone", resourceOperationTable)) {
- operationFound = true;
- } else {
- // on continue pour voir la suite
- }
- } else {
- // on continue pour voir la suite
- }
- if (!operationFound) {
- LOGGER.error("Le service ne propose pas d'operations disponibles pour ce type de source (ex. route, isochrone), il n'est donc pas possible de charger cette source.");
- return false;
- }
+ }
- if (!this.checkSourceValhalla(sourceJsonObject)) {
- LOGGER.error("Erreur lors de la verification de la source valhalla.");
- return false;
- } else {
- // il n'y a eu aucun problème, la ressource est correctement configurée.
- }
- } else {
- // On va voir si c'est un autre type.
+ // Projection
+ if (!sourceJsonObject.projection) {
+ LOGGER.error("Mauvaise configuration: source.projection absent");
+ return false;
+ } else {
+ // Vérification de la projection
+ if (!this._projectionManager.isProjectionChecked(sourceJsonObject.projection)) {
+ LOGGER.error("La source indique une projection non disponible sur le service: " + topologyJsonDescription.projection);
+ return false;
}
- //------ VALHALLA
+ }
- // Si ce n'est aucun type valide, on renvoie une erreur.
- if (!available) {
- LOGGER.error("La source indique un type invalide: " + sourceJsonObject.type);
+ // Bbox
+ if (!sourceJsonObject.bbox) {
+ LOGGER.error("Mauvaise configuration: source.bbox absent");
+ return false;
+ } else {
+ // Vérification de la bbox
+ if (!this._projectionManager.checkBboxConfiguration(sourceJsonObject.bbox, sourceJsonObject.projection)) {
+ LOGGER.error("La source indique une projection non disponible sur le service: " + topologyJsonDescription.projection);
return false;
}
}
+
LOGGER.info("Fin de la verification de la source.");
return true;
@@ -316,6 +346,14 @@ module.exports = class sourceManager {
LOGGER.info("Verification de la source osrm...");
+ // On vérifie que le module osrm est disponible
+ try {
+ let osrmTest = require('osrm');
+ } catch(error) {
+ LOGGER.error("Le module osrm n'est pas disponible mais une source osrm est proposée dans la configuration.");
+ return false;
+ }
+
// Storage
if (!sourceJsonObject.storage) {
LOGGER.error("La ressource contient une source sans stockage.");
@@ -384,6 +422,14 @@ module.exports = class sourceManager {
LOGGER.info("Verification de la source pgr...");
+ // On vérifie que le module pg est disponible
+ try {
+ let { poolTest } = require('pg');
+ } catch(error) {
+ LOGGER.error("Le module pg n'est pas disponible mais une source pgrouting est proposée dans la configuration.");
+ return false;
+ }
+
// Storage
if (!sourceJsonObject.storage) {
LOGGER.error("La ressource contient une source sans stockage.");
@@ -592,18 +638,61 @@ module.exports = class sourceManager {
}
+ /**
+ *
+ * @function
+ * @name loadSourceDirectory
+ * @description Fonction utilisée pour créer les sources contenues dans un dossier.
+ * @param {string} directory - Dossier qui contient les configurations des ressources
+ * @return {boolean}
+ *
+ */
+
+ loadSourceDirectory(directory) {
+
+ // Pour chaque fichier du dossier des sources, on crée une source
+ let files = fs.readdirSync(directory).filter( (file) => {
+ return path.extname(file).toLowerCase() === ".source";
+ });
+
+ for (let fileName of files) {
+
+ let sourceFile = directory + "/" + fileName;
+ LOGGER.info("Chargement de la source : " + sourceFile);
+
+ // Récupération du contenu en objet pour vérification puis création de la source
+ let sourceContent = {};
+ try {
+ sourceContent = JSON.parse(fs.readFileSync(sourceFile));
+ } catch (error) {
+ LOGGER.error(error);
+ LOGGER.error("Erreur lors de la lecture de la source: " + sourceFile);
+ }
+
+ // Création de la ressource
+ if (!this.loadSourceConfiguration(sourceContent)) {
+ LOGGER.error("La source configurée dans le fichier " + sourceFile + " n'a pas pu être chargée");
+ } else {
+ LOGGER.info("Source chargée : " + sourceFile);
+ }
+
+ }
+
+ return true;
+
+ }
+
/**
*
* @function
* @name loadSourceConfiguration
* @description Fonction utilisée pour créer une source.
* @param {json} sourceJsonObject - Description JSON de la source
- * @param {Topology} topology - Instance de la classe Topology
* @return {boolean}
*
*/
- loadSourceConfiguration(sourceJsonObject, topology) {
+ loadSourceConfiguration(sourceJsonObject) {
LOGGER.info("Creation de la source: " + sourceJsonObject.id);
diff --git a/src/js/topology/topologyManager.js b/src/js/topology/topologyManager.js
index 0f0a5df..c3ba6b9 100644
--- a/src/js/topology/topologyManager.js
+++ b/src/js/topology/topologyManager.js
@@ -150,7 +150,7 @@ module.exports = class topologyManager {
return false;
} else {
// Vérification de la projection
- if (!this._projectionManager.isChecked(topologyJsonDescription.projection)) {
+ if (!this._projectionManager.isProjectionChecked(topologyJsonDescription.projection)) {
LOGGER.error("La topologie indique une projection non disponible sur le service: " + topologyJsonDescription.projection);
return false;
}
From 8f678fcf580af4d25202c9ddcfca71c8569586f7 Mon Sep 17 00:00:00 2001
From: Loic
Date: Thu, 3 Nov 2022 09:23:19 +0100
Subject: [PATCH 12/93] WIP: suppression des topologies
---
changelog.md | 2 +
.../configuration/sources/pgrSource.json | 196 +++++++
src/js/resources/resourceManager.js | 36 +-
src/js/service/service.js | 11 +-
src/js/sources/osrmSource.js | 31 +-
src/js/sources/pgrSource.js | 148 +++--
src/js/sources/smartroutingSource.js | 3 +-
src/js/sources/source.js | 26 +-
src/js/sources/sourceManager.js | 416 ++++++++++----
src/js/sources/valhallaSource.js | 46 +-
src/js/topology/dbTopology.js | 137 -----
src/js/topology/osmTopology.js | 47 --
src/js/topology/topology.js | 99 ----
src/js/topology/topologyManager.js | 515 ------------------
src/js/utils/storageManager.js | 84 ---
test/integration/readme.md | 13 +-
16 files changed, 675 insertions(+), 1135 deletions(-)
create mode 100644 documentation/configuration/sources/pgrSource.json
delete mode 100644 src/js/topology/dbTopology.js
delete mode 100644 src/js/topology/osmTopology.js
delete mode 100644 src/js/topology/topology.js
delete mode 100644 src/js/topology/topologyManager.js
delete mode 100644 src/js/utils/storageManager.js
diff --git a/changelog.md b/changelog.md
index 7659939..42c3f18 100644
--- a/changelog.md
+++ b/changelog.md
@@ -8,6 +8,8 @@ ADDED:
CHANGED:
- L'option --configCheck au démarrage de Road2 n'a plus exactement le même comportement.
- Le fichier server.json permet maintenant de configurer l'administrateur et donc n'a plus le même contenu. Ce dernier est dans service.json.
+ - Les sources ne sont plus configurées dans le même fichier que les ressources. Chaque source est configurée dans son fichier. L'ensemble est placé dans un dossier de sources. Il peut y en avoir plusieurs.
+ - Les sources PGRouting et Valhalla ne sont plus configurées de la même manière : chaque source de ces types peut contenir plusieurs coûts.
# 1.1.2
diff --git a/documentation/configuration/sources/pgrSource.json b/documentation/configuration/sources/pgrSource.json
new file mode 100644
index 0000000..4a68be5
--- /dev/null
+++ b/documentation/configuration/sources/pgrSource.json
@@ -0,0 +1,196 @@
+{
+ "id": "bduni-idf-car-fastest-pgr",
+ "description":"test",
+ "type": "pgr",
+ "projection": "EPSG:4326",
+ "bbox": "1.7,48.4,3.3,49.1",
+ "storage": {
+ "base": {
+ "dbConfig": "/home/docker/data/output_base.json",
+ "schema": "public",
+ "attributes": [
+ {
+ "key": "name",
+ "column": "way_names",
+ "default": "false"
+ },
+ {
+ "key": "nom_1_gauche",
+ "column": "nom_1_gauche",
+ "default": "true"
+ },
+ {
+ "key": "nom_1_droite",
+ "column": "nom_1_droite",
+ "default": "true"
+ },
+ {
+ "key": "cpx_numero",
+ "column": "cpx_numero",
+ "default": "true"
+ },
+ {
+ "key": "cpx_toponyme_route_nommee",
+ "column": "cpx_toponyme_route_nommee",
+ "default": "true"
+ },
+ {
+ "key": "cleabs",
+ "column": "cleabs",
+ "default": "false"
+ },
+ {
+ "key": "nature",
+ "column": "nature",
+ "default": "false"
+ },
+ {
+ "key": "importance",
+ "column": "importance",
+ "default": "false"
+ },
+ {
+ "key": "position_par_rapport_au_sol",
+ "column": "position_par_rapport_au_sol",
+ "default": "false"
+ },
+ {
+ "key": "nombre_de_voies",
+ "column": "nombre_de_voies",
+ "default": "false"
+ },
+ {
+ "key": "largeur_de_chaussee",
+ "column": "largeur_de_chaussee",
+ "default": "false"
+ },
+ {
+ "key": "itineraire_vert",
+ "column": "itineraire_vert",
+ "default": "false"
+ },
+ {
+ "key": "sens_de_circulation",
+ "column": "sens_de_circulation",
+ "default": "false"
+ },
+ {
+ "key": "bande_cyclable",
+ "column": "bande_cyclable",
+ "default": "false"
+ },
+ {
+ "key": "reserve_aux_bus",
+ "column": "reserve_aux_bus",
+ "default": "false"
+ },
+ {
+ "key": "urbain",
+ "column": "urbain",
+ "default": "false"
+ },
+ {
+ "key": "vitesse_moyenne_vl",
+ "column": "vitesse_moyenne_vl",
+ "default": "false"
+ },
+ {
+ "key": "acces_vehicule_leger",
+ "column": "acces_vehicule_leger",
+ "default": "false"
+ },
+ {
+ "key": "acces_pieton",
+ "column": "acces_pieton",
+ "default": "false"
+ },
+ {
+ "key": "nature_de_la_restriction",
+ "column": "nature_de_la_restriction",
+ "default": "false"
+ },
+ {
+ "key": "restriction_de_hauteur",
+ "column": "restriction_de_hauteur",
+ "default": "false"
+ },
+ {
+ "key": "restriction_de_poids_total",
+ "column": "restriction_de_poids_total",
+ "default": "false"
+ },
+ {
+ "key": "restriction_de_poids_par_essieu",
+ "column": "restriction_de_poids_par_essieu",
+ "default": "false"
+ },
+ {
+ "key": "restriction_de_largeur",
+ "column": "restriction_de_largeur",
+ "default": "false"
+ },
+ {
+ "key": "restriction_de_longueur",
+ "column": "restriction_de_longueur",
+ "default": "false"
+ },
+ {
+ "key": "matieres_dangereuses_interdites",
+ "column": "matieres_dangereuses_interdites",
+ "default": "false"
+ },
+ {
+ "key": "insee_commune_gauche",
+ "column": "insee_commune_gauche",
+ "default": "false"
+ },
+ {
+ "key": "insee_commune_droite",
+ "column": "insee_commune_droite",
+ "default": "false"
+ },
+ {
+ "key": "cpx_numero_route_europeenne",
+ "column": "cpx_numero_route_europeenne",
+ "default": "false"
+ },
+ {
+ "key": "cpx_classement_administratif",
+ "column": "cpx_classement_administratif",
+ "default": "false"
+ },
+ {
+ "key": "cpx_gestionnaire",
+ "column": "cpx_gestionnaire",
+ "default": "false"
+ }
+ ]
+ }
+ },
+ "costs": [
+ {
+ "profile": "car",
+ "optimization": "fastest",
+ "costColumn": "cost_s_car",
+ "rcostColumn": "reverse_cost_s_car"
+ },
+ {
+ "profile": "car",
+ "optimization": "shortest",
+ "costColumn": "cost_s_car",
+ "rcostColumn": "reverse_cost_s_car"
+ },
+ {
+ "profile": "pedestrian",
+ "optimization": "fastest",
+ "costColumn": "cost_s_car",
+ "rcostColumn": "reverse_cost_s_car"
+ },
+ {
+ "profile": "pedestrian",
+ "optimization": "shortest",
+ "costColumn": "cost_s_car",
+ "rcostColumn": "reverse_cost_s_car"
+ }
+ ]
+ }
diff --git a/src/js/resources/resourceManager.js b/src/js/resources/resourceManager.js
index 897e3f5..9a80015 100644
--- a/src/js/resources/resourceManager.js
+++ b/src/js/resources/resourceManager.js
@@ -20,7 +20,7 @@ module.exports = class resourceManager {
* @description Constructeur de la classe resourceManager
*
*/
- constructor(sourceManager, operationManager, topologyManager) {
+ constructor(sourceManager, operationManager) {
// Liste des ids des ressources chargées par le manager
this._loadedResourceId = new Array();
@@ -34,9 +34,6 @@ module.exports = class resourceManager {
// Liste des types de ressource gérées par le manager
this._availableResourceTypes = ["pgr", "smartpgr","osrm","valhalla"];
- // Manager de topology
- this._topologyManager = topologyManager;
-
// Manager de source
this._sourceManager = sourceManager;
@@ -66,7 +63,7 @@ module.exports = class resourceManager {
*
*/
- async checkResourceDirectory(directory) {
+ checkResourceDirectory(directory) {
LOGGER.info("Vérification d'un dossier de ressources...");
LOGGER.info("Nom du dossier: " + directory);
@@ -108,7 +105,7 @@ module.exports = class resourceManager {
return false;
}
- if (!(await this.checkResourceConfiguration(resourceConf))) {
+ if (!this.checkResourceConfiguration(resourceConf)) {
LOGGER.error("La ressource décrite dans le fichier " + resourceFile + " est mal configuée");
return false;
} else {
@@ -137,7 +134,7 @@ module.exports = class resourceManager {
*
*/
- async checkResourceConfiguration(resourceJsonObject) {
+ checkResourceConfiguration(resourceJsonObject) {
LOGGER.info("Verification de la configuration d'une ressource...");
@@ -213,19 +210,6 @@ module.exports = class resourceManager {
return false;
}
- // Topology
- if (!resourceJsonObject.resource.topology) {
- LOGGER.error("La ressource ne contient pas de topologie.");
- return false;
- } else {
- if (!(await this._topologyManager.checkTopologyConfiguration(resourceJsonObject.resource.topology))) {
- LOGGER.error("La ressource contient une topologie incorrecte.");
- return false;
- } else {
- this._topologyManager.saveCheckedTopology(resourceJsonObject.resource.topology);
- }
- }
-
// Sources
if (!resourceJsonObject.resource.sources) {
LOGGER.error("La ressource ne contient pas de sources.");
@@ -378,17 +362,7 @@ module.exports = class resourceManager {
// C'est la première ressource créée
}
- // Création de la topology associée
- LOGGER.info("Chargement de la topology associé...");
- let currentTopology = {};
- if (!this._topologyManager.loadTopologyConfiguration(resourceJsonObject.resource.topology)) {
- LOGGER.error("Impossible de créer la topology associée à la ressource");
- return false;
- } else {
- currentTopology = this._topologyManager.getTopology(resourceJsonObject.resource.topology.id);
- }
-
- // Création des sources associées
+ // Vérification des sources associées
LOGGER.info("Vérification du chargement des sources associées...");
for (let i = 0; i < resourceJsonObject.resource.sources.length; i++) {
if (!this._sourceManager.isLoadedSourceAvailable(resourceJsonObject.resource.sources[i])) {
diff --git a/src/js/service/service.js b/src/js/service/service.js
index 66344c3..85f4e81 100644
--- a/src/js/service/service.js
+++ b/src/js/service/service.js
@@ -10,7 +10,6 @@ const ResourceManager = require('../resources/resourceManager');
const SourceManager = require('../sources/sourceManager');
const OperationManager = require('../operations/operationManager');
const BaseManager = require('../base/baseManager');
-const TopologyManager = require('../topology/topologyManager');
const ProjectionManager = require('../geography/projectionManager');
const ServerManager = require('../server/serverManager');
const LogManager = require('../utils/logManager');
@@ -48,14 +47,11 @@ module.exports = class Service {
// Manager des projections
this._projectionManager = new ProjectionManager();
- // Manager des topologies du service
- this._topologyManager = new TopologyManager(this._baseManager, this._projectionManager);
-
// Manager des sources du service.
- this._sourceManager = new SourceManager(this._projectionManager);
+ this._sourceManager = new SourceManager(this._projectionManager, this._baseManager);
// Manager des ressources du service.
- this._resourceManager = new ResourceManager(this._sourceManager, this._operationManager, this._topologyManager);
+ this._resourceManager = new ResourceManager(this._sourceManager, this._operationManager);
// Manager des apis du service
this._apisManager = new ApisManager();
@@ -520,7 +516,7 @@ module.exports = class Service {
let directory = path.resolve(path.dirname(userConfigurationPath), resourcesDirectories[i]);
- if (!(await this._resourceManager.checkResourceDirectory(directory))) {
+ if (!this._resourceManager.checkResourceDirectory(directory)) {
LOGGER.error("Le dossier " + directory + " contient des ressources dont la vérification a échoué");
return false;
} else {
@@ -654,7 +650,6 @@ module.exports = class Service {
this._operationManager.flushCheckedOperation();
this._resourceManager.flushCheckedResource();
this._sourceManager.flushCheckedSource();
- this._topologyManager.flushCheckedTopology();
this._serverManager.flushCheckedServer();
LOGGER.info("Verification terminee.");
diff --git a/src/js/sources/osrmSource.js b/src/js/sources/osrmSource.js
index ea39ec5..3115c92 100644
--- a/src/js/sources/osrmSource.js
+++ b/src/js/sources/osrmSource.js
@@ -39,13 +39,12 @@ module.exports = class osrmSource extends Source {
* @name constructor
* @description Constructeur de la classe osrmSource
* @param {json} sourceJsonObject - Description de la source en json
- * @param {topology} topology - Instance de la classe Topology
*
*/
- constructor(sourceJsonObject, topology) {
+ constructor(sourceJsonObject) {
// Constructeur parent
- super(sourceJsonObject.id,sourceJsonObject.type, topology);
+ super(sourceJsonObject.id, "osrm", sourceJsonObject.description, sourceJsonObject.projection, sourceJsonObject.bbox);
// Stockage de la configuration
this._configuration = sourceJsonObject;
@@ -173,15 +172,15 @@ module.exports = class osrmSource extends Source {
// Coordonnées
let coordinatesTable = new Array();
// start
- coordinatesTable.push(request.start.getCoordinatesIn(this.topology.projection));
+ coordinatesTable.push(request.start.getCoordinatesIn(super.projection));
// intermediates
if (request.intermediates.length !== 0) {
for (let i = 0; i < request.intermediates.length; i++) {
- coordinatesTable.push(request.intermediates[i].getCoordinatesIn(this.topology.projection));
+ coordinatesTable.push(request.intermediates[i].getCoordinatesIn(super.projection));
}
}
// end
- coordinatesTable.push(request.end.getCoordinatesIn(this.topology.projection));
+ coordinatesTable.push(request.end.getCoordinatesIn(super.projection));
LOGGER.debug("coordinates:");
LOGGER.debug(coordinatesTable);
@@ -286,7 +285,7 @@ module.exports = class osrmSource extends Source {
// ---
let osrmRequest = {};
- osrmRequest.coordinates = [request.coordinates.getCoordinatesIn(this.topology.projection)];
+ osrmRequest.coordinates = [request.coordinates.getCoordinatesIn(super.projection)];
osrmRequest.number = request.number;
// ---
@@ -400,10 +399,10 @@ module.exports = class osrmSource extends Source {
let askedProjection = routeRequest.start.projection;
LOGGER.debug("asked projection: " + askedProjection);
- LOGGER.debug("topology projection: " + this.topology.projection);
+ LOGGER.debug("source projection: " + super.projection);
// start
- start = new Point(osrmResponse.waypoints[0].location[0], osrmResponse.waypoints[0].location[1], this.topology.projection);
+ start = new Point(osrmResponse.waypoints[0].location[0], osrmResponse.waypoints[0].location[1], super.projection);
if (!start.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of start in OSRM response. ");
} else {
@@ -412,7 +411,7 @@ module.exports = class osrmSource extends Source {
}
// end
- end = new Point(osrmResponse.waypoints[osrmResponse.waypoints.length-1].location[0], osrmResponse.waypoints[osrmResponse.waypoints.length-1].location[1], this.topology.projection);
+ end = new Point(osrmResponse.waypoints[osrmResponse.waypoints.length-1].location[0], osrmResponse.waypoints[osrmResponse.waypoints.length-1].location[1], super.projection);
if (!end.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of end in OSRM response. ");
} else {
@@ -439,7 +438,7 @@ module.exports = class osrmSource extends Source {
let currentOsrmRoute = osrmResponse.routes[i];
// On commence par créer l'itinéraire avec les attributs obligatoires
- routes[i] = new Route( new Line(currentOsrmRoute.geometry, "geojson", this._topology.projection) );
+ routes[i] = new Route( new Line(currentOsrmRoute.geometry, "geojson", super.projection) );
if (!routes[i].geometry.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of geometry in OSRM response. ");
} else {
@@ -465,7 +464,7 @@ module.exports = class osrmSource extends Source {
let currentOsrmRouteLeg = currentOsrmRoute.legs[j];
- let legStart = new Point(osrmResponse.waypoints[j].location[0], osrmResponse.waypoints[j].location[1], this.topology.projection);
+ let legStart = new Point(osrmResponse.waypoints[j].location[0], osrmResponse.waypoints[j].location[1], super.projection);
if (!legStart.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of leg start in OSRM response. ");
} else {
@@ -473,7 +472,7 @@ module.exports = class osrmSource extends Source {
LOGGER.debug(legStart);
}
- let legEnd = new Point(osrmResponse.waypoints[j+1].location[0], osrmResponse.waypoints[j+1].location[1], this.topology.projection);
+ let legEnd = new Point(osrmResponse.waypoints[j+1].location[0], osrmResponse.waypoints[j+1].location[1], super.projection);
if (!legEnd.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of leg end in OSRM response. ");
} else {
@@ -496,7 +495,7 @@ module.exports = class osrmSource extends Source {
LOGGER.debug("Step number " + k + " of portion number " + j + " for route number " + i);
let currentOsrmRouteStep = currentOsrmRouteLeg.steps[k];
- steps[k] = new Step( new Line(currentOsrmRouteStep.geometry, "geojson", this._topology.projection) );
+ steps[k] = new Step( new Line(currentOsrmRouteStep.geometry, "geojson", super.projection) );
if (!steps[k].geometry.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of step's geometry in OSRM response. ");
} else {
@@ -561,7 +560,7 @@ module.exports = class osrmSource extends Source {
let askedProjection = nearestRequest.coordinates.projection;
LOGGER.debug("asked projection: " + askedProjection);
- LOGGER.debug("topology projection: " + this.topology.projection);
+ LOGGER.debug("source projection: " + super.projection);
// Création de la réponse
let nearestResponse = new NearestResponse(nearestRequest.resource, nearestRequest.coordinates);
@@ -577,7 +576,7 @@ module.exports = class osrmSource extends Source {
if (osrmResponse.waypoints[i].location) {
- let pointGeom = new Point(osrmResponse.waypoints[i].location[0], osrmResponse.waypoints[i].location[1], this.topology.projection);
+ let pointGeom = new Point(osrmResponse.waypoints[i].location[0], osrmResponse.waypoints[i].location[1], super.projection);
if (!pointGeom.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of a point in OSRM response. ");
} else {
diff --git a/src/js/sources/pgrSource.js b/src/js/sources/pgrSource.js
index 1f1a68e..a766888 100644
--- a/src/js/sources/pgrSource.js
+++ b/src/js/sources/pgrSource.js
@@ -36,25 +36,64 @@ module.exports = class pgrSource extends Source {
* @name constructor
* @description Constructeur de la classe pgrSource
* @param{json} sourceJsonObject - Description de la source
- * @param{topology} topology - Instance de la classe Topology
+ * @param{Base} base - Instance de Base pour permettre les requêtes vers le serveur PGRouting
*
*/
- constructor(sourceJsonObject, topology) {
+ constructor(sourceJsonObject, base) {
// Constructeur parent
- super(sourceJsonObject.id, "pgr", topology);
+ super(sourceJsonObject.id, "pgr", sourceJsonObject.description, sourceJsonObject.projection, sourceJsonObject.bbox);
// Stockage de la configuration
this._configuration = sourceJsonObject;
- // Coût
- this._cost = sourceJsonObject.storage.costColumn;
+ // Base de données PGRouting
+ this._base = base;
- // Coût inverse
- this._reverseCost = sourceJsonObject.storage.rcostColumn;
+ // Schéma contenant les données dans la base
+ this._schema = sourceJsonObject.storage.base.schema;
- // Profil
- this._profile = sourceJsonObject.cost.profile;
+ // Attributs par défaut sur les voies dans la base
+ this._defaultAttributes = new Array();
+
+ // Attributs disponibles sur les voies dans la base
+ this._otherAttributes = new Array();
+
+ // Création des tableaux d'attributs
+ for (let i = 0; i < sourceJsonObject.storage.base.attributes.length; i++) {
+ let curAttribute = sourceJsonObject.storage.base.attributes[i];
+ if (curAttribute.default === "true") {
+ this._defaultAttributes.push(curAttribute);
+ } else if (curAttribute.default === "false") {
+ this._otherAttributes.push(curAttribute);
+ } else {
+ // cela ne doit pas arriver
+ }
+ }
+
+ // stockage des attributs dans des tableaux pour le traitement des requêtes
+ this._defaultAttributesTable = new Array();
+ this._defaultAttributesKeyTable = new Array();
+ for (let i = 0; i < this._defaultAttributes.length; i++) {
+ this._defaultAttributesTable.push("'" + this._defaultAttributes[i].column + "'");
+ this._defaultAttributesKeyTable.push(this._defaultAttributes[i].key);
+ }
+
+ // stockage des attributs par défaut en une chaîne de caractères pour le traitement des requêtes
+ this._defaultAttributesString = this._defaultAttributesTable.join(",");
+
+ // Coûts disponibles
+ this._costs = {};
+
+ // Initialisation des coûts disponibles
+ for (let i = 0; i < sourceJsonObject.costs.length; i++) {
+ Object.defineProperty(this._costs, sourceJsonObject.costs[i].profile, { value: new Object(), configurable: true, enumerable: true, writable: true });
+ Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile], sourceJsonObject.costs[i].optimization, { value: new Object(), configurable: true, enumerable: true, writable: true });
+ Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].optimization], "costColumn", { value: sourceJsonObject.costs[i].costColumn, configurable: true, enumerable: true, writable: true });
+ Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].optimization], "rcostColumn", { value: sourceJsonObject.costs[i].rcostColumn, configurable: true, enumerable: true, writable: true });
+ Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].costType], "costColumn", { value: sourceJsonObject.costs[i].costColumn, configurable: true, enumerable: true, writable: true });
+ Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].costType], "rcostColumn", { value: sourceJsonObject.costs[i].rcostColumn, configurable: true, enumerable: true, writable: true });
+ }
}
@@ -90,12 +129,12 @@ module.exports = class pgrSource extends Source {
*/
async connect() {
- if (!this._topology.base.connected) {
+ if (!this._base.connected) {
// Connection à la base de données
try {
- await this._topology.base.connect();
+ await this._base.connect();
this._connected = true;
} catch (err) {
@@ -124,11 +163,11 @@ module.exports = class pgrSource extends Source {
LOGGER.info("Tentative de deconnection de la base...");
- if (this._topology.base.connected) {
+ if (this._base.connected) {
try {
- await this._topology.base.disconnect();
+ await this._base.disconnect();
LOGGER.info("Deconnection de la base effectuee");
this._connected = false;
@@ -181,15 +220,15 @@ module.exports = class pgrSource extends Source {
// Coordonnées
// start
- coordinatesTable.push(request.start.getCoordinatesIn(this.topology.projection));
+ coordinatesTable.push(request.start.getCoordinatesIn(super.projection));
// intermediates
if (request.intermediates.length !== 0) {
for (let i = 0; i < request.intermediates.length; i++) {
- coordinatesTable.push(request.intermediates[i].getCoordinatesIn(this.topology.projection));
+ coordinatesTable.push(request.intermediates[i].getCoordinatesIn(super.projection));
}
}
// end
- coordinatesTable.push(request.end.getCoordinatesIn(this.topology.projection));
+ coordinatesTable.push(request.end.getCoordinatesIn(super.projection));
LOGGER.debug("coordinates:");
LOGGER.debug(coordinatesTable);
@@ -198,11 +237,12 @@ module.exports = class pgrSource extends Source {
// --- waysAttributes
// attributes est déjà vide, on met les attributs par défaut
- attributes = this._topology.defaultAttributesString;
+ attributes = this._defaultAttributesString;
LOGGER.debug("default attributes: " + attributes);
// on complète avec les attributs demandés
+ // TODO : refaire cette partie, et donc la manière dont l'info est stockée dans la classe
if (request.waysAttributes.length !== 0) {
let requestedAttributes = new Array();
@@ -210,17 +250,17 @@ module.exports = class pgrSource extends Source {
// on récupère le nom de la colonne en fonction de l'id de l'attribut demandé
let isDefault = false;
- for (let j = 0; j < this._topology.defaultAttributes.length; j++) {
- if (request.waysAttributes[i] === this._topology.defaultAttributes[j].key) {
+ for (let j = 0; j < this._defaultAttributes.length; j++) {
+ if (request.waysAttributes[i] === this._defaultAttributes[j].key) {
isDefault = true;
break;
}
}
if (!isDefault) {
- for (let j = 0; j < this._topology.otherAttributes.length; j++) {
- if (request.waysAttributes[i] === this._topology.otherAttributes[j].key) {
- requestedAttributes.push("'" + this._topology.otherAttributes[j].column + "'");
+ for (let j = 0; j < this._otherAttributes.length; j++) {
+ if (request.waysAttributes[i] === this._otherAttributes[j].key) {
+ requestedAttributes.push("'" + this._otherAttributes[j].column + "'");
break;
}
}
@@ -292,20 +332,20 @@ module.exports = class pgrSource extends Source {
}
// ---
- const queryString = `SELECT * FROM ${this._topology.schema}.shortest_path_pgrouting(ARRAY ${JSON.stringify(coordinatesTable)},$1,$2,$3,ARRAY [${attributes}]::text[],$4)`;
+ const queryString = `SELECT * FROM ${this._schema}.shortest_path_pgrouting(ARRAY ${JSON.stringify(coordinatesTable)},$1,$2,$3,ARRAY [${attributes}]::text[],$4)`;
let SQLParametersTable;
if (looseConstraintsArray.length === 0) {
SQLParametersTable = [
- this._profile,
- this._cost,
- this._reverseCost,
+ request.profile,
+ this._costs[request.profile][request.optimization].costColumn,
+ this._costs[request.profile][request.optimization].rcostColumn,
constraints
];
} else {
- let onTheFlyCosts = LooseConstraint.looseConstraintsToSQL(looseConstraintsArray, this._cost, this._reverseCost);
+ let onTheFlyCosts = LooseConstraint.looseConstraintsToSQL(looseConstraintsArray, this._costs[request.profile][request.optimization].costColumn, this._costs[request.profile][request.optimization].rcostColumn);
SQLParametersTable = [
- this._profile,
+ request.profile,
onTheFlyCosts[0],
onTheFlyCosts[1],
constraints
@@ -319,11 +359,11 @@ module.exports = class pgrSource extends Source {
LOGGER.debug("SQLParametersTable:");
LOGGER.debug(SQLParametersTable);
- if (this._topology.base.pool) {
+ if (this._base.pool) {
try {
- this._topology.base.pool.query(queryString, SQLParametersTable, (err, result) => {
+ this._base.pool.query(queryString, SQLParametersTable, (err, result) => {
this.state = "green";
@@ -402,14 +442,14 @@ module.exports = class pgrSource extends Source {
LOGGER.debug("no constraints asked");
}
- const queryString = `SELECT * FROM ${this._topology.schema}.generateIsochrone(ARRAY ${JSON.stringify(point)}, $1, $2, $3, $4, $5, $6)`;
+ const queryString = `SELECT * FROM ${this._schema}.generateIsochrone(ARRAY ${JSON.stringify(point)}, $1, $2, $3, $4, $5, $6)`;
const SQLParametersTable = [
request.costValue,
request.direction,
parseInt(request.askedProjection.split(':')[1]), // e.g. Transformer "EPSG:4326" en 4326 (pour PostGIS).
- this._configuration.storage.costColumn,
- this._configuration.storage.rcostColumn,
+ this._costs[request.profile][request.costType].costColumn,
+ this._costs[request.profile][request.costType].rcostColumn,
constraints
];
@@ -419,11 +459,11 @@ module.exports = class pgrSource extends Source {
LOGGER.debug("SQLParametersTable:");
LOGGER.debug(SQLParametersTable);
- if (this._topology.base.pool) {
+ if (this._base.pool) {
try {
- this._topology.base.pool.query(queryString, SQLParametersTable, (err, result) => {
+ this._base.pool.query(queryString, SQLParametersTable, (err, result) => {
this.state = "green";
@@ -548,10 +588,10 @@ module.exports = class pgrSource extends Source {
LOGGER.debug("attributes management");
// On fait la liste des attributs par défaut
- if (this._topology.defaultAttributesKeyTable.length !== 0) {
- for (let i = 0; i < this._topology.defaultAttributesKeyTable.length; i++) {
- finalAttributesKey.push(this._topology.defaultAttributesKeyTable[i]);
- LOGGER.debug(this._topology.defaultAttributesKeyTable[i] + " added");
+ if (this._defaultAttributesKeyTable.length !== 0) {
+ for (let i = 0; i < this._defaultAttributesKeyTable.length; i++) {
+ finalAttributesKey.push(this._defaultAttributesKeyTable[i]);
+ LOGGER.debug(this._defaultAttributesKeyTable[i] + " added");
}
} else {
// il n'y a aucun attribut par défaut
@@ -564,18 +604,18 @@ module.exports = class pgrSource extends Source {
// on récupère le nom de la colonne en fonction de l'id de l'attribut demandé
let isDefault = false;
- for (let j = 0; j < this._topology.defaultAttributes.length; j++) {
- if (routeRequest.waysAttributes[i] === this._topology.defaultAttributes[j].key) {
+ for (let j = 0; j < this._defaultAttributes.length; j++) {
+ if (routeRequest.waysAttributes[i] === this._defaultAttributes[j].key) {
isDefault = true;
break;
}
}
if (!isDefault) {
- for (let j = 0; j < this._topology.otherAttributes.length; j++) {
- if (routeRequest.waysAttributes[i] === this._topology.otherAttributes[j].key) {
- finalAttributesKey.push(this._topology.otherAttributes[j].key);
- LOGGER.debug(this._topology.otherAttributes[j].key + " added");
+ for (let j = 0; j < this._otherAttributes.length; j++) {
+ if (routeRequest.waysAttributes[i] === this._otherAttributes[j].key) {
+ finalAttributesKey.push(this._otherAttributes[j].key);
+ LOGGER.debug(this._otherAttributes[j].key + " added");
break;
}
}
@@ -742,7 +782,7 @@ module.exports = class pgrSource extends Source {
let askedProjection = routeRequest.start.projection;
// start
- start = new Point(response.waypoints[0].location[0], response.waypoints[0].location[1], this.topology.projection);
+ start = new Point(response.waypoints[0].location[0], response.waypoints[0].location[1], super.projection);
if (!start.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of start in PGR response. ");
} else {
@@ -751,7 +791,7 @@ module.exports = class pgrSource extends Source {
}
// end
- end = new Point(response.waypoints[response.waypoints.length-1].location[0], response.waypoints[response.waypoints.length-1].location[1], this.topology.projection);
+ end = new Point(response.waypoints[response.waypoints.length-1].location[0], response.waypoints[response.waypoints.length-1].location[1], super.projection);
if (!end.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of end in PGR response. ");
} else {
@@ -779,7 +819,7 @@ module.exports = class pgrSource extends Source {
let currentPgrRoute = response.routes[i];
// On commence par créer l'itinéraire avec les attributs obligatoires
- routes[i] = new Route( new Line(currentPgrRoute.geometry, "geojson", this._topology.projection) );
+ routes[i] = new Route( new Line(currentPgrRoute.geometry, "geojson", super.projection) );
if (!routes[i].geometry.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of geometry in PGR response. ");
} else {
@@ -798,7 +838,7 @@ module.exports = class pgrSource extends Source {
let portionDuration = 0;
let currentPgrRouteLeg = currentPgrRoute.legs[j];
- let legStart = new Point(response.waypoints[j].location[0], response.waypoints[j].location[1], this.topology.projection);
+ let legStart = new Point(response.waypoints[j].location[0], response.waypoints[j].location[1], super.projection);
if (!legStart.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of leg start in OSRM response. ");
} else {
@@ -807,7 +847,7 @@ module.exports = class pgrSource extends Source {
}
- let legEnd = new Point(response.waypoints[j+1].location[0], response.waypoints[j+1].location[1], this.topology.projection);
+ let legEnd = new Point(response.waypoints[j+1].location[0], response.waypoints[j+1].location[1], super.projection);
if (!legEnd.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of leg end in OSRM response. ");
} else {
@@ -940,7 +980,7 @@ module.exports = class pgrSource extends Source {
newPortionGeomCoords.push(currentPgrRouteStep.geometry.coordinates);
- steps[k] = new Step( new Line(currentPgrRouteStep.geometry, "geojson", this._topology.projection) );
+ steps[k] = new Step( new Line(currentPgrRouteStep.geometry, "geojson", super.projection) );
if (!steps[k].geometry.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of step's geometry in PGR response. ");
} else {
@@ -983,7 +1023,7 @@ module.exports = class pgrSource extends Source {
routes[i].duration = new Duration(Math.round(routeDuration * 10) / 10,"second");
currentPgrRoute.geometry.coordinates = newRouteGeomCoords;
- routes[i].geometry = new Line(currentPgrRoute.geometry, "geojson", this._topology.projection);
+ routes[i].geometry = new Line(currentPgrRoute.geometry, "geojson", super.projection);
if (!routes[i].geometry.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of step's geometry in PGR response. ");
} else {
@@ -1021,7 +1061,7 @@ module.exports = class pgrSource extends Source {
}
// Création d'un objet Point (utile plus tard).
- point = new Point(isochroneRequest.point.lon, isochroneRequest.point.lat, this.topology.projection);
+ point = new Point(isochroneRequest.point.lon, isochroneRequest.point.lat, super.projection);
let rawGeometry = JSON.parse(pgrResponse.rows[0].geometry);
@@ -1037,7 +1077,7 @@ module.exports = class pgrSource extends Source {
}
// Création d'un objet Polygon à partir du GeoJSON reçu.
- geometry = new Polygon(rawGeometry, "geojson", this._topology.projection);
+ geometry = new Polygon(rawGeometry, "geojson", super.projection);
/* Envoi de la réponse au proxy. */
return new IsochroneResponse(
diff --git a/src/js/sources/smartroutingSource.js b/src/js/sources/smartroutingSource.js
index 1fd701f..3fc6d2d 100644
--- a/src/js/sources/smartroutingSource.js
+++ b/src/js/sources/smartroutingSource.js
@@ -42,13 +42,14 @@ module.exports = class smartroutingSource extends Source {
constructor(sourceJsonObject) {
// Constructeur parent
- super(sourceJsonObject.id,sourceJsonObject.type, undefined);
+ super(sourceJsonObject.id, "pgr", sourceJsonObject.description, sourceJsonObject.projection, sourceJsonObject.bbox);
// Stockage de la configuration
this._configuration = sourceJsonObject;
// Opérateur pour les requêtes http
this._httpQuery = new httpQuery({prefixUrl: this._configuration.storage.url});
+
}
/**
diff --git a/src/js/sources/source.js b/src/js/sources/source.js
index 79c22ad..e115204 100644
--- a/src/js/sources/source.js
+++ b/src/js/sources/source.js
@@ -18,10 +18,9 @@ module.exports = class Source {
* @description Constructeur de la classe source
* @param {string} id - Identifiant de la source
* @param {string} type - Type de la source
- * @param {Topology} topology - Topologie dont dérive la source (classe fille de topology)
*
*/
- constructor(id, type, topology) {
+ constructor(id, type, description, projection, bbox) {
// Id d'une source. Il doit être unique.
this._id = id;
@@ -29,12 +28,18 @@ module.exports = class Source {
// Type de la source
this._type = type;
+ // Description de la source
+ this._description = description;
+
+ // Projection de la source
+ this._projection = projection;
+
+ // Emprise de la source
+ this._bbox = bbox;
+
// État de la connexion de la source
this._connected = false;
- // Topologie dont dérive la source
- this._topology = topology;
-
// État de la source (même si connectée, elle peut être disfonctionnelle)
// Peut être : "green" si la dernière requête a fonctionnée, "orange" si la source est connectée mais injoignable, "red" à l'initialisation ou si plus gros problème
// Ajouter la gestion de ce paramètre dans chaque classe fille
@@ -110,17 +115,6 @@ module.exports = class Source {
this._state = st;
}
- /**
- *
- * @function
- * @name get topology
- * @description Récupérer la topologie de la source
- *
- */
- get topology () {
- return this._topology;
- }
-
/**
*
* @function
diff --git a/src/js/sources/sourceManager.js b/src/js/sources/sourceManager.js
index 7c7ac7b..b9f32f8 100644
--- a/src/js/sources/sourceManager.js
+++ b/src/js/sources/sourceManager.js
@@ -1,8 +1,6 @@
'use strict';
const assert = require('assert').strict;
-const storageManager = require('../utils/storageManager');
-const errorManager = require('../utils/errorManager');
const osrmSource = require('../sources/osrmSource');
const pgrSource = require('../sources/pgrSource');
const smartroutingSource = require('../sources/smartroutingSource');
@@ -21,7 +19,7 @@ module.exports = class sourceManager {
* @description Constructeur de la classe sourceManager
*
*/
- constructor(projectionManager) {
+ constructor(projectionManager, baseManager) {
// Liste des ids des sources chargées par le manager
this._loadedSourceId = new Array();
@@ -41,6 +39,9 @@ module.exports = class sourceManager {
// Manager des projections
this._projectionManager = projectionManager;
+ // Manager de bases de données (utiles pour certaines sources)
+ this._baseManager = baseManager;
+
// Correspondance entre les sources et les opérations possibles
this._operationsByType = {
"osrm": ["nearest", "route"],
@@ -133,7 +134,7 @@ module.exports = class sourceManager {
*
*/
- checkSourceDirectory(directory) {
+ async checkSourceDirectory(directory) {
LOGGER.info("Vérification d'un dossier de sources...");
LOGGER.info("Nom du dossier: " + directory);
@@ -204,7 +205,7 @@ module.exports = class sourceManager {
*
*/
- checkSourceConfiguration(sourceJsonObject) {
+ async checkSourceConfiguration(sourceJsonObject) {
LOGGER.info("Verification de la source...");
@@ -261,6 +262,43 @@ module.exports = class sourceManager {
}
+ // Description
+ if (!sourceJsonObject.description) {
+ LOGGER.error("Mauvaise configuration: source.description absent");
+ return false;
+ } else {
+ if (typeof(sourceJsonObject.description) !== "string") {
+ LOGGER.error("Mauvaise configuration: source.description n'est pas une chaine de caractère");
+ return false;
+ } else {
+ LOGGER.debug("source.description présent");
+ }
+ }
+
+ // Projection
+ if (!sourceJsonObject.projection) {
+ LOGGER.error("Mauvaise configuration: source.projection absent");
+ return false;
+ } else {
+ // Vérification de la projection
+ if (!this._projectionManager.isProjectionChecked(sourceJsonObject.projection)) {
+ LOGGER.error("La source indique une projection non disponible sur le service: " + sourceJsonObject.projection);
+ return false;
+ }
+ }
+
+ // Bbox
+ if (!sourceJsonObject.bbox) {
+ LOGGER.error("Mauvaise configuration: source.bbox absent");
+ return false;
+ } else {
+ // Vérification de la bbox
+ if (!this._projectionManager.checkBboxConfiguration(sourceJsonObject.bbox, sourceJsonObject.projection)) {
+ LOGGER.error("La source indique une bbox incorrecte: " + sourceJsonObject.bbox);
+ return false;
+ }
+ }
+
// Type
if (!sourceJsonObject.type) {
LOGGER.error("Mauvaise configuration: source.type absent");
@@ -283,7 +321,7 @@ module.exports = class sourceManager {
if (sourceJsonObject.type === "osrm") {
validation = this.checkSourceOsrm(sourceJsonObject);
} else if (sourceJsonObject.type === "pgr") {
- validation = this.checkSourcePgr(sourceJsonObject);
+ validation = await this.checkSourcePgr(sourceJsonObject);
} else if (sourceJsonObject.type === "valhalla") {
validation = this.checkSourceValhalla(sourceJsonObject);
} else if (sourceJsonObject.type === "smartrouting") {
@@ -302,31 +340,6 @@ module.exports = class sourceManager {
}
- // Projection
- if (!sourceJsonObject.projection) {
- LOGGER.error("Mauvaise configuration: source.projection absent");
- return false;
- } else {
- // Vérification de la projection
- if (!this._projectionManager.isProjectionChecked(sourceJsonObject.projection)) {
- LOGGER.error("La source indique une projection non disponible sur le service: " + topologyJsonDescription.projection);
- return false;
- }
- }
-
- // Bbox
- if (!sourceJsonObject.bbox) {
- LOGGER.error("Mauvaise configuration: source.bbox absent");
- return false;
- } else {
- // Vérification de la bbox
- if (!this._projectionManager.checkBboxConfiguration(sourceJsonObject.bbox, sourceJsonObject.projection)) {
- LOGGER.error("La source indique une projection non disponible sur le service: " + topologyJsonDescription.projection);
- return false;
- }
- }
-
-
LOGGER.info("Fin de la verification de la source.");
return true;
@@ -338,7 +351,7 @@ module.exports = class sourceManager {
* @name checkSourceOsrm
* @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source osrm.
* @param {json} sourceJsonObject - Description JSON de la source
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
+ * @return {boolean}
*
*/
@@ -356,52 +369,46 @@ module.exports = class sourceManager {
// Storage
if (!sourceJsonObject.storage) {
- LOGGER.error("La ressource contient une source sans stockage.");
+ LOGGER.error("Mauvaise configuration : 'source.storage' absent");
return false;
} else {
- if (!storageManager.checkJsonStorage(sourceJsonObject.storage)) {
- LOGGER.error("Stockage de la source incorrect.");
+
+ LOGGER.debug("'source.storage' présent");
+
+ if (!sourceJsonObject.storage.file) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.file' absent");
return false;
} else {
- // Normalement, il n'y a plus rien à faire car la fonction checkDuplicationSource() vérifie déjà que la source n'est pas dupliquée
+ LOGGER.debug("'source.storage.file' présent");
+ // TODO : Vérifier l'existence et les droits de lecture
}
}
// Cost
if (!sourceJsonObject.cost) {
- LOGGER.error("La ressource contient une source sans cout.");
+ LOGGER.error("Mauvaise configuration : 'source.cost' absent");
return false;
} else {
+
+ LOGGER.debug("'source.storage.cost' présent");
+
// Profile
if (!sourceJsonObject.cost.profile) {
- LOGGER.error("La ressource contient une source sans profile.");
+ LOGGER.error("Mauvaise configuration : 'source.cost.profile' absent");
return false;
} else {
// rien à faire
+ LOGGER.debug("'source.cost.profile' présent");
}
// Optimization
if (!sourceJsonObject.cost.optimization) {
- LOGGER.error("La ressource contient une source sans optimization.");
+ LOGGER.error("Mauvaise configuration : 'source.cost.optimization' absent");
return false;
} else {
// rien à faire
+ LOGGER.debug("'source.cost.optimization' présent");
}
- // Compute
- if (!sourceJsonObject.cost.compute) {
- LOGGER.info("La ressource contient une source sans compute.");
- } else {
- if (!sourceJsonObject.cost.compute.storage) {
- LOGGER.error("La ressource contient une source ayant un cout sans stockage.");
- return false;
- } else {
- if (!storageManager.checkJsonStorage(sourceJsonObject.cost.compute.storage)) {
- LOGGER.warn("La ressource contient une source ayant un stockage du cout incorrect.");
- } else {
- // rien à faire
- }
- }
- //TODO: ajouter la vérification de configuration
- }
+
}
LOGGER.info("Fin de la verification de la source osrm.");
@@ -414,11 +421,11 @@ module.exports = class sourceManager {
* @name checkSourcePgr
* @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source pgr.
* @param {json} sourceJsonObject - Description JSON de la source
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
+ * @return {boolean}
*
*/
- checkSourcePgr(sourceJsonObject) {
+ async checkSourcePgr(sourceJsonObject) {
LOGGER.info("Verification de la source pgr...");
@@ -432,57 +439,171 @@ module.exports = class sourceManager {
// Storage
if (!sourceJsonObject.storage) {
- LOGGER.error("La ressource contient une source sans stockage.");
+
+ LOGGER.error("Mauvaise configuration : 'source.storage' absent");
return false;
+
} else {
- if (!storageManager.checkJsonStorage(sourceJsonObject.storage)) {
- LOGGER.error("Stockage de la source incorrect.");
+
+ LOGGER.debug("'source.storage' présent");
+
+ if (!sourceJsonObject.storage.base) {
+
+ LOGGER.error("Mauvaise configuration : 'source.storage.base' absent");
return false;
+
} else {
- // Normalement, il n'y a plus rien à faire car la fonction checkDuplicationSource() vérifie déjà que la source n'est pas dupliquée
+
+ LOGGER.debug("'source.storage.base' présent");
+
+ if (!sourceJsonObject.storage.base.dbConfig) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.base.dbConfig' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.storage.base.dbConfig' présent");
+
+ if (!(await this._baseManager.checkBaseConfiguration(sourceJsonObject.storage.base.dbConfig))) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.base.dbConfig' invalide");
+ return false;
+ } else {
+ LOGGER.debug("'source.storage.base.dbConfig' valide");
+ this._baseManager.saveCheckedBaseConfiguration(sourceJsonObject.storage.base.dbConfig);
+ }
+
+ }
+
+ if (!sourceJsonObject.storage.base.schema) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.base.schema' absent");
+ return false;
+ } else {
+
+ LOGGER.debug("'source.storage.base.schema' présent");
+
+ if (typeof(sourceJsonObject.storage.base.schema) !== "string") {
+ LOGGER.error("Mauvaise configuration : 'source.storage.base.schema' n'est pas une chaine de caractères");
+ return false;
+ }
+
+ }
+
+ if (!sourceJsonObject.storage.base.attributes) {
+ // Cet élément n'est pas obligatoire pour laisser plus de liberté
+ LOGGER.info("Configuration : 'source.storage.base.attributes' absent");
+ } else {
+
+ LOGGER.debug("'source.storage.base.attributes' présent");
+
+ if (!Array.isArray(sourceJsonObject.storage.base.attributes)) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes' n'est pas un tableau");
+ return false;
+ } else {
+ LOGGER.debug("'source.storage.base.attributes' est un tableau");
+ }
+
+ if (sourceJsonObject.storage.base.attributes.length === 0) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes' est un tableau vide");
+ return false;
+ } else {
+ LOGGER.debug("'source.storage.base.attributes' est un tableau non vide");
+ }
+
+ for (let j = 0; j < sourceJsonObject.storage.base.attributes.length; j++) {
+
+ if (sourceJsonObject.storage.base.attributes[j].key) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes["+j+"].key' est absent");
+ return false;
+ }
+
+ if (sourceJsonObject.storage.base.attributes[j].column) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes["+j+"].column' est absent");
+ return false;
+ }
+
+ if (sourceJsonObject.storage.base.attributes[j].default) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes["+j+"].default' est absent");
+ return false;
+ } else {
+ if (sourceJsonObject.storage.base.attributes[j].default !== "true" && sourceJsonObject.storage.base.attributes[j].default !== "false" ) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes["+j+"].default' doit être 'true' or 'false' (string)");
+ return false;
+ }
+ }
+
+ }
+
+ }
+
}
+
}
- // Cost
- if (!sourceJsonObject.cost) {
- LOGGER.error("La ressource contient une source sans cout.");
+ // Coûts
+ if (!sourceJsonObject.costs) {
+ LOGGER.error("Mauvaise configuration : 'source.costs' absent");
return false;
} else {
- // Profile
- if (!sourceJsonObject.cost.profile) {
- LOGGER.error("La ressource contient une source sans profile.");
+
+ LOGGER.debug("'source.costs' présent");
+
+ if (!Array.isArray(sourceJsonObject.costs)) {
+ LOGGER.error("Mauvaise configuration : 'source.costs' n'est pas un tableau");
return false;
} else {
- // rien à faire
+ LOGGER.debug("'source.costs' est un tableau");
}
- // Optimization
- if (!sourceJsonObject.cost.optimization) {
- LOGGER.error("La ressource contient une source sans optimization.");
+
+ if (sourceJsonObject.costs.length === 0) {
+ LOGGER.error("Mauvaise configuration : 'source.costs' est un tableau vide");
return false;
} else {
- // rien à faire
+ LOGGER.debug("'source.costs' n'est pas un tableau vide");
}
- // Compute
- if (!sourceJsonObject.cost.compute) {
- LOGGER.info("La ressource contient une source sans compute.");
- } else {
- if (!sourceJsonObject.cost.compute.storage) {
- LOGGER.error("La ressource contient une source ayant un cout sans stockage.");
+
+ for (let i = 0; i < sourceJsonObject.costs.length; i++) {
+
+ if (!sourceJsonObject.costs[i].profile) {
+ LOGGER.error("Mauvaise configuration : 'source.costs["+i+"].profile' absent");
return false;
} else {
- if (!storageManager.checkJsonStorage(sourceJsonObject.cost.compute.storage)) {
- LOGGER.error("La ressource contient une source ayant un stockage du cout incorrect.");
- return false;
- } else {
- // rien à faire
- }
+ LOGGER.debug("'source.costs["+i+"].profile' présent");
}
- // TODO: ajouter la vérification de configuration
+
+ if (!sourceJsonObject.costs[i].optimization) {
+ LOGGER.error("Mauvaise configuration : 'source.costs["+i+"].optimization' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.costs["+i+"].optimization' présent");
+ }
+
+ if (!sourceJsonObject.costs[i].costType) {
+ LOGGER.error("Mauvaise configuration : 'source.costs["+i+"].costType' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.costs["+i+"].costType' présent");
+ }
+
+ if (!sourceJsonObject.costs[i].costColumn) {
+ LOGGER.error("Mauvaise configuration : 'source.costs["+i+"].costColumn' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.costs["+i+"].costColumn' présent");
+ }
+
+ if (!sourceJsonObject.costs[i].rcostColumn) {
+ LOGGER.error("Mauvaise configuration : 'source.costs["+i+"].rcostColumn' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.costs["+i+"].rcostColumn' présent");
+ }
+
}
+
}
+
LOGGER.info("Fin de la verification de la source pgr.");
return true;
+
}
/**
@@ -491,29 +612,34 @@ module.exports = class sourceManager {
* @name checkSourceSmartrouting
* @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source smartrouting.
* @param {json} sourceJsonObject - Description JSON de la source
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
+ * @return {boolean}
*
*/
- checkSourceSmartrouting(sourceJsonObject) {
+ checkSourceSmartrouting(sourceJsonObject) {
LOGGER.info("Verification de la source smartrouting...");
// Storage
if (!sourceJsonObject.storage) {
- LOGGER.error("La ressource contient une source sans stockage.");
+ LOGGER.error("Mauvaise configuration : 'source.storage' absent");
return false;
} else {
- if (!storageManager.checkJsonStorage(sourceJsonObject.storage)) {
- LOGGER.error("Stockage de la source incorrect.");
+
+ LOGGER.debug("'source.storage' présent");
+
+ if (!sourceJsonObject.storage.url) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.url' absent");
return false;
} else {
- // Normalement, il n'y a plus rien à faire car la fonction checkDuplicationSource() vérifie déjà que la source n'est pas dupliquée
+ LOGGER.debug("'source.storage.url' présent");
+ // TODO: vérifier la forme de l'URL avec une regex
}
}
LOGGER.info("Fin de la verification de la source smartrouting.");
return true;
+
}
/**
@@ -522,7 +648,7 @@ module.exports = class sourceManager {
* @name checkSourceValhalla
* @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source valhalla.
* @param {json} sourceJsonObject - Description JSON de la source
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
+ * @return {boolean}
*
*/
@@ -532,19 +658,96 @@ module.exports = class sourceManager {
// Storage
if (!sourceJsonObject.storage) {
- LOGGER.error("La ressource contient une source sans stockage.");
+
+ LOGGER.error("Mauvaise configuration : 'source.storage' absent");
return false;
+
} else {
- if (!storageManager.checkJsonStorage(sourceJsonObject.storage)) {
- LOGGER.error("Stockage de la source incorrect.");
+
+ LOGGER.debug("'source.storage' présent");
+
+ if (!sourceJsonObject.storage.tar) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.tar' absent");
return false;
} else {
- // Normalement, il n'y a plus rien à faire car la fonction checkDuplicationSource() vérifie déjà que la source n'est pas dupliquée
+ LOGGER.debug("'source.storage.tar' présent");
+ }
+
+ if (!sourceJsonObject.storage.dir) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.dir' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.storage.dir' présent");
+ }
+
+ if (!sourceJsonObject.storage.config) {
+ LOGGER.error("Mauvaise configuration : 'source.storage.config' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.storage.config' présent");
+ }
+
+ }
+
+ // Coûts
+ if (!sourceJsonObject.costs) {
+ LOGGER.error("Mauvaise configuration : 'source.costs' absent");
+ return false;
+ } else {
+
+ LOGGER.debug("'source.costs' présent");
+
+ if (!Array.isArray(sourceJsonObject.costs)) {
+ LOGGER.error("Mauvaise configuration : 'source.costs' n'est pas un tableau");
+ return false;
+ } else {
+ LOGGER.debug("'source.costs' est un tableau");
+ }
+
+ if (sourceJsonObject.costs.length === 0) {
+ LOGGER.error("Mauvaise configuration : 'source.costs' est un tableau vide");
+ return false;
+ } else {
+ LOGGER.debug("'source.costs' n'est pas un tableau vide");
+ }
+
+ for (let i = 0; i < sourceJsonObject.costs.length; i++) {
+
+ if (!sourceJsonObject.costs[i].profile) {
+ LOGGER.error("Mauvaise configuration : 'source.costs["+i+"].profile' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.costs["+i+"].profile' présent");
+ }
+
+ if (!sourceJsonObject.costs[i].optimization) {
+ LOGGER.error("Mauvaise configuration : 'source.costs["+i+"].optimization' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.costs["+i+"].optimization' présent");
+ }
+
+ if (!sourceJsonObject.costs[i].costType) {
+ LOGGER.error("Mauvaise configuration : 'source.costs["+i+"].costType' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.costs["+i+"].costType' présent");
+ }
+
+ if (!sourceJsonObject.costs[i].costing) {
+ LOGGER.error("Mauvaise configuration : 'source.costs["+i+"].costing' absent");
+ return false;
+ } else {
+ LOGGER.debug("'source.costs["+i+"].costing' présent");
+ }
+
}
+
}
LOGGER.info("Fin de la verification de la source smartrouting.");
return true;
+
}
/**
@@ -704,20 +907,31 @@ module.exports = class sourceManager {
}
if (sourceJsonObject.type === "osrm") {
- source = new osrmSource(sourceJsonObject, topology);
+ source = new osrmSource(sourceJsonObject);
} else if (sourceJsonObject.type === "pgr") {
- source = new pgrSource(sourceJsonObject, topology);
+
+ // Création de la base associée
+ let base = {};
+ if (!this._baseManager.loadBaseConfiguration(sourceJsonObject.storage.base.dbConfig)) {
+ LOGGER.error("Impossible de charger la base configurée dans " + sourceJsonObject.storage.base.dbConfig);
+ return false;
+ } else {
+ base = this._baseManager.getBase(sourceJsonObject.storage.base.dbConfig);
+ }
+ // Création de la source
+ source = new pgrSource(sourceJsonObject, base);
+
} else if (sourceJsonObject.type === "smartrouting") {
- // smartrouting n'utilise pas la topologie définie dans la conf
source = new smartroutingSource(sourceJsonObject);
} else if (sourceJsonObject.type === "valhalla") {
- source = new valhallaSource(sourceJsonObject, topology);
+ source = new valhallaSource(sourceJsonObject);
} else {
- // On va voir si c'est un autre type.
LOGGER.error("Le type de la source est inconnu");
return false;
}
+ // On sauvegarde la source et certains éléments pour le manager afin de pouvoir réutiliser ces infomations plus tard
+ // Notamment dans la gestion (ajout/suppression/modification) de sources durant la vie du service
this._loadedSourceId.push(sourceJsonObject.id);
this._loadedSourceConfiguration[sourceJsonObject.id] = sourceJsonObject;
this._source[sourceJsonObject.id] = source;
diff --git a/src/js/sources/valhallaSource.js b/src/js/sources/valhallaSource.js
index dd86535..fa6c83d 100644
--- a/src/js/sources/valhallaSource.js
+++ b/src/js/sources/valhallaSource.js
@@ -22,7 +22,7 @@ const LOGGER = log4js.getLogger("VALHALLASOURCE");
*
* @class
* @name valhallaSource
-* @description Classe modélisant une source pgRouting.
+* @description Classe modélisant une source Valhalla.
*
*/
module.exports = class valhallaSource extends Source {
@@ -32,17 +32,27 @@ module.exports = class valhallaSource extends Source {
* @name constructor
* @description Constructeur de la classe valhallaSource
* @param{json} sourceJsonObject - Description de la source
- * @param{topology} topology - Instance de la classe Topology
*
*/
- constructor(sourceJsonObject, topology) {
+ constructor(sourceJsonObject) {
// Constructeur parent
- super(sourceJsonObject.id, "valhalla", topology);
+ super(sourceJsonObject.id, "valhalla", sourceJsonObject.description, sourceJsonObject.projection, sourceJsonObject.bbox);
// Stockage de la configuration
this._configuration = sourceJsonObject;
+ // Gestions des coûts disponibles
+ this._costs = {};
+
+ // Initialisation des coûts
+ for (let i = 0; i < sourceJsonObject.costs.length; i++) {
+ Object.defineProperty(this._costs, sourceJsonObject.costs[i].profile, { value: new Object(), configurable: true, enumerable: true, writable: true });
+ Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile], sourceJsonObject.costs[i].optimization, { value: new Object(), configurable: true, enumerable: true, writable: true });
+ Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].optimization], "costing", { value: sourceJsonObject.costs[i].costing, configurable: true, enumerable: true, writable: true });
+ Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].costType], "costing", { value: sourceJsonObject.costs[i].costing, configurable: true, enumerable: true, writable: true });
+ }
+
}
/**
@@ -119,15 +129,15 @@ module.exports = class valhallaSource extends Source {
// Coordonnées
// start
- coordinatesTable.push(request.start.getCoordinatesIn(this.topology.projection));
+ coordinatesTable.push(request.start.getCoordinatesIn(super.projection));
// intermediates
if (request.intermediates.length !== 0) {
for (let i = 0; i < request.intermediates.length; i++) {
- coordinatesTable.push(request.intermediates[i].getCoordinatesIn(this.topology.projection));
+ coordinatesTable.push(request.intermediates[i].getCoordinatesIn(super.projection));
}
}
// end
- coordinatesTable.push(request.end.getCoordinatesIn(this.topology.projection));
+ coordinatesTable.push(request.end.getCoordinatesIn(super.projection));
LOGGER.debug("coordinates:");
LOGGER.debug(coordinatesTable);
@@ -169,7 +179,7 @@ module.exports = class valhallaSource extends Source {
locationsString = locationsString.slice(0, -1);
locationsString += "]";
- const costingString = `"costing":"${this._configuration.cost.compute.configuration.costing}"`;
+ const costingString = `"costing":"${this._costs[request.profile][request.optimization].costing}"`;
// Permet de grandement se simplifier le parsing !!
const optionsString = `"directions_options":{"format":"osrm"}`;
const commandString = `valhalla_service ${this._configuration.storage.config} route '{${locationsString},${costingString},${optionsString}}' `;
@@ -258,7 +268,7 @@ module.exports = class valhallaSource extends Source {
}
const locationsString = `"locations":[{"lat":${request.point.lat},"lon":${request.point.lon}}]`;
- const costingString = `"costing":"${this._configuration.cost.compute.configuration.costing}"`;
+ const costingString = `"costing":"${this._costs[request.profile][request.costType].costing}"`;
const contoursString = `"contours":[{"${request.costType}":${costValue}}]`;
const reverseString = `"reverse":${reverse}`;
const commandString = `valhalla_service ${this._configuration.storage.config} isochrone '{${locationsString},${costingString},${contoursString},${reverseString}}' `;
@@ -372,10 +382,10 @@ module.exports = class valhallaSource extends Source {
let askedProjection = routeRequest.start.projection;
LOGGER.debug("asked projection: " + askedProjection);
- LOGGER.debug("topology projection: " + this.topology.projection);
+ LOGGER.debug("source projection: " + super.projection);
// start
- start = new Point(valhallaResponse.waypoints[0].location[0], valhallaResponse.waypoints[0].location[1], this.topology.projection);
+ start = new Point(valhallaResponse.waypoints[0].location[0], valhallaResponse.waypoints[0].location[1], super.projection);
if (!start.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of start in OSRM response. ");
} else {
@@ -384,7 +394,7 @@ module.exports = class valhallaSource extends Source {
}
// end
- end = new Point(valhallaResponse.waypoints[valhallaResponse.waypoints.length-1].location[0], valhallaResponse.waypoints[valhallaResponse.waypoints.length-1].location[1], this.topology.projection);
+ end = new Point(valhallaResponse.waypoints[valhallaResponse.waypoints.length-1].location[0], valhallaResponse.waypoints[valhallaResponse.waypoints.length-1].location[1], super.projection);
if (!end.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of end in OSRM response. ");
} else {
@@ -411,7 +421,7 @@ module.exports = class valhallaSource extends Source {
let currentOsrmRoute = valhallaResponse.routes[i];
// On commence par créer l'itinéraire avec les attributs obligatoires
- routes[i] = new Route( new Line(currentOsrmRoute.geometry, "polyline", this._topology.projection, 6) );
+ routes[i] = new Route( new Line(currentOsrmRoute.geometry, "polyline", super.projection, 6) );
if (!routes[i].geometry.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of geometry in OSRM response. ");
} else {
@@ -437,7 +447,7 @@ module.exports = class valhallaSource extends Source {
let currentOsrmRouteLeg = currentOsrmRoute.legs[j];
- let legStart = new Point(valhallaResponse.waypoints[j].location[0], valhallaResponse.waypoints[j].location[1], this.topology.projection);
+ let legStart = new Point(valhallaResponse.waypoints[j].location[0], valhallaResponse.waypoints[j].location[1], super.projection);
if (!legStart.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of leg start in OSRM response. ");
} else {
@@ -445,7 +455,7 @@ module.exports = class valhallaSource extends Source {
LOGGER.debug(legStart);
}
- let legEnd = new Point(valhallaResponse.waypoints[j+1].location[0], valhallaResponse.waypoints[j+1].location[1], this.topology.projection);
+ let legEnd = new Point(valhallaResponse.waypoints[j+1].location[0], valhallaResponse.waypoints[j+1].location[1], super.projection);
if (!legEnd.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of leg end in OSRM response. ");
} else {
@@ -468,7 +478,7 @@ module.exports = class valhallaSource extends Source {
LOGGER.debug("Step number " + k + " of portion number " + j + " for route number " + i);
let currentOsrmRouteStep = currentOsrmRouteLeg.steps[k];
- steps[k] = new Step( new Line(currentOsrmRouteStep.geometry, "polyline", this._topology.projection, 6) );
+ steps[k] = new Step( new Line(currentOsrmRouteStep.geometry, "polyline", super.projection, 6) );
if (!steps[k].geometry.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of step's geometry in OSRM response. ");
} else {
@@ -545,7 +555,7 @@ module.exports = class valhallaSource extends Source {
}
// Création d'un objet Point (utile plus tard).
- point = new Point(isochroneRequest.point.lon, isochroneRequest.point.lat, this.topology.projection);
+ point = new Point(isochroneRequest.point.lon, isochroneRequest.point.lat, super.projection);
let rawGeometry = valhallaResponse.features[0].geometry;
@@ -561,7 +571,7 @@ module.exports = class valhallaSource extends Source {
}
// Création d'un objet Polygon à partir du GeoJSON reçu.
- geometry = new Polygon(rawGeometry, "geojson", this._topology.projection);
+ geometry = new Polygon(rawGeometry, "geojson", super.projection);
/* Envoi de la réponse au proxy. */
return new IsochroneResponse(
diff --git a/src/js/topology/dbTopology.js b/src/js/topology/dbTopology.js
deleted file mode 100644
index 45217fd..0000000
--- a/src/js/topology/dbTopology.js
+++ /dev/null
@@ -1,137 +0,0 @@
-'use strict';
-
-const Topology = require('./topology');
-
-/**
-*
-* @class
-* @name dbTopology
-* @description Classe modélisant une topologie se basant sur une base de données.
-*
-*/
-module.exports = class dbTopology extends Topology {
-
- /**
- *
- * @function
- * @name constructor
- * @description Constructeur de la classe dbTopology
- * @param{string} id - Id de la topologie
- * @param{string} description - Description de la topologie
- * @param{string} projection - Projection de la topologie
- * @param{string} bbox - Bbox de la topologie
- * @param{object} base - Instance de la classe Base
- * @param{string} schema - Nom de la schema contenant la topologie
- * @param{table} defaultAttributes - Tableau d'objets {key: 'test', column:'test_column', default: 'true'}
- * @param{table} otherAttributes - Tableau d'objets {key: 'test', column:'test_column', default: 'false'}
- *
- */
- constructor(id, description, projection, bbox, base, schema, defaultAttributes, otherAttributes) {
-
- // ID de la topologie
- super(id, "db", description, projection, bbox);
-
- // Référence à la base de données
- this._base = base;
-
- // Schema contenant la topologie
- this._schema = schema;
-
- // stockage des attributs par défaut
- this._defaultAttributes = defaultAttributes;
-
- // stockage des attributs dans un tableau
- this._defaultAttributesTable = new Array();
- this._defaultAttributesKeyTable = new Array();
- for (let i = 0; i < this._defaultAttributes.length; i++) {
- this._defaultAttributesTable.push("'" + this._defaultAttributes[i].column + "'");
- this._defaultAttributesKeyTable.push(this._defaultAttributes[i].key);
- }
-
- // stockage des attributs par défaut en une chaîne de caractères
- this._defaultAttributesString = this._defaultAttributesTable.join(",");
-
- // stockage des attributs restants et disponibles
- this._otherAttributes = otherAttributes;
-
- }
-
- /**
- *
- * @function
- * @name get base
- * @description Récupérer la base
- *
- */
- get base () {
- return this._base;
- }
-
- /**
- *
- * @function
- * @name get schema
- * @description Récupérer le schema
- *
- */
- get schema () {
- return this._schema;
- }
-
- /**
- *
- * @function
- * @name get defaultAttributes
- * @description Récupérer les attributs (colonne) par défaut de la topologie
- *
- */
- get defaultAttributes () {
- return this._defaultAttributes;
- }
-
- /**
- *
- * @function
- * @name get defaultAttributesString
- * @description Récupérer les attributs (colonne) par défaut de la topologie en une chaîne de caractères
- *
- */
- get defaultAttributesString () {
- return this._defaultAttributesString;
- }
-
- /**
- *
- * @function
- * @name get defaultAttributesTable
- * @description Récupérer les attributs (colonne) par défaut de la topologie en tableau
- *
- */
- get defaultAttributesTable () {
- return this._defaultAttributesTable;
- }
-
- /**
- *
- * @function
- * @name get defaultAttributesKeyTable
- * @description Récupérer les attributs (clé) par défaut de la topologie en tableau
- *
- */
- get defaultAttributesKeyTable () {
- return this._defaultAttributesKeyTable;
- }
-
- /**
- *
- * @function
- * @name get otherAttributes
- * @description Récupérer les attributs facultatifs de la topologie
- *
- */
- get otherAttributes () {
- return this._otherAttributes;
- }
-
-
-}
diff --git a/src/js/topology/osmTopology.js b/src/js/topology/osmTopology.js
deleted file mode 100644
index 7604d78..0000000
--- a/src/js/topology/osmTopology.js
+++ /dev/null
@@ -1,47 +0,0 @@
-'use strict';
-
-const Topology = require('./topology');
-
-/**
-*
-* @class
-* @name dbTopology
-* @description Classe modélisant une topologie se basant sur un fichier osm.
-*
-*/
-module.exports = class osmTopology extends Topology {
-
- /**
- *
- * @function
- * @name constructor
- * @description Constructeur de la classe dbTopology
- * @param{string} id - Id de la topologie
- * @param{string} description - Description de la topologie
- * @param{string} projection - Projection de la topologie
- * @param{string} bbox - Bbox de la topologie
- * @param{string} file - Nom du fichier osm
- *
- */
- constructor(id, description, projection, bbox, file) {
-
- // ID de la topologie
- super(id, "osm", description, projection, bbox);
-
- // Nom du fichier osm
- this._file = file;
-
- }
-
- /**
- *
- * @function
- * @name get file
- * @description Récupérer le nom du fichier osm
- *
- */
- get file () {
- return this._file;
- }
-
-}
diff --git a/src/js/topology/topology.js b/src/js/topology/topology.js
deleted file mode 100644
index 1a6c934..0000000
--- a/src/js/topology/topology.js
+++ /dev/null
@@ -1,99 +0,0 @@
-'use strict';
-
-/**
-*
-* @class
-* @name Topology
-* @description Classe modélisant une topologie.
-*
-*/
-module.exports = class Topology {
-
- /**
- *
- * @function
- * @name constructor
- * @description Constructeur de la classe Topology
- * @param{string} id - Id de la topologie
- * @param{string} type - Type de la topologie
- * @param{string} description - Description de la topologie
- * @param{string} projection - Projection de la topologie
- * @param{string} bbox - Bbox de la topologie
- *
- */
- constructor(id, type, description, projection, bbox) {
-
- // ID de la topologie
- this._id = id;
-
- // type
- this._type = type;
-
- // Description
- this._description = description;
-
- // Projection
- this._projection = projection;
-
- // Bbox
- this._bbox = bbox;
-
- }
-
- /**
- *
- * @function
- * @name get id
- * @description Récupérer l'id
- *
- */
- get id () {
- return this._id;
- }
-
- /**
- *
- * @function
- * @name get type
- * @description Récupérer le type
- *
- */
- get type () {
- return this._type;
- }
-
- /**
- *
- * @function
- * @name get description
- * @description Récupérer la description
- *
- */
- get description () {
- return this._description;
- }
-
- /**
- *
- * @function
- * @name get projection
- * @description Récupérer la projection
- *
- */
- get projection () {
- return this._projection;
- }
-
- /**
- *
- * @function
- * @name get bbox
- * @description Récupérer la bbox
- *
- */
- get bbox () {
- return this._bbox;
- }
-
-
-}
diff --git a/src/js/topology/topologyManager.js b/src/js/topology/topologyManager.js
deleted file mode 100644
index c3ba6b9..0000000
--- a/src/js/topology/topologyManager.js
+++ /dev/null
@@ -1,515 +0,0 @@
-'use strict';
-
-const log4js = require('log4js');
-const storageManager = require('../utils/storageManager');
-const DbTopology = require('./dbTopology');
-const OsmTopology = require('./osmTopology');
-const assert = require('assert');
-
-// Création du LOGGER
-const LOGGER = log4js.getLogger("TOPOLOGYMANAGER");
-
-/**
-*
-* @class
-* @name topologyManager
-* @description Classe modélisant le manager des topologies.
-*
-*/
-module.exports = class topologyManager {
-
- /**
- *
- * @function
- * @name constructor
- * @description Constructeur de la classe topologyManager
- * @param{BaseManager} baseManager - Manager de bases
- *
- */
- constructor(baseManager, projectionManager) {
-
- // Liste des descriptions de topologies chargées par le manager
- this._loadedTopologyId = new Array();
-
- // Liste des descriptions de topologies vérifiées et validées par le manager
- this._checkedTopologyId = new Array();
-
- // Descriptions des topologies chargées par le manager
- this._loadedTopologyConfiguration = {};
-
- // Descriptions des topologies vérifiées par le manager
- this._checkedTopologyConfiguration = {};
-
- // Le catalogue des topologies créées par le manager
- this._topologyCatalog = {};
-
- // Manager de bases
- this._baseManager = baseManager;
-
- // Manager de projections
- this._projectionManager = projectionManager;
-
- }
-
- /**
- *
- * @function
- * @name get topologyCatalog
- * @description Récupérer le catalogue des topologies
- *
- */
- get topologyCatalog() {
- return this._topologyCatalog;
- }
-
- /**
- *
- * @function
- * @name getTopology
- * @description Récupérer une topologie via son id
- * @param {string} id - Id de la topologie
- *
- */
- getTopology(id) {
- if (this._topologyCatalog[id]) {
- return this._topologyCatalog[id];
- } else {
- return {};
- }
-
- }
-
- /**
- *
- * @function
- * @name checkTopologyConfiguration
- * @description Vérification de la description d'une topologie
- * @param{json} topologyJsonDescription - JSON décrivant une topologie
- *
- */
- async checkTopologyConfiguration(topologyJsonDescription) {
-
- // Id de la topologie
- if (!topologyJsonDescription.id) {
- LOGGER.error("La topologie ne contient pas d'id.");
- return false;
- } else {
-
- // On vérifie que l'id n'est pas déjà chargés.
- if (this._loadedTopologyId.length !== 0) {
-
- for (let i = 0; i < this._loadedTopologyId.length; i++ ) {
- if (this._loadedTopologyId[i] === topologyJsonDescription.id) {
-
- LOGGER.info("La topologie contenant l'id " + topologyJsonDescription.id + " est deja chargée.");
- // On vérifie que la topology décrite et celle déjà identifiée soient exactement les mêmes
- if (this.checkDuplicationLoadedTopology(topologyJsonDescription)) {
- LOGGER.info("La topologie contenant l'id " + topologyJsonDescription.id + " est identique à la topologie deja identifiee.");
- return true;
- } else {
- LOGGER.error("La topologie contenant l'id " + topologyJsonDescription.id + " n'est pas identique à la topologie deja identifiee.");
- return false;
- }
-
- }
- }
- }
-
- // On vérifie que l'id n'est pas déjà vérifiés.
- if (this._checkedTopologyId.length !== 0) {
-
- for (let i = 0; i < this._checkedTopologyId.length; i++ ) {
- if (this._checkedTopologyId[i] === topologyJsonDescription.id) {
-
- LOGGER.info("La topologie contenant l'id " + topologyJsonDescription.id + " est deja vérifiée.");
- // On vérifie que la topology décrite et celle déjà identifiée soient exactement les mêmes
- if (this.checkDuplicationCheckedTopology(topologyJsonDescription)) {
- LOGGER.info("La topologie contenant l'id " + topologyJsonDescription.id + " est identique à la topologie deja identifiee.");
- return true;
- } else {
- LOGGER.error("La topologie contenant l'id " + topologyJsonDescription.id + " n'est pas identique à la topologie deja identifiee.");
- return false;
- }
-
- }
- }
- }
- }
-
- // Description de la topologie
- if (!topologyJsonDescription.description) {
- LOGGER.error("La ressource ne contient pas de description de la topologie.");
- return false;
- } else {
- // rien à faire
- }
-
- // Projection de la topologie
- if (!topologyJsonDescription.projection) {
- LOGGER.error("La ressource ne contient pas d'information sur la projection de la topologie.")
- return false;
- } else {
- // Vérification de la projection
- if (!this._projectionManager.isProjectionChecked(topologyJsonDescription.projection)) {
- LOGGER.error("La topologie indique une projection non disponible sur le service: " + topologyJsonDescription.projection);
- return false;
- }
- }
-
- // Bbox de la topologie
- if (!topologyJsonDescription.bbox) {
- LOGGER.error("La ressource ne contient pas d'information sur la bbox de la topologie.")
- return false;
- } else {
- // TODO: vérifier la bbox
- }
-
- if (!topologyJsonDescription.type) {
- LOGGER.error("La ressource ne contient pas de type de la topologie.");
- return false;
- } else {
-
- if (topologyJsonDescription.type === "db") {
- if (!(await this.checkDbTopology(topologyJsonDescription))) {
- LOGGER.error("La topologie db est incorrecte.");
- return false;
- }
- } else if (topologyJsonDescription.type === "osm") {
- if (!this.checkOsmTopology(topologyJsonDescription)) {
- LOGGER.error("La topologie osm est incorrecte.");
- return false;
- }
- } else {
- LOGGER.error("La ressource contient un type inconnu pour la topologie.");
- return false;
- }
-
- }
-
- return true;
-
- }
-
- /**
- *
- * @function
- * @name checkOsmTopology
- * @description Vérification de la description d'une topologie OSM
- * @param{json} topologyJsonDescription - JSON décrivant une topologie
- *
- */
- checkOsmTopology(topologyJsonDescription) {
-
- // Stockage de la topologie
- if (!topologyJsonDescription.storage) {
- LOGGER.info("La ressource ne contient pas d'information sur le stockage du fichier de generation de la topologie.");
- } else {
- if (!storageManager.checkJsonStorage(topologyJsonDescription.storage)) {
- LOGGER.warn("Stockage de la topologie incorrect.");
- } else {
- // rien à faire
- }
- }
-
- return true;
-
- }
-
- /**
- *
- * @function
- * @name checkDbTopology
- * @description Vérification de la description d'une topologie issue d'une base de données
- * @param{json} topologyJsonDescription - JSON décrivant une topologie
- *
- */
- async checkDbTopology(topologyJsonDescription) {
-
- // Stockage de la topologie
- if (!topologyJsonDescription.storage) {
- LOGGER.error("La ressource ne contient pas d'information sur le stockage du fichier de generation de la topologie.");
- return false;
- } else {
- // on continue
- }
-
- if (!topologyJsonDescription.storage.base) {
- LOGGER.error("La ressource ne contient pas de parametre 'topology.storage.base'.");
- return false;
- }
-
- // dbConfig
- if (!topologyJsonDescription.storage.base.dbConfig) {
- LOGGER.error("La ressource ne contient pas de parametre 'topology.storage.dbConfig'.");
- return false;
- } else {
- if (!(await this._baseManager.checkBaseConfiguration(topologyJsonDescription.storage.base.dbConfig))) {
- LOGGER.error("La ressource contient un parametre 'topology.storage.dbConfig' incorrect.");
- return false;
- } else {
- this._baseManager.saveCheckedBaseConfiguration(topologyJsonDescription.storage.base.dbConfig);
- }
- }
-
- // schema
- if (!topologyJsonDescription.storage.base.schema) {
- LOGGER.error("La ressource ne contient pas de parametre 'topology.storage.base.schema'.");
- return false;
- } else {
- // TODO: vérification que ce n'est pas du code injecté
- }
-
- // Attributs
- if (topologyJsonDescription.storage.base.attributes) {
-
- // on vérifie que c'est un tableau
- if (!Array.isArray(topologyJsonDescription.storage.base.attributes)) {
- LOGGER.error("Le parametre resource.topology.attributes n'est pas un tableau.");
- return false;
- }
-
- // que le tableau n'est pas vide
- if (topologyJsonDescription.storage.base.attributes.length === 0) {
- LOGGER.error("Le parametre resource.topology.attributes est un tableau vide.");
- return false;
- }
-
- // on va vérifier que chaque attribut est complet et unique dans sa description
- let attributesKeyTable = new Array();
- let attributesColumnTable = new Array();
-
- for (let i = 0; i < topologyJsonDescription.storage.base.attributes.length; i++) {
- let curAttribute = topologyJsonDescription.storage.base.attributes[i];
-
-
- if (!curAttribute.key) {
- LOGGER.error("La description de l'attribut est incomplete: key");
- return false;
- } else {
-
- if (attributesKeyTable.length !== 0) {
- for (let j = 0; j < attributesKeyTable.length; j++) {
- if (curAttribute.key === attributesKeyTable[j]) {
- LOGGER.error("La description de l'attribut indique une cle deja utilisee.");
- return false;
- }
- }
- }
-
- }
-
- if (!curAttribute.column) {
- LOGGER.error("La description de l'attribut est incomplete: column");
- return false;
- } else {
-
- if (attributesColumnTable.length !== 0) {
- for (let j = 0; j < attributesColumnTable.length; j++) {
- if (curAttribute.column === attributesColumnTable[j]) {
- LOGGER.error("La description de l'attribut indique une colonne deja utilisee.");
- return false;
- }
- }
- }
-
- // TODO: vérification que ce n'est pas du code injecté
-
- }
-
- if (!curAttribute.default) {
- LOGGER.error("La description de l'attribut est incomplete: default");
- return false;
- } else {
-
- if (curAttribute.default !== "true" && curAttribute.default !== "false") {
- LOGGER.error("La description de l'attribut a un parametre 'default' incorrect.");
- return false;
- }
-
- }
-
- attributesKeyTable.push(curAttribute.key);
- attributesColumnTable.push(curAttribute.column);
-
- }
- } else {
- // rien à faire
- }
-
- return true;
-
- }
-
- /**
- *
- * @function
- * @name checkDuplicationLoadedTopology
- * @description Fonction utilisée pour vérifier que le contenu d'un fichier de description d'une source est bien le même qu'un autre.
- * @param {json} topologyJsonDescription - Description JSON de la topologie
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
- *
- */
-
- checkDuplicationLoadedTopology(topologyJsonDescription) {
-
- LOGGER.info("Comparaison des deux topologies identifiees et devant etre identiques...");
-
- // On récupère la description de la topologie faisant office de référence car lue la première.
- let referenceTopology = this._loadedTopologyConfiguration[topologyJsonDescription.id];
-
- // On compare les deux objets
- try {
- assert.deepStrictEqual(topologyJsonDescription, referenceTopology);
- } catch (err) {
- LOGGER.error("Les deux topologies ne sont pas identiques.");
- LOGGER.error(err);
- return false;
- }
-
- LOGGER.info("Les deux topologies sont identiques.");
- return true;
-
- }
-
- /**
- *
- * @function
- * @name checkDuplicationCheckedTopology
- * @description Fonction utilisée pour vérifier que le contenu d'un fichier de description d'une source est bien le même qu'un autre.
- * @param {json} topologyJsonDescription - Description JSON de la topologie
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
- *
- */
-
- checkDuplicationCheckedTopology(topologyJsonDescription) {
-
- LOGGER.info("Comparaison des deux topologies identifiees et devant etre identiques...");
-
- // On récupère la description de la topologie faisant office de référence car lue la première.
- let referenceTopology = this._checkedTopologyConfiguration[topologyJsonDescription.id];
-
- // On compare les deux objets
- try {
- assert.deepStrictEqual(topologyJsonDescription, referenceTopology);
- } catch (err) {
- LOGGER.error("Les deux topologies ne sont pas identiques.");
- LOGGER.error(err);
- return false;
- }
-
- LOGGER.info("Les deux topologies sont identiques.");
- return true;
-
- }
-
- /**
- *
- * @function
- * @name saveCheckedTopology
- * @description Sauvegarder l'id de la topology vérifié
- * @param {object} configuration - Id de la topology que l'on veut sauvegarder
- *
- */
- saveCheckedTopology(configuration) {
-
- this._checkedTopologyId.push(configuration.id);
- this._checkedTopologyConfiguration[configuration.id] = configuration;
-
- }
-
- /**
- *
- * @function
- * @name flushCheckedTopology
- * @description Vider la liste des topology déjà vérifiées
- *
- */
- flushCheckedTopology() {
-
- this._checkedTopologyId = new Array();
- this._checkedTopologyConfiguration = {};
-
- }
-
- /**
- *
- * @function
- * @name loadTopologyConfiguration
- * @description Fonction utilisée pour créer une source.
- * @param {json} topologyJsonObject - Description JSON de la topologie
- * @return {Topology} Topologie créée - Instance d'une classe fille de Topology
- *
- */
-
- loadTopologyConfiguration(topologyJsonObject) {
-
- LOGGER.info("Creation de la topologie: " + topologyJsonObject.id);
-
- let topology;
-
- // on vérifie d'abord que la topologie n'a pas déjà été créée
- if (this._topologyCatalog[topologyJsonObject.id]) {
- LOGGER.info("La topologie " + topologyJsonObject.id + " existe déjà");
- return true;
- } else {
- // la topologie n'existe pas, on continue
- }
-
- if (topologyJsonObject.type === "osm") {
-
- let osmFile = "";
- if (topologyJsonObject.storage) {
- osmFile = topologyJsonObject.storage.file;
- } else {
- // ce n'est pas obligatoire
- }
-
- topology = new OsmTopology(topologyJsonObject.id, topologyJsonObject.description,
- topologyJsonObject.projection, topologyJsonObject.bbox, osmFile);
-
- } else if (topologyJsonObject.type === "db") {
-
- // récupération de la base
- let base = {};
- if (!this._baseManager.loadBaseConfiguration(topologyJsonObject.storage.base.dbConfig)) {
- LOGGER.error("Impossible de charger la base configurée dans " + topologyJsonObject.storage.base.dbConfig);
- return false;
- } else {
- base = this._baseManager.getBase(topologyJsonObject.storage.base.dbConfig);
- }
-
- // création des tableaux d'attributs
- let defaultAttributes = new Array();
- let otherAttributes = new Array();
- for (let i = 0; i < topologyJsonObject.storage.base.attributes.length; i++) {
- let curAttribute = topologyJsonObject.storage.base.attributes[i];
- if (curAttribute.default === "true") {
- defaultAttributes.push(curAttribute);
- } else if (curAttribute.default === "false") {
- otherAttributes.push(curAttribute);
- } else {
- // cela ne doit pas arriver
- }
- }
-
- // création de la topologie
- topology = new DbTopology(topologyJsonObject.id, topologyJsonObject.description,
- topologyJsonObject.projection, topologyJsonObject.bbox, base, topologyJsonObject.storage.base.schema,
- defaultAttributes, otherAttributes);
-
- } else {
- // On va voir si c'est un autre type.
- LOGGER.error("Type de la topology inconnu");
- return false;
- }
-
- // on sauvegarde l'id de la topologie pour savoir qu'elle a déjà été vérifiée et que sa description est valide
- this._loadedTopologyId.push(topologyJsonObject.id);
- this._loadedTopologyConfiguration[topologyJsonObject.id] = topologyJsonObject;
- this._topologyCatalog[topologyJsonObject.id] = topology;
-
- return true;
-
- }
-
-}
diff --git a/src/js/utils/storageManager.js b/src/js/utils/storageManager.js
deleted file mode 100644
index 1c533e9..0000000
--- a/src/js/utils/storageManager.js
+++ /dev/null
@@ -1,84 +0,0 @@
-'use strict';
-
-const fs = require('fs');
-const log4js = require('log4js');
-
-// Création du LOGGER
-var LOGGER = log4js.getLogger("STORAGEMANAGER");
-
-module.exports = {
-
- /**
- *
- * @function
- * @name checkJsonStorage
- * @description Fonction utilisée pour vérifier l'écriture d'un json au niveau du stockage.
- * @param {json} jsonStorage - Json décrivant le stockage
- * @return {boolean} vrai si tout c'est bien passé et faux s'il y a eu une erreur
- *
- */
-
- checkJsonStorage: function(jsonStorage) {
-
- let storageFound = false;
-
- // On regarde si c'est du stokage fichier
- if (jsonStorage.file) {
- // Vérification que le fichier existe et peut être lu.
- if (fs.existsSync(jsonStorage.file)) {
- try {
- fs.accessSync(jsonStorage.file, fs.constants.R_OK);
- } catch (err) {
- LOGGER.error("Le fichier " + jsonStorage.file + " ne peut etre lu.");
- return false;
- }
- storageFound = true;
- } else {
- LOGGER.error("Le fichier " + jsonStorage.file + " n'existe pas.");
- return false;
- }
- } else if (jsonStorage.tar || jsonStorage.config) {
- // Vérification que le fichier existe et peut être lu.
- if (fs.existsSync(jsonStorage.tar)) {
- try {
- fs.accessSync(jsonStorage.tar, fs.constants.R_OK);
- } catch (err) {
- LOGGER.error("Le fichier " + jsonStorage.tar + " ne peut etre lu.");
- return false;
- }
- storageFound = true;
- } else {
- LOGGER.error("Le fichier " + jsonStorage.tar + " n'existe pas.");
- return false;
- }
- } else if (jsonStorage.config) {
- // Vérification que le fichier existe et peut être lu.
- if (fs.existsSync(jsonStorage.config)) {
- try {
- fs.accessSync(jsonStorage.config, fs.constants.R_OK);
- } catch (err) {
- LOGGER.error("Le fichier " + jsonStorage.config + " ne peut etre lu.");
- return false;
- }
- storageFound = true;
- } else {
- LOGGER.error("Le fichier " + jsonStorage.config + " n'existe pas.");
- return false;
- }
- } else if (jsonStorage.costColumn) {
- // TODO: Pas trop possible de vérifier sans requête
- storageFound = true;
- } else if (jsonStorage.rcostColumn) {
- // TODO: Pas trop possible de vérifier sans requête
- storageFound = true;
- } else if (jsonStorage.url) {
- // TODO: Pas trop possible de vérifier sans requête
- storageFound = true;
- } else {
- // on va tester d'autres types
- }
-
- return storageFound;
- }
-
-}
diff --git a/test/integration/readme.md b/test/integration/readme.md
index b60d3b8..3d54512 100644
--- a/test/integration/readme.md
+++ b/test/integration/readme.md
@@ -20,8 +20,6 @@ C'est l'approche bottom-up qui a été choisie pour ces tests. On va tester les
- routeRequest (request)
- isochroneRequest (request)
- serverManager (server, ExpressJS, log4js)
- - osmTopology (topology)
- - dbTopology (topology, base)
- Deuxième niveau:
- resourceOperation (resourceParameter)
@@ -32,8 +30,7 @@ C'est l'approche bottom-up qui a été choisie pour ces tests. On va tester les
- constraintParameter (resourceParameter, constraint, looseConstraint)
- isochroneResponse (response, point, geometry)
- step (line, duration, distance)
- - topologyManager (osmTopology, dbTopology, storageManager, baseManager, projectionManager, log4js)
- - source (osmTopology, bdTopology, )
+ - source (baseManager, projectionManager)
- Troisième niveau:
- parameterManager (parameter, boolParameter, enumParameter, floatParameter, pointParameter, constraintParameter, log4js)
@@ -50,17 +47,17 @@ Cinquième niveau:
- routeResponse (response, point, route)
Sixième niveau:
- - osrmSource (source, osrm, osmTopology, routeResponse, route, portion, line, point, step, distance, duration, errorManager, log4js)
- - pgrSource (source, dbTopology, routeResponse, isochroneResponse, route, portion, line, point, polygon, step, distance, duration, errorManager, gisManager, copyManager, simplify, turf, looseConstraint, log4js)
+ - osrmSource (source, osrm, routeResponse, route, portion, line, point, step, distance, duration, errorManager, log4js)
+ - pgrSource (source, routeResponse, isochroneResponse, route, portion, line, point, polygon, step, distance, duration, errorManager, gisManager, copyManager, simplify, turf, looseConstraint, log4js)
Septième niveau:
- - sourceManager (osrmSource, pgrSource, errorManager, storageManager, operationManager, osmTopology, dbTopology, log4js)
+ - sourceManager (osrmSource, pgrSource, errorManager, storageManager, operationManager, log4js)
Huitième niveau:
- resourceManager (osrmResource, pgrResource, sourceManager, operationManager, log4js)
Neuvième niveau:
- - service (apisManager, resourceManager, sourceManager, operationManager, baseManager, topologyManager, projectionManager, serverManager, errorManager, ExpressJS, log4js)
+ - service (apisManager, resourceManager, sourceManager, operationManager, baseManager, projectionManager, serverManager, errorManager, ExpressJS, log4js)
Autres:
- road2.js
From 7aad581e68379a55758729ab348dd8dfe2cbceb4 Mon Sep 17 00:00:00 2001
From: Loic
Date: Fri, 4 Nov 2022 13:16:10 +0100
Subject: [PATCH 13/93] WIP: modification des ressources pour pointer sur les
bonnes sources
---
.../simple/1.0.0/controller/controller.js | 27 ++-
src/js/resources/osrmResource.js | 98 +++++++---
src/js/resources/pgrResource.js | 113 +++++++-----
src/js/resources/resource.js | 32 ++++
src/js/resources/resourceManager.js | 18 +-
src/js/resources/smartpgrResource.js | 171 ++++++++++++------
src/js/resources/valhallaResource.js | 112 ++++++++----
src/js/service/service.js | 28 ---
src/js/sources/sourceManager.js | 20 ++
9 files changed, 420 insertions(+), 199 deletions(-)
diff --git a/src/js/apis/simple/1.0.0/controller/controller.js b/src/js/apis/simple/1.0.0/controller/controller.js
index d5b298f..98d99b1 100644
--- a/src/js/apis/simple/1.0.0/controller/controller.js
+++ b/src/js/apis/simple/1.0.0/controller/controller.js
@@ -185,13 +185,6 @@ module.exports = {
}
-
- // Vérification de la validité du profile et de sa compatibilité avec l'optimisation
- if (!resource.linkedSource[profile+optimization]) {
- throw errorManager.createError(" Parameters 'profile' and 'optimization' are not compatible ", 400);
- } else {
- LOGGER.debug("profile et optimization compatibles");
- }
// ---
@@ -200,6 +193,12 @@ module.exports = {
LOGGER.debug(routeRequest);
+ // Vérification de la validité du profile et de sa compatibilité avec l'optimisation
+ if (!resource.checkSourceAvailibilityFromRequest(routeRequest)) {
+ throw errorManager.createError(" Parameters 'profile' and 'optimization' are not compatible ", 400);
+ } else {
+ LOGGER.debug("profile et optimization compatibles");
+ }
// On va vérifier la présence des paramètres non obligatoires pour l'API et l'objet RouteRequest
@@ -850,13 +849,6 @@ module.exports = {
}
- /* Vérification de la validité du profile et de sa compatibilité avec le costType. */
- if (!resource.linkedSource[profile+costType]) {
- throw errorManager.createError("Parameters 'profile' and 'costType' are not compatible.", 400);
- } else {
- LOGGER.debug("Parameters 'profile' and 'costType' are compatible");
- }
-
/* Paramètre 'direction'. */
if (parameters.direction) {
@@ -914,6 +906,13 @@ module.exports = {
distanceUnit
);
+ /* Vérification de la validité du profile et de sa compatibilité avec le costType. */
+ if (!resource.checkSourceAvailibilityFromRequest(isochroneRequest)) {
+ throw errorManager.createError("Parameters 'profile' and 'costType' are not compatible.", 400);
+ } else {
+ LOGGER.debug("Parameters 'profile' and 'costType' are compatible");
+ }
+
// Contraintes
// ---
if (parameters.constraints) {
diff --git a/src/js/resources/osrmResource.js b/src/js/resources/osrmResource.js
index d202ea5..2f4183a 100644
--- a/src/js/resources/osrmResource.js
+++ b/src/js/resources/osrmResource.js
@@ -33,19 +33,9 @@ module.exports = class osrmResource extends Resource {
// Correspondance entre profile/optimization et sourceId
this._linkedSource = {};
- // Instanciation de la correspondance entre profile/optimization et sourceId
- // et instanciation du profile et de l'optimisation par défaut
- for (let i=0; i < this._configuration.sources.length; i++) {
-
- let linkedId = this._configuration.sources[i].cost.profile + this._configuration.sources[i].cost.optimization;
- this._linkedSource[linkedId] = this._configuration.sources[i].id;
-
- }
-
- // id de la source utilisée pour l'opération nearest
- // on prend la première de la configuration
- // TODO : à voir si on rend cela plus configurable
- this._nearestSource = this._configuration.sources[0].id;
+ // Correspondance pour l'opération nearest
+ // Il s'agit de l'id de la source utilisée pour l'opération nearest
+ this._nearestSource = "";
// Attribut des voies
// Par défaut, OSRM ne renvoit que le nom des voies empruntées.
@@ -68,23 +58,60 @@ module.exports = class osrmResource extends Resource {
/**
*
* @function
- * @name get linkedSource
- * @description Récupérer la correspondance entre profile/optimization et sourceId de la ressource
+ * @name get waysAttributes
+ * @description Récupérer la liste des attributs disponibles pour les voies empruntées.
*
*/
- get linkedSource () {
- return this._linkedSource;
+ get waysAttributes () {
+ return this._waysAttributes;
}
/**
*
* @function
- * @name get waysAttributes
- * @description Récupérer la liste des attributs disponibles pour les voies empruntées.
+ * @name initResource
+ * @description Créer les liens entre divers éléments d'une ressource et les sources associées
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * @param {SourceManager} sourceManager - Manager des sources du service
+ * @return {boolean}
*
*/
- get waysAttributes () {
- return this._waysAttributes;
+ initResource (sourceManager) {
+
+ // Instanciation de la correspondance entre profile/optimization et sourceId
+ for (let i=0; i < this._configuration.sources.length; i++) {
+
+ if (!sourceManager.isLoadedSourceAvailable(this._configuration.sources[i])) {
+ LOGGER.error("La source n'a pas été chargée");
+ return false;
+ } else {
+
+ LOGGER.debug("La source est bien disponible");
+
+ let source = sourceManager.getSourceById(this._configuration.sources[i]);
+
+ // TODO : faire cette vérification aussi pendant le check de la ressource
+ if (source.type !== "osrm") {
+ LOGGER.error("La source n'est pas de type 'osrm'");
+ return false;
+ }
+
+ let linkedId = source.configuration.cost.profile + source.configuration.cost.optimization;
+ this._linkedSource[linkedId] = source.configuration.id;
+
+ if (i === 0) {
+ // Gestion de nearest
+ // on prend la première de la configuration
+ // TODO : à voir si on rend cela plus configurable
+ this._nearestSource = source.configuration.id;
+ }
+
+ }
+
+ }
+
+ return true;
+
}
/**
@@ -124,9 +151,7 @@ module.exports = class osrmResource extends Resource {
*/
getSourceIdFromRequest (request) {
- const currentOperation = request.operation;
-
- if (currentOperation === "nearest") {
+ if (request.operation === "nearest") {
return this._nearestSource;
} else {
if (this._linkedSource[request.profile+request.optimization]) {
@@ -136,7 +161,32 @@ module.exports = class osrmResource extends Resource {
}
}
+ }
+
+ /**
+ *
+ * @function
+ * @name checkSourceAvailibilityFromRequest
+ * @description Savoir s'il y a une source disponible pour répondre à la requête. Par exemple, pour un itinéraire, il s'agira de savoir si un couple profile/optimization est disponible.
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * @param {Request} request - Objet Request ou ou dérivant de la classe Request
+ * @return {boolean}
+ *
+ */
+ checkSourceAvailibilityFromRequest (request) {
+ if (request.operation === "nearest") {
+ // On utilise toujours la première source. Il y en a forcément une.
+ return true;
+ } else if (request.operation === "route") {
+ if (this._linkedSource[request.profile+request.optimization]) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
}
diff --git a/src/js/resources/pgrResource.js b/src/js/resources/pgrResource.js
index 1a26e1b..b33a892 100644
--- a/src/js/resources/pgrResource.js
+++ b/src/js/resources/pgrResource.js
@@ -36,32 +36,6 @@ module.exports = class pgrResource extends Resource {
// Correspondance entre profile/optimization et sourceId
this._linkedSource = {};
- // Instanciation de la correspondance entre profile/optimization et sourceId
- // et instanciation du profile et de l'optimisation par défaut
- for (let i=0; i < this._configuration.sources.length; i++) {
-
- /* TODO: Il serait mieux, dans le futur, d'avoir un nouveau type de ressource, dédiée à l'isochrone. */
- const currentSourceOptimization = this._configuration.sources[i].cost.optimization;
-
- let linkedId = '';
- if (operations["isochrone"]) {
- if (currentSourceOptimization === "fastest") {
- linkedId = this._configuration.sources[i].cost.profile + "time";
- } else if (currentSourceOptimization === "shortest") {
- linkedId = this._configuration.sources[i].cost.profile + "distance";
- } else {
- /* TODO: À repenser. */
- }
-
- this._linkedSource[linkedId] = this._configuration.sources[i].id;
- }
- if (operations["route"]) {
- linkedId = this._configuration.sources[i].cost.profile + this._configuration.sources[i].cost.optimization;
-
- this._linkedSource[linkedId] = this._configuration.sources[i].id;
- }
- }
-
}
/**
@@ -78,23 +52,44 @@ module.exports = class pgrResource extends Resource {
/**
*
* @function
- * @name get linkedSource
- * @description Récupérer la correspondance entre profile/optimization et sourceId de la ressource
+ * @name initResource
+ * @description Créer les liens entre divers éléments d'une ressource et les sources associées
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * @param {SourceManager} sourceManager - Manager des sources du service
+ * @return {boolean}
*
*/
- get linkedSource () {
- return this._linkedSource;
- }
+ initResource (sourceManager) {
- /**
- *
- * @function
- * @name set linkedSource
- * @description Attribuer la correspondance entre profile/optimization et sourceId de la ressource
- *
- */
- set linkedSource (ls) {
- this._linkedSource = ls;
+ // Instanciation de la correspondance entre profile/optimization et sourceId
+ for (let i=0; i < this._configuration.sources.length; i++) {
+
+ if (!sourceManager.isLoadedSourceAvailable(this._configuration.sources[i])) {
+ LOGGER.error("La source n'a pas été chargée");
+ return false;
+ } else {
+
+ LOGGER.debug("La source est bien disponible");
+
+ let source = sourceManager.getSourceById(this._configuration.sources[i]);
+
+ // TODO : faire cette vérification aussi pendant le check de la ressource
+ if (source.type !== "pgr") {
+ LOGGER.error("La source n'est pas de type 'pgr'");
+ return false;
+ }
+
+ let linkedIdRoute = source.configuration.cost.profile + source.configuration.cost.optimization;
+ let linkedIdIso = source.configuration.cost.profile + source.configuration.cost.costType;
+ this._linkedSource[linkedIdRoute] = source.configuration.id;
+ this._linkedSource[linkedIdIso] = source.configuration.id;
+
+ }
+
+ }
+
+ return true;
+
}
/**
@@ -109,14 +104,14 @@ module.exports = class pgrResource extends Resource {
*/
getSourceIdFromRequest (request) {
- const currentOperation = request.operation;
let source = "";
- /* TODO: Pour le moment, c'est un contrôle en dur sur le type de l'opération. Il serait mieux de revoir cette façon de voir (avoir peut-être un catalogue de correspondance ? Maybe..). */
- if (currentOperation === "isochrone") {
+ if (request.operation === "isochrone") {
source = request.profile + request.costType;
- } else {
+ } else if (request.operation === "route") {
source = request.profile + request.optimization;
+ } else {
+ return null;
}
if (this._linkedSource[source]) {
@@ -127,4 +122,34 @@ module.exports = class pgrResource extends Resource {
}
+ /**
+ *
+ * @function
+ * @name checkSourceAvailibilityFromRequest
+ * @description Savoir s'il y a une source disponible pour répondre à la requête. Par exemple, pour un itinéraire, il s'agira de savoir si un couple profile/optimization est disponible.
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * @param {Request} request - Objet Request ou ou dérivant de la classe Request
+ * @return {boolean}
+ *
+ */
+ checkSourceAvailibilityFromRequest (request) {
+
+ let source = "";
+
+ if (request.operation === "isochrone") {
+ source = request.profile + request.costType;
+ } else if (request.operation === "route") {
+ source = request.profile + request.optimization;
+ } else {
+ return false;
+ }
+
+ if (this._linkedSource[source]) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
}
diff --git a/src/js/resources/resource.js b/src/js/resources/resource.js
index 354ae65..73fd087 100644
--- a/src/js/resources/resource.js
+++ b/src/js/resources/resource.js
@@ -98,6 +98,38 @@ module.exports = class Resource {
return sourceId;
}
+ /**
+ *
+ * @function
+ * @name checkSourceAvailibilityFromRequest
+ * @description Savoir s'il y a une source disponible pour répondre à la requête. Par exemple, pour un itinéraire, il s'agira de savoir si un couple profile/optimization est disponible.
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * Dans la classe actuelle, ce n'est que pour indiquer qu'il faut implémenter la fonction
+ * dans chacune des classes filles.
+ * @param {Request} request - Objet Request ou ou dérivant de la classe Request
+ * @return {boolean}
+ *
+ */
+ checkSourceAvailibilityFromRequest (request) {
+ return false;
+ }
+
+ /**
+ *
+ * @function
+ * @name initResource
+ * @description Créer les liens entre divers éléments d'une ressource et les sources associées
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * Dans la classe actuelle, ce n'est que pour indiquer qu'il faut implémenter la fonction
+ * dans chacune des classes filles.
+ * @param {SourceManager} sourceManager - Manager des sources du service
+ * @return {boolean}
+ *
+ */
+ initResource (sourceManager) {
+ return false;
+ }
+
/**
*
* @function
diff --git a/src/js/resources/resourceManager.js b/src/js/resources/resourceManager.js
index 9a80015..0c24926 100644
--- a/src/js/resources/resourceManager.js
+++ b/src/js/resources/resourceManager.js
@@ -216,7 +216,17 @@ module.exports = class resourceManager {
return false;
} else {
- LOGGER.info("Verification des sources...")
+ LOGGER.info("Verification des sources...");
+
+ if (Array.isArray(resourceJsonObject.resource.sources)) {
+ LOGGER.error("Mauvaise configuration: 'resource.sources' n'est pas un tableau");
+ return false;
+ }
+
+ if (resourceJsonObject.resource.sources.length === 0) {
+ LOGGER.error("Mauvaise configuration: 'resource.sources' est un tableau vide");
+ return false;
+ }
for (let i = 0; i < resourceJsonObject.resource.sources.length; i++ ) {
@@ -392,6 +402,12 @@ module.exports = class resourceManager {
return false;
}
+ // Initialisation de la correspondance entre ressource et sources
+ if (!resource.initResource(this._sourceManager)) {
+ LOGGER.error("Impossible d'instancier les liens avec les sources");
+ return false;
+ }
+
// on sauvegarde l'id de la ressource pour savoir qu'elle a déjà été créée et la ressource elle-même
this._loadedResourceId.push(resourceJsonObject.resource.id);
this._resource[resourceJsonObject.resource.id] = resource;
diff --git a/src/js/resources/smartpgrResource.js b/src/js/resources/smartpgrResource.js
index c08a9e6..77252d9 100644
--- a/src/js/resources/smartpgrResource.js
+++ b/src/js/resources/smartpgrResource.js
@@ -36,45 +36,13 @@ module.exports = class smartpgrResource extends Resource {
this._configuration = resourceJsonObject.resource;
// Seuils de switch entre les sources smartrouting et pgr
- this._distThreshold = this._configuration.threshold; // en metres
- this._timeThresholdCar = (this._distThreshold / 130000) * 3600; // en secondes
- this._timeThresholdPedestrian = (this._distThreshold / 4000) * 3600; // en secondes
+ this._distThreshold; // en metres
+ this._timeThresholdCar; // en secondes
+ this._timeThresholdPedestrian; // en secondes
// Correspondance entre profile/optimization et sourceId
this._linkedSource = {};
- // Instanciation de la correspondance entre profile/optimization et sourceId
- // et instanciation du profile et de l'optimisation par défaut
- for (let i=0; i < this._configuration.sources.length; i++) {
-
- // on recupere l'id de l'unique source smartrouting
- if (this._configuration.sources[i].type === 'smartrouting') {
- this._linkedSource['smartrouting'] = this._configuration.sources[i].id;
- continue;
- }
-
- /* TODO: Il serait mieux, dans le futur, d'avoir un nouveau type de ressource, dédiée à l'isochrone. */
- const currentSourceOptimization = this._configuration.sources[i].cost.optimization;
-
- let linkedId = '';
- if (operations["isochrone"]) {
- if (currentSourceOptimization === "fastest") {
- linkedId = this._configuration.sources[i].cost.profile + "time";
- } else if (currentSourceOptimization === "shortest") {
- linkedId = this._configuration.sources[i].cost.profile + "distance";
- } else {
- /* TODO: À repenser. */
- }
-
- this._linkedSource[linkedId] = this._configuration.sources[i].id;
- }
- if (operations["route"]) {
- linkedId = this._configuration.sources[i].cost.profile + this._configuration.sources[i].cost.optimization;
-
- this._linkedSource[linkedId] = this._configuration.sources[i].id;
- }
- }
-
}
/**
@@ -91,23 +59,62 @@ module.exports = class smartpgrResource extends Resource {
/**
*
* @function
- * @name get linkedSource
- * @description Récupérer la correspondance entre profile/optimization et sourceId de la ressource
+ * @name initResource
+ * @description Créer les liens entre divers éléments d'une ressource et les sources associées
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * @param {SourceManager} sourceManager - Manager des sources du service
+ * @return {boolean}
*
*/
- get linkedSource () {
- return this._linkedSource;
- }
+ initResource (sourceManager) {
- /**
- *
- * @function
- * @name set linkedSource
- * @description Attribuer la correspondance entre profile/optimization et sourceId de la ressource
- *
- */
- set linkedSource (ls) {
- this._linkedSource = ls;
+ // Seuils de switch entre les sources smartrouting et pgr
+ this._distThreshold = this._configuration.threshold; // en metres
+ this._timeThresholdCar = (this._distThreshold / 130000) * 3600; // en secondes
+ this._timeThresholdPedestrian = (this._distThreshold / 4000) * 3600; // en secondes
+
+ // Instanciation de la correspondance entre profile/optimization et sourceId
+ for (let i=0; i < this._configuration.sources.length; i++) {
+
+ if (!sourceManager.isLoadedSourceAvailable(this._configuration.sources[i])) {
+
+ LOGGER.error("La source n'a pas été chargée");
+ return false;
+
+ } else {
+
+ LOGGER.debug("La source est bien disponible");
+
+ let source = sourceManager.getSourceById(this._configuration.sources[i]);
+
+
+
+ // on recupere l'id de l'unique source smartrouting
+ if (source.type === 'smartrouting') {
+
+ this._linkedSource['smartrouting'] = source.configuration.id;
+
+ } else if (source.type === 'pgr') {
+
+ let linkedIdRoute = source.configuration.cost.profile + source.configuration.cost.optimization;
+ let linkedIdIso = source.configuration.cost.profile + source.configuration.cost.costType;
+ this._linkedSource[linkedIdRoute] = source.configuration.id;
+ this._linkedSource[linkedIdIso] = source.configuration.id;
+
+ } else {
+
+ // TODO : faire cette vérification aussi pendant le check de la ressource
+ LOGGER.error("La source n'est pas de type 'pgr' ou 'smartrouting'");
+ return false;
+
+ }
+
+ }
+
+ }
+
+ return true;
+
}
/**
@@ -122,13 +129,12 @@ module.exports = class smartpgrResource extends Resource {
*/
getSourceIdFromRequest (request) {
- const currentOperation = request.operation;
let source = "";
- /*TODO: Pour le moment, c'est un contrôle en dur sur le type de l'opération. Il serait mieux de revoir cette façon de voir (avoir peut-être un catalogue de correspondance ? Maybe..). */
- if (currentOperation === "isochrone") {
+ if (request.operation === "isochrone") {
let useSmartrouting = false;
+
if (request.costType === 'distance') {
// Note costValue est déjà en metres
useSmartrouting = request.costValue > this._distThreshold;
@@ -146,8 +152,14 @@ module.exports = class smartpgrResource extends Resource {
} else {
source = request.profile + request.costType;
}
- } else {
+
+ } else if (request.operation === "route") {
+
+ // On décide de faire uniquement du PGR sur cette ressource dans le cas de l'iti
source = request.profile + request.optimization;
+
+ } else {
+ return null;
}
if (this._linkedSource[source]) {
@@ -158,4 +170,57 @@ module.exports = class smartpgrResource extends Resource {
}
+ /**
+ *
+ * @function
+ * @name checkSourceAvailibilityFromRequest
+ * @description Savoir s'il y a une source disponible pour répondre à la requête. Par exemple, pour un itinéraire, il s'agira de savoir si un couple profile/optimization est disponible.
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * @param {Request} request - Objet Request ou ou dérivant de la classe Request
+ * @return {boolean}
+ *
+ */
+ checkSourceAvailibilityFromRequest (request) {
+
+ let source = "";
+
+ if (request.operation === "isochrone") {
+
+ let useSmartrouting = false;
+
+ if (request.costType === 'distance') {
+ // Note costValue est déjà en metres
+ useSmartrouting = request.costValue > this._distThreshold;
+ } else if (request.costType === 'time') {
+ // Note costValue est déjà en secondes
+ if (request.profile === 'car') {
+ useSmartrouting = request.costValue > this._timeThresholdCar
+ } else if (request.profile === 'pedestrian') {
+ useSmartrouting = request.costValue > this._timeThresholdPedestrian
+ }
+ }
+
+ if (useSmartrouting) {
+ source = 'smartrouting';
+ } else {
+ source = request.profile + request.costType;
+ }
+
+ } else if (request.operation === "route") {
+
+ // On décide de faire uniquement du PGR sur cette ressource dans le cas de l'iti
+ source = request.profile + request.optimization;
+
+ } else {
+ return false;
+ }
+
+ if (this._linkedSource[source]) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
}
diff --git a/src/js/resources/valhallaResource.js b/src/js/resources/valhallaResource.js
index f470787..4ec0229 100644
--- a/src/js/resources/valhallaResource.js
+++ b/src/js/resources/valhallaResource.js
@@ -33,29 +33,6 @@ module.exports = class valhallaResource extends Resource {
// Correspondance entre profile/optimization et sourceId
this._linkedSource = {};
- // Instanciation de la correspondance entre profile/optimization et sourceId
- // et instanciation du profile et de l'optimisation par défaut
- for (let i=0; i < this._configuration.sources.length; i++) {
-
- /* TODO: Il serait mieux, dans le futur, d'avoir un nouveau type de ressource, dédiée à l'isochrone. */
- const currentSourceOptimization = this._configuration.sources[i].cost.optimization;
- let linkedId = '';
- if (operations["isochrone"]) {
- if (currentSourceOptimization === "fastest") {
- linkedId = this._configuration.sources[i].cost.profile + "time";
- } else if (currentSourceOptimization === "shortest") {
- linkedId = this._configuration.sources[i].cost.profile + "distance";
- } else {
- /* TODO: À repenser. */
- }
- this._linkedSource[linkedId] = this._configuration.sources[i].id;
- }
- if (operations["route"]) {
- linkedId = this._configuration.sources[i].cost.profile + this._configuration.sources[i].cost.optimization;
- this._linkedSource[linkedId] = this._configuration.sources[i].id;
- }
- }
-
// Attribut des voies
// Par défaut, OSRM ne renvoit que le nom des voies empruntées.
this._waysAttributes = new Array();
@@ -77,23 +54,55 @@ module.exports = class valhallaResource extends Resource {
/**
*
* @function
- * @name get linkedSource
- * @description Récupérer la correspondance entre profile/optimization et sourceId de la ressource
+ * @name get waysAttributes
+ * @description Récupérer la liste des attributs disponibles pour les voies empruntées.
*
*/
- get linkedSource () {
- return this._linkedSource;
+ get waysAttributes () {
+ return this._waysAttributes;
}
/**
*
* @function
- * @name get waysAttributes
- * @description Récupérer la liste des attributs disponibles pour les voies empruntées.
+ * @name initResource
+ * @description Créer les liens entre divers éléments d'une ressource et les sources associées
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * @param {SourceManager} sourceManager - Manager des sources du service
+ * @return {boolean}
*
*/
- get waysAttributes () {
- return this._waysAttributes;
+ initResource (sourceManager) {
+
+ // Instanciation de la correspondance entre profile/optimization et sourceId
+ for (let i=0; i < this._configuration.sources.length; i++) {
+
+ if (!sourceManager.isLoadedSourceAvailable(this._configuration.sources[i])) {
+ LOGGER.error("La source n'a pas été chargée");
+ return false;
+ } else {
+
+ LOGGER.debug("La source est bien disponible");
+
+ let source = sourceManager.getSourceById(this._configuration.sources[i]);
+
+ // TODO : faire cette vérification aussi pendant le check de la ressource
+ if (source.type !== "valhalla") {
+ LOGGER.error("La source n'est pas de type 'valhalla'");
+ return false;
+ }
+
+ let linkedIdRoute = source.configuration.cost.profile + source.configuration.cost.optimization;
+ let linkedIdIso = source.configuration.cost.profile + source.configuration.cost.costType;
+ this._linkedSource[linkedIdRoute] = source.configuration.id;
+ this._linkedSource[linkedIdIso] = source.configuration.id;
+
+ }
+
+ }
+
+ return true;
+
}
/**
@@ -133,19 +142,52 @@ module.exports = class valhallaResource extends Resource {
*/
getSourceIdFromRequest (request) {
- const currentOperation = request.operation;
let source = "";
- /* TODO: Pour le moment, c'est un contrôle en dur sur le type de l'opération. Il serait mieux de revoir cette façon de voir (avoir peut-être un catalogue de correspondance ? Maybe..). */
- if (currentOperation === "isochrone") {
+
+ if (request.operation === "isochrone") {
source = request.profile + request.costType;
- } else {
+ } else if (request.operation === "route") {
source = request.profile + request.optimization;
+ } else {
+ return null;
}
+
if (this._linkedSource[source]) {
return this._linkedSource[source];
} else {
return null;
}
+
+ }
+
+ /**
+ *
+ * @function
+ * @name checkSourceAvailibilityFromRequest
+ * @description Savoir s'il y a une source disponible pour répondre à la requête. Par exemple, pour un itinéraire, il s'agira de savoir si un couple profile/optimization est disponible.
+ * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête.
+ * @param {Request} request - Objet Request ou ou dérivant de la classe Request
+ * @return {boolean}
+ *
+ */
+ checkSourceAvailibilityFromRequest (request) {
+
+ let source = "";
+
+ if (request.operation === "isochrone") {
+ source = request.profile + request.costType;
+ } else if (request.operation === "route") {
+ source = request.profile + request.optimization;
+ } else {
+ return false;
+ }
+
+ if (this._linkedSource[source]) {
+ return true;
+ } else {
+ return false;
+ }
+
}
}
diff --git a/src/js/service/service.js b/src/js/service/service.js
index 85f4e81..096314f 100644
--- a/src/js/service/service.js
+++ b/src/js/service/service.js
@@ -175,34 +175,6 @@ module.exports = class Service {
}
}
- /**
- *
- * @function
- * @name getSourceById
- * @description Récupérer une source par son id
- * @param {string} id - Id de la source
- *
- */
- getSourceById(id) {
- return this._sourceManager.source[id];
- }
-
- /**
- *
- * @function
- * @name verifySourceExistenceById
- * @description Savoir si une source existe à partir de son id
- * @param {string} id - Id de la source
- *
- */
- verifySourceExistenceById(id) {
- if (this._sourceManager.source[id]) {
- return true;
- } else {
- return false;
- }
- }
-
/**
*
* @function
diff --git a/src/js/sources/sourceManager.js b/src/js/sources/sourceManager.js
index b9f32f8..9939818 100644
--- a/src/js/sources/sourceManager.js
+++ b/src/js/sources/sourceManager.js
@@ -99,6 +99,26 @@ module.exports = class sourceManager {
}
+ /**
+ *
+ * @function
+ * @name getSourceById
+ * @description Fonction utilisée pour récupérer une source
+ * @param {string} id - Id de la source
+ * @return {source} source - Instance fille de la classe Source
+ *
+ */
+
+ getSourceById(id) {
+
+ if (this.isLoadedSourceAvailable(id)) {
+ return this._source[id];
+ } else {
+ return null;
+ }
+
+ }
+
/**
*
* @function
From 933778c193c6fefe41eede65fe1468125e7c4319 Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 14 Nov 2022 13:51:49 +0100
Subject: [PATCH 14/93] =?UTF-8?q?fin=20des=20devs=20pour=20s=C3=A9parer=20?=
=?UTF-8?q?les=20sources?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docker/dev/docker-compose.yml | 2 +-
src/js/geography/projectionManager.js | 27 +++++++++------
src/js/operations/operationManager.js | 5 +++
src/js/resources/osrmResource.js | 4 +++
src/js/resources/pgrResource.js | 22 +++++++-----
src/js/resources/resourceManager.js | 49 ++++++++++++++++-----------
src/js/resources/smartpgrResource.js | 15 +++++---
src/js/resources/valhallaResource.js | 24 +++++++++----
src/js/sources/pgrSource.js | 6 +++-
src/js/sources/smartroutingSource.js | 2 +-
src/js/sources/source.js | 22 ++++++++++++
src/js/sources/sourceManager.js | 23 +++++--------
12 files changed, 133 insertions(+), 68 deletions(-)
diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml
index d4756d8..b0edc31 100644
--- a/docker/dev/docker-compose.yml
+++ b/docker/dev/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- pgrouting
environment:
- NODE_ENV=debug
- command : "sleep 60000"
+ command : "npm run debug -- --ROAD2_CONF_FILE=../config/road2.json"
ports:
- 8080:8080
- 9229:9229
diff --git a/src/js/geography/projectionManager.js b/src/js/geography/projectionManager.js
index a58c178..fdd4a88 100644
--- a/src/js/geography/projectionManager.js
+++ b/src/js/geography/projectionManager.js
@@ -112,7 +112,8 @@ module.exports = class ProjectionManager {
*/
checkBboxConfiguration (bbox, projectionId) {
- LOGGER.info("Vérification d'une bbox...");
+ LOGGER.info("Vérification d'une bbox... ");
+ LOGGER.debug("bbox:'" + bbox+"'");
if (!bbox) {
LOGGER.error("Aucune bbox fournie");
@@ -124,27 +125,31 @@ module.exports = class ProjectionManager {
return false;
}
- let regex = new RegExp("^(-?\d+\.?\d*),(-?\d+\.?\d*),(-?\d+\.?\d*),(-?\d+\.?\d*)$");
- if (!regex.test(bbox)) {
- LOGGER.error("La bbox n'est pas correctement formattée");
- return false;
- }
-
- let bboxArray = new Array(4);
+ let bboxArray = new Array();
try {
- bboxArray = regex.exec(bbox);
+ bboxArray = bbox.match(/^(-?\d+\.?\d*),(-?\d+\.?\d*),(-?\d+\.?\d*),(-?\d+\.?\d*)$/);
} catch(error) {
LOGGER.error("Impossible d'analyser la bbox");
LOGGER.error(error);
return false;
}
- if (bboxArray[0] >= bboxArray[2]) {
- LOGGER.error("Mauvaise configuration : Xmin est supérieur ou égal à Xmax");
+ if (bboxArray === null) {
+ LOGGER.error("La bbox n'est pas correctement formattée : aucune correspondance n'a été trouvée");
+ return false;
+ }
+
+ if (bboxArray.length !== 5) {
+ LOGGER.error("La bbox n'est pas correctement formattée : l'ensemble des correspondances n'a pas été correctement identifié");
return false;
}
if (bboxArray[1] >= bboxArray[3]) {
+ LOGGER.error("Mauvaise configuration : Xmin est supérieur ou égal à Xmax");
+ return false;
+ }
+
+ if (bboxArray[2] >= bboxArray[4]) {
LOGGER.error("Mauvaise configuration : Ymin est supérieur ou égal à Ymax");
return false;
}
diff --git a/src/js/operations/operationManager.js b/src/js/operations/operationManager.js
index 919f1aa..ca6528c 100644
--- a/src/js/operations/operationManager.js
+++ b/src/js/operations/operationManager.js
@@ -401,6 +401,11 @@ module.exports = class operationManager {
LOGGER.info("Verification de l'operation de la ressource...");
+ if (!Array.isArray(resourceOperationJsonObject)) {
+ LOGGER.error("Mauvais configuration : la configuration d'opérations fournie n'est pas un tableau");
+ return false;
+ }
+
// on regarde d'abord la taille du tableau donné en entrée
if (resourceOperationJsonObject.length === 0) {
LOGGER.error("Il n'y aucune operation decrite");
diff --git a/src/js/resources/osrmResource.js b/src/js/resources/osrmResource.js
index 2f4183a..d4fa9e0 100644
--- a/src/js/resources/osrmResource.js
+++ b/src/js/resources/osrmResource.js
@@ -1,6 +1,10 @@
'use strict';
const Resource = require('./resource');
+const log4js = require('log4js');
+
+// Création du LOGGER
+var LOGGER = log4js.getLogger("OSRMRESOURCE");
/**
*
diff --git a/src/js/resources/pgrResource.js b/src/js/resources/pgrResource.js
index b33a892..b4dbedd 100644
--- a/src/js/resources/pgrResource.js
+++ b/src/js/resources/pgrResource.js
@@ -1,9 +1,10 @@
'use strict';
const Resource = require('./resource');
+const log4js = require('log4js');
// Création du LOGGER
-const log4js = require('log4js');
+var LOGGER = log4js.getLogger("PGRRESOURCE");
/**
*
@@ -62,16 +63,16 @@ module.exports = class pgrResource extends Resource {
initResource (sourceManager) {
// Instanciation de la correspondance entre profile/optimization et sourceId
- for (let i=0; i < this._configuration.sources.length; i++) {
+ for (let s=0; s < this._configuration.sources.length; s++) {
- if (!sourceManager.isLoadedSourceAvailable(this._configuration.sources[i])) {
+ if (!sourceManager.isLoadedSourceAvailable(this._configuration.sources[s])) {
LOGGER.error("La source n'a pas été chargée");
return false;
} else {
LOGGER.debug("La source est bien disponible");
- let source = sourceManager.getSourceById(this._configuration.sources[i]);
+ let source = sourceManager.getSourceById(this._configuration.sources[s]);
// TODO : faire cette vérification aussi pendant le check de la ressource
if (source.type !== "pgr") {
@@ -79,14 +80,19 @@ module.exports = class pgrResource extends Resource {
return false;
}
- let linkedIdRoute = source.configuration.cost.profile + source.configuration.cost.optimization;
- let linkedIdIso = source.configuration.cost.profile + source.configuration.cost.costType;
- this._linkedSource[linkedIdRoute] = source.configuration.id;
- this._linkedSource[linkedIdIso] = source.configuration.id;
+ for (let i = 0; i < source.configuration.costs.length; i++) {
+
+ let linkedIdRoute = source.configuration.costs[i].profile + source.configuration.costs[i].optimization;
+ let linkedIdIso = source.configuration.costs[i].profile + source.configuration.costs[i].costType;
+ this._linkedSource[linkedIdRoute] = source.configuration.id;
+ this._linkedSource[linkedIdIso] = source.configuration.id;
+ }
+
}
}
+
return true;
diff --git a/src/js/resources/resourceManager.js b/src/js/resources/resourceManager.js
index 0c24926..ac13fe5 100644
--- a/src/js/resources/resourceManager.js
+++ b/src/js/resources/resourceManager.js
@@ -31,8 +31,15 @@ module.exports = class resourceManager {
// Liste des ressources chargées dans le manager
this._resource = {};
- // Liste des types de ressource gérées par le manager
- this._availableResourceTypes = ["pgr", "smartpgr","osrm","valhalla"];
+ // Correspondance entre les ressources et les opérations possibles
+ // Le contenu de ce tableau dépend du code écrit dans la ressource correspondante, de ce nous avons choisis de l'implémenter dans Road2
+ // Ce tableau peut beaucoup ressembler à son équivalent du sourceManager mais il peut aussi s'en écarter selon les futures ressources qui seront implémentées
+ this._operationsByType = {
+ "osrm": ["nearest", "route"],
+ "pgr": ["route", "isochrone"],
+ "smartpgr": ["route", "isochrone"],
+ "valhalla": ["route", "isochrone"]
+ };
// Manager de source
this._sourceManager = sourceManager;
@@ -139,8 +146,10 @@ module.exports = class resourceManager {
LOGGER.info("Verification de la configuration d'une ressource...");
if (!resourceJsonObject.resource) {
- LOGGER.error("Le fichier ne contient pas d'objet resource");
+ LOGGER.error("La configuration ne contient pas d'objet resource");
return false;
+ } else {
+ LOGGER.debug("La configuration contient bien un objet resource");
}
// ID
@@ -148,6 +157,7 @@ module.exports = class resourceManager {
LOGGER.error("La ressource ne contient pas d'id.");
return false;
} else {
+
LOGGER.info("Ressource id: " + resourceJsonObject.resource.id);
// On vérifie que l'id de la ressource n'est pas déjà pris par une autre ressource chargée
@@ -181,6 +191,9 @@ module.exports = class resourceManager {
LOGGER.error("La ressource ne contient pas de version.");
return false;
} else {
+
+ LOGGER.debug("La ressource contient une version " + resourceJsonObject.resource.resourceVersion);
+
// on vérifie que c'est bien une string
if (typeof resourceJsonObject.resource.resourceVersion !== "string") {
LOGGER.error("La version de la ressource n'est pas une chaine de carateres.");
@@ -194,8 +207,10 @@ module.exports = class resourceManager {
return false;
} else {
+ LOGGER.debug("La ressource contient un type " + resourceJsonObject.resource.type);
+
// Vérification que le type est valide
- if (this._availableResourceTypes.includes(resourceJsonObject.resource.type)) {
+ if (Object.keys(this._operationsByType).includes(resourceJsonObject.resource.type)) {
LOGGER.info("Type de la ressource disponible: " + resourceJsonObject.resource.type);
} else {
LOGGER.error("La ressource indique un type invalide: " + resourceJsonObject.resource.type);
@@ -208,7 +223,9 @@ module.exports = class resourceManager {
if (!resourceJsonObject.resource.description) {
LOGGER.error("La ressource ne contient pas de description.");
return false;
- }
+ } else {
+ LOGGER.debug("La ressource contient une description");
+ }
// Sources
if (!resourceJsonObject.resource.sources) {
@@ -218,7 +235,7 @@ module.exports = class resourceManager {
LOGGER.info("Verification des sources...");
- if (Array.isArray(resourceJsonObject.resource.sources)) {
+ if (!Array.isArray(resourceJsonObject.resource.sources)) {
LOGGER.error("Mauvaise configuration: 'resource.sources' n'est pas un tableau");
return false;
}
@@ -232,13 +249,16 @@ module.exports = class resourceManager {
let sourceId = resourceJsonObject.resource.sources[i];
if (!this._sourceManager.isCheckedSourceAvailable(sourceId)) {
- LOGGER.error("La ressource contient une source non disponible.");
+ LOGGER.error("La ressource contient une source non disponible : " + sourceId);
return false;
} else {
// TODO : on stocke l'id de la ressource pour cette source donnée
}
}
+
+ LOGGER.debug("Vérification des sources terminée");
+
}
// availableOperations
@@ -258,19 +278,10 @@ module.exports = class resourceManager {
for (let i = 0; i < resourceJsonObject.resource.availableOperations.length; i++) {
let operationId = resourceJsonObject.resource.availableOperations[i].id;
- let found = false;
-
- for (let j = 0; resourceJsonObject.resource.sources; j++) {
- let sourceType = resourceJsonObject.resource.sources[j].type;
- let operations = this._sourceManager.operationsByType[sourceType];
- if (operations.includes(operationId)) {
- found = true;
- break;
- }
- }
+ let availableOperationsOfType = this._operationsByType[resourceJsonObject.resource.type];
- if (!found) {
- LOGGER.error("L'opération " + operationId + " n'a pas de source pour y répondre");
+ if (!availableOperationsOfType.includes(operationId)) {
+ LOGGER.error("L'opération " + operationId + " n'est pas disponible pour le type de ressource " + resourceJsonObject.resource.type);
return false;
}
diff --git a/src/js/resources/smartpgrResource.js b/src/js/resources/smartpgrResource.js
index 77252d9..5f273e5 100644
--- a/src/js/resources/smartpgrResource.js
+++ b/src/js/resources/smartpgrResource.js
@@ -1,7 +1,6 @@
'use strict';
const Resource = require('./resource');
-const Duration = require('../time/duration');
const log4js = require('log4js');
// Création du LOGGER
@@ -96,10 +95,16 @@ module.exports = class smartpgrResource extends Resource {
} else if (source.type === 'pgr') {
- let linkedIdRoute = source.configuration.cost.profile + source.configuration.cost.optimization;
- let linkedIdIso = source.configuration.cost.profile + source.configuration.cost.costType;
- this._linkedSource[linkedIdRoute] = source.configuration.id;
- this._linkedSource[linkedIdIso] = source.configuration.id;
+ console.log(source);
+
+ for (let j = 0; j < source.configuration.costs.length; j++) {
+
+ let linkedIdRoute = source.configuration.costs[j].profile + source.configuration.costs[j].optimization;
+ let linkedIdIso = source.configuration.costs[j].profile + source.configuration.costs[j].costType;
+ this._linkedSource[linkedIdRoute] = source.configuration.id;
+ this._linkedSource[linkedIdIso] = source.configuration.id;
+
+ }
} else {
diff --git a/src/js/resources/valhallaResource.js b/src/js/resources/valhallaResource.js
index 4ec0229..340d91a 100644
--- a/src/js/resources/valhallaResource.js
+++ b/src/js/resources/valhallaResource.js
@@ -1,6 +1,10 @@
'use strict';
const Resource = require('./resource');
+const log4js = require('log4js');
+
+// Création du LOGGER
+var LOGGER = log4js.getLogger("VALRESOURCE");
/**
*
@@ -75,16 +79,16 @@ module.exports = class valhallaResource extends Resource {
initResource (sourceManager) {
// Instanciation de la correspondance entre profile/optimization et sourceId
- for (let i=0; i < this._configuration.sources.length; i++) {
+ for (let s=0; s < this._configuration.sources.length; s++) {
- if (!sourceManager.isLoadedSourceAvailable(this._configuration.sources[i])) {
+ if (!sourceManager.isLoadedSourceAvailable(this._configuration.sources[s])) {
LOGGER.error("La source n'a pas été chargée");
return false;
} else {
LOGGER.debug("La source est bien disponible");
- let source = sourceManager.getSourceById(this._configuration.sources[i]);
+ let source = sourceManager.getSourceById(this._configuration.sources[s]);
// TODO : faire cette vérification aussi pendant le check de la ressource
if (source.type !== "valhalla") {
@@ -92,15 +96,21 @@ module.exports = class valhallaResource extends Resource {
return false;
}
- let linkedIdRoute = source.configuration.cost.profile + source.configuration.cost.optimization;
- let linkedIdIso = source.configuration.cost.profile + source.configuration.cost.costType;
- this._linkedSource[linkedIdRoute] = source.configuration.id;
- this._linkedSource[linkedIdIso] = source.configuration.id;
+ for (let i = 0; i < source.configuration.costs.length; i++) {
+
+ let linkedIdRoute = source.configuration.costs[i].profile + source.configuration.costs[i].optimization;
+ let linkedIdIso = source.configuration.costs[i].profile + source.configuration.costs[i].costType;
+ this._linkedSource[linkedIdRoute] = source.configuration.id;
+ this._linkedSource[linkedIdIso] = source.configuration.id;
+
+ }
}
}
+
+
return true;
}
diff --git a/src/js/sources/pgrSource.js b/src/js/sources/pgrSource.js
index a766888..88c71c0 100644
--- a/src/js/sources/pgrSource.js
+++ b/src/js/sources/pgrSource.js
@@ -59,6 +59,7 @@ module.exports = class pgrSource extends Source {
// Attributs disponibles sur les voies dans la base
this._otherAttributes = new Array();
+ // TODO : à l'exemple des ressources, faire une fonction init() pour chaque source appelée dans le sourceManager
// Création des tableaux d'attributs
for (let i = 0; i < sourceJsonObject.storage.base.attributes.length; i++) {
let curAttribute = sourceJsonObject.storage.base.attributes[i];
@@ -87,8 +88,11 @@ module.exports = class pgrSource extends Source {
// Initialisation des coûts disponibles
for (let i = 0; i < sourceJsonObject.costs.length; i++) {
- Object.defineProperty(this._costs, sourceJsonObject.costs[i].profile, { value: new Object(), configurable: true, enumerable: true, writable: true });
+ if (!this._costs[sourceJsonObject.costs[i].profile]) {
+ Object.defineProperty(this._costs, sourceJsonObject.costs[i].profile, { value: new Object(), configurable: true, enumerable: true, writable: true });
+ }
Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile], sourceJsonObject.costs[i].optimization, { value: new Object(), configurable: true, enumerable: true, writable: true });
+ Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile], sourceJsonObject.costs[i].costType, { value: new Object(), configurable: true, enumerable: true, writable: true });
Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].optimization], "costColumn", { value: sourceJsonObject.costs[i].costColumn, configurable: true, enumerable: true, writable: true });
Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].optimization], "rcostColumn", { value: sourceJsonObject.costs[i].rcostColumn, configurable: true, enumerable: true, writable: true });
Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].costType], "costColumn", { value: sourceJsonObject.costs[i].costColumn, configurable: true, enumerable: true, writable: true });
diff --git a/src/js/sources/smartroutingSource.js b/src/js/sources/smartroutingSource.js
index 3fc6d2d..31733d3 100644
--- a/src/js/sources/smartroutingSource.js
+++ b/src/js/sources/smartroutingSource.js
@@ -42,7 +42,7 @@ module.exports = class smartroutingSource extends Source {
constructor(sourceJsonObject) {
// Constructeur parent
- super(sourceJsonObject.id, "pgr", sourceJsonObject.description, sourceJsonObject.projection, sourceJsonObject.bbox);
+ super(sourceJsonObject.id, "smartrouting", sourceJsonObject.description, sourceJsonObject.projection, sourceJsonObject.bbox);
// Stockage de la configuration
this._configuration = sourceJsonObject;
diff --git a/src/js/sources/source.js b/src/js/sources/source.js
index e115204..318f597 100644
--- a/src/js/sources/source.js
+++ b/src/js/sources/source.js
@@ -69,6 +69,28 @@ module.exports = class Source {
return this._type;
}
+ /**
+ *
+ * @function
+ * @name get description
+ * @description Récupérer la description de la source
+ *
+ */
+ get description () {
+ return this._description;
+ }
+
+ /**
+ *
+ * @function
+ * @name get projection
+ * @description Récupérer la projection de la source
+ *
+ */
+ get projection () {
+ return this._projection;
+ }
+
/**
*
* @function
diff --git a/src/js/sources/sourceManager.js b/src/js/sources/sourceManager.js
index 9939818..fa598af 100644
--- a/src/js/sources/sourceManager.js
+++ b/src/js/sources/sourceManager.js
@@ -1,5 +1,7 @@
'use strict';
+const fs = require('fs');
+const path = require('path');
const assert = require('assert').strict;
const osrmSource = require('../sources/osrmSource');
const pgrSource = require('../sources/pgrSource');
@@ -43,6 +45,8 @@ module.exports = class sourceManager {
this._baseManager = baseManager;
// Correspondance entre les sources et les opérations possibles
+ // Le contenu de ce tableau dépend du moteur et du code écrit dans la source correspondante
+ // Par exemple, le projet OSRM permet de faire du nearest et nous avons choisis de l'implémenter dans Road2
this._operationsByType = {
"osrm": ["nearest", "route"],
"pgr": ["route", "isochrone"],
@@ -63,17 +67,6 @@ module.exports = class sourceManager {
return this._source;
}
- /**
- *
- * @function
- * @name get operationsByType
- * @description Récupérer l'ensemble des opérations possibles par type de source
- *
- */
- get operationsByType() {
- return this._operationsByType;
- }
-
/**
*
* @function
@@ -200,7 +193,7 @@ module.exports = class sourceManager {
LOGGER.error("La source décrite dans le fichier " + sourceFile + " est mal configuée");
return false;
} else {
- this._checkedSourceId.push(sourceConf.source.id);
+ this._checkedSourceId.push(sourceConf.id);
}
}
@@ -529,17 +522,17 @@ module.exports = class sourceManager {
for (let j = 0; j < sourceJsonObject.storage.base.attributes.length; j++) {
- if (sourceJsonObject.storage.base.attributes[j].key) {
+ if (!sourceJsonObject.storage.base.attributes[j].key) {
LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes["+j+"].key' est absent");
return false;
}
- if (sourceJsonObject.storage.base.attributes[j].column) {
+ if (!sourceJsonObject.storage.base.attributes[j].column) {
LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes["+j+"].column' est absent");
return false;
}
- if (sourceJsonObject.storage.base.attributes[j].default) {
+ if (!sourceJsonObject.storage.base.attributes[j].default) {
LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes["+j+"].default' est absent");
return false;
} else {
From 6a181bd4c2430c08a8f3229ffeda66c294d8138d Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 14 Nov 2022 15:10:27 +0100
Subject: [PATCH 15/93] ajout des tests sur la configuration du service
---
src/js/resources/smartpgrResource.js | 2 -
.../cucumber/features/conf-service.feature | 71 +++++++++++++++++++
2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/src/js/resources/smartpgrResource.js b/src/js/resources/smartpgrResource.js
index 5f273e5..ddd5037 100644
--- a/src/js/resources/smartpgrResource.js
+++ b/src/js/resources/smartpgrResource.js
@@ -95,8 +95,6 @@ module.exports = class smartpgrResource extends Resource {
} else if (source.type === 'pgr') {
- console.log(source);
-
for (let j = 0; j < source.configuration.costs.length; j++) {
let linkedIdRoute = source.configuration.costs[j].profile + source.configuration.costs[j].optimization;
diff --git a/test/functional/configuration/cucumber/features/conf-service.feature b/test/functional/configuration/cucumber/features/conf-service.feature
index 91f70fe..82991b1 100644
--- a/test/functional/configuration/cucumber/features/conf-service.feature
+++ b/test/functional/configuration/cucumber/features/conf-service.feature
@@ -399,6 +399,77 @@ Feature: Road2 service configuration
# TODO
# Tester un dossier de ressources dont une des ressources ne peut être lues
+ Scenario: [service.json] (sources different)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.sources" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:sources:directories' manquant !"
+
+ Scenario: [service.json] (sources vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.sources" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:sources' manquant !"
+
+ Scenario: [service.json] (sources absent)
+ Given a valid configuration
+ And without attribute "application.sources" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Objet 'application:sources' manquant !"
+
+ Scenario: [service.json] (sources.directories est une chaine de caracteres)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.sources.directories" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:sources:directories' n'est pas un tableau !"
+
+ # TODO
+ # Tester le paramètre sources.directories sur un tableau vide
+
+ Scenario: [service.json] (sources.directories sur un dossier qui n'existe pas et en chemin relatif)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.sources.directories.[1]" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the server log should contain "Mauvaise configuration: Le dossier n'existe pas:"
+
+ Scenario: [service.json] (sources.directories sur deux dossiers qui n'existent pas et en chemins relatifs)
+ Given a valid configuration
+ And with parameter "test" for attribute "application.sources.directories.[0]" in service configuration
+ And with parameter "test1" for attribute "application.sources.directories.[1]" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Le dossier n'existe pas"
+
+ Scenario: [service.json] (sources.directories contient un élément vide)
+ Given a valid configuration
+ And with parameter "" for attribute "application.sources.directories.[1]" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 0
+ Then the server log should contain "Mauvaise configuration: Champ 'application:sources:directories' contient un élément vide"
+
+ Scenario: [service.json] (sources.directories contient que des éléments vides)
+ Given a valid configuration
+ And with parameter "" for attribute "application.sources.directories.[0]" in service configuration
+ And with parameter "" for attribute "application.sources.directories.[1]" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Aucun dossier de source n'a été validé"
+
+ Scenario: [service.json] (sources.directories absent)
+ Given a valid configuration
+ And without attribute "application.sources.directories" in service configuration
+ When I test the configuration
+ Then the configuration analysis should give an exit code 1
+ Then the server log should contain "Mauvaise configuration: Champ 'application:sources:directories' manquant !"
+
+ # TODO
+ # Tester un dossier de ressources dont une des ressources ne peut être lues
+
Scenario: [service.json] (network different)
Given a valid configuration
And with parameter "test" for attribute "application.network" in service configuration
From 75407928301e2314c6e680008c5f033f88d52b05 Mon Sep 17 00:00:00 2001
From: Loic
Date: Tue, 15 Nov 2022 14:41:52 +0100
Subject: [PATCH 16/93] =?UTF-8?q?maj=20de=20la=20doc=20pour=20cette=20s?=
=?UTF-8?q?=C3=A9paration=20des=20sources?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../{ => administration}/admin_model.yaml | 0
.../{ => pgrouting}/configuration_bdd.json | 0
.../constraints.resource.example | 0
.../{ => projections}/projection_model.yaml | 0
documentation/configuration/readme.md | 30 +-
.../configuration/resource_model_osrm.yaml | 146 ----
.../configuration/resource_model_pgr.yaml | 190 -----
.../osrm.resource} | 38 +-
.../pgr.resource} | 290 +-------
.../resources/resource_model.yaml | 64 ++
.../configuration/resources/smartpgr.resource | 673 ++++++++++++++++++
.../configuration/resources/valhalla.resource | 229 ++++++
.../{ => services}/service_model.yaml | 0
.../configuration/sources/osrm.source | 14 +
.../configuration/sources/pgr.source | 200 ++++++
.../configuration/sources/pgrSource.json | 196 -----
.../configuration/sources/smartrouting.source | 10 +
.../configuration/sources/source_model.yaml | 43 ++
.../configuration/sources/valhalla.source | 32 +
documentation/data/readme.md | 15 +-
documentation/developers/concepts.md | 26 +-
documentation/developers/readme.md | 2 +-
readme.md | 8 +-
23 files changed, 1339 insertions(+), 867 deletions(-)
rename documentation/configuration/{ => administration}/admin_model.yaml (100%)
rename documentation/configuration/{ => pgrouting}/configuration_bdd.json (100%)
rename documentation/configuration/{ => pgrouting}/constraints.resource.example (100%)
rename documentation/configuration/{ => projections}/projection_model.yaml (100%)
delete mode 100644 documentation/configuration/resource_model_osrm.yaml
delete mode 100644 documentation/configuration/resource_model_pgr.yaml
rename documentation/configuration/{corse.resource => resources/osrm.resource} (80%)
rename documentation/configuration/{bduni_idf_pgr.resource => resources/pgr.resource} (71%)
create mode 100644 documentation/configuration/resources/resource_model.yaml
create mode 100644 documentation/configuration/resources/smartpgr.resource
create mode 100644 documentation/configuration/resources/valhalla.resource
rename documentation/configuration/{ => services}/service_model.yaml (100%)
create mode 100644 documentation/configuration/sources/osrm.source
create mode 100644 documentation/configuration/sources/pgr.source
delete mode 100644 documentation/configuration/sources/pgrSource.json
create mode 100644 documentation/configuration/sources/smartrouting.source
create mode 100644 documentation/configuration/sources/source_model.yaml
create mode 100644 documentation/configuration/sources/valhalla.source
diff --git a/documentation/configuration/admin_model.yaml b/documentation/configuration/administration/admin_model.yaml
similarity index 100%
rename from documentation/configuration/admin_model.yaml
rename to documentation/configuration/administration/admin_model.yaml
diff --git a/documentation/configuration/configuration_bdd.json b/documentation/configuration/pgrouting/configuration_bdd.json
similarity index 100%
rename from documentation/configuration/configuration_bdd.json
rename to documentation/configuration/pgrouting/configuration_bdd.json
diff --git a/documentation/configuration/constraints.resource.example b/documentation/configuration/pgrouting/constraints.resource.example
similarity index 100%
rename from documentation/configuration/constraints.resource.example
rename to documentation/configuration/pgrouting/constraints.resource.example
diff --git a/documentation/configuration/projection_model.yaml b/documentation/configuration/projections/projection_model.yaml
similarity index 100%
rename from documentation/configuration/projection_model.yaml
rename to documentation/configuration/projections/projection_model.yaml
diff --git a/documentation/configuration/readme.md b/documentation/configuration/readme.md
index ed6e663..3352638 100644
--- a/documentation/configuration/readme.md
+++ b/documentation/configuration/readme.md
@@ -13,22 +13,23 @@ Ce fichier va indiquer plusieurs informations et deux éléments :
- un *log4js.json* pour les logs de l'administrateur
Chaque *service.json* va indiquer les éléments suivants :
-- un *log4js.json* pour les logs de l'administrateur et un par service,
+- un *log4js.json* par service pour les logs,
- un *cors.json* par service si on souhaite spécifier une politique de CORS,
- le dossier des *projections*,
-- les dossiers des *ressources*.
+- les dossiers des *ressources*,
+- les dossiers des *sources*.
## administration.json
Ce fichier indique quelques informations générales liées à l'instance d'administration. Son principal objectif est l'indication des logs et des services gérés.
-On peut trouver un [exemple](../../docker/config/road2.json) de ce fichier et le [modèle](./admin_model.yaml) au format YAML.
+On peut trouver un [exemple](../../docker/config/road2.json) de ce fichier et le [modèle](./administration/administration_model.yaml) au format YAML.
## service.json
-Ce fichier indique quelques informations générales liées à l'instance de Road2. Son principal objectif est l'indication des logs et des ressources du serveur. Néanmoins, il permet de préciser beaucoup plus d'informations, comme les opérations ou les projections disponibles sur l'instance.
+Ce fichier indique quelques informations générales liées à l'instance d'un service. Son principal objectif est l'indication des logs, des sources et des ressources du serveur. Néanmoins, il permet de préciser beaucoup plus d'informations, comme les opérations ou les projections disponibles sur l'instance.
-On peut trouver un [exemple](../../docker/config/service.json) de ce fichier et le [modèle](./service_model.yaml) au format YAML.
+On peut trouver un [exemple](../../docker/config/service.json) de ce fichier et le [modèle](./services/service_model.yaml) au format YAML.
## log4js.json
@@ -46,25 +47,24 @@ On peut trouver un [exemple](../../docker/config/cors.json) de ce fichier au for
## Les projections
-Le fichier *server.json* indique un dossier de projections. Ce dossier peut contenir plusieurs fichiers JSON. Ces fichiers seront lus, indépendamment de leur extension, pour obtenir les informations nécessaires permettant à [PROJ4](http://proj4js.org/) d'effectuer des reprojections.
+Le fichier *service.json* indique un dossier de projections. Ce dossier peut contenir plusieurs fichiers JSON. Ces fichiers seront lus, indépendamment de leur extension, pour obtenir les informations nécessaires permettant à [PROJ4](http://proj4js.org/) d'effectuer des reprojections.
-On peut trouver un [exemple](../../docker/config/projections/projection.json) de ce fichier et le [modèle](./projection_model.yaml) au format YAML.
+On peut trouver un [exemple](../../docker/config/projections/projection.json) de ce fichier et le [modèle](./projections/projection_model.yaml) au format YAML.
-## Les ressources
+## Les sources
-Dans le fichier *server.json*, il est possible d'indiquer plusieurs dossiers *resources*. Chaque dossier sera lu et les fichiers `*.resource` seront analysés par Road2. Chacun de ces fichiers représente une ressource pour Road2.
+Dans les fichiers du type *service.json*, il est possible d'indiquer plusieurs dossiers *sources*. Chaque dossier sera lu et les fichiers `*.source` seront analysés par Road2. Chacun de ces fichiers représente une source pour Road2.
-On peut trouver un [exemple](../../docker/config/resources/corse.resource) de ce fichier et le [modèle](./resource_model_osrm.yaml) au format YAML pour OSRM. Pour PGRouting, il y a également un [exemple](./bduni_idf_pgr.resource) et un [modèle](./resource_model_pgr.yaml).
+On peut trouver, dans ce [dossier](./sources/), un exemple de ce genre de fichier pour chaque type de source disponible dans le code de Road2.
-### Les lua et les json des sources
+## Les ressources
-Chaque source d'une ressource est rattaché à un profile et une optimisation. Cela détermine un coût pour chaque tronçon du graphe. Pour calculer ces coût, nous utilisons un fichier spécifique qui contient les règles de passage des attributs d'un tronçon à son coût. Ce fichier est un json géré dans le projet route-graph-generator. Cer dernier contient donc au moins un exemple.
-À partir de ce json, un lua est créé pour OSRM. Ce fichier lua est aussi dans le projet route-graph-generator.
+Dans les fichiers *service.json*, il peut également indiquer plusieurs dossiers *resources*. Chaque dossier sera lu et les fichiers `*.resource` seront analysés par Road2. Chacun de ces fichiers représente cette fois-ci une ressource pour Road2.
-Ces deux fichiers ne sont pas obligatoires dans la configuration mais ils sont fournis pour que l'on puisse retrouver les informations de création des graphes. Il est donc utile de les avoir. Ils devraient être fournis par route-graph-generator lors d'une génération.
+On peut trouver, dans ce [dossier](./resources/), un exemple de ce genre de fichier pour chaque type de ressource disponible dans le code de Road2. Chaque type suit le même modèle YAML.
## Les fichiers liés à certains moteurs de Road2
### PGRouting: La configuration d'une base de données
-Afin de lire les données dans un base, il est nécessaire de fournir à Road2 un fichier qui lui donne les identifiants de connexion à la base. Cela est possible via un fichier json. Un exemple de ce fichier est fourni [ici](./configuration_bdd.json). Le contenu de ce fichier correspond aux options du module NodeJS `pg`.
\ No newline at end of file
+Afin de lire les données dans un base, il est nécessaire de fournir à Road2 un fichier qui lui donne les identifiants de connexion à la base. Cela est possible via un fichier json. Un exemple de ce fichier est fourni [ici](./pgrouting/configuration_bdd.json). Le contenu de ce fichier correspond aux options du module NodeJS `pg`.
\ No newline at end of file
diff --git a/documentation/configuration/resource_model_osrm.yaml b/documentation/configuration/resource_model_osrm.yaml
deleted file mode 100644
index e26d7ab..0000000
--- a/documentation/configuration/resource_model_osrm.yaml
+++ /dev/null
@@ -1,146 +0,0 @@
-# Description d'un fichier des ressources OSRM pour Road2
-
-
-# Information sur la ressource générée. La plupart de ces informations permettront de générer le fichier de ressource utilisable par l'application de calcul d'itinéraire.
-"resource":
- type: object
- required: true
- properties:
- # Id de la ressource
- "id":
- type: string
- required: true
- # Type de la ressource, osrm dans ce cas
- "type":
- type: string
- required: true
- # Description de la ressource
- "description":
- type: string
- required: true
- # Version de la ressource. C'est généralement la date de génération de cette ressource.
- "resourceVersion"
- type: "string"
- required: true
- # Informations sur la topologie de la ressource
- "topology":
- type: object
- required: true
- properties:
- # id de la topologie, utile pour la charger une seule fois dans Road2
- "id":
- type: string
- required: true
- # Type de la topologie
- "type":
- type: string
- required: true
- # Description de la topologie
- "description":
- type: string
- required: true
- # Stockage de la topologie
- "storage":
- $ref: "#/components/schemas/storage"
- required: true
- # Projection des données sources
- "projection":
- type: string
- required: true
- # Bbox des données de la topologie, pas nécessairement la même que pour la ressource
- "bbox":
- type: string
- required: true
- # Liste des sources qui vont être générées
- "sources":
- type: array
- required: true
- minItems: 1
- items:
- type: object
- properties:
- # id de la source, utile pour la charger une seule fois dans Road2.
- "id":
- type: string
- required: true
- # Type de la source, ici ce doit être osrm
- "type":
- type: string
- required: true
- # Stockage de la source, du .osrm en l'occurence
- "storage":
- $ref: "#/components/schemas/storage"
- required: true
- # Coûts calculés sur la topologie précisée précedemment. On peut en avoir plusieurs.
- "cost":
- type: object
- required: true
- properties:
- # Chaque coût correspond à un profil
- "profile":
- type: string
- required: true
- # Chaque coût correspond à un profil
- "optmization":
- type: string
- required: true
- # Fichier permettant de calculer le coût
- "compute":
- type: object
- required: false
- properties:
- # Stockage du fichier permettant de calculer le coût
- "storage":
- $ref: "#/components/schemas/storage"
- # Configuration pour le calcul des couts
- "configuration":
- type: object
- required: true
- properties:
- # Nom du coût dans le fichier de configuration
- "name":
- type: string
- required: true
- # Stockage du fichier de calcul des couts. C'est un JSON.
- "storage":
- $ref: "#/components/schemas/storage"
- # Informations sur les opérations autorisées sur la ressource qui va être générée.
- "availableOperations":
- type: array
- required: true
- minItems: 1
- items:
- # Id de l'opération
- "id":
- type: string
- required: true
- # Paramètres de l'opération
- "parameters":
- type: array
- required: true
- items:
- type: object
- properties:
- # Id du parametre
- "id":
- type: string
- required: true
- # Valeur par défaut possible pour ce parametre
- "defaultValueContent":
- type: string
- required: false
- # Valeurs possibles pour ce parametre
- "values":
- type: string or array or object
- required: true
-
-components:
- schemas:
- # storage d'un document: fichier ou ceph
- "storage":
- type: object
- properties:
- # Fichier
- "file":
- type: string
- required: false
\ No newline at end of file
diff --git a/documentation/configuration/resource_model_pgr.yaml b/documentation/configuration/resource_model_pgr.yaml
deleted file mode 100644
index f95f8c1..0000000
--- a/documentation/configuration/resource_model_pgr.yaml
+++ /dev/null
@@ -1,190 +0,0 @@
-# Description d'un fichier de configuration de génération pour des ressources OSRM
-
-# Information sur la ressource générée. La plupart de ces informations permettront de générer le fichier de ressource utilisable par l'application de calcul d'itinéraire.
-"resource":
- type: object
- required: true
- properties:
- # Id de la ressource
- "id":
- type: string
- required: true
- # Type de la ressource, pge dans ce cas
- "type":
- type: string
- required: true
- # Description de la ressource
- "description":
- type: string
- required: true
- # Version de la ressource. C'est généralement la date de génération de cette ressource.
- "resourceVersion"
- type: "string"
- required: true
- # Informations sur la topologie de la ressource
- "topology":
- type: object
- required: true
- properties:
- # id de la topologie, utile pour la charger une seule fois dans Road2
- "id":
- type: string
- required: true
- # Type de la topologie
- "type":
- type: string
- required: true
- # Description de la topologie
- "description":
- type: string
- required: true
- # Stockage de la topologie
- "storage":
- type: object
- required: true
- properties:
- # Information sur la base qui contient la topologie
- "base":
- type: object
- required: true
- properties:
- # Fichier de configuration pour se connecter à la base de données, utile que pour Road2
- "dbConfig":
- type: string
- required: true
- # Schéma dans la base de données
- "schema":
- type: string
- required: true
- # Liste des attributs de le topologie disponibles dans la réponse
- "attributes":
- type: array
- required: false
- items:
- type: object
- properties:
- # Clé utilisée par le client de l'api
- "key":
- type: string
- required: true
- # Nom de la colonne dans la base de donnés
- "column":
- type: string
- required: true
- # Indique si l'attribut est présent par défaut dans la réponse, "true" ou "false"
- "default":
- type: string
- required: true
- # Projection des données sources
- "projection":
- type: string
- required: true
- # Bbox des données de la topologie, pas nécessairement la même que pour la ressource
- "bbox":
- type: string
- required: true
- # Liste des sources qui vont être générées
- "sources":
- type: array
- required: true
- minItems: 1
- items:
- type: object
- properties:
- # id de la source, utile pour la charger une seule fois dans Road2.
- "id":
- type: string
- required: true
- # Type de la source, ici ce doit être osrm
- "type":
- type: string
- required: true
- # Stockage de la source, du .osrm en l'occurence
- "storage":
- type: object
- required: true
- properties:
- # Fichier de configuration de la base de données
- "dbConfig":
- type: string
- required: true
- # Colonne des coûts
- "costColumn":
- type: string
- required: true
- # Colonne des coûts inverse
- "rcostColumn":
- type: string
- required: true
- # Coûts qui seront calculés sur la topologie précisée précedemment. On peut en avoir plusieurs.
- "cost":
- type: object
- required: true
- properties:
- # Chaque coût correspond à un profil
- "profile":
- type: string
- required: true
- # Chaque coût correspond à un profil
- "optmization":
- type: string
- required: true
- # Fichier permettant de calculer le coût
- "compute":
- type: object
- required: true
- properties:
- # Stockage du fichier permettant de calculer le coût
- "storage":
- $ref: "#/components/schemas/storage"
- # Configuration pour le calcul des couts
- "configuration":
- type: object
- required: false
- properties:
- # Nom du coût dans le fichier de configuration
- "name":
- type: string
- required: true
- # Stockage du fichier de calcul des couts. C'est un JSON.
- "storage":
- $ref: "#/components/schemas/storage"
- # Informations sur les opérations autorisées sur la ressource qui va être générée.
- "availableOperations":
- type: array
- required: true
- minItems: 1
- items:
- # Id de l'opération
- "id":
- type: string
- required: true
- # Paramètres de l'opération
- "parameters":
- type: array
- required: true
- items:
- type: object
- properties:
- # Id du parametre
- "id":
- type: string
- required: true
- # Valeur par défaut possible pour ce parametre
- "defaultValueContent":
- type: string
- required: false
- # Valeurs possibles pour ce parametre
- "values":
- type: string or array or object
- required: true
-components:
- schemas:
- # storage d'un document: fichier ou ceph
- "storage":
- type: object
- properties:
- # Fichier
- "file":
- type: string
- required: false
\ No newline at end of file
diff --git a/documentation/configuration/corse.resource b/documentation/configuration/resources/osrm.resource
similarity index 80%
rename from documentation/configuration/corse.resource
rename to documentation/configuration/resources/osrm.resource
index 555ee9a..a92cd82 100644
--- a/documentation/configuration/corse.resource
+++ b/documentation/configuration/resources/osrm.resource
@@ -1,36 +1,11 @@
{
"resource": {
- "id": "corse-osm",
+ "id": "data-osm",
"type": "osrm",
- "description": "Exemple d'une ressource sur la Corse avec les données OSM.",
- "resourceVersion": "2020-09-28",
- "topology": {
- "id": "corse-osm",
- "type": "osm",
- "description": "Données OSM sur la Corse.",
- "storage": {
- "file": "/home/docker/internal/corse-latest.osm.pbf"
- },
- "projection": "EPSG:4326",
- "bbox": "-90,-180,90,180"
- },
+ "description": "Exemple d'une ressource créée à partir des données OSM.",
+ "resourceVersion": "yyyy-mm-dd",
"sources": [
- {
- "id": "corse-car-fastest",
- "type": "osrm",
- "storage": {
- "file": "/home/docker/internal/corse-latest.osrm"
- },
- "cost": {
- "profile": "car",
- "optimization": "fastest",
- "compute": {
- "storage": {
- "file": "/usr/local/share/osrm/profiles/car.lua"
- }
- }
- }
- }
+ "data-osm-car-fastest"
],
"availableOperations":[
{
@@ -39,7 +14,7 @@
{
"id": "resource",
"values": [
- "corse-osm"
+ "data-osm"
]
},
{
@@ -157,7 +132,7 @@
{
"id": "resource",
"values": [
- "corse-osm"
+ "data-osm"
]
},
{
@@ -169,6 +144,7 @@
},
{
"id": "number",
+ "defaultValueContent": 1,
"values": {
"min": 1,
"max": 10
diff --git a/documentation/configuration/bduni_idf_pgr.resource b/documentation/configuration/resources/pgr.resource
similarity index 71%
rename from documentation/configuration/bduni_idf_pgr.resource
rename to documentation/configuration/resources/pgr.resource
index ef058a3..71d25ab 100644
--- a/documentation/configuration/bduni_idf_pgr.resource
+++ b/documentation/configuration/resources/pgr.resource
@@ -2,271 +2,10 @@
"resource": {
"id": "bduni-idf-pgr",
"type": "pgr",
- "description": "Donn\u00e9es BDUNI v2.",
- "resourceVersion": "10/05/2020",
- "topology": {
- "id": "base-bduni",
- "type": "db",
- "description": "Donn\u00e9es issues de la BDUNI de l'IGN.",
- "storage": {
- "base": {
- "dbConfig": "/home/docker/data/output_base.json",
- "schema": "public",
- "attributes": [
- {
- "key": "name",
- "column": "way_names",
- "default": "false"
- },
- {
- "key": "nom_1_gauche",
- "column": "nom_1_gauche",
- "default": "true"
- },
- {
- "key": "nom_1_droite",
- "column": "nom_1_droite",
- "default": "true"
- },
- {
- "key": "cpx_numero",
- "column": "cpx_numero",
- "default": "true"
- },
- {
- "key": "cpx_toponyme_route_nommee",
- "column": "cpx_toponyme_route_nommee",
- "default": "true"
- },
- {
- "key": "cleabs",
- "column": "cleabs",
- "default": "false"
- },
- {
- "key": "nature",
- "column": "nature",
- "default": "false"
- },
- {
- "key": "importance",
- "column": "importance",
- "default": "false"
- },
- {
- "key": "position_par_rapport_au_sol",
- "column": "position_par_rapport_au_sol",
- "default": "false"
- },
- {
- "key": "nombre_de_voies",
- "column": "nombre_de_voies",
- "default": "false"
- },
- {
- "key": "largeur_de_chaussee",
- "column": "largeur_de_chaussee",
- "default": "false"
- },
- {
- "key": "itineraire_vert",
- "column": "itineraire_vert",
- "default": "false"
- },
- {
- "key": "sens_de_circulation",
- "column": "sens_de_circulation",
- "default": "false"
- },
- {
- "key": "bande_cyclable",
- "column": "bande_cyclable",
- "default": "false"
- },
- {
- "key": "reserve_aux_bus",
- "column": "reserve_aux_bus",
- "default": "false"
- },
- {
- "key": "urbain",
- "column": "urbain",
- "default": "false"
- },
- {
- "key": "vitesse_moyenne_vl",
- "column": "vitesse_moyenne_vl",
- "default": "false"
- },
- {
- "key": "acces_vehicule_leger",
- "column": "acces_vehicule_leger",
- "default": "false"
- },
- {
- "key": "acces_pieton",
- "column": "acces_pieton",
- "default": "false"
- },
- {
- "key": "nature_de_la_restriction",
- "column": "nature_de_la_restriction",
- "default": "false"
- },
- {
- "key": "restriction_de_hauteur",
- "column": "restriction_de_hauteur",
- "default": "false"
- },
- {
- "key": "restriction_de_poids_total",
- "column": "restriction_de_poids_total",
- "default": "false"
- },
- {
- "key": "restriction_de_poids_par_essieu",
- "column": "restriction_de_poids_par_essieu",
- "default": "false"
- },
- {
- "key": "restriction_de_largeur",
- "column": "restriction_de_largeur",
- "default": "false"
- },
- {
- "key": "restriction_de_longueur",
- "column": "restriction_de_longueur",
- "default": "false"
- },
- {
- "key": "matieres_dangereuses_interdites",
- "column": "matieres_dangereuses_interdites",
- "default": "false"
- },
- {
- "key": "insee_commune_gauche",
- "column": "insee_commune_gauche",
- "default": "false"
- },
- {
- "key": "insee_commune_droite",
- "column": "insee_commune_droite",
- "default": "false"
- },
- {
- "key": "cpx_numero_route_europeenne",
- "column": "cpx_numero_route_europeenne",
- "default": "false"
- },
- {
- "key": "cpx_classement_administratif",
- "column": "cpx_classement_administratif",
- "default": "false"
- },
- {
- "key": "cpx_gestionnaire",
- "column": "cpx_gestionnaire",
- "default": "false"
- }
- ]
- }
- },
- "projection": "EPSG:4326",
- "bbox": "1.7,48.4,3.3,49.1"
- },
+ "description": "Données BDUNI v2.",
+ "resourceVersion": "yyyy-mm-dd",
"sources": [
- {
- "id": "bduni-idf-car-fastest-pgr",
- "type": "pgr",
- "storage": {
- "costColumn": "cost_s_car",
- "rcostColumn": "reverse_cost_s_car"
- },
- "cost": {
- "profile": "car",
- "optimization": "fastest",
- "compute": {
- "storage": {
- "file": "/home/docker/data/costs_calculation_sample.json"
- },
- "configuration": {
- "name": "cost_s_car",
- "storage": {
- "file": "/home/docker/data/costs_calculation_sample.json"
- }
- }
- }
- }
- },
- {
- "id": "bduni-idf-car-shortest-pgr",
- "type": "pgr",
- "storage": {
- "costColumn": "cost_m_car",
- "rcostColumn": "reverse_cost_m_car"
- },
- "cost": {
- "profile": "car",
- "optimization": "shortest",
- "compute": {
- "storage": {
- "file": "/home/docker/data/costs_calculation_sample.json"
- },
- "configuration": {
- "name": "cost_m_car",
- "storage": {
- "file": "/home/docker/data/costs_calculation_sample.json"
- }
- }
- }
- }
- },
- {
- "id": "bduni-idf-pedestrian-fastest-pgr",
- "type": "pgr",
- "storage": {
- "costColumn": "cost_s_pedestrian",
- "rcostColumn": "reverse_cost_s_pedestrian"
- },
- "cost": {
- "profile": "pedestrian",
- "optimization": "fastest",
- "compute": {
- "storage": {
- "file": "/home/docker/data/costs_calculation_sample.json"
- },
- "configuration": {
- "name": "cost_s_pedestrian",
- "storage": {
- "file": "/home/docker/data/costs_calculation_sample.json"
- }
- }
- }
- }
- },
- {
- "id": "bduni-idf-pedestrian-shortest-pgr",
- "type": "pgr",
- "storage": {
- "costColumn": "cost_m_pedestrian",
- "rcostColumn": "reverse_cost_m_pedestrian"
- },
- "cost": {
- "profile": "pedestrian",
- "optimization": "shortest",
- "compute": {
- "storage": {
- "file": "/home/docker/data/costs_calculation_sample.json"
- },
- "configuration": {
- "name": "cost_m_pedestrian",
- "storage": {
- "file": "/home/docker/data/costs_calculation_sample.json"
- }
- }
- }
- }
- }
+ "bduni-idf-pgr"
],
"availableOperations": [
{
@@ -433,7 +172,7 @@
},
{
"keyType": "numerical-pgr",
- "key": "LARGEUR",
+ "key": "largeur",
"availableConstraintType": [
"banned"
],
@@ -441,15 +180,17 @@
},
{
"keyType": "numerical-pgr",
- "key": "IMPORTANCE",
+ "key": "importance",
"availableConstraintType": [
- "banned"
+ "banned",
+ "avoid",
+ "prefer"
],
"field": "importance"
},
{
"keyType": "name-pgr",
- "key": "NATURE",
+ "key": "nature",
"availableConstraintType": [
"banned"
],
@@ -546,9 +287,11 @@
},
{
"keyType": "name-pgr",
- "key": "CL_ADMIN",
+ "key": "cpx_classement_administratif",
"availableConstraintType": [
- "banned"
+ "banned",
+ "prefer",
+ "avoid"
],
"availableValues": [
{
@@ -630,7 +373,11 @@
]
},
{
- "id": "costValue"
+ "id": "costValue",
+ "values": {
+ "min": 100,
+ "max": 20000
+ }
},
{
"id": "profile",
@@ -923,4 +670,3 @@
}
]
}
-}
\ No newline at end of file
diff --git a/documentation/configuration/resources/resource_model.yaml b/documentation/configuration/resources/resource_model.yaml
new file mode 100644
index 0000000..47d5aba
--- /dev/null
+++ b/documentation/configuration/resources/resource_model.yaml
@@ -0,0 +1,64 @@
+# Description d'un fichier de ressource pour Road2
+
+# Information sur la ressource diffusée.
+"resource":
+ type: object
+ required: true
+ properties:
+ # Id de la ressource, unique par instance de Road2
+ "id":
+ type: string
+ required: true
+ # Type de la ressource
+ "type":
+ type: string
+ required: true
+ enum: ["osrm","pgr","smartpgr","valhalla"]
+ # Description de la ressource
+ "description":
+ type: string
+ required: true
+ # Version de la ressource. C'est généralement la date de génération de cette ressource.
+ "resourceVersion"
+ type: "string"
+ required: true
+ # Liste des sources proposée dans cette ressource. On indique seulement les ids des sources.
+ # Il y a une correspondance qui doit être respectée entre les types de source et de ressource
+ "sources":
+ type: array
+ required: true
+ minItems: 1
+ items:
+ type: string
+ # Informations sur les opérations autorisées sur la ressource qui va être générée.
+ "availableOperations":
+ type: array
+ required: true
+ minItems: 1
+ items:
+ type: object
+ properties:
+ # Id de l'opération
+ "id":
+ type: string
+ required: true
+ # Paramètres de l'opération
+ "parameters":
+ type: array
+ required: true
+ items:
+ type: object
+ properties:
+ # Id du parametre
+ "id":
+ type: string
+ required: true
+ # Valeur par défaut possible pour ce parametre
+ "defaultValueContent":
+ type: string
+ required: false
+ # Valeurs possibles pour ce parametre
+ # TODO : finir de spécifier (en attendant, voir les exemples de fichier)
+ "values":
+ type: string or array or object
+ required: true
diff --git a/documentation/configuration/resources/smartpgr.resource b/documentation/configuration/resources/smartpgr.resource
new file mode 100644
index 0000000..5d610ed
--- /dev/null
+++ b/documentation/configuration/resources/smartpgr.resource
@@ -0,0 +1,673 @@
+{
+ "resource": {
+ "id": "bduni-idf-smartpgr",
+ "type": "smartpgr",
+ "resourceVersion": "yyyy-mm-dd",
+ "threshold": 30000,
+ "description": "Donn\u00e9es BDUNI v2.",
+ "sources": [
+ "bdtopo-smartrouting",
+ "bduni-idf-pgr"
+ ],
+ "availableOperations": [
+ {
+ "id": "route",
+ "parameters": [
+ {
+ "id": "resource",
+ "values": [
+ "bduni-idf-smartpgr"
+ ]
+ },
+ {
+ "id": "start",
+ "values": {
+ "bbox": "1.7,48.4,3.3,49.1",
+ "projection": "EPSG:4326"
+ }
+ },
+ {
+ "id": "end",
+ "values": {
+ "bbox": "1.7,48.4,3.3,49.1",
+ "projection": "EPSG:4326"
+ }
+ },
+ {
+ "id": "profile",
+ "defaultValueContent": "car",
+ "values": [
+ "car",
+ "pedestrian"
+ ]
+ },
+ {
+ "id": "optimization",
+ "defaultValueContent": "fastest",
+ "values": [
+ "fastest",
+ "shortest"
+ ]
+ },
+ {
+ "id": "intermediates",
+ "values": {
+ "bbox": "1.7,48.4,3.3,49.1",
+ "projection": "EPSG:4326"
+ }
+ },
+ {
+ "id": "getSteps",
+ "defaultValueContent": "true"
+ },
+ {
+ "id": "waysAttributes",
+ "values": [
+ "name",
+ "nom_1_gauche",
+ "nom_1_droite",
+ "cpx_numero",
+ "cpx_toponyme_route_nommee",
+ "cleabs",
+ "nature",
+ "importance",
+ "position_par_rapport_au_sol",
+ "nombre_de_voies",
+ "largeur_de_chaussee",
+ "itineraire_vert",
+ "sens_de_circulation",
+ "bande_cyclable",
+ "reserve_aux_bus",
+ "urbain",
+ "vitesse_moyenne_vl",
+ "acces_vehicule_leger",
+ "acces_pieton",
+ "nature_de_la_restriction",
+ "restriction_de_hauteur",
+ "restriction_de_poids_total",
+ "restriction_de_poids_par_essieu",
+ "restriction_de_largeur",
+ "restriction_de_longueur",
+ "matieres_dangereuses_interdites",
+ "insee_commune_gauche",
+ "insee_commune_droite",
+ "cpx_numero_route_europeenne",
+ "cpx_classement_administratif",
+ "cpx_gestionnaire"
+ ]
+ },
+ {
+ "id": "geometryFormat",
+ "defaultValueContent": "geojson",
+ "values": [
+ "geojson",
+ "polyline"
+ ]
+ },
+ {
+ "id": "bbox",
+ "defaultValueContent": "true"
+ },
+ {
+ "id": "projection",
+ "defaultValueContent": "EPSG:4326",
+ "values": [
+ "EPSG:4326",
+ "EPSG:2154"
+ ]
+ },
+ {
+ "id": "timeUnit",
+ "defaultValueContent": "minute",
+ "values": [
+ "hour",
+ "minute",
+ "second",
+ "standard"
+ ]
+ },
+ {
+ "id": "distanceUnit",
+ "defaultValueContent": "meter",
+ "values": [
+ "meter",
+ "kilometer"
+ ]
+ },
+ {
+ "id": "constraints",
+ "defaultPreferredCostRatio": 0.8,
+ "defaultAvoidCostRatio": 1.2,
+ "values": [
+ {
+ "keyType": "name-pgr",
+ "key": "wayType",
+ "availableConstraintType": [
+ "banned"
+ ],
+ "availableValues": [
+ {
+ "value": "autoroute",
+ "field": "acces_vehicule_leger",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$A p\u00e9age$niv4$"
+ }
+ },
+ {
+ "value": "tunnel",
+ "field": "position_par_rapport_au_sol",
+ "condition": {
+ "type": "less",
+ "value": "0"
+ }
+ },
+ {
+ "value": "pont",
+ "field": "position_par_rapport_au_sol",
+ "condition": {
+ "type": "greater",
+ "value": "0"
+ }
+ }
+ ]
+ },
+ {
+ "keyType": "numerical-pgr",
+ "key": "largeur",
+ "availableConstraintType": [
+ "banned"
+ ],
+ "field": "largeur_de_chaussee"
+ },
+ {
+ "keyType": "numerical-pgr",
+ "key": "importance",
+ "availableConstraintType": [
+ "banned",
+ "avoid",
+ "prefer"
+ ],
+ "field": "importance"
+ },
+ {
+ "keyType": "name-pgr",
+ "key": "nature",
+ "availableConstraintType": [
+ "banned"
+ ],
+ "availableValues": [
+ {
+ "value": "sentier",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Sentier$niv4$"
+ }
+ },
+ {
+ "value": "bac_ou_liaison_maritime",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Bac ou liaison maritime$niv4$"
+ }
+ },
+ {
+ "value": "bretelle",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Bretelle$niv4$"
+ }
+ },
+ {
+ "value": "chemin",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Chemin$niv4$"
+ }
+ },
+ {
+ "value": "escalier",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Escalier$niv4$"
+ }
+ },
+ {
+ "value": "piste_cyclable",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Piste cyclable$niv4$"
+ }
+ },
+ {
+ "value": "rond-point",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Rond-point$niv4$"
+ }
+ },
+ {
+ "value": "route_a_1_chaussee",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Route \u00e0 1 chauss\u00e9e$niv4$"
+ }
+ },
+ {
+ "value": "route_a_2_chaussees",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Route \u00e0 2 chauss\u00e9es$niv4$"
+ }
+ },
+ {
+ "value": "route_empierree",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Route empierr\u00e9e$niv4$"
+ }
+ },
+ {
+ "value": "type_autoroutier",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Type autoroutier$niv4$"
+ }
+ }
+ ]
+ },
+ {
+ "keyType": "name-pgr",
+ "key": "cpx_classement_administratif",
+ "availableConstraintType": [
+ "banned",
+ "prefer",
+ "avoid"
+ ],
+ "availableValues": [
+ {
+ "value": "vide",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$$niv4$"
+ }
+ },
+ {
+ "value": "autoroute",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "like",
+ "value": "$niv4$%Autoroute%$niv4$"
+ }
+ },
+ {
+ "value": "nationale",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Nationale$niv4$"
+ }
+ },
+ {
+ "value": "departementale",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$D\u00e9partementale$niv4$"
+ }
+ },
+ {
+ "value": "voie_communale",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Voie communale$niv4$"
+ }
+ },
+ {
+ "value": "chemin_rural",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Chemin rural$niv4$"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "isochrone",
+ "parameters": [
+ {
+ "id": "resource",
+ "values": [
+ "bduni-idf-smartpgr"
+ ]
+ },
+ {
+ "id": "point",
+ "values": {
+ "bbox": "1.7,48.4,3.3,49.1",
+ "projection": "EPSG:4326"
+ }
+ },
+ {
+ "id": "costType",
+ "defaultValueContent": "time",
+ "values": [
+ "time",
+ "distance"
+ ]
+ },
+ {
+ "id": "costValue",
+ "values": {
+ "min": 1
+ }
+ },
+ {
+ "id": "profile",
+ "defaultValueContent": "car",
+ "values": [
+ "car",
+ "pedestrian"
+ ]
+ },
+ {
+ "id": "direction",
+ "defaultValueContent": "departure",
+ "values": [
+ "departure",
+ "arrival"
+ ]
+ },
+ {
+ "id": "projection",
+ "defaultValueContent": "EPSG:4326",
+ "values": [
+ "EPSG:4326",
+ "EPSG:2154",
+ "EPSG:4559",
+ "EPSG:2972",
+ "EPSG:2975",
+ "EPSG:4471",
+ "EPSG:3857"
+ ]
+ },
+ {
+ "id": "geometryFormat",
+ "defaultValueContent": "geojson",
+ "values": [
+ "geojson",
+ "polyline"
+ ]
+ },
+ {
+ "id": "timeUnit",
+ "defaultValueContent": "second",
+ "values": [
+ "hour",
+ "minute",
+ "second"
+ ]
+ },
+ {
+ "id": "distanceUnit",
+ "defaultValueContent": "meter",
+ "values": [
+ "meter",
+ "kilometer"
+ ]
+ },
+ {
+ "id": "constraints",
+ "values": [
+ {
+ "keyType": "name-pgr",
+ "key": "wayType",
+ "availableConstraintType": [
+ "banned"
+ ],
+ "availableValues": [
+ {
+ "value": "autoroute",
+ "field": "acces_vehicule_leger",
+ "condition": {
+ "type": "equal",
+ "value": "$niv3$A p\u00e9age$niv3$"
+ }
+ },
+ {
+ "value": "tunnel",
+ "field": "position_par_rapport_au_sol",
+ "condition": {
+ "type": "less",
+ "value": "0"
+ }
+ },
+ {
+ "value": "pont",
+ "field": "position_par_rapport_au_sol",
+ "condition": {
+ "type": "greater",
+ "value": "0"
+ }
+ }
+ ]
+ },
+ {
+ "keyType": "numerical-pgr",
+ "key": "LARGEUR",
+ "availableConstraintType": [
+ "banned"
+ ],
+ "field": "largeur_de_chaussee"
+ },
+ {
+ "keyType": "numerical-pgr",
+ "key": "IMPORTANCE",
+ "availableConstraintType": [
+ "banned"
+ ],
+ "field": "importance"
+ },
+ {
+ "keyType": "name-pgr",
+ "key": "RESTR_MAT",
+ "availableConstraintType": [
+ "banned"
+ ],
+ "availableValues": [
+ {
+ "value": "vrai",
+ "field": "matieres_dangereuses_interdites",
+ "condition": {
+ "type": "equal",
+ "value": "true"
+ }
+ },
+ {
+ "value": "faux",
+ "field": "matieres_dangereuses_interdites",
+ "condition": {
+ "type": "equal",
+ "value": "false"
+ }
+ }
+ ]
+ },
+ {
+ "keyType": "name-pgr",
+ "key": "NATURE",
+ "availableConstraintType": [
+ "banned"
+ ],
+ "availableValues": [
+ {
+ "value": "sentier",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Sentier$niv4$"
+ }
+ },
+ {
+ "value": "bac_ou_liaison_maritime",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Bac ou liaison maritime$niv4$"
+ }
+ },
+ {
+ "value": "bretelle",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Bretelle$niv4$"
+ }
+ },
+ {
+ "value": "chemin",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Chemin$niv4$"
+ }
+ },
+ {
+ "value": "escalier",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Escalier$niv4$"
+ }
+ },
+ {
+ "value": "piste_cyclable",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Piste cyclable$niv4$"
+ }
+ },
+ {
+ "value": "rond-point",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Rond-point$niv4$"
+ }
+ },
+ {
+ "value": "route_a_1_chaussee",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Route \u00e0 1 chauss\u00e9e$niv4$"
+ }
+ },
+ {
+ "value": "route_a_2_chaussees",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Route \u00e0 2 chauss\u00e9es$niv4$"
+ }
+ },
+ {
+ "value": "route_empierree",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Route empierr\u00e9e$niv4$"
+ }
+ },
+ {
+ "value": "type_autoroutier",
+ "field": "nature",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$Type autoroutier$niv4$"
+ }
+ }
+ ]
+ },
+ {
+ "keyType": "name-pgr",
+ "key": "CL_ADMIN",
+ "availableConstraintType": [
+ "banned"
+ ],
+ "availableValues": [
+ {
+ "value": "vide",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "equal",
+ "value": "$niv4$$niv4$"
+ }
+ },
+ {
+ "value": "autoroute",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "like",
+ "value": "$niv3$%Autoroute%$niv3$"
+ }
+ },
+ {
+ "value": "nationale",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "equal",
+ "value": "$niv3$Nationale$niv3$"
+ }
+ },
+ {
+ "value": "departementale",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "equal",
+ "value": "$niv3$D\u00e9partementale$niv3$"
+ }
+ },
+ {
+ "value": "voie_communale",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "equal",
+ "value": "$niv3$Voie communale$niv3$"
+ }
+ },
+ {
+ "value": "chemin_rural",
+ "field": "cpx_classement_administratif",
+ "condition": {
+ "type": "equal",
+ "value": "$niv3$Chemin rural$niv3$"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
diff --git a/documentation/configuration/resources/valhalla.resource b/documentation/configuration/resources/valhalla.resource
new file mode 100644
index 0000000..ee66b77
--- /dev/null
+++ b/documentation/configuration/resources/valhalla.resource
@@ -0,0 +1,229 @@
+"resource": {
+ "id": "bdtopo-valhalla",
+ "type": "valhalla",
+ "description": "Données BDUNI v2.",
+ "sources": [
+ "bdtopo-auto-valhalla",
+ ],
+ "availableOperations":[
+ {
+ "id": "route",
+ "parameters": [
+ {
+ "id": "resource",
+ "values": [
+ "bdtopo-valhalla"
+ ]
+ },
+ {
+ "id": "start",
+ "values": {
+ "bbox": "-180,-90,180,90",
+ "projection": "EPSG:4326"
+ }
+ },
+ {
+ "id": "end",
+ "values": {
+ "bbox": "-180,-90,180,90",
+ "projection": "EPSG:4326"
+ }
+ },
+ {
+ "id": "profile",
+ "defaultValueContent": "car",
+ "values": [
+ "car",
+ "pedestrian"
+ ]
+ },
+ {
+ "id": "optimization",
+ "defaultValueContent": "fastest",
+ "values": [
+ "fastest",
+ "shortest"
+ ]
+ },
+ {
+ "id": "intermediates",
+ "values": {
+ "bbox": "-180,-90,180,90",
+ "projection": "EPSG:4326"
+ }
+ },
+ {
+ "id": "getSteps",
+ "defaultValueContent": "true"
+ },
+ {
+ "id": "waysAttributes",
+ "values": [
+ "name"
+ ]
+ },
+ {
+ "id": "geometryFormat",
+ "defaultValueContent": "geojson",
+ "values": [
+ "geojson",
+ "polyline"
+ ]
+ },
+ {
+ "id": "bbox",
+ "defaultValueContent": "true"
+ },
+ {
+ "id": "projection",
+ "defaultValueContent": "EPSG:4326",
+ "values": [
+ "EPSG:4326",
+ "EPSG:2154"
+ ]
+ },
+ {
+ "id": "timeUnit",
+ "defaultValueContent": "minute",
+ "values": [
+ "hour",
+ "minute",
+ "second",
+ "standard"
+ ]
+ },
+ {
+ "id": "distanceUnit",
+ "defaultValueContent": "meter",
+ "values": [
+ "meter",
+ "kilometer"
+ ]
+ },
+ {
+ "id": "constraints",
+ "values": [
+ {
+ "keyType": "name-valhalla",
+ "key": "wayType",
+ "availableConstraintType": ["banned"],
+ "availableValues": [
+ {
+ "value": "autoroute",
+ "field": "toll"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "isochrone",
+ "parameters": [
+ {
+ "id": "resource",
+ "values": [
+ "bdtopo-pgr"
+ ]
+ },
+ {
+ "id": "point",
+ "values": {
+ "bbox": "-180,-90,180,90",
+ "projection": "EPSG:4326"
+ }
+ },
+ {
+ "id": "costType",
+ "defaultValueContent": "time",
+ "values": [
+ "time",
+ "distance"
+ ]
+ },
+ {
+ "id": "costValue",
+ "values": {
+ "min": 100,
+ "max": 50000
+ }
+ },
+ {
+ "id": "profile",
+ "defaultValueContent": "car",
+ "values": [
+ "car",
+ "pedestrian"
+ ]
+ },
+ {
+ "id": "direction",
+ "defaultValueContent": "departure",
+ "values": [
+ "departure",
+ "arrival"
+ ]
+ },
+ {
+ "id": "constraints",
+ "values": [
+ {
+ "keyType": "name-pgr",
+ "key": "wayType",
+ "availableConstraintType": ["banned"],
+ "availableValues": [
+ {
+ "value": "autoroute",
+ "field": "acces_vehicule_leger",
+ "condition": {
+ "type": "equal",
+ "value": "$niv3$A péage$niv3$"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "projection",
+ "defaultValueContent": "EPSG:4326",
+ "values": [
+ "EPSG:4326",
+ "EPSG:2154",
+ "EPSG:4559",
+ "EPSG:2972",
+ "EPSG:2975",
+ "EPSG:4471",
+ "EPSG:3857"
+ ]
+ },
+ {
+ "id": "geometryFormat",
+ "defaultValueContent": "geojson",
+ "values": [
+ "geojson",
+ "polyline"
+ ]
+ },
+ {
+ "id": "timeUnit",
+ "defaultValueContent": "second",
+ "values": [
+ "hour",
+ "minute",
+ "second"
+ ]
+ },
+ {
+ "id": "distanceUnit",
+ "defaultValueContent": "meter",
+ "values": [
+ "meter",
+ "kilometer"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/documentation/configuration/service_model.yaml b/documentation/configuration/services/service_model.yaml
similarity index 100%
rename from documentation/configuration/service_model.yaml
rename to documentation/configuration/services/service_model.yaml
diff --git a/documentation/configuration/sources/osrm.source b/documentation/configuration/sources/osrm.source
new file mode 100644
index 0000000..b4d128b
--- /dev/null
+++ b/documentation/configuration/sources/osrm.source
@@ -0,0 +1,14 @@
+{
+ "id": "bduni-idf-car-fastest",
+ "description":"test osrm",
+ "type": "osrm",
+ "projection": "EPSG:4326",
+ "bbox": "1.7,48.4,3.3,49.1",
+ "storage": {
+ "file": "/home/docker/data/bduni-idf-car-fastest/bduni-idf-car-fastest.osrm"
+ },
+ "cost": {
+ "profile": "car",
+ "optimization": "fastest"
+ }
+}
diff --git a/documentation/configuration/sources/pgr.source b/documentation/configuration/sources/pgr.source
new file mode 100644
index 0000000..4c726e4
--- /dev/null
+++ b/documentation/configuration/sources/pgr.source
@@ -0,0 +1,200 @@
+{
+ "id": "bduni-idf-car-fastest-pgr",
+ "description":"test pgr",
+ "type": "pgr",
+ "projection": "EPSG:4326",
+ "bbox": "1.7,48.4,3.3,49.1",
+ "storage": {
+ "base": {
+ "dbConfig": "/home/docker/data/output_base.json",
+ "schema": "public",
+ "attributes": [
+ {
+ "key": "name",
+ "column": "way_names",
+ "default": "false"
+ },
+ {
+ "key": "nom_1_gauche",
+ "column": "nom_1_gauche",
+ "default": "true"
+ },
+ {
+ "key": "nom_1_droite",
+ "column": "nom_1_droite",
+ "default": "true"
+ },
+ {
+ "key": "cpx_numero",
+ "column": "cpx_numero",
+ "default": "true"
+ },
+ {
+ "key": "cpx_toponyme_route_nommee",
+ "column": "cpx_toponyme_route_nommee",
+ "default": "true"
+ },
+ {
+ "key": "cleabs",
+ "column": "cleabs",
+ "default": "false"
+ },
+ {
+ "key": "nature",
+ "column": "nature",
+ "default": "false"
+ },
+ {
+ "key": "importance",
+ "column": "importance",
+ "default": "false"
+ },
+ {
+ "key": "position_par_rapport_au_sol",
+ "column": "position_par_rapport_au_sol",
+ "default": "false"
+ },
+ {
+ "key": "nombre_de_voies",
+ "column": "nombre_de_voies",
+ "default": "false"
+ },
+ {
+ "key": "largeur_de_chaussee",
+ "column": "largeur_de_chaussee",
+ "default": "false"
+ },
+ {
+ "key": "itineraire_vert",
+ "column": "itineraire_vert",
+ "default": "false"
+ },
+ {
+ "key": "sens_de_circulation",
+ "column": "sens_de_circulation",
+ "default": "false"
+ },
+ {
+ "key": "bande_cyclable",
+ "column": "bande_cyclable",
+ "default": "false"
+ },
+ {
+ "key": "reserve_aux_bus",
+ "column": "reserve_aux_bus",
+ "default": "false"
+ },
+ {
+ "key": "urbain",
+ "column": "urbain",
+ "default": "false"
+ },
+ {
+ "key": "vitesse_moyenne_vl",
+ "column": "vitesse_moyenne_vl",
+ "default": "false"
+ },
+ {
+ "key": "acces_vehicule_leger",
+ "column": "acces_vehicule_leger",
+ "default": "false"
+ },
+ {
+ "key": "acces_pieton",
+ "column": "acces_pieton",
+ "default": "false"
+ },
+ {
+ "key": "nature_de_la_restriction",
+ "column": "nature_de_la_restriction",
+ "default": "false"
+ },
+ {
+ "key": "restriction_de_hauteur",
+ "column": "restriction_de_hauteur",
+ "default": "false"
+ },
+ {
+ "key": "restriction_de_poids_total",
+ "column": "restriction_de_poids_total",
+ "default": "false"
+ },
+ {
+ "key": "restriction_de_poids_par_essieu",
+ "column": "restriction_de_poids_par_essieu",
+ "default": "false"
+ },
+ {
+ "key": "restriction_de_largeur",
+ "column": "restriction_de_largeur",
+ "default": "false"
+ },
+ {
+ "key": "restriction_de_longueur",
+ "column": "restriction_de_longueur",
+ "default": "false"
+ },
+ {
+ "key": "matieres_dangereuses_interdites",
+ "column": "matieres_dangereuses_interdites",
+ "default": "false"
+ },
+ {
+ "key": "insee_commune_gauche",
+ "column": "insee_commune_gauche",
+ "default": "false"
+ },
+ {
+ "key": "insee_commune_droite",
+ "column": "insee_commune_droite",
+ "default": "false"
+ },
+ {
+ "key": "cpx_numero_route_europeenne",
+ "column": "cpx_numero_route_europeenne",
+ "default": "false"
+ },
+ {
+ "key": "cpx_classement_administratif",
+ "column": "cpx_classement_administratif",
+ "default": "false"
+ },
+ {
+ "key": "cpx_gestionnaire",
+ "column": "cpx_gestionnaire",
+ "default": "false"
+ }
+ ]
+ }
+ },
+ "costs": [
+ {
+ "profile": "car",
+ "optimization": "fastest",
+ "costType": "time",
+ "costColumn": "cost_s_car",
+ "rcostColumn": "reverse_cost_s_car"
+ },
+ {
+ "profile": "car",
+ "optimization": "shortest",
+ "costType": "distance",
+ "costColumn": "cost_m_car",
+ "rcostColumn": "reverse_cost_m_car"
+ },
+ {
+ "profile": "pedestrian",
+ "optimization": "fastest",
+ "costType": "time",
+ "costColumn": "cost_s_pedestrian",
+ "rcostColumn": "reverse_cost_s_pedestrian"
+ },
+ {
+ "profile": "pedestrian",
+ "optimization": "shortest",
+ "costType": "distance",
+ "costColumn": "cost_m_pedestrian",
+ "rcostColumn": "reverse_cost_m_pedestrian"
+ }
+ ]
+}
diff --git a/documentation/configuration/sources/pgrSource.json b/documentation/configuration/sources/pgrSource.json
deleted file mode 100644
index 4a68be5..0000000
--- a/documentation/configuration/sources/pgrSource.json
+++ /dev/null
@@ -1,196 +0,0 @@
-{
- "id": "bduni-idf-car-fastest-pgr",
- "description":"test",
- "type": "pgr",
- "projection": "EPSG:4326",
- "bbox": "1.7,48.4,3.3,49.1",
- "storage": {
- "base": {
- "dbConfig": "/home/docker/data/output_base.json",
- "schema": "public",
- "attributes": [
- {
- "key": "name",
- "column": "way_names",
- "default": "false"
- },
- {
- "key": "nom_1_gauche",
- "column": "nom_1_gauche",
- "default": "true"
- },
- {
- "key": "nom_1_droite",
- "column": "nom_1_droite",
- "default": "true"
- },
- {
- "key": "cpx_numero",
- "column": "cpx_numero",
- "default": "true"
- },
- {
- "key": "cpx_toponyme_route_nommee",
- "column": "cpx_toponyme_route_nommee",
- "default": "true"
- },
- {
- "key": "cleabs",
- "column": "cleabs",
- "default": "false"
- },
- {
- "key": "nature",
- "column": "nature",
- "default": "false"
- },
- {
- "key": "importance",
- "column": "importance",
- "default": "false"
- },
- {
- "key": "position_par_rapport_au_sol",
- "column": "position_par_rapport_au_sol",
- "default": "false"
- },
- {
- "key": "nombre_de_voies",
- "column": "nombre_de_voies",
- "default": "false"
- },
- {
- "key": "largeur_de_chaussee",
- "column": "largeur_de_chaussee",
- "default": "false"
- },
- {
- "key": "itineraire_vert",
- "column": "itineraire_vert",
- "default": "false"
- },
- {
- "key": "sens_de_circulation",
- "column": "sens_de_circulation",
- "default": "false"
- },
- {
- "key": "bande_cyclable",
- "column": "bande_cyclable",
- "default": "false"
- },
- {
- "key": "reserve_aux_bus",
- "column": "reserve_aux_bus",
- "default": "false"
- },
- {
- "key": "urbain",
- "column": "urbain",
- "default": "false"
- },
- {
- "key": "vitesse_moyenne_vl",
- "column": "vitesse_moyenne_vl",
- "default": "false"
- },
- {
- "key": "acces_vehicule_leger",
- "column": "acces_vehicule_leger",
- "default": "false"
- },
- {
- "key": "acces_pieton",
- "column": "acces_pieton",
- "default": "false"
- },
- {
- "key": "nature_de_la_restriction",
- "column": "nature_de_la_restriction",
- "default": "false"
- },
- {
- "key": "restriction_de_hauteur",
- "column": "restriction_de_hauteur",
- "default": "false"
- },
- {
- "key": "restriction_de_poids_total",
- "column": "restriction_de_poids_total",
- "default": "false"
- },
- {
- "key": "restriction_de_poids_par_essieu",
- "column": "restriction_de_poids_par_essieu",
- "default": "false"
- },
- {
- "key": "restriction_de_largeur",
- "column": "restriction_de_largeur",
- "default": "false"
- },
- {
- "key": "restriction_de_longueur",
- "column": "restriction_de_longueur",
- "default": "false"
- },
- {
- "key": "matieres_dangereuses_interdites",
- "column": "matieres_dangereuses_interdites",
- "default": "false"
- },
- {
- "key": "insee_commune_gauche",
- "column": "insee_commune_gauche",
- "default": "false"
- },
- {
- "key": "insee_commune_droite",
- "column": "insee_commune_droite",
- "default": "false"
- },
- {
- "key": "cpx_numero_route_europeenne",
- "column": "cpx_numero_route_europeenne",
- "default": "false"
- },
- {
- "key": "cpx_classement_administratif",
- "column": "cpx_classement_administratif",
- "default": "false"
- },
- {
- "key": "cpx_gestionnaire",
- "column": "cpx_gestionnaire",
- "default": "false"
- }
- ]
- }
- },
- "costs": [
- {
- "profile": "car",
- "optimization": "fastest",
- "costColumn": "cost_s_car",
- "rcostColumn": "reverse_cost_s_car"
- },
- {
- "profile": "car",
- "optimization": "shortest",
- "costColumn": "cost_s_car",
- "rcostColumn": "reverse_cost_s_car"
- },
- {
- "profile": "pedestrian",
- "optimization": "fastest",
- "costColumn": "cost_s_car",
- "rcostColumn": "reverse_cost_s_car"
- },
- {
- "profile": "pedestrian",
- "optimization": "shortest",
- "costColumn": "cost_s_car",
- "rcostColumn": "reverse_cost_s_car"
- }
- ]
- }
diff --git a/documentation/configuration/sources/smartrouting.source b/documentation/configuration/sources/smartrouting.source
new file mode 100644
index 0000000..d7c6462
--- /dev/null
+++ b/documentation/configuration/sources/smartrouting.source
@@ -0,0 +1,10 @@
+{
+ "id": "bdtopo-smartrouting",
+ "type": "smartrouting",
+ "description":"test",
+ "projection": "EPSG:4326",
+ "bbox": "-90,-180,90,180",
+ "storage": {
+ "url": "https://wxs.ign.fr/calcul"
+ }
+}
diff --git a/documentation/configuration/sources/source_model.yaml b/documentation/configuration/sources/source_model.yaml
new file mode 100644
index 0000000..3b4358f
--- /dev/null
+++ b/documentation/configuration/sources/source_model.yaml
@@ -0,0 +1,43 @@
+# Description d'un fichier de source pour Road2
+
+# id de la source, utile pour la charger une seule fois dans Road2.
+"id":
+ type: string
+ required: true
+# Description de la source
+"description":
+ type: string
+ required: true
+# Type de la source
+"type":
+ type: string
+ required: true
+ enum: ["osrm","pgr","smartrouting","valhalla"]
+# Projection des données sources
+"projection":
+ type: string
+ required: true
+# Bbox des données dans la projection précisée
+"bbox":
+ type: string
+ required: true
+# Stockage de la source. Elle dépend de son type
+# TODO : finir de spécifier (en attendant, voir les exemples)
+"storage":
+ type: object
+ required: true
+# Coûts calculés sur la topologie précisée précedemment. On peut en avoir plusieurs.
+# TODO : finir de spécifier (en attendant, regarder les exemples de fichier)
+"cost":
+ type: object
+ required: true
+ properties:
+ # Chaque coût correspond à un profil
+ "profile":
+ type: string
+ required: true
+ # Chaque coût correspond à un profil
+ "optmization":
+ type: string
+ required: true
+
\ No newline at end of file
diff --git a/documentation/configuration/sources/valhalla.source b/documentation/configuration/sources/valhalla.source
new file mode 100644
index 0000000..62b86e1
--- /dev/null
+++ b/documentation/configuration/sources/valhalla.source
@@ -0,0 +1,32 @@
+{
+ "id": "bdtopo-auto-valhalla",
+ "description":"test valhalla",
+ "type": "valhalla",
+ "projection": "EPSG:4326",
+ "bbox": "1.7,48.4,3.3,49.1",
+ "storage": {
+ "tar": "/home/docker/data/bdtopo-valhalla-tiles.tar",
+ "dir": "/home/docker/data/bdtopo-valhalla-tiles/",
+ "config": "/home/docker/data/valhalla.json"
+ },
+ "costs": [
+ {
+ "profile": "car",
+ "optimization": "fastest",
+ "costType": "time",
+ "costing": "auto"
+ },
+ {
+ "profile": "car",
+ "optimization": "shortest",
+ "costType": "distance",
+ "costing": "auto_shorter"
+ },
+ {
+ "profile": "pedestrian",
+ "optimization": "shortest",
+ "costType": "distance",
+ "costing": "pedestrian"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/documentation/data/readme.md b/documentation/data/readme.md
index 25866a7..693262e 100644
--- a/documentation/data/readme.md
+++ b/documentation/data/readme.md
@@ -39,14 +39,21 @@ Il est possible d'utiliser des données au format d'OSRM. La seule contrainte es
### Données PGRouting
-Si des données au format PGRouting sont disponibles, il est possible de les utiliser avec Road2. A priori, il n'y a pas de fortes contraintes sur la version de PGRouting utilisée. La seule contrainte est au niveau logiciel. Il est nécessaire d'installer les procédures du projet GIT `pgrouting-procedures` afin que Road2 puisse requêter la base qui héberge les données et les fonctions de PGRouting.
+Si des données au format PGRouting sont disponibles, il est possible de les utiliser avec Road2. A priori, il n'y a pas de fortes contraintes sur la version de PGRouting utilisée. La seule contrainte est au niveau logiciel. Il est nécessaire d'installer les procédures du projet [GIT](https://github.com/IGNF/pgrouting-procedures) `pgrouting-procedures` afin que Road2 puisse requêter la base qui héberge les données et les fonctions de PGRouting.
+
+### Données Valhalla
+
+De la même manière, il est possible d'utiliser Road2 avec des données Valhalla.
### Les autres données
-Lorsque les données ne sont pas dans l'un des formats gérés par Road2, il reste possible de les convertir. Chacun peut le faire comme il le souhaite pour aboutir à l'un des formats cités précédemment. Cependant, si certains le veulent, un projet GIT a été mis en place, `route-graph-generator`, afin de convertir les données.
+Lorsque les données ne sont pas dans l'un des formats gérés par Road2, il reste possible de les convertir. Chacun peut le faire comme il le souhaite pour aboutir à l'un des formats cités précédemment. Cependant, si certains le veulent, un projet [GIT](https://github.com/IGNF/route-graph-generator) a été mis en place, `route-graph-generator`, afin de convertir les données.
+
+`route-graph-generator` est un ensemble de scripts python qui lisent des données dans différents formats et la convertissent dans un format pivot au sein d'une base de données. À partir de la base pivot, il est possible de convertir les données dans n'importe quel format géré par Road2. Ainsi, une même donnée d'entrée peut permettre des calculs par l'ensemble des moteurs.
+
+Les formats d'entrée possibles pour les scripts sont une base de données ou le format OSM.
-`route-graph-generator` est un ensemble de scripts python qui lisent des données dans une base postgreSQL et la convertissent dans un format pivot. À partir de la base pivot, il est possible de convertir les données dans n'importe quel format géré par Road2. Ainsi, une même donnée d'entrée peut permettre des calculs par l'ensemble des moteurs.
-Pour information, la conversion de données quelconques dans le format pivot est effectué par des scripts SQL. Pour le moment, il n'y en a qu'un seul qui permet de convertir des données IGN. Cependant, il est facile d'en ajouter de nouveaux pour partir d'un format différent et d'aboutir au format pivot. À partir de ce format pivot, tout les outils existent déjà pour aboutir aux formats gérés par Road2.
+Dans le cas d'une base, la conversion de données dans le format pivot est effectué par des scripts SQL. Pour le moment, il n'y en a qu'un seul qui permet de convertir des données IGN. Cependant, il est facile d'en ajouter de nouveaux pour partir d'un format différent et d'aboutir au format pivot. À partir de ce format pivot, tout les outils existent déjà pour aboutir aux formats gérés par Road2.
diff --git a/documentation/developers/concepts.md b/documentation/developers/concepts.md
index ee3e3fe..5d04b8b 100644
--- a/documentation/developers/concepts.md
+++ b/documentation/developers/concepts.md
@@ -38,15 +38,15 @@ C'est le second concept le plus important après l'indépendance des APIs et des
#### 1.2.1 Notion de graphe
-Il semble utile de passer la notion de *graphe*, selon Road2, pour expliquer ce qui suit. Quand on fait du calcul d'itinéraire, on utilise un moteur qui lit un *graphe* pour générer l'itinéraire. Or, **un *graphe* est une topologie, c'est-à-dire un ensemble de noeuds et d'arcs qui forment un tout navigable, sur laquelle il y a un unique coût**.
+Il semble utile de passer la notion de *graphe*, selon Road2, pour expliquer ce qui suit. Quand on fait du calcul d'itinéraire, on utilise un moteur qui lit un *graphe* pour générer l'itinéraire. Or, **un *graphe* est une topologie, c'est-à-dire un ensemble de noeuds et d'arcs qui forment un tout navigable, sur laquelle il y a au moins un coût**.
En effet, à chaque arc est associé au minimum un coût. Ce coût peut être la distance de l'arc ou le temps nécessaire pour le parcourir en voiture. Ainsi, chaque coût peut être vu comme le couple *profile/optimisation*, où *profile* est le moyen de transport (ex. voiture) et *optimisation* est le type de déplacement que l'on souhaite (ex. "plus rapide").
-Certains graphes peuvent avoir plusieurs coûts par topologie (ex. PGRouting) et d'autres non (ex. OSRM). Mais lors d'un calcul d'itinéraire, un seul coût est utilisé. On peut donc considérer que chaque graphe n'a qu'un seul coût.
+Certains graphes peuvent avoir plusieurs coûts par topologie (ex. PGRouting, Valhalla) et d'autres non (ex. OSRM). Mais lors d'un calcul d'itinéraire, un seul coût est utilisé.
#### 1.2.2 Notion de source
-Comme précisé juste au-dessus, pour avoir un itinéraire, il est nécessaire de faire appel à un moteur et à un graphe. La *source*, dans le langage conceptuel de Road2, est l'origine du calcul. **La source contient l'appel à un moteur sur un graphe précis pour obtenir le résultat d'un calcul**. C'est le lien entre l'application et le calcul réel, comme celui d'un itinéraire par exemple.
+Comme précisé juste au-dessus, pour avoir un itinéraire, il est nécessaire de faire appel à un moteur qui utilise un graphe. La *source*, dans le langage conceptuel de Road2, est l'origine du calcul. **La source contient l'appel à un moteur sur un graphe précis pour obtenir le résultat d'un calcul**. C'est le lien entre l'application et le calcul réel, comme celui d'un itinéraire par exemple.
Concrètement, une *source* regroupe deux entités :
- une classe Javascript qui fait le lien entre le reste du code et le moteur. Chaque moteur sera donc lié à Road2 par une classe fille de la classe `Source`. Cette classe fille devra contenir le code qui permet de demander au moteur un itinéraire ou autre chose (ex. isochrone, etc...). C'est ce qui concerne le développeur.
@@ -56,19 +56,27 @@ De tout ce qui vient d'être dit, on remarque qu'ajouter un moteur revient à aj
De plus, en théorie, une unique source peut faire appel à plusieurs moteurs pour rendre un résultat. L'essentiel est qu'une source ne renvoie qu'un résultat pour une seule requête.
+Au final, une source va prendre prendre en compte une instance de `Request`, faire le calcul et renvoyer une instance de `Response`. Cela permet à la source de rester indépendante du reste du code.
+
+Lorsque l’on fait du calcul d’itinéraire, il faut à minima une topologie et des coûts associés à cette topologie. Un coût correspond à un seul mode de déplacement et une seule optimisation (ex. le couple Voiture/plus court).
+
+Il se trouve qu'un graphe OSRM ne contient qu’un seul coût par dossier. Il permet donc de calculer des itinéraires uniquement sur un seul mode de déplacement et une seule optimisation. Par contre, PgRouting propose autant de colonnes de coût que l'on souhaite sur une même topologie. On retrouve le même regroupement de couples sur une topologie dans Valhalla.
+
#### 1.2.3 Notion de ressource
-Il est une contrainte technique qu’il serait préférable de masquer à l’utilisateur. Lorsque l’on fait du calcul d’itinéraire, il faut à minima une topologie et des coûts associés à cette topologie. Un coût correspond à un seul mode de déplacement et une seule optimisation(ex. Voiture/plus court).
+Cependant, pour l'utilisateur et pour l'administrateur du service, nous avons créé la notion de *ressource*. **Une ressource sera définie comme un ensemble de sources**. C'est elle qui fait le lien entre une requête et la bonne source permettant d'y répondre.
+
+À l'origine, l'objectif était de pouvoir associer plusieurs sources issues des mêmes données mais ayant un calcul de coût différent, et donc de donner à l’*utilisateur* une vue simplifiée des contraintes techniques. La ressource étant donc le *lien* entre la vue technique et la vue utilisateur. **Une autre manière de voir la ressource est de la voir comme un graphe qui a plusieurs coûts sur chaque arc**.
-Par exemple, un graphe OSRM ne contient qu’un seul coût. Il permet donc de calculer des itinéraires uniquement sur un seul mode de déplacement et une seule optimisation. De la même manière, une fonction PgRouting utilise une seule colonne de coût à la fois.
+Cela est utile pour OSRM par exemple. Dans ce cas, il faut donc être vigilant lors de la génération des données. Lorsque l’on fera une ressource, il est alors impératif d’utiliser une même topologie pour plusieurs calculs de coûts différents.
-Afin de masquer cette contrainte technique, on va regrouper plusieurs graphes issus des mêmes données topologiques mais ayant des coûts différents. Ce regroupement sera une *ressource*. **Une ressource sera alors définie comme un ensemble de sources**. En associant plusieurs sources issues des mêmes données mais ayant un calcul de coût différent, on peut donner à l’utilisateur une vue simplifiée des contraintes techniques. La ressource est donc le *lien* entre la vue technique et la vue utilisateur. **Une autre manière de voir la ressource est de la voir comme un graphe qui a plusieurs coûts sur chaque arc**.
+Mais depuis le début du projet, nous avons élargi les possibilités en permettant d'associer des sources qui n'ont pas la même topologie. Ainsi, aujourd'hui, une ressource n'est qu'un regroupement de sources. Il peut n'y en avoir qu'une. C'est souvent le cas pour PGRouting.
-Il faudra donc être vigilant lors de la génération des données. Lorsque l’on fera une ressource, il sera impératif d’utiliser une même topologie pour plusieurs calculs de coûts différents. Cela peut d'ailleurs avoir un impact sur les contraintes, comme les filtres. En effet, les contraintes sont appliquées au niveau de la ressource et non d’une source. C’est un choix qui permet de simplifier la configuration.
+Pour l'*administrateur*, une instance de Road2 doit pouvoir gérer plusieurs ressources. Une ressource sera notamment configurable par un fichier. Le serveur lira l’ensemble des fichiers contenus dans un dossier indiqué par la configuration générale.
-De plus, une instance de Road2 doit pouvoir gérer plusieurs ressources. Une ressource sera notamment configurable par un fichier. Le serveur lira l’ensemble des fichiers contenus dans un dossier indiqué par la configuration générale.
+Il est à noter que tout cela peut d'ailleurs avoir un impact sur les contraintes, comme les filtres. En effet, les contraintes sont appliquées au niveau de la ressource et non d’une source. C’est un choix qui permet de simplifier la configuration.
-Enfin, Road2 est codé pour qu'il soit facile d'ajouter de nouveaux types de ressources et de sources indépendamment. Il est donc possible de créer différents types de source et de les associer au sein de divers types de ressources.
+Enfin, précisons que Road2 est codé pour qu'il soit facile d'ajouter de nouveaux types de ressources et de sources indépendamment. Il est donc possible de créer différents types de source et de les associer au sein de divers types de ressources.
### 1.3 Les opérations
diff --git a/documentation/developers/readme.md b/documentation/developers/readme.md
index 088204c..2db5a2c 100644
--- a/documentation/developers/readme.md
+++ b/documentation/developers/readme.md
@@ -16,7 +16,7 @@ L'ensemble des fonctionnalités sont répertoriées à [part](./functionnalities
## Participer aux développements
-Les participations à ce projet sont encouragées. L'ajout de moteurs ou d'API, bien évidemment. Mais toutes autres fonctionnalités sont les bienvenues.
+Les participations à ce projet sont encouragées. L'ajout de moteurs ou d'API, bien évidemment. Mais toutes autres fonctionnalités sont les bienvenues. Encore, une fois, il vous est demandé de réaliser vos développements en partant de la branche *develop*.
### Prise en main du projet
diff --git a/readme.md b/readme.md
index 627a1c1..05ca3ae 100644
--- a/readme.md
+++ b/readme.md
@@ -67,13 +67,13 @@ Pour une discussion détaillée sur les données attendues, on pourra se référ
### Configuration
-Afin que le serveur fonctionne, il est nécessaire de le [configurer](./documentation/configuration/readme.md). Il s'agit de créer une arborescence de quelques fichiers JSON, au minimum quatre, permettant l'instanciation du serveur avec des ressources.
+Afin que le serveur fonctionne, il est nécessaire de le [configurer](./documentation/configuration/readme.md). Il s'agit de créer une arborescence de quelques fichiers JSON permettant l'instanciation du serveur avec des ressources.
### Lancement
Une fois configuré, il est possible de lancer une instance de Road2 avec la commande:
```
-node ${road2}/src/js/road2.js --ROAD2_CONF_FILE=${configuration}/server.json
+node ${road2}/src/js/road2.js --ROAD2_CONF_FILE=${configuration}/administration.json
```
### Pour plus de détails
@@ -82,11 +82,13 @@ On trouvera dans le dossier [docker/distrubutions](./docker/distributions) diff
## Participer aux développements
+Les participations à ce projet sont encouragées. Il vous est demandé de réaliser vos développements en partant de la branche *develop*.
+
On trouvera une documentation dédiée aux développeurs [ici](./documentation/developers/readme.md). Elle indique les concepts utiles pour effectuer des développements sur Road2.
Pour en savoir plus sur notre roadmap, vous pouvez regarder ce [document](./documentation/developers/roadmap.md).
-De plus, il est possible d'utiliser ce [docker-compose](./docker/dev/readme.md) pour avoir un environnement de développement incluant la construction des binaires, des modules et la génération des données.
+Enfin, il est possible d'utiliser ce [docker-compose](./docker/dev/readme.md) pour avoir un environnement de développement incluant la construction des binaires, des modules et la génération des données.
## Utilisation en production
From f3d01f48308b390c27c48249c6f434a95daf5fcb Mon Sep 17 00:00:00 2001
From: Loic
Date: Thu, 17 Nov 2022 18:15:51 +0100
Subject: [PATCH 17/93] fix des bbox
---
.../apis/simple/1.0.0/getCapabilities_example.yaml | 6 +++---
documentation/configuration/resources/osrm.resource | 8 ++++----
documentation/configuration/sources/pgr.source | 2 +-
documentation/configuration/sources/smartrouting.source | 2 +-
documentation/configuration/sources/valhalla.source | 2 +-
.../mocha/resources/integrationOsrmResource.js | 2 +-
.../integration/mocha/resources/integrationPgrResource.js | 2 +-
.../mocha/resources/integrationResourceManager.js | 8 ++++----
.../mocha/resources/integrationSmartPgrResource.js | 2 +-
.../mocha/resources/integrationValhallaResource.js | 2 +-
test/integration/mocha/sources/integrationOsrmSource.js | 2 +-
test/integration/mocha/sources/integrationPgrSource.js | 2 +-
.../integration/mocha/sources/integrationSourceManager.js | 6 +++---
.../mocha/sources/integrationValhallaSource.js | 2 +-
.../resources/topology/correctOSMTopology.json | 2 +-
.../resources/topology/incorrectOSMTopology.json | 2 +-
test/unit/mocha/config/resources/corse.resource | 8 ++++----
test/unit/mocha/topology/testsTopology.js | 2 +-
18 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/documentation/apis/simple/1.0.0/getCapabilities_example.yaml b/documentation/apis/simple/1.0.0/getCapabilities_example.yaml
index 7b57e9a..053392b 100644
--- a/documentation/apis/simple/1.0.0/getCapabilities_example.yaml
+++ b/documentation/apis/simple/1.0.0/getCapabilities_example.yaml
@@ -266,15 +266,15 @@ getCapabilities:
values: {"bduni"}
- id: "start"
values:
- bbox: "-90,-180,90,180"
+ bbox: "-180,-90,180,90"
projection: "EPSG:4326"
- id: "end"
values:
- bbox: "-90,-180,90,180"
+ bbox: "-180,-90,180,90"
projection: "EPSG:4326"
- id: "intermediates"
values:
- bbox: "-90,-180,90,180"
+ bbox: "-180,-90,180,90"
projection: "EPSG:4326"
- id: "profile"
default: "car"
diff --git a/documentation/configuration/resources/osrm.resource b/documentation/configuration/resources/osrm.resource
index a92cd82..7620497 100644
--- a/documentation/configuration/resources/osrm.resource
+++ b/documentation/configuration/resources/osrm.resource
@@ -20,14 +20,14 @@
{
"id": "start",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
{
"id": "end",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
@@ -48,7 +48,7 @@
{
"id": "intermediates",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
@@ -138,7 +138,7 @@
{
"id": "coordinates",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
diff --git a/documentation/configuration/sources/pgr.source b/documentation/configuration/sources/pgr.source
index 4c726e4..c1f0ed6 100644
--- a/documentation/configuration/sources/pgr.source
+++ b/documentation/configuration/sources/pgr.source
@@ -1,5 +1,5 @@
{
- "id": "bduni-idf-car-fastest-pgr",
+ "id": "bduni-pgr",
"description":"test pgr",
"type": "pgr",
"projection": "EPSG:4326",
diff --git a/documentation/configuration/sources/smartrouting.source b/documentation/configuration/sources/smartrouting.source
index d7c6462..3bdee18 100644
--- a/documentation/configuration/sources/smartrouting.source
+++ b/documentation/configuration/sources/smartrouting.source
@@ -3,7 +3,7 @@
"type": "smartrouting",
"description":"test",
"projection": "EPSG:4326",
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"storage": {
"url": "https://wxs.ign.fr/calcul"
}
diff --git a/documentation/configuration/sources/valhalla.source b/documentation/configuration/sources/valhalla.source
index 62b86e1..a9d959a 100644
--- a/documentation/configuration/sources/valhalla.source
+++ b/documentation/configuration/sources/valhalla.source
@@ -1,5 +1,5 @@
{
- "id": "bdtopo-auto-valhalla",
+ "id": "bdtopo-valhalla",
"description":"test valhalla",
"type": "valhalla",
"projection": "EPSG:4326",
diff --git a/test/integration/mocha/resources/integrationOsrmResource.js b/test/integration/mocha/resources/integrationOsrmResource.js
index afd8824..ba8123d 100644
--- a/test/integration/mocha/resources/integrationOsrmResource.js
+++ b/test/integration/mocha/resources/integrationOsrmResource.js
@@ -46,7 +46,7 @@ describe('Test de la classe OsrmResource', function() {
],
"defaultSourceId": "corse-car-fastest",
- "boundingBox": "-90,-180,90,180",
+ "boundingBox": "-180,-90,180,90",
"defaultProjection": "EPSG:4326",
"availableProjections": ["EPSG:4326","EPSG:2154"]
}
diff --git a/test/integration/mocha/resources/integrationPgrResource.js b/test/integration/mocha/resources/integrationPgrResource.js
index 37ddd16..fdc3cde 100644
--- a/test/integration/mocha/resources/integrationPgrResource.js
+++ b/test/integration/mocha/resources/integrationPgrResource.js
@@ -48,7 +48,7 @@ describe('Test de la classe PgrResource', function() {
],
"defaultSourceId": "test-car-fastest",
- "boundingBox": "-90,-180,90,180",
+ "boundingBox": "-180,-90,180,90",
"defaultProjection": "EPSG:4326",
"availableProjections": ["EPSG:4326","EPSG:2154"]
}
diff --git a/test/integration/mocha/resources/integrationResourceManager.js b/test/integration/mocha/resources/integrationResourceManager.js
index 711034e..6c0f930 100644
--- a/test/integration/mocha/resources/integrationResourceManager.js
+++ b/test/integration/mocha/resources/integrationResourceManager.js
@@ -42,7 +42,7 @@ describe('Test de la classe ResourceManager', function() {
"file": "/home/docker/internal/corse-latest.osm.pbf"
},
"projection": "EPSG:4326",
- "bbox": "-90,-180,90,180"
+ "bbox": "-180,-90,180,90"
},
"sources": [
{
@@ -75,14 +75,14 @@ describe('Test de la classe ResourceManager', function() {
{
"id": "start",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
{
"id": "end",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
@@ -103,7 +103,7 @@ describe('Test de la classe ResourceManager', function() {
{
"id": "intermediates",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
diff --git a/test/integration/mocha/resources/integrationSmartPgrResource.js b/test/integration/mocha/resources/integrationSmartPgrResource.js
index c9c1467..ab5b8ae 100644
--- a/test/integration/mocha/resources/integrationSmartPgrResource.js
+++ b/test/integration/mocha/resources/integrationSmartPgrResource.js
@@ -56,7 +56,7 @@ describe('Test de la classe SmartpgrResource', function() {
],
"defaultSourceId": "test-car-fastest",
- "boundingBox": "-90,-180,90,180",
+ "boundingBox": "-180,-90,180,90",
"defaultProjection": "EPSG:4326",
"availableProjections": ["EPSG:4326","EPSG:2154"]
}
diff --git a/test/integration/mocha/resources/integrationValhallaResource.js b/test/integration/mocha/resources/integrationValhallaResource.js
index 56a2267..0f2dfce 100644
--- a/test/integration/mocha/resources/integrationValhallaResource.js
+++ b/test/integration/mocha/resources/integrationValhallaResource.js
@@ -54,7 +54,7 @@ describe('Test de la classe ValhallaResource', function() {
],
"defaultSourceId": "corse-auto-valhalla",
- "boundingBox": "-90,-180,90,180",
+ "boundingBox": "-180,-90,180,90",
"defaultProjection": "EPSG:4326",
"availableProjections": ["EPSG:4326","EPSG:2154"]
}
diff --git a/test/integration/mocha/sources/integrationOsrmSource.js b/test/integration/mocha/sources/integrationOsrmSource.js
index 7c8e886..a58073b 100644
--- a/test/integration/mocha/sources/integrationOsrmSource.js
+++ b/test/integration/mocha/sources/integrationOsrmSource.js
@@ -77,7 +77,7 @@ describe('Test de la classe osrmSource', function() {
"file": "/home/docker/internal/corse-latest.osm.pbf"
},
"projection": "EPSG:4326",
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
};
diff --git a/test/integration/mocha/sources/integrationPgrSource.js b/test/integration/mocha/sources/integrationPgrSource.js
index 4d71f57..b72f9e7 100644
--- a/test/integration/mocha/sources/integrationPgrSource.js
+++ b/test/integration/mocha/sources/integrationPgrSource.js
@@ -40,7 +40,7 @@ describe('Test de la classe pgrSource', function() {
"file": "/home/docker/internal/corse-latest.osm.pbf"
},
"projection": "EPSG:4326",
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"base": {connected: false, connect(){this.connected = true;}},
"defaultAttributesKeyTable": {length: 0}
diff --git a/test/integration/mocha/sources/integrationSourceManager.js b/test/integration/mocha/sources/integrationSourceManager.js
index 83a0123..a3dde9c 100644
--- a/test/integration/mocha/sources/integrationSourceManager.js
+++ b/test/integration/mocha/sources/integrationSourceManager.js
@@ -63,14 +63,14 @@ describe('Test de la classe SourceManager', function() {
{
"id": "start",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
{
"id": "end",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
@@ -91,7 +91,7 @@ describe('Test de la classe SourceManager', function() {
{
"id": "intermediates",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
diff --git a/test/integration/mocha/sources/integrationValhallaSource.js b/test/integration/mocha/sources/integrationValhallaSource.js
index 39d0d6a..1ac57df 100644
--- a/test/integration/mocha/sources/integrationValhallaSource.js
+++ b/test/integration/mocha/sources/integrationValhallaSource.js
@@ -64,7 +64,7 @@ describe('Test de la classe valhallaSource', function() {
"file": "/home/docker/data/corse-latest.osm.pbf"
},
"projection": "EPSG:4326",
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
};
diff --git a/test/integration/resources/topology/correctOSMTopology.json b/test/integration/resources/topology/correctOSMTopology.json
index 2f419ca..133bdfa 100644
--- a/test/integration/resources/topology/correctOSMTopology.json
+++ b/test/integration/resources/topology/correctOSMTopology.json
@@ -6,5 +6,5 @@
"file": "/home/docker/internal/corse-latest.osm.pbf"
},
"projection": "EPSG:4326",
- "bbox": "-90,-180,90,180"
+ "bbox": "-180,-90,180,90"
}
\ No newline at end of file
diff --git a/test/integration/resources/topology/incorrectOSMTopology.json b/test/integration/resources/topology/incorrectOSMTopology.json
index af42b00..8597726 100644
--- a/test/integration/resources/topology/incorrectOSMTopology.json
+++ b/test/integration/resources/topology/incorrectOSMTopology.json
@@ -5,5 +5,5 @@
"file": "/home/docker/internal/corse-latest.osm.pbf"
},
"projection": "EPSG:4326",
- "bbox": "-90,-180,90,180"
+ "bbox": "-180,-90,180,90"
}
\ No newline at end of file
diff --git a/test/unit/mocha/config/resources/corse.resource b/test/unit/mocha/config/resources/corse.resource
index 7e85160..f6e6da5 100644
--- a/test/unit/mocha/config/resources/corse.resource
+++ b/test/unit/mocha/config/resources/corse.resource
@@ -11,7 +11,7 @@
"file": "/home/docker/internal/corse-latest.osm.pbf"
},
"projection": "EPSG:4326",
- "bbox": "-90,-180,90,180"
+ "bbox": "-180,-90,180,90"
},
"sources": [
{
@@ -44,14 +44,14 @@
{
"id": "start",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
{
"id": "end",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
@@ -72,7 +72,7 @@
{
"id": "intermediates",
"values": {
- "bbox": "-90,-180,90,180",
+ "bbox": "-180,-90,180,90",
"projection": "EPSG:4326"
}
},
diff --git a/test/unit/mocha/topology/testsTopology.js b/test/unit/mocha/topology/testsTopology.js
index a139640..e877eca 100644
--- a/test/unit/mocha/topology/testsTopology.js
+++ b/test/unit/mocha/topology/testsTopology.js
@@ -14,7 +14,7 @@ describe('Test de la classe Topology', function() {
"type": "osm",
"description": "Corse en version OSM",
"projection": "EPSG:4326",
- "bbox": "-90,-180,90,180"
+ "bbox": "-180,-90,180,90"
};
From a826e5ed64fe6185631fe73ec712b3c1a18aae00 Mon Sep 17 00:00:00 2001
From: Loic
Date: Wed, 23 Nov 2022 13:12:24 +0100
Subject: [PATCH 18/93] fix for valhalla sources
---
src/js/parameters/constraintParameter.js | 26 +++++++++++++++++--
src/js/parameters/parameterManager.js | 4 +--
src/js/sources/valhallaSource.js | 5 +++-
.../resources/integrationValhallaResource.js | 2 +-
.../sources/integrationValhallaSource.js | 4 +--
5 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/src/js/parameters/constraintParameter.js b/src/js/parameters/constraintParameter.js
index f7d360c..3cb9dbb 100644
--- a/src/js/parameters/constraintParameter.js
+++ b/src/js/parameters/constraintParameter.js
@@ -188,6 +188,21 @@ module.exports = class ConstraintParameter extends ResourceParameter {
}
+ } else if (this._values[i].keyType === "name-valhalla") {
+
+ this._verification[this._values[i].key.toLowerCase()].keyType = "name-valhalla";
+
+ currentKeyDescription.availableOperators = new Array();
+ currentKeyDescription.availableOperators.push("=");
+ currentKeyDescription.values = new Array();
+
+ for(let l = 0; l < this._values[i].availableValues.length; l++) {
+
+ this._verification[this._values[i].key.toLowerCase()][this._values[i].availableValues[l].value] = this._values[i].availableValues[l].field;
+ currentKeyDescription.values.push(this._values[i].availableValues[l].value);
+
+ }
+
} else {
return false;
}
@@ -304,9 +319,10 @@ module.exports = class ConstraintParameter extends ResourceParameter {
}
- if (this._verification[userJson.key.toLowerCase()].keyType === "name-pgr" || this._verification[userJson.key.toLowerCase()].keyType === "name-osrm") {
+ let nameTable = ["name-pgr","name-osrm","name-valhalla"];
+ if (nameTable.includes(this._verification[userJson.key.toLowerCase()].keyType)) {
- LOGGER.debug("keyType is name-pgr ror name-osrm");
+ LOGGER.debug("keyType is name-pgr ror name-osrm ror name-valhalla");
// Vérification de l'opérateur
if (!userJson.operator) {
@@ -468,6 +484,12 @@ module.exports = class ConstraintParameter extends ResourceParameter {
} else if (this._verification[userJson.key.toLowerCase()].keyType === "name-osrm") {
let field = this._verification[userJson.key.toLowerCase()][userJson.value];
+ if (userJson.constraintType === 'banned') {
+ constraint = new Constraint(userJson.constraintType, userJson.key.toLowerCase(), field, userJson.operator, userJson.value);
+ }
+ } else if (this._verification[userJson.key.toLowerCase()].keyType === "name-valhalla") {
+ let field = this._verification[userJson.key.toLowerCase()][userJson.value];
+
if (userJson.constraintType === 'banned') {
constraint = new Constraint(userJson.constraintType, userJson.key.toLowerCase(), field, userJson.operator, userJson.value);
}
diff --git a/src/js/parameters/parameterManager.js b/src/js/parameters/parameterManager.js
index 11bf941..c90626e 100644
--- a/src/js/parameters/parameterManager.js
+++ b/src/js/parameters/parameterManager.js
@@ -753,7 +753,7 @@ module.exports = class parameterManager {
LOGGER.error("Le type de la cle contrainte n'est pas precise");
return false;
} else {
- if ( !(["name-pgr", "numerical-pgr", "name-osrm"].includes(key.keyType)) ) {
+ if ( !(["name-pgr", "numerical-pgr", "name-osrm","name-valhalla"].includes(key.keyType)) ) {
LOGGER.error("Le type de la cle contrainte est invalide");
return false;
} else {
@@ -845,7 +845,7 @@ module.exports = class parameterManager {
}
}
- } else if (key.keyType === "name-osrm") {
+ } else if (key.keyType === "name-osrm" || key.keyType === "name-valhalla") {
if (!key.availableValues) {
LOGGER.error("Les valeurs de la cle contrainte ne sont pas precisees");
diff --git a/src/js/sources/valhallaSource.js b/src/js/sources/valhallaSource.js
index fa6c83d..1413082 100644
--- a/src/js/sources/valhallaSource.js
+++ b/src/js/sources/valhallaSource.js
@@ -47,8 +47,11 @@ module.exports = class valhallaSource extends Source {
// Initialisation des coûts
for (let i = 0; i < sourceJsonObject.costs.length; i++) {
- Object.defineProperty(this._costs, sourceJsonObject.costs[i].profile, { value: new Object(), configurable: true, enumerable: true, writable: true });
+ if (!this._costs[sourceJsonObject.costs[i].profile]) {
+ Object.defineProperty(this._costs, sourceJsonObject.costs[i].profile, { value: new Object(), configurable: true, enumerable: true, writable: true });
+ }
Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile], sourceJsonObject.costs[i].optimization, { value: new Object(), configurable: true, enumerable: true, writable: true });
+ Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile], sourceJsonObject.costs[i].costType, { value: new Object(), configurable: true, enumerable: true, writable: true });
Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].optimization], "costing", { value: sourceJsonObject.costs[i].costing, configurable: true, enumerable: true, writable: true });
Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].costType], "costing", { value: sourceJsonObject.costs[i].costing, configurable: true, enumerable: true, writable: true });
}
diff --git a/test/integration/mocha/resources/integrationValhallaResource.js b/test/integration/mocha/resources/integrationValhallaResource.js
index 0f2dfce..b248a59 100644
--- a/test/integration/mocha/resources/integrationValhallaResource.js
+++ b/test/integration/mocha/resources/integrationValhallaResource.js
@@ -43,7 +43,7 @@ describe('Test de la classe ValhallaResource', function() {
"configuration": {
"costing": "auto",
"storage": {
- "file": "/home/docker/config/costs_calculation.json"
+ "file": "/home/docker/config/costs_calculation_sample.json"
}
}
}
diff --git a/test/integration/mocha/sources/integrationValhallaSource.js b/test/integration/mocha/sources/integrationValhallaSource.js
index 1ac57df..fffb9d4 100644
--- a/test/integration/mocha/sources/integrationValhallaSource.js
+++ b/test/integration/mocha/sources/integrationValhallaSource.js
@@ -20,7 +20,7 @@ describe('Test de la classe valhallaSource', function() {
},
"/home/docker/config": {
"graph_bdtopo.lua": "",
- "costs_calculation.json": "",
+ "costs_calculation_sample.json": "",
},
"/home/docker/data/corse-latest-valhalla-tiles": {
}
@@ -49,7 +49,7 @@ describe('Test de la classe valhallaSource', function() {
"configuration": {
"costing": "auto",
"storage": {
- "file": "/home/docker/config/costs_calculation.json"
+ "file": "/home/docker/config/costs_calculation_sample.json"
}
}
}
From 0b9e28d519dc40588bc3ece1b10cd4f7b716ad26 Mon Sep 17 00:00:00 2001
From: Loic
Date: Fri, 25 Nov 2022 15:50:11 +0100
Subject: [PATCH 19/93] =?UTF-8?q?[tests]=20maj=20d'un=20test=20sur=20les?=
=?UTF-8?q?=20donn=C3=A9es?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docker/dev/readme.md | 1 +
test/functional/request/cucumber/data/bduni/common/normale.json | 2 +-
.../cucumber/features/req-simple-1.0.0-smartrouting.feature | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/docker/dev/readme.md b/docker/dev/readme.md
index 1d608bd..e6508f5 100644
--- a/docker/dev/readme.md
+++ b/docker/dev/readme.md
@@ -27,6 +27,7 @@ Si on utilise ces Dockerfile avec un VPN, on vérifiera que les configurations D
Si on utilise ces Dockerfile sur un réseau avec lequel il peut y avoir des problèmes d'IP, il sera utile de dédier à Docker une plage d'IP non utilisées:
- L'attribut `bip` du fichier ``/etc/docker/daemon.json` permet de préciser une plage d'IP.
- Si bip a été rempli, on veillera à ce que ces IP soient bien ajouter à l'interface `docker0`. La commande `sudo ip route add {plage_ip} dev docker0` permet de le faire.
+- On pourra aussi avoir besoin d'ajouter le réseau créer par ce compose : `sudo ip route add {plage_ip} dev br-{id_du_network} proto kernel scope link src {ip_gateway}` où l'id est obtenu en faisant un `docker network ls`.
Cette plage d'IP sera différente de celle attribuée à la stack Road2 lancée via docker-compose (eg. celui présent dans le fichier `.env`).
diff --git a/test/functional/request/cucumber/data/bduni/common/normale.json b/test/functional/request/cucumber/data/bduni/common/normale.json
index 12498d4..1be3405 100644
--- a/test/functional/request/cucumber/data/bduni/common/normale.json
+++ b/test/functional/request/cucumber/data/bduni/common/normale.json
@@ -1 +1 @@
-{"resource":"bduni-idf-osrm","resourceVersion":"01/07/2021","start":"2.342023,48.84574","end":"2.321707,48.845556","profile":"car","optimization":"fastest","geometry":{"coordinates":[[2.342023,48.84574],[2.341431,48.845918],[2.341353,48.845934],[2.341214,48.845967],[2.341154,48.84609],[2.340819,48.846724],[2.34079,48.846772],[2.340715,48.846878],[2.340634,48.846972],[2.340797,48.84727],[2.34084,48.847339],[2.340833,48.847402],[2.34083,48.847427],[2.340819,48.847451],[2.340804,48.847469],[2.340781,48.847489],[2.340753,48.847507],[2.340715,48.847523],[2.340611,48.847552],[2.340093,48.847664],[2.339948,48.84782],[2.339443,48.84842],[2.339191,48.848721],[2.339119,48.848803],[2.339051,48.848935],[2.339043,48.849092],[2.338961,48.849125],[2.338839,48.849169],[2.338772,48.849183],[2.338682,48.84919],[2.338575,48.849192],[2.33843,48.849181],[2.338139,48.849225],[2.337843,48.849261],[2.337594,48.849285],[2.337328,48.849298],[2.336388,48.849282],[2.335956,48.849274],[2.335676,48.849257],[2.335449,48.849239],[2.335242,48.849202],[2.3351,48.84917],[2.335014,48.849148],[2.334846,48.849116],[2.334587,48.849063],[2.334309,48.849013],[2.334105,48.848977],[2.333713,48.848897],[2.333197,48.848797],[2.332955,48.848754],[2.332766,48.848688],[2.332552,48.848625],[2.332473,48.848624],[2.332386,48.848613],[2.331662,48.84842],[2.331044,48.848247],[2.329567,48.847825],[2.328125,48.847397],[2.327933,48.847347],[2.327818,48.847315],[2.327442,48.847209],[2.32739,48.847207],[2.327336,48.84721],[2.327284,48.847225],[2.32717,48.847265],[2.326987,48.847076],[2.326868,48.84695],[2.326783,48.84687],[2.325614,48.845661],[2.325193,48.845231],[2.324544,48.844565],[2.324174,48.844181],[2.324099,48.844163],[2.324033,48.844145],[2.323799,48.8441],[2.323365,48.844036],[2.323193,48.844091],[2.322905,48.844184],[2.321285,48.844725],[2.320553,48.844967],[2.320121,48.845097],[2.320575,48.845222],[2.321707,48.845556]],"type":"LineString"},"crs":"EPSG:4326","distanceUnit":"meter","timeUnit":"minute","bbox":[2.320121,48.844036,2.342023,48.849298],"distance":2256.9,"duration":3.0349999999999997,"constraints":[],"portions":[{"start":"2.342023,48.84574","end":"2.321707,48.845556","distance":2256.9,"duration":3.0349999999999997,"bbox":[2.320121,48.844036,2.342023,48.849298],"steps":[{"geometry":{"coordinates":[[2.342023,48.84574],[2.341431,48.845918],[2.341353,48.845934],[2.341214,48.845967]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R ROYER-COLLARD","nom_1_droite":"R ROYER-COLLARD","cpx_numero":"","cpx_toponyme":""}},"distance":64.4,"duration":0.13},{"geometry":{"coordinates":[[2.341214,48.845967],[2.341154,48.84609],[2.340819,48.846724],[2.34079,48.846772],[2.340715,48.846878],[2.340634,48.846972]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R GAY-LUSSAC","nom_1_droite":"R GAY-LUSSAC","cpx_numero":"","cpx_toponyme":""}},"distance":119.8,"duration":0.18000000000000002},{"geometry":{"coordinates":[[2.340634,48.846972],[2.340797,48.84727],[2.34084,48.847339]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"PL EDMOND ROSTAND","nom_1_droite":"PL EDMOND ROSTAND","cpx_numero":"","cpx_toponyme":""}},"distance":43.5,"duration":0.06666666666666667},{"geometry":{"coordinates":[[2.34084,48.847339],[2.340833,48.847402],[2.34083,48.847427],[2.340819,48.847451],[2.340804,48.847469],[2.340781,48.847489],[2.340753,48.847507],[2.340715,48.847523],[2.340611,48.847552],[2.340093,48.847664]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"PL EDMOND ROSTAND","nom_1_droite":"PL EDMOND ROSTAND","cpx_numero":"","cpx_toponyme":""}},"distance":72,"duration":0.13666666666666666},{"geometry":{"coordinates":[[2.340093,48.847664],[2.339948,48.84782],[2.339443,48.84842],[2.339191,48.848721],[2.339119,48.848803],[2.339051,48.848935],[2.339043,48.849092]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE MEDICIS","nom_1_droite":"R DE MEDICIS","cpx_numero":"","cpx_toponyme":""}},"distance":178.4,"duration":0.20166666666666666},{"geometry":{"coordinates":[[2.339043,48.849092],[2.338961,48.849125],[2.338839,48.849169],[2.338772,48.849183],[2.338682,48.84919],[2.338575,48.849192],[2.33843,48.849181]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"PL PAUL CLAUDEL","nom_1_droite":"PL PAUL CLAUDEL","cpx_numero":"","cpx_toponyme":""}},"distance":47.5,"duration":0.07166666666666667},{"geometry":{"coordinates":[[2.33843,48.849181],[2.338139,48.849225],[2.337843,48.849261],[2.337594,48.849285],[2.337328,48.849298],[2.336388,48.849282],[2.335956,48.849274],[2.335676,48.849257],[2.335449,48.849239],[2.335242,48.849202],[2.3351,48.84917],[2.335014,48.849148],[2.334846,48.849116],[2.334587,48.849063],[2.334309,48.849013],[2.334105,48.848977],[2.333713,48.848897],[2.333197,48.848797],[2.332955,48.848754],[2.332766,48.848688],[2.332552,48.848625],[2.332473,48.848624],[2.332386,48.848613],[2.331662,48.84842],[2.331044,48.848247],[2.329567,48.847825],[2.328125,48.847397],[2.327933,48.847347],[2.327818,48.847315],[2.327442,48.847209],[2.32739,48.847207],[2.327336,48.84721],[2.327284,48.847225],[2.32717,48.847265]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE VAUGIRARD","nom_1_droite":"R DE VAUGIRARD","cpx_numero":"","cpx_toponyme":""}},"distance":870.6,"duration":1.1016666666666666},{"geometry":{"coordinates":[[2.32717,48.847265],[2.326987,48.847076],[2.326868,48.84695],[2.326783,48.84687],[2.325614,48.845661],[2.325193,48.845231],[2.324544,48.844565],[2.324174,48.844181]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE RENNES","nom_1_droite":"R DE RENNES","cpx_numero":"","cpx_toponyme":""}},"distance":407.1,"duration":0.5433333333333333},{"geometry":{"coordinates":[[2.324174,48.844181],[2.324099,48.844163],[2.324033,48.844145],[2.323799,48.8441],[2.323365,48.844036]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"PL DU 18 JUIN 1940","nom_1_droite":"PL DU 18 JUIN 1940","cpx_numero":"","cpx_toponyme":""}},"distance":61.5,"duration":0.08166666666666668},{"geometry":{"coordinates":[[2.323365,48.844036],[2.323193,48.844091],[2.322905,48.844184],[2.321285,48.844725],[2.320553,48.844967],[2.320121,48.845097]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"BD DU MONTPARNASSE","nom_1_droite":"BD DU MONTPARNASSE","cpx_numero":"","cpx_toponyme":""}},"distance":265.2,"duration":0.35333333333333333},{"geometry":{"coordinates":[[2.320121,48.845097],[2.320575,48.845222],[2.321707,48.845556]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE VAUGIRARD","nom_1_droite":"R DE VAUGIRARD","cpx_numero":"","cpx_toponyme":""}},"distance":126.8,"duration":0.16833333333333333},{"geometry":{"coordinates":[[2.321707,48.845556],[2.321707,48.845556]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE VAUGIRARD","nom_1_droite":"R DE VAUGIRARD","cpx_numero":"","cpx_toponyme":""}},"distance":0,"duration":0}]}]}
\ No newline at end of file
+{"resource":"bduni-idf-osrm","resourceVersion":"2022-11-24","start":"2.342023,48.84574","end":"2.321707,48.845556","profile":"car","optimization":"fastest","geometry":{"coordinates":[[2.342023,48.84574],[2.342245,48.845673],[2.342677,48.845592],[2.342952,48.846098],[2.343346,48.846797],[2.342813,48.84691],[2.342433,48.846991],[2.341951,48.847098],[2.34169,48.847155],[2.3412,48.847258],[2.34095,48.847314],[2.34084,48.847339],[2.340833,48.847402],[2.34083,48.847427],[2.340819,48.847451],[2.340804,48.847469],[2.340781,48.847489],[2.340753,48.847507],[2.340715,48.847523],[2.340611,48.847552],[2.340093,48.847664],[2.339948,48.84782],[2.339443,48.84842],[2.339191,48.848721],[2.339119,48.848803],[2.339051,48.848935],[2.339043,48.849092],[2.338961,48.849125],[2.338839,48.849169],[2.338772,48.849183],[2.338682,48.84919],[2.338575,48.849192],[2.33843,48.849181],[2.338139,48.849225],[2.337843,48.849261],[2.337594,48.849285],[2.337328,48.849298],[2.336388,48.849282],[2.335956,48.849274],[2.335676,48.849257],[2.335449,48.849239],[2.335242,48.849202],[2.3351,48.84917],[2.335014,48.849148],[2.334846,48.849116],[2.334587,48.849063],[2.334309,48.849013],[2.334105,48.848977],[2.333713,48.848897],[2.333197,48.848797],[2.332955,48.848754],[2.332766,48.848688],[2.332552,48.848625],[2.332473,48.848624],[2.332386,48.848613],[2.331662,48.84842],[2.331044,48.848247],[2.329567,48.847825],[2.328125,48.847397],[2.327933,48.847347],[2.327818,48.847315],[2.327442,48.847209],[2.32739,48.847207],[2.327336,48.84721],[2.327284,48.847225],[2.32717,48.847265],[2.326987,48.847076],[2.326868,48.84695],[2.326783,48.84687],[2.325614,48.845661],[2.325193,48.845231],[2.324544,48.844565],[2.324174,48.844181],[2.324099,48.844163],[2.324033,48.844145],[2.323799,48.8441],[2.323365,48.844036],[2.323193,48.844091],[2.322905,48.844184],[2.321285,48.844725],[2.320553,48.844967],[2.320121,48.845097],[2.320575,48.845222],[2.321707,48.845556]],"type":"LineString"},"crs":"EPSG:4326","distanceUnit":"meter","timeUnit":"minute","bbox":[2.320121,48.844036,2.343346,48.849298],"distance":2415.7,"duration":3.2216666666666667,"constraints":[],"portions":[{"start":"2.342023,48.84574","end":"2.321707,48.845556","distance":2415.7,"duration":3.2216666666666667,"bbox":[2.320121,48.844036,2.343346,48.849298],"steps":[{"geometry":{"coordinates":[[2.342023,48.84574],[2.342245,48.845673],[2.342677,48.845592]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R ROYER-COLLARD","nom_1_droite":"R ROYER-COLLARD","cpx_numero":"","cpx_toponyme":""}},"distance":50.8,"duration":0.075,"instruction":{"type":"depart"}},{"geometry":{"coordinates":[[2.342677,48.845592],[2.342952,48.846098],[2.343346,48.846797]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R SAINT-JACQUES","nom_1_droite":"R SAINT-JACQUES","cpx_numero":"","cpx_toponyme":""}},"distance":142.7,"duration":0.215,"instruction":{"type":"turn","modifier":"left"}},{"geometry":{"coordinates":[[2.343346,48.846797],[2.342813,48.84691],[2.342433,48.846991],[2.341951,48.847098],[2.34169,48.847155],[2.3412,48.847258],[2.34095,48.847314],[2.34084,48.847339]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R SOUFFLOT","nom_1_droite":"R SOUFFLOT","cpx_numero":"","cpx_toponyme":""}},"distance":193.1,"duration":0.25833333333333336,"instruction":{"type":"turn","modifier":"left"}},{"geometry":{"coordinates":[[2.34084,48.847339],[2.340833,48.847402],[2.34083,48.847427],[2.340819,48.847451],[2.340804,48.847469],[2.340781,48.847489],[2.340753,48.847507],[2.340715,48.847523],[2.340611,48.847552],[2.340093,48.847664]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"PL EDMOND ROSTAND","nom_1_droite":"PL EDMOND ROSTAND","cpx_numero":"","cpx_toponyme":""}},"distance":72,"duration":0.14,"instruction":{"type":"turn","modifier":"slight right"}},{"geometry":{"coordinates":[[2.340093,48.847664],[2.339948,48.84782],[2.339443,48.84842],[2.339191,48.848721],[2.339119,48.848803],[2.339051,48.848935],[2.339043,48.849092]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE MEDICIS","nom_1_droite":"R DE MEDICIS","cpx_numero":"","cpx_toponyme":""}},"distance":178.4,"duration":0.2033333333333333,"instruction":{"type":"new name","modifier":"right"}},{"geometry":{"coordinates":[[2.339043,48.849092],[2.338961,48.849125],[2.338839,48.849169],[2.338772,48.849183],[2.338682,48.84919],[2.338575,48.849192],[2.33843,48.849181]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"PL PAUL CLAUDEL","nom_1_droite":"PL PAUL CLAUDEL","cpx_numero":"","cpx_toponyme":""}},"distance":47.5,"duration":0.07,"instruction":{"type":"turn","modifier":"left"}},{"geometry":{"coordinates":[[2.33843,48.849181],[2.338139,48.849225],[2.337843,48.849261],[2.337594,48.849285],[2.337328,48.849298],[2.336388,48.849282],[2.335956,48.849274],[2.335676,48.849257],[2.335449,48.849239],[2.335242,48.849202],[2.3351,48.84917],[2.335014,48.849148],[2.334846,48.849116],[2.334587,48.849063],[2.334309,48.849013],[2.334105,48.848977],[2.333713,48.848897],[2.333197,48.848797],[2.332955,48.848754],[2.332766,48.848688],[2.332552,48.848625],[2.332473,48.848624],[2.332386,48.848613],[2.331662,48.84842],[2.331044,48.848247],[2.329567,48.847825],[2.328125,48.847397],[2.327933,48.847347],[2.327818,48.847315],[2.327442,48.847209],[2.32739,48.847207],[2.327336,48.84721],[2.327284,48.847225],[2.32717,48.847265]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE VAUGIRARD","nom_1_droite":"R DE VAUGIRARD","cpx_numero":"","cpx_toponyme":""}},"distance":870.6,"duration":1.1116666666666666,"instruction":{"type":"new name","modifier":"straight"}},{"geometry":{"coordinates":[[2.32717,48.847265],[2.326987,48.847076],[2.326868,48.84695],[2.326783,48.84687],[2.325614,48.845661],[2.325193,48.845231],[2.324544,48.844565],[2.324174,48.844181]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE RENNES","nom_1_droite":"R DE RENNES","cpx_numero":"","cpx_toponyme":""}},"distance":407.1,"duration":0.5433333333333333,"instruction":{"type":"turn","modifier":"left"}},{"geometry":{"coordinates":[[2.324174,48.844181],[2.324099,48.844163],[2.324033,48.844145],[2.323799,48.8441],[2.323365,48.844036]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"PL DU 18 JUIN 1940","nom_1_droite":"PL DU 18 JUIN 1940","cpx_numero":"","cpx_toponyme":""}},"distance":61.5,"duration":0.08,"instruction":{"type":"turn","modifier":"right"}},{"geometry":{"coordinates":[[2.323365,48.844036],[2.323193,48.844091],[2.322905,48.844184],[2.321285,48.844725],[2.320553,48.844967],[2.320121,48.845097]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"BD DU MONTPARNASSE","nom_1_droite":"BD DU MONTPARNASSE","cpx_numero":"","cpx_toponyme":""}},"distance":265.2,"duration":0.3549999999999999,"instruction":{"type":"turn","modifier":"slight right"}},{"geometry":{"coordinates":[[2.320121,48.845097],[2.320575,48.845222],[2.321707,48.845556]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE VAUGIRARD","nom_1_droite":"R DE VAUGIRARD","cpx_numero":"","cpx_toponyme":""}},"distance":126.8,"duration":0.16999999999999998,"instruction":{"type":"turn","modifier":"sharp right"}},{"geometry":{"coordinates":[[2.321707,48.845556],[2.321707,48.845556]],"type":"LineString"},"attributes":{"name":{"nom_1_gauche":"R DE VAUGIRARD","nom_1_droite":"R DE VAUGIRARD","cpx_numero":"","cpx_toponyme":""}},"distance":0,"duration":0,"instruction":{"type":"arrive"}}]}]}
\ No newline at end of file
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
index fb704ae..7a08241 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
@@ -52,7 +52,7 @@ Feature: Road2-SMARTROUTING
And the response should contain a complete and valid iso
And the response should contain an attribute "constraints.[0].key"
- Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource smartpgr avec appel à la source pgr
+ Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource smartpgr avec appel à la source smartrouting
Given an "GET" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone-smartpgr"
And with query parameters:
From 225b3af5184585d046c40af29147e05a9fec65f3 Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 28 Nov 2022 14:00:10 +0100
Subject: [PATCH 20/93] maj des submodules
---
docker/motors/pgrouting-procedures | 2 +-
docker/route-graph-generator | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docker/motors/pgrouting-procedures b/docker/motors/pgrouting-procedures
index 6178fb8..4336f8d 160000
--- a/docker/motors/pgrouting-procedures
+++ b/docker/motors/pgrouting-procedures
@@ -1 +1 @@
-Subproject commit 6178fb87383b55c4d0ba22a2305bf12168038e52
+Subproject commit 4336f8da74d76ed95971113f4d878525ca3ca2d5
diff --git a/docker/route-graph-generator b/docker/route-graph-generator
index 7fcbda6..602f543 160000
--- a/docker/route-graph-generator
+++ b/docker/route-graph-generator
@@ -1 +1 @@
-Subproject commit 7fcbda665e52a4ff61319ff1a1eb5b284b0127b7
+Subproject commit 602f5432ac37128b1a3069e195ad36b045d471e7
From ac08d5c17b2f5ec2e69c44b511c811ab9758a70a Mon Sep 17 00:00:00 2001
From: Loic
Date: Tue, 29 Nov 2022 13:27:33 +0100
Subject: [PATCH 21/93] [test] maj des tests de charge
---
docker/dev/docker-compose.yml | 1 +
docker/test/Dockerfile | 7 +-
docker/test/compose.env.example | 7 +-
docker/test/docker-compose.yml | 22 +-
docker/test/readme.md | 43 ++-
.../{road2_parameters_iso.ssv => isoPgr.ssv} | 0
.../user-files/resources/road2_parameters.ssv | 101 ------
.../road2_parameters_idf_pgr_wo_int.ssv | 323 ------------------
.../user-files/resources/routeOsrm.ssv | 101 ++++++
.../gatling/user-files/resources/routePgr.ssv | 101 ++++++
.../{road2_route.scala => dataOsm.scala} | 6 +-
.../{road2_iso.scala => isoPgr.scala} | 6 +-
...{road2_route_pgr.scala => routeOsrm.scala} | 8 +-
.../user-files/simulations/routePgr.scala | 23 ++
test/load/readme.md | 7 +-
15 files changed, 291 insertions(+), 465 deletions(-)
rename test/load/gatling/user-files/resources/{road2_parameters_iso.ssv => isoPgr.ssv} (100%)
delete mode 100644 test/load/gatling/user-files/resources/road2_parameters.ssv
delete mode 100644 test/load/gatling/user-files/resources/road2_parameters_idf_pgr_wo_int.ssv
create mode 100644 test/load/gatling/user-files/resources/routeOsrm.ssv
create mode 100644 test/load/gatling/user-files/resources/routePgr.ssv
rename test/load/gatling/user-files/simulations/{road2_route.scala => dataOsm.scala} (74%)
rename test/load/gatling/user-files/simulations/{road2_iso.scala => isoPgr.scala} (73%)
rename test/load/gatling/user-files/simulations/{road2_route_pgr.scala => routeOsrm.scala} (65%)
create mode 100644 test/load/gatling/user-files/simulations/routePgr.scala
diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml
index b0edc31..7def3fc 100644
--- a/docker/dev/docker-compose.yml
+++ b/docker/dev/docker-compose.yml
@@ -73,6 +73,7 @@ volumes:
networks:
iti-network:
+ # Nom utilisé ailleurs dans ce projet
name: iti-network
driver: bridge
ipam:
diff --git a/docker/test/Dockerfile b/docker/test/Dockerfile
index 52b48a6..f89c2ec 100644
--- a/docker/test/Dockerfile
+++ b/docker/test/Dockerfile
@@ -1,11 +1,8 @@
-FROM debian:buster-slim
+FROM r-base:latest
LABEL maintainer="IGN "
LABEL version="1.0"
-### MAJ et installation de R
-RUN apt -y update && apt install -y r-base
-
### Récupération des sources du script de génération des requêtes aléatoires
WORKDIR /home/docker
COPY test/load/random-route-generator ./
@@ -13,4 +10,4 @@ COPY test/load/random-iso-generator ./
VOLUME ["/home/docker/data"]
-CMD ["R", "-f", "/home/docker/routeGenerator.R", "--args", "/home/docker/data/road2_parameters.ssv", "100", "corse-osm", "8.61", "41.40", "9.52", "42.62"]
+CMD ["R", "-f", "/home/docker/routeGenerator.R", "--args", "/home/docker/data/road2_parameters.ssv", "100", "data-osm", "8.61", "41.40", "9.52", "42.62"]
diff --git a/docker/test/compose.env.example b/docker/test/compose.env.example
index a952ecd..2be6f08 100644
--- a/docker/test/compose.env.example
+++ b/docker/test/compose.env.example
@@ -1,8 +1,8 @@
# Exemple de fichier de variables d'environnements
-# Variables pour la génération de fichier aléatoire
+# Variables pour la génération de données aléatoires
nb_line=100
-resource=corse-osm
+resource=data-osm
xmin=8.61
ymin=41.40
xmax=9.52
@@ -10,4 +10,5 @@ ymax=42.62
# Variables pour gatling
gatling_results=/home/user/gatling/results
-gatling_user-files=/home/user/gatling/user-files
\ No newline at end of file
+gatling_user_files=/home/user/gatling/user-files
+gatling_scenario=routeOsrm
\ No newline at end of file
diff --git a/docker/test/docker-compose.yml b/docker/test/docker-compose.yml
index 1edb29a..ab9d2b4 100644
--- a/docker/test/docker-compose.yml
+++ b/docker/test/docker-compose.yml
@@ -1,16 +1,12 @@
version: "3.7"
services:
- load-road2-generation:
+ generate-load-data:
build:
context: ../..
dockerfile: ./docker/test/Dockerfile
- args:
- - dnsIP=${dns_ip}
- - dnsHost=${dns_host}
- - proxy=${proxy}
- image: load-road2-generation
- container_name: load-road2-generation-launch
+ image: generate-load-data
+ container_name: generate-load-data-launch
command: ["R", "-f", "/home/docker/routeGenerator.R", "--args", "/home/docker/data/road2_parameters.ssv", "${nb_line}", "${resource}", "${xmin}", "${ymin}", "${xmax}", "${ymax}"]
volumes:
- iti-load-data-volume:/home/docker/data
@@ -21,9 +17,15 @@ services:
volumes:
- iti-load-data-volume:/home/docker/data
- ${gatling_results}:/opt/gatling/results
- - ${gatling_user-files}:/opt/gatling/user-files
- command: "-s road2LoadTest"
+ - ${gatling_user_files}:/opt/gatling/user-files
+ command: ["-s", "${gatling_scenario}"]
volumes:
iti-load-data-volume:
- name: iti-load-data-volume
\ No newline at end of file
+ name: iti-load-data-volume
+
+networks:
+ default:
+ # Nom du réseau utilisé dans le docker-compose du dossier ../dev/
+ name: iti-network
+ external: true
\ No newline at end of file
diff --git a/docker/test/readme.md b/docker/test/readme.md
index a9b0644..6b476f8 100644
--- a/docker/test/readme.md
+++ b/docker/test/readme.md
@@ -1,4 +1,4 @@
-# Docker pour faire des tests de charge
+# Docker-compose pour faire des tests
# Construction et utilisation avec docker-compose
@@ -6,16 +6,47 @@
Pour utiliser `docker-compose`, il suffit de :
- installer `docker`.
-- se placer dans le dossier `/docker/load/` du projet Road2.
+- se placer dans le dossier `/docker/test/` du projet Road2.
- créer un fichier `.env` à côté du `docker-compose.yml` qui sera une copie adaptée du `compose.env.example`
## Construction des images
-Il possible d'utiliser les Dockerfiles de chaque projet pour builder les images unes par une. Mais cela peut se faire automatiquement via docker-compose.
+Il possible d'utiliser les Dockerfiles de chaque projet pour builder les images une par une. Mais cela peut se faire automatiquement via docker-compose.
Il suffit de lancer la commande `docker-compose build`.
-## Démarrage des services
+## Lancer des tests
-Pour lancer un service, il suffit d'exécuter la commande `docker-compose up $service` avec :
-- `$service=load-road2` pour lancer les tests.
+### Tests de charge avec gatling
+
+Après avoir rempli le `.env` en pointant, par exemple, sur le `user-files` de ce [dépôt](../../test/load/gatling/user-files) et en ayant pris soin de choisir un scénario, il suffit d'exécuter la commande :
+```
+# Une fois le .env modifié pour choisir le scénario notamment
+# Choisir le scénario (attention road2Docker ne fonctionne pas tant que docker-compose up generate-load-data n'a pas été appelé au moins une fois)
+docker-compose up load-road2
+```
+
+## Générer des données pour les tests
+
+### Tests de charge avec gatling
+
+Par défaut, l'image docker de r2gg permet de générer des données pour Road2 qui sont issues de données OSM. Dans ce cas, ce dépôt contient déjà des requêtes et des scénarii gatling permettant de tester Road2 sur ces données.
+
+Mais si l'image docker de r2gg a été utilisée pour créer une ressource pointant sur un endroit différent, il sera nécessaire de générer des données pour les tests.
+
+Pour cela, il suffira de modifier la bbox du `.env` et de lancer la commande suivante :
+```
+# Une fois le .env modifié
+docker-compose up generate-load-data
+```
+
+Cette commande lance la génération d'un fichier `ssv` dans un volume docker. Ce fichier est ensuite proposé dans les scénarii gatling sous le nom de `dataOsm`. Par ailleurs, ce scénario ne fonctionnera donc pas tant qu'une donnée n'aura pas été générée avec ce docker-compose.
+```
+# Après la génération via ce docker-compose
+# Modifier le .env pour choisir le scénario 'dataOsm'
+docker-compose up load-road2
+```
+
+## Utiliser des données et scénarii de la machine hôte
+
+Si on souhaite utiliser des données et des scénarii stockés sur la machine hôte, il suffira de modifier le `.env` pour pointer vers un autre `user-files`.
diff --git a/test/load/gatling/user-files/resources/road2_parameters_iso.ssv b/test/load/gatling/user-files/resources/isoPgr.ssv
similarity index 100%
rename from test/load/gatling/user-files/resources/road2_parameters_iso.ssv
rename to test/load/gatling/user-files/resources/isoPgr.ssv
diff --git a/test/load/gatling/user-files/resources/road2_parameters.ssv b/test/load/gatling/user-files/resources/road2_parameters.ssv
deleted file mode 100644
index 30a590c..0000000
--- a/test/load/gatling/user-files/resources/road2_parameters.ssv
+++ /dev/null
@@ -1,101 +0,0 @@
-resource;start;end;intermediates;profile;optimization;geometryFormat;getSteps;getBbox
-corse-osm;41.8390713617206,9.43703397945734;42.334460593434,8.81305585236754;;;;polyline;true;true
-corse-osm;42.334460593434,8.81305585236754;42.0576301801484,8.92986093250336;;car;fastest;polyline;true;true
-corse-osm;42.5176797365304,9.29212701178389;41.6038459739462,9.08565157287987;42.3690578503627,9.04352678218158|42.5137092300737,9.30879551293794;;;polyline;true;true
-corse-osm;42.0576301801484,8.92986093250336;41.7700933746574,9.26606619605562;42.4888796936115,9.40771683264757;car;fastest;polyline;true;true
-corse-osm;41.8898966115573,9.14893843763275;42.0045748996176,9.4801379238395;;;fastest;polyline;true;true
-corse-osm;41.6038459739462,9.08565157287987;41.5443718961766,8.81483415379655;;car;fastest;polyline;true;true
-corse-osm;41.5208031673077,9.04400089748669;42.4807446733722,8.82998053117189;;car;;polyline;true;true
-corse-osm;41.7700933746574,9.26606619605562;41.7168139981618,8.96842432008358;;car;;polyline;true;true
-corse-osm;41.5691899219435,8.61595866435207;42.1262043018127,9.49186793667497;;;;polyline;true;true
-corse-osm;42.0045748996176,9.4801379238395;42.5137092300737,9.30879551293794;;car;fastest;polyline;true;true
-corse-osm;42.5515449205646,8.85099329014542;41.6805704825697,9.08087568214163;;;;polyline;true;true
-corse-osm;41.5443718961766,8.81483415379655;42.1700654321304,9.36840610945132;;;fastest;polyline;true;true
-corse-osm;42.0174223158089,9.17767921910621;42.3719795257691,9.21603240483208;;;fastest;polyline;true;true
-corse-osm;42.4807446733722,8.82998053117189;41.819807130415,8.77448105972027;;;;polyline;true;true
-corse-osm;42.1330393094104,9.00609113303013;42.378296860843,9.1144110000669;;;fastest;polyline;true;true
-corse-osm;41.7168139981618,8.96842432008358;42.4030268945405,8.87973424090771;;;fastest;polyline;true;true
-corse-osm;42.5866242765915,8.74477297541685;42.5958667070745,9.39867358952761;;;fastest;polyline;true;true
-corse-osm;42.1262043018127,9.49186793667497;42.5686403946159,8.91411050735973;41.9089993005665,9.03362404228421;car;fastest;polyline;true;true
-corse-osm;42.0322090332024,9.50982478241669;41.5795820110664,9.312642352283;41.6396245398792,8.77595625129528|41.7625999935204,8.81336904539494;;;polyline;true;true
-corse-osm;42.5137092300737,9.30879551293794;41.4012516786857,9.04828990633832;;;fastest;polyline;true;true
-corse-osm;42.0873594105476,9.25942658633692;41.5776313054049,8.92804898730246;41.8145273264637,9.3352991024428;;fastest;polyline;true;true
-corse-osm;41.6805704825697,9.08087568214163;42.1666513166623,9.00361947242636;;car;fastest;polyline;true;true
-corse-osm;42.0815073242411,9.27633386080852;41.7078604440065,9.36320603026543;41.9084671810875,9.25054778496502;car;fastest;polyline;true;true
-corse-osm;42.1700654321304,9.36840610945132;41.6666503222939,8.74630874421447;;;fastest;polyline;true;true
-corse-osm;41.6851247442979,9.43301792607177;42.506083633448,8.82026979235467;41.452086844258,9.27340428662486|42.5137092300737,9.30879551293794;;;polyline;true;true
-corse-osm;42.3719795257691,9.21603240483208;41.9555506897019,8.68532789486228;;;fastest;polyline;true;true
-corse-osm;41.7175621405244,8.75750602712855;41.8445159427682,8.89615235476755;42.2842764702672,8.82059491696069;;;polyline;true;true
-corse-osm;41.819807130415,8.77448105972027;41.6849748234777,9.32622428155271;;car;fastest;polyline;true;true
-corse-osm;41.6866839826386,8.93716305163223;41.858134907037,9.20794566819444;;;fastest;polyline;true;true
-corse-osm;42.378296860843,9.1144110000669;41.4660151358461,8.8860222974699;42.0873594105476,9.25942658633692;;fastest;polyline;true;true
-corse-osm;41.6749367836071,8.96070477749221;41.403155911793,9.17498027076479;;;fastest;polyline;true;true
-corse-osm;42.4030268945405,8.87973424090771;41.6874637901364,9.35961340215057;42.2551984808268,9.03867767836666|41.5086117511056,8.82709097801242;;fastest;polyline;true;true
-corse-osm;41.6723431202676,8.8915827107965;42.3936194989178,9.29247102554887;;car;;polyline;true;true
-corse-osm;42.5958667070745,9.39867358952761;42.2634152425406,8.89967834537383;42.5958667070745,9.39867358952761|42.4757081105839,9.00439814660465;;;polyline;true;true
-corse-osm;41.6429873885401,9.18426055066753;41.4106993408641,9.23118901771959;;car;fastest;polyline;true;true
-corse-osm;42.5686403946159,8.91411050735973;42.2733301856043,8.74593808557372;;;fastest;polyline;true;true
-corse-osm;41.6214101031329,8.63401646217331;42.5111556108762,9.19636671333108;;;;polyline;true;true
-corse-osm;41.5795820110664,9.312642352283;41.9834078009333,9.19273838646011;;;;polyline;true;true
-corse-osm;42.2730661670724,8.84360980622703;41.9441022483632,8.8211155277933;41.403155911793,9.17498027076479;;;polyline;true;true
-corse-osm;41.4012516786857,9.04828990633832;41.8017727926048,9.4208018352068;;;fastest;polyline;true;true
-corse-osm;41.7625999935204,8.81336904539494;41.5086117511056,8.82709097801242;;;fastest;polyline;true;true
-corse-osm;41.5776313054049,8.92804898730246;41.8001302840142,8.72909356556134;;;fastest;polyline;true;true
-corse-osm;42.0097980653122,9.3990617027157;41.8772974060429,9.33969355768524;;;fastest;polyline;true;true
-corse-osm;42.1666513166623,9.00361947242636;42.4682025083341,8.66486343656899;41.5243050086871,9.17988557741279;;fastest;polyline;true;true
-corse-osm;42.3690578503627,9.04352678218158;42.2568490340933,9.44058851207607;;car;fastest;polyline;true;true
-corse-osm;41.7078604440065,9.36320603026543;41.452086844258,9.27340428662486;41.4106993408641,9.23118901771959|41.5776313054049,8.92804898730246;;fastest;polyline;true;true
-corse-osm;41.5173095955746,8.97918169950368;42.3306093888311,9.06481667523738;;;fastest;polyline;true;true
-corse-osm;41.6666503222939,8.74630874421447;42.2842764702672,8.82059491696069;41.5447278332477,9.4502070946293|41.9653323202627,9.43658244673163;car;;polyline;true;true
-corse-osm;42.2551984808268,9.03867767836666;42.5227550248848,8.72837697610259;;car;;polyline;true;true
-corse-osm;42.506083633448,8.82026979235467;42.3646928772656,9.08748776409775;;;;polyline;true;true
-corse-osm;41.9003083875682,8.66257920836564;41.4584874248691,9.4635921856924;;;;polyline;true;true
-corse-osm;41.9555506897019,8.68532789486228;41.946342536225,9.05973404563498;;;;polyline;true;true
-corse-osm;41.9176718784869,8.7010508329235;41.4314189526392,8.66987570240162;41.5795820110664,9.312642352283|41.934920910662,9.50605613883352;;;polyline;true;true
-corse-osm;41.8445159427682,8.89615235476755;42.082487929929,9.25706393969012;;car;fastest;polyline;true;true
-corse-osm;42.3572007760731,9.24177032827865;42.2108392546605,8.75812957913149;;;;polyline;true;true
-corse-osm;41.6849748234777,9.32622428155271;42.1913173122285,9.40794291629456;;car;;polyline;true;true
-corse-osm;42.2105902813002,8.6446172799333;41.5447278332477,9.4502070946293;;car;;polyline;true;true
-corse-osm;41.858134907037,9.20794566819444;41.8056710250862,9.43171103302157;;;fastest;polyline;true;true
-corse-osm;41.9084671810875,9.25054778496502;42.5666334762098,9.04389483707957;;;fastest;polyline;true;true
-corse-osm;41.4660151358461,8.8860222974699;41.5249742140342,9.37807809574529;42.435111695868,9.41587828371441|41.5447278332477,9.4502070946293;;fastest;polyline;true;true
-corse-osm;41.4551911537768,8.80163558300817;41.4877674316568,9.10140649212291;42.152276415322,9.01439847547561;car;fastest;polyline;true;true
-corse-osm;41.403155911793,9.17498027076479;41.8687981342059,9.0173717990634;42.1913173122285,9.40794291629456|42.5123430562858,8.77329099609284;car;fastest;polyline;true;true
-corse-osm;41.5289915177179,9.30639446315123;41.8208918450773,8.84050445493543;;car;;polyline;true;true
-corse-osm;41.6874637901364,9.35961340215057;41.4251622726209,9.25125729649793;;;fastest;polyline;true;true
-corse-osm;42.1648399454355,8.80847324477043;41.6825082851062,9.21949539138935;41.8295057986397,9.07088365096599;car;fastest;polyline;true;true
-corse-osm;42.3936194989178,9.29247102554887;42.0587649330869,9.05149065919686;41.5988790655928,9.25546265950426|42.4961663060402,9.05523221762618;car;;polyline;true;true
-corse-osm;42.5214857479557,8.93552818699973;41.944711162243,9.09422703535994;42.435111695868,9.41587828371441;;fastest;polyline;true;true
-corse-osm;42.2634152425406,8.89967834537383;41.6707154264813,9.01356327175163;;car;fastest;polyline;true;true
-corse-osm;42.4411236823583,9.4519938291423;42.5189796673646,8.70935858873883;;;fastest;polyline;true;true
-corse-osm;41.4106993408641,9.23118901771959;41.8295057986397,9.07088365096599;41.7158439768711,8.83304398993961;car;;polyline;true;true
-corse-osm;41.8284015439451,9.18656722351909;41.6070336664841,9.18811432216782;41.8017727926048,9.4208018352068;;;polyline;true;true
-corse-osm;42.2733301856043,8.74593808557372;42.4888796936115,9.40771683264757;;car;;polyline;true;true
-corse-osm;42.4757081105839,9.00439814660465;42.102765710582,8.85466590945842;;car;;polyline;true;true
-corse-osm;42.5111556108762,9.19636671333108;41.6295969960652,8.98008235168876;;;fastest;polyline;true;true
-corse-osm;41.6479650687659,9.17928158494411;41.934920910662,9.50605613883352;41.5443718961766,8.81483415379655|41.7181254419638,8.83353409022093;car;fastest;polyline;true;true
-corse-osm;41.9834078009333,9.19273838646011;41.644861626178,8.69926636145683;;car;fastest;polyline;true;true
-corse-osm;42.5287861881033,8.81088402156718;41.4308762018941,8.73917361909058;;car;fastest;polyline;true;true
-corse-osm;41.9441022483632,8.8211155277933;41.4099069674127,9.22870442251675;;car;;polyline;true;true
-corse-osm;41.7924136599246,8.9339339953335;42.1354349009041,8.65786910869181;;car;;polyline;true;true
-corse-osm;41.8017727926048,9.4208018352068;41.5988790655928,9.25546265950426;41.6805704825697,9.08087568214163;;fastest;polyline;true;true
-corse-osm;42.3305276056007,8.70194345247;41.6439420561772,8.64062120559625;41.4251622726209,9.25125729649793|41.8772974060429,9.33969355768524;;;polyline;true;true
-corse-osm;41.5086117511056,8.82709097801242;42.2167505581444,9.07964677869808;41.8295057986397,9.07088365096599|42.1330393094104,9.00609113303013;car;fastest;polyline;true;true
-corse-osm;41.901051981952,9.47062301342841;41.9366499936115,9.20706611588132;;;fastest;polyline;true;true
-corse-osm;41.8001302840142,8.72909356556134;42.4864402093366,9.14811788067687;;;;polyline;true;true
-corse-osm;42.349353075549,8.63202592339832;42.6074890049919,9.27597146087792;;car;;polyline;true;true
-corse-osm;41.8772974060429,9.33969355768524;42.4699638921302,8.96327671280829;;;;polyline;true;true
-corse-osm;41.9525726294145,9.37636758358218;42.4308665731316,9.01329457859276;41.6195584457507,8.8770418198267|41.5443718961766,8.81483415379655;car;fastest;polyline;true;true
-corse-osm;42.4682025083341,8.66486343656899;42.5077289510425,9.11789920960087;;;;polyline;true;true
-corse-osm;41.9947181914747,9.09560710758669;42.0291180216428,9.40954979021568;;;;polyline;true;true
-corse-osm;42.2568490340933,9.44058851207607;41.916848609685,9.4602077349578;;car;;polyline;true;true
-corse-osm;41.6495313064661,8.98924457477173;42.4952977301553,9.22894780667731;;;fastest;polyline;true;true
-corse-osm;41.452086844258,9.27340428662486;41.46966379249,8.8737880191789;;;;polyline;true;true
-corse-osm;42.2822493783897,8.78145097695291;42.1267964139348,8.74122072576079;;;;polyline;true;true
-corse-osm;42.3306093888311,9.06481667523738;42.5387388469232,9.2439115669555;;car;fastest;polyline;true;true
-corse-osm;41.5012060890626,8.95517995507689;41.7282898358814,8.69446236072108;42.0174223158089,9.17767921910621;;fastest;polyline;true;true
-corse-osm;42.2842764702672,8.82059491696069;41.5135319576738,8.704888927727;;;fastest;polyline;true;true
-corse-osm;41.958078510887,9.48947655160678;42.3546094470844,9.01441730997059;;car;fastest;polyline;true;true
-corse-osm;42.5227550248848,8.72837697610259;42.3999119296111,8.77976285032462;;;fastest;polyline;true;true
-corse-osm;42.2476443565777,9.45852444905788;42.152276415322,9.01439847547561;;;;polyline;true;true
-corse-osm;42.3646928772656,9.08748776409775;42.3625371469837,8.65749502528924;41.858134907037,9.20794566819444;car;fastest;polyline;true;true
diff --git a/test/load/gatling/user-files/resources/road2_parameters_idf_pgr_wo_int.ssv b/test/load/gatling/user-files/resources/road2_parameters_idf_pgr_wo_int.ssv
deleted file mode 100644
index c0df906..0000000
--- a/test/load/gatling/user-files/resources/road2_parameters_idf_pgr_wo_int.ssv
+++ /dev/null
@@ -1,323 +0,0 @@
-resource;start;end;intermediates;profile;optimization;geometryFormat;getSteps;getBbox
-bduni-idf-pgr;2.44302401952445,48.4137148207752;2.7731701053679,48.868175015063;;;fastest;polyline;true;true
-bduni-idf-pgr;2.7731701053679,48.868175015063;2.56277133412659,48.6960634629475;;;fastest;polyline;true;true
-bduni-idf-pgr;2.35450194738805,49.0751770148287;1.85215365886688,48.4394219123526;;car;;polyline;true;true
-bduni-idf-pgr;2.56277133412659,48.6960634629475;1.74224134907126,48.9479846086819;;car;;polyline;true;true
-bduni-idf-pgr;2.23373788073659,48.6410320689902;2.62949723191559,48.6433561834972;;car;;polyline;true;true
-bduni-idf-pgr;1.85215365886688,48.4394219123526;1.77042682394385,48.6283194552176;;car;;polyline;true;true
-bduni-idf-pgr;2.63650365769863,49.0903410648694;3.14853146634996,48.9014406567905;;;;polyline;true;true
-bduni-idf-pgr;1.74224134907126,48.9479846086819;2.08896000832319,49.0502271274105;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.97092077694833,48.887046989752;2.41960498057306,49.0230359021341;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.62949723191559,48.6433561834972;3.03651972003281,48.6488741465611;;;;polyline;true;true
-bduni-idf-pgr;2.33698104396462,48.5964256068459;1.72928794324398,48.8457934149308;;;fastest;polyline;true;true
-bduni-idf-pgr;1.77042682394385,48.6283194552176;2.29819886684418,48.839445828693;;;fastest;polyline;true;true
-bduni-idf-pgr;2.15232158452272,48.7187696998008;1.94806619845331,48.4511461691232;;;;polyline;true;true
-bduni-idf-pgr;3.14853146634996,48.9014406567905;3.05042917504907,48.5749592368724;;car;;polyline;true;true
-bduni-idf-pgr;3.17251162007451,48.6573443401372;2.33938915580511,49.036685355613;;;;polyline;true;true
-bduni-idf-pgr;2.08896000832319,49.0502271274105;2.82994266860187,49.0329269678332;;car;;polyline;true;true
-bduni-idf-pgr;2.68978281058371,48.8112607997376;3.02433839887381,49.0986915396061;;car;;polyline;true;true
-bduni-idf-pgr;2.41960498057306,49.0230359021341;2.61582909338176,48.7528171760961;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.07776795178652,49.0640629309462;3.29302724190056,48.4269115800736;;;;polyline;true;true
-bduni-idf-pgr;3.03651972003281,48.6488741465611;2.9313952114433,49.0990003583254;;;;polyline;true;true
-bduni-idf-pgr;1.71925774142146,48.551671803114;1.9602685533464,49.0086243897676;;car;;polyline;true;true
-bduni-idf-pgr;1.72928794324398,48.8457934149308;1.87770117819309,48.959950564173;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.28236234672368,48.561669227411;2.80005635507405,48.6121139103547;;;;polyline;true;true
-bduni-idf-pgr;2.29819886684418,48.839445828693;1.80565406046808,48.8567842453951;;;;polyline;true;true
-bduni-idf-pgr;2.65340593419969,48.5115093970904;2.22147331535816,48.7309725905536;;car;;polyline;true;true
-bduni-idf-pgr;1.94806619845331,48.4511461691232;2.21968059018254,48.9512196605792;;;;polyline;true;true
-bduni-idf-pgr;1.79766307622194,49.0639751890674;2.04447524771094,48.604622562998;;;fastest;polyline;true;true
-bduni-idf-pgr;3.05042917504907,48.5749592368724;2.7201017331332,49.03883580931;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.94450366199017,49.0480559564894;2.92997411340475,48.7645577440504;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.33938915580511,49.036685355613;3.13090001307428,49.0978166022105;;car;;polyline;true;true
-bduni-idf-pgr;3.00574745200574,48.6070149338106;2.14300098456442,48.4424930648878;;;fastest;polyline;true;true
-bduni-idf-pgr;2.82994266860187,49.0329269678332;3.03060300946236,48.9548852890963;;;fastest;polyline;true;true
-bduni-idf-pgr;1.75955604799092,48.7252603389323;3.02805497646332,48.7392871859018;;;fastest;polyline;true;true
-bduni-idf-pgr;3.02433839887381,49.0986915396061;3.2080610755831,48.9742621842306;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.86801247894764,48.5516593190609;1.89905630238354,48.9370307860896;;;fastest;polyline;true;true
-bduni-idf-pgr;2.61582909338176,48.7528171760961;2.74377198666334,48.5289590148954;;;;polyline;true;true
-bduni-idf-pgr;3.2478683128953,49.0825153477024;2.52931407950819,48.82735147723;;car;;polyline;true;true
-bduni-idf-pgr;3.29302724190056,48.4269115800736;2.52194954827428,48.7472926355898;;;;polyline;true;true
-bduni-idf-pgr;1.74633691161871,49.0965433740057;2.00636674277484,48.590260257991;;;fastest;polyline;true;true
-bduni-idf-pgr;2.9313952114433,49.0990003583254;2.77043087631464,48.698779434571;;;fastest;polyline;true;true
-bduni-idf-pgr;3.10948592796922,49.0504662042484;2.08577245622873,48.5230459463317;;;;polyline;true;true
-bduni-idf-pgr;1.9602685533464,49.0086243897676;3.00240580327809,49.011906299321;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.28719979822636,48.7777114449535;2.51701880581677,48.4398246585857;;car;;polyline;true;true
-bduni-idf-pgr;1.87770117819309,48.959950564173;3.13924142792821,48.7964165377198;;;fastest;polyline;true;true
-bduni-idf-pgr;2.85333677828312,48.6062430019956;1.85347410105169,48.5623292586068;;;;polyline;true;true
-bduni-idf-pgr;2.80005635507405,48.6121139103547;1.71951768808067,48.4922047724947;;car;;polyline;true;true
-bduni-idf-pgr;2.86846008636057,48.8194918020628;2.65721126645803,49.0341246748343;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.80565406046808,48.8567842453951;3.15767398253083,48.4921172051691;;car;;polyline;true;true
-bduni-idf-pgr;2.21233152970672,49.0853195460746;1.74986352920532,48.4846012684749;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.22147331535816,48.7309725905536;3.24412962421775,48.5043474580627;;;;polyline;true;true
-bduni-idf-pgr;2.46903090253472,48.7825470240787;2.24155541658401,48.924730171659;;car;;polyline;true;true
-bduni-idf-pgr;2.21968059018254,48.9512196605792;2.07961494810879,48.4085965128383;;;;polyline;true;true
-bduni-idf-pgr;2.15995734296739,48.6497260325123;3.08779237866402,48.9104905051412;;;;polyline;true;true
-bduni-idf-pgr;2.04447524771094,48.604622562998;2.26028655618429,48.65906533706;;car;;polyline;true;true
-bduni-idf-pgr;2.63795228265226,48.470772205526;2.10360035635531,48.7667713400209;;car;;polyline;true;true
-bduni-idf-pgr;2.7201017331332,49.03883580931;2.92441692948341,49.0818783620838;;car;;polyline;true;true
-bduni-idf-pgr;3.24241158999503,48.5104270996992;2.68016149103642,48.9174412503606;;;fastest;polyline;true;true
-bduni-idf-pgr;2.92997411340475,48.7645577440504;2.25455458052456,48.5617117720889;;;fastest;polyline;true;true
-bduni-idf-pgr;3.10586747080088,48.8151862436673;2.11147376447916,48.7175056818407;;;;polyline;true;true
-bduni-idf-pgr;3.13090001307428,49.0978166022105;3.06813656724989,49.0666487353155;;;;polyline;true;true
-bduni-idf-pgr;1.75176373198628,48.6717312326888;2.97977443821728,48.5418979424285;;car;;polyline;true;true
-bduni-idf-pgr;2.14300098456442,48.4424930648878;1.77868135385215,48.6940694178222;;;fastest;polyline;true;true
-bduni-idf-pgr;1.77052700333297,48.5874861966819;2.28014034964144,48.4508814013563;;;fastest;polyline;true;true
-bduni-idf-pgr;3.03060300946236,48.9548852890963;2.16519124992192,48.4554131807759;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.82130594663322,48.9569179091603;2.56359329149127,49.0558625487611;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.02805497646332,48.7392871859018;2.20090577974915,48.8656499942997;;;;polyline;true;true
-bduni-idf-pgr;1.77758952975273,48.8166411499027;1.81617962121964,49.029776561656;;;;polyline;true;true
-bduni-idf-pgr;3.2080610755831,48.9742621842306;2.3203807298094,49.0524362850701;;car;;polyline;true;true
-bduni-idf-pgr;1.79864390790462,48.8007683404721;2.40034448355436,49.0499207292916;;;fastest;polyline;true;true
-bduni-idf-pgr;1.89905630238354,48.9370307860896;3.01475152149796,48.7522216537734;;;fastest;polyline;true;true
-bduni-idf-pgr;2.80626571998,48.7127389817731;2.9590084515512,48.7590084518772;;;fastest;polyline;true;true
-bduni-idf-pgr;2.74377198666334,48.5289590148954;2.66359091699123,48.5864080399973;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.62659822516143,49.0045754485996;2.69223699234426,48.781094395183;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.52931407950819,48.82735147723;1.84350316822529,48.7271079975413;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.92537104487419,48.4460248626536;2.06936389505863,48.4106162068434;;car;;polyline;true;true
-bduni-idf-pgr;2.52194954827428,48.7472926355898;2.12147863954306,48.6167812872445;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.00405092947185,48.928900136007;3.05554540157318,48.9368265053024;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.00636674277484,48.590260257991;1.72362964600325,48.8008628757438;;;;polyline;true;true
-bduni-idf-pgr;2.44998060241342,48.9409831087571;2.58977488055825,48.5484650451224;;;fastest;polyline;true;true
-bduni-idf-pgr;2.77043087631464,48.698779434571;2.85722216144204,48.8624128093012;;;;polyline;true;true
-bduni-idf-pgr;2.36744628064334,48.5593186914921;2.24830394499004,48.447400964587;;car;;polyline;true;true
-bduni-idf-pgr;2.08577245622873,48.5230459463317;1.89837341569364,48.5615852880524;;;fastest;polyline;true;true
-bduni-idf-pgr;2.97855033129454,48.4272446077317;1.86097037009895,48.9765269104158;;;fastest;polyline;true;true
-bduni-idf-pgr;3.00240580327809,49.011906299321;1.77136054523289,48.5881791703403;;;;polyline;true;true
-bduni-idf-pgr;2.01686525307596,48.559019746189;2.92506045550108,48.8759416235844;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.51701880581677,48.4398246585857;1.82099920958281,48.9100377754308;;;;polyline;true;true
-bduni-idf-pgr;2.54839190617204,48.508401370002;2.26064089313149,48.600889604562;;;;polyline;true;true
-bduni-idf-pgr;3.13924142792821,48.7964165377198;2.33598023504019,48.9742363027763;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.1219716783613,48.9284332596697;1.93459122255445,48.9302670808276;;;;polyline;true;true
-bduni-idf-pgr;1.85347410105169,48.5623292586068;1.87565202154219,48.8267301582033;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.2769722353667,49.0718624827452;2.48952550180256,48.8390767888166;;;fastest;polyline;true;true
-bduni-idf-pgr;1.71951768808067,48.4922047724947;2.371133909747,48.6451014467282;;;;polyline;true;true
-bduni-idf-pgr;2.27931108362973,48.5834542725701;1.78422989808023,48.6993033653358;;;;polyline;true;true
-bduni-idf-pgr;2.65721126645803,49.0341246748343;2.4685234580189,48.4883759838995;;;fastest;polyline;true;true
-bduni-idf-pgr;1.72670273520052,48.6091325195273;3.18409432508051,48.6388877378544;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.15767398253083,48.4921172051691;2.56231252923608,48.6639785184991;;;fastest;polyline;true;true
-bduni-idf-pgr;2.33809377290308,49.0662992510945;2.64215860851109,48.984148150729;;car;;polyline;true;true
-bduni-idf-pgr;1.74986352920532,48.4846012684749;3.15085980184376,48.600839496241;;;fastest;polyline;true;true
-bduni-idf-pgr;1.88929816000164,48.7471217040671;1.97713369987905,48.791406722297;;car;;polyline;true;true
-bduni-idf-pgr;3.24412962421775,48.5043474580627;1.82923176512122,48.8328967497917;;car;;polyline;true;true
-bduni-idf-pgr;2.80613363981247,48.5143222743878;3.28460853025317,48.4831821521511;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.24155541658401,48.924730171659;3.22628464661539,48.9242739787558;;;fastest;polyline;true;true
-bduni-idf-pgr;2.49616491571069,49.0556509082206;2.61654628627002,48.5710180676775;;;fastest;polyline;true;true
-bduni-idf-pgr;2.07961494810879,48.4085965128383;2.37246924117207,48.7314217333682;;car;;polyline;true;true
-bduni-idf-pgr;2.42679364904761,48.7121110518929;3.23969852700829,48.535220417357;;;;polyline;true;true
-bduni-idf-pgr;3.08779237866402,48.9104905051412;1.96024861447513,49.056108039245;;car;;polyline;true;true
-bduni-idf-pgr;2.96242040134966,48.9512265204685;3.155211642012,48.4280089232605;;car;;polyline;true;true
-bduni-idf-pgr;2.26028655618429,48.65906533706;3.23662505336106,48.5814448561752;;;fastest;polyline;true;true
-bduni-idf-pgr;2.36061288639903,48.6042591482634;2.89913119934499,48.5183612552704;;car;;polyline;true;true
-bduni-idf-pgr;2.10360035635531,48.7667713400209;2.61894542127848,48.8922312215669;;car;;polyline;true;true
-bduni-idf-pgr;1.81379353366792,48.6845802163007;2.59792239181697,48.9980786484433;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.92441692948341,49.0818783620838;1.76166519001126,48.6214782817755;;car;;polyline;true;true
-bduni-idf-pgr;2.28350601159036,49.0320976303658;3.13369113653898,48.4495781086152;;;fastest;polyline;true;true
-bduni-idf-pgr;2.68016149103642,48.9174412503606;3.27710180804133,48.8345374118537;;car;;polyline;true;true
-bduni-idf-pgr;2.6395819529891,48.7474210214568;2.8658278092742,48.8326704449952;;car;;polyline;true;true
-bduni-idf-pgr;2.25455458052456,48.5617117720889;2.03776987977326,48.7019950303948;;;fastest;polyline;true;true
-bduni-idf-pgr;2.38692319877446,48.8723046395462;2.92958007454872,48.7282504305243;;car;;polyline;true;true
-bduni-idf-pgr;2.11147376447916,48.7175056818407;2.69896444119513,49.0269234210951;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.87514612339437,48.6180083501386;3.09881096854806,48.9550993709359;;;;polyline;true;true
-bduni-idf-pgr;3.06813656724989,49.0666487353155;2.63602442666888,48.8933715506224;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.6561216879636,48.4137725349516;1.90038941502571,48.4410803312436;;;;polyline;true;true
-bduni-idf-pgr;2.97977443821728,48.5418979424285;3.20843671634793,48.6092077212874;;;fastest;polyline;true;true
-bduni-idf-pgr;1.80677667967975,48.9877160120523;2.88024089708924,48.8595147127518;;;;polyline;true;true
-bduni-idf-pgr;1.77868135385215,48.6940694178222;2.31517860740423,48.7657573206117;;;fastest;polyline;true;true
-bduni-idf-pgr;2.88020384497941,49.0967500364408;2.44282567165792,49.0601615046151;;car;;polyline;true;true
-bduni-idf-pgr;2.28014034964144,48.4508814013563;2.30205286554992,49.0095631321194;;;fastest;polyline;true;true
-bduni-idf-pgr;2.98547409772873,48.9869357196148;1.71405324935913,48.9862172704889;;;fastest;polyline;true;true
-bduni-idf-pgr;2.16519124992192,48.4554131807759;2.60954860933125,48.4981848334428;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.1965329580009,48.9146899617976;3.20797933265567,48.8752215392655;;;;polyline;true;true
-bduni-idf-pgr;2.56359329149127,49.0558625487611;2.49760761782527,48.9654066073243;;;fastest;polyline;true;true
-bduni-idf-pgr;2.02813939489424,48.8874126581941;2.81265951655805,48.8858365442837;;;;polyline;true;true
-bduni-idf-pgr;2.20090577974915,48.8656499942997;2.63893944807351,48.6464220805326;;;;polyline;true;true
-bduni-idf-pgr;2.25354071334004,48.8318400320131;2.98378565572202,48.4430167715531;;;;polyline;true;true
-bduni-idf-pgr;1.81617962121964,49.029776561656;2.21188332661986,48.5665090380236;;car;;polyline;true;true
-bduni-idf-pgr;2.17518935017288,49.0241894028615;2.42714392915368,48.8056369547965;;;;polyline;true;true
-bduni-idf-pgr;2.3203807298094,49.0524362850701;1.90414913594723,48.8445831454825;;;fastest;polyline;true;true
-bduni-idf-pgr;1.83959630317986,48.4131046754308;2.60319691188633,48.6644521122798;;;fastest;polyline;true;true
-bduni-idf-pgr;2.40034448355436,49.0499207292916;1.94474933221936,49.0013767180964;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.79377773739398,48.4947809746489;1.90096779540181,48.7199568069773;;car;;polyline;true;true
-bduni-idf-pgr;3.01475152149796,48.7522216537734;1.98849392086267,48.7762989106355;;car;;polyline;true;true
-bduni-idf-pgr;2.30098935961723,48.7266279263888;3.17967119179666,49.033109962428;;car;;polyline;true;true
-bduni-idf-pgr;2.9590084515512,48.7590084518772;2.37337832003832,49.0185763883637;;car;;polyline;true;true
-bduni-idf-pgr;2.48865631446242,48.8171713173157;2.66718358658254,48.6502973634982;;;fastest;polyline;true;true
-bduni-idf-pgr;2.66359091699123,48.5864080399973;2.65378841906786,48.8530607349938;;car;;polyline;true;true
-bduni-idf-pgr;3.02200339883566,48.8232395383529;1.75942298993468,48.6627617059974;;;fastest;polyline;true;true
-bduni-idf-pgr;2.69223699234426,48.781094395183;1.78632455803454,48.9274080703268;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.46888927929103,48.6387730957242;2.34170696213841,48.6132798478706;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.84350316822529,48.7271079975413;3.04588063806295,48.4732514865231;;car;;polyline;true;true
-bduni-idf-pgr;2.19786168299615,48.8458025997505;2.47313884682953,49.0847438615281;;;fastest;polyline;true;true
-bduni-idf-pgr;2.06936389505863,48.4106162068434;2.98047252073884,48.4200417489512;;;;polyline;true;true
-bduni-idf-pgr;1.82886183969676,48.9577273936942;2.90867525599897,48.577031161054;;car;;polyline;true;true
-bduni-idf-pgr;2.12147863954306,48.6167812872445;1.87185139842331,48.5202892370056;;;;polyline;true;true
-bduni-idf-pgr;2.96994536928833,49.0740880992496;2.72634820900857,48.9121631982736;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.05554540157318,48.9368265053024;3.25897775925696,48.947050251835;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.81734802238643,48.6399777745828;1.95096476227045,48.6524713821942;;;;polyline;true;true
-bduni-idf-pgr;1.72362964600325,48.8008628757438;2.08726699501276,48.4177114662481;;;fastest;polyline;true;true
-bduni-idf-pgr;2.43606786131859,48.6523412133101;3.00724473297596,48.5413840666413;;car;;polyline;true;true
-bduni-idf-pgr;2.58977488055825,48.5484650451224;3.12126296684146,49.0275092432508;;car;;polyline;true;true
-bduni-idf-pgr;2.81350911594927,49.053426356311;3.16698793284595,49.0059921407374;;;fastest;polyline;true;true
-bduni-idf-pgr;2.85722216144204,48.8624128093012;3.18716344460845,48.8380181001034;;;;polyline;true;true
-bduni-idf-pgr;1.71817801259458,48.9931880616117;3.03308020718396,48.8012332331622;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.24830394499004,48.447400964587;3.01740132682025,48.9715511559974;;;;polyline;true;true
-bduni-idf-pgr;2.12365882359445,48.5913832220249;2.90906613878906,48.8651268957183;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.89837341569364,48.5615852880524;2.14403748773038,48.6982124962611;;car;;polyline;true;true
-bduni-idf-pgr;2.9955084014684,48.6209766281303;2.29415314942598,48.7855380748166;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.86097037009895,48.9765269104158;1.77023191601038,48.835192236281;;;fastest;polyline;true;true
-bduni-idf-pgr;2.20131517611444,48.5984010657296;2.80260041020811,49.0229929501656;;;;polyline;true;true
-bduni-idf-pgr;1.77136054523289,48.5881791703403;2.62434866689146,48.7142322225496;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.9883840225637,49.0811516144313;2.51490940265357,48.7803513203748;;;;polyline;true;true
-bduni-idf-pgr;2.92506045550108,48.8759416235844;2.55255498997867,48.9194628409808;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.18449685834348,48.8928286401788;1.7239506047219,48.7769301553955;;;;polyline;true;true
-bduni-idf-pgr;1.82099920958281,48.9100377754308;2.62849176079035,48.9117487736046;;;;polyline;true;true
-bduni-idf-pgr;3.08201187215745,48.9602073112968;2.42771309092641,48.6845061585074;;;;polyline;true;true
-bduni-idf-pgr;2.26064089313149,48.600889604562;2.2642200101167,48.7073045867961;;;fastest;polyline;true;true
-bduni-idf-pgr;2.95409759096801,48.4892538063927;3.24920990467072,48.7504414305324;;;fastest;polyline;true;true
-bduni-idf-pgr;2.33598023504019,48.9742363027763;2.65315005257726,49.0268406333635;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.07744960524142,48.9785587020451;3.06247456669807,48.4134095962858;;;fastest;polyline;true;true
-bduni-idf-pgr;1.93459122255445,48.9302670808276;2.70311385728419,48.6855158704799;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.73912299089134,48.4744705524063;2.33896833099425,48.7248882452725;;;;polyline;true;true
-bduni-idf-pgr;1.87565202154219,48.8267301582033;1.93512160927057,48.6344014046714;;;;polyline;true;true
-bduni-idf-pgr;1.77118125297129,49.0274510557763;2.63065129593015,48.7589763323078;;car;;polyline;true;true
-bduni-idf-pgr;2.48952550180256,48.8390767888166;2.61563961282372,49.0248309108894;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.78129711225629,48.7091508675599;2.35468277707696,48.5030348944478;;;;polyline;true;true
-bduni-idf-pgr;2.371133909747,48.6451014467282;3.17790134847164,48.8820506641408;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.80124563872814,48.6732986173127;2.79613966569304,48.5741212349851;;;fastest;polyline;true;true
-bduni-idf-pgr;1.78422989808023,48.6993033653358;1.77025827243924,48.8180651763687;;car;;polyline;true;true
-bduni-idf-pgr;2.91238521821797,48.9932538401103;2.3657249815762,48.5469554207986;;;;polyline;true;true
-bduni-idf-pgr;2.4685234580189,48.4883759838995;2.47266492471099,48.7841440092307;;car;;polyline;true;true
-bduni-idf-pgr;2.65210498459637,48.5873672699323;2.14741960763931,49.0060348907718;;;;polyline;true;true
-bduni-idf-pgr;3.18409432508051,48.6388877378544;2.30891627632082,48.4137112971162;;;;polyline;true;true
-bduni-idf-pgr;2.93746135793626,48.846178816841;2.13674341440201,48.6730940852081;;;;polyline;true;true
-bduni-idf-pgr;2.56231252923608,48.6639785184991;2.88402340710163,48.4173302368261;;;fastest;polyline;true;true
-bduni-idf-pgr;2.8157651361078,48.5403529864969;2.7808874193579,48.6516721581575;;;fastest;polyline;true;true
-bduni-idf-pgr;2.64215860851109,48.984148150729;2.53900687582791,49.0219269554829;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.72624706290662,48.7940942401299;2.92554791979492,48.7662857511314;;car;;polyline;true;true
-bduni-idf-pgr;3.15085980184376,48.600839496241;2.61457718908787,48.7606833498226;;car;;polyline;true;true
-bduni-idf-pgr;2.34993697851896,49.0004024068359;2.44997046217322,48.7542010897305;;car;;polyline;true;true
-bduni-idf-pgr;1.97713369987905,48.791406722297;2.69174239560962,48.5570644505555;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.21946005299687,48.9128135661362;2.40341152437031,48.8191350154579;;;fastest;polyline;true;true
-bduni-idf-pgr;1.82923176512122,48.8328967497917;2.42162180915475,49.0414450021693;;;;polyline;true;true
-bduni-idf-pgr;2.13496898785233,48.9560354938498;2.39156349077821,48.5970387435518;;;fastest;polyline;true;true
-bduni-idf-pgr;3.28460853025317,48.4831821521511;1.97832168713212,48.8806318745948;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.77608941085637,48.678063773131;2.22452594041824,48.7712506627198;;;;polyline;true;true
-bduni-idf-pgr;3.22628464661539,48.9242739787558;2.411614953354,48.6086867272854;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.16368755064905,48.8144462611061;2.51069469451904,48.5629805336241;;car;;polyline;true;true
-bduni-idf-pgr;2.61654628627002,48.5710180676775;1.84811977297068,48.5118584437063;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.86342695392668,48.5766375748673;2.81744394339621,48.6286925512133;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.37246924117207,48.7314217333682;1.77044644728303,48.835936860228;;car;;polyline;true;true
-bduni-idf-pgr;2.13166442662477,48.5503719745437;2.18552004061639,48.5676715224516;;;;polyline;true;true
-bduni-idf-pgr;3.23969852700829,48.535220417357;2.07531846836209,48.4924617862562;;car;;polyline;true;true
-bduni-idf-pgr;3.17785889729857,49.0330999343423;2.74112369641662,48.6395581742749;;car;;polyline;true;true
-bduni-idf-pgr;1.96024861447513,49.056108039245;3.00984625890851,48.936620601383;;;fastest;polyline;true;true
-bduni-idf-pgr;1.88465708866715,48.4449474926805;3.24550998099148,48.8833222137997;;car;;polyline;true;true
-bduni-idf-pgr;3.155211642012,48.4280089232605;2.96623665466905,48.4148942076834;;;fastest;polyline;true;true
-bduni-idf-pgr;3.00523122362792,48.9940215313109;2.42308107987046,48.6953704123618;;;;polyline;true;true
-bduni-idf-pgr;3.23662505336106,48.5814448561752;3.17843544334173,48.6447293995181;;car;;polyline;true;true
-bduni-idf-pgr;1.7113136716187,48.553526684246;3.06107096299529,49.0866241728189;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.89913119934499,48.5183612552704;1.70145761668682,48.5891884437297;;;fastest;polyline;true;true
-bduni-idf-pgr;2.70785078518093,48.507257003407;2.17305626124144,48.4751185767585;;;fastest;polyline;true;true
-bduni-idf-pgr;2.61894542127848,48.8922312215669;2.12264413237572,48.6806732026394;;;;polyline;true;true
-bduni-idf-pgr;1.78459358438849,48.4057517669629;3.27955346107483,48.6691871895455;;;fastest;polyline;true;true
-bduni-idf-pgr;2.59792239181697,48.9980786484433;2.77620098814368,48.4779397946317;;;fastest;polyline;true;true
-bduni-idf-pgr;2.53806917257607,48.7204011785099;2.79147772714496,48.7053473231615;;car;;polyline;true;true
-bduni-idf-pgr;1.76166519001126,48.6214782817755;2.25704414881766,48.5834885267075;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.21513230241835,48.636160280765;3.00117604546249,48.5279869676102;;;fastest;polyline;true;true
-bduni-idf-pgr;3.13369113653898,48.4495781086152;2.51610577963293,48.6193799407454;;car;;polyline;true;true
-bduni-idf-pgr;1.70224213190377,48.5667912617559;2.60930366925895,48.5994060098426;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.27710180804133,48.8345374118537;2.1088197439909,49.0329182558227;;;fastest;polyline;true;true
-bduni-idf-pgr;1.93520829193294,48.5822563250083;2.97879804186523,49.0418382084463;;car;;polyline;true;true
-bduni-idf-pgr;2.8658278092742,48.8326704449952;1.74143002107739,48.6502963735489;;;;polyline;true;true
-bduni-idf-pgr;3.14830018132925,48.4963647234254;2.36237132549286,49.0024718885776;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.03776987977326,48.7019950303948;2.27105385474861,48.4473506370559;;;fastest;polyline;true;true
-bduni-idf-pgr;2.77452237308025,48.5603685131995;3.19282997846603,48.4008056103019;;car;;polyline;true;true
-bduni-idf-pgr;2.92958007454872,48.7282504305243;3.2312304135412,49.0795749890851;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.84637838639319,49.009762154636;3.08899837583303,49.0383949865354;;car;;polyline;true;true
-bduni-idf-pgr;2.69896444119513,49.0269234210951;3.02624191790819,48.587071515806;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.82771084494889,48.7242462720955;1.75015484318137,48.9140947713051;;;fastest;polyline;true;true
-bduni-idf-pgr;3.09881096854806,48.9550993709359;2.29008085019886,48.7066363268299;;;fastest;polyline;true;true
-bduni-idf-pgr;2.67328545004129,48.8863567294087;2.48435933217406,48.5286500309128;;;fastest;polyline;true;true
-bduni-idf-pgr;2.63602442666888,48.8933715506224;2.34159820824862,49.0844875207171;;car;;polyline;true;true
-bduni-idf-pgr;1.88642966076732,48.9083162062801;2.85769811905921,48.8256619161693;;car;;polyline;true;true
-bduni-idf-pgr;1.90038941502571,48.4410803312436;2.09707062914968,48.816647517751;;;fastest;polyline;true;true
-bduni-idf-pgr;1.83894036822021,49.0832666419912;2.69410366714001,48.8021550313104;;;;polyline;true;true
-bduni-idf-pgr;3.20843671634793,48.6092077212874;2.55717359632254,48.8056579111144;;;fastest;polyline;true;true
-bduni-idf-pgr;3.08813234567642,48.9295926973224;3.22132597714663,48.6693156572292;;;;polyline;true;true
-bduni-idf-pgr;2.88024089708924,48.8595147127518;3.06893367916346,48.7707151483744;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.70997451581061,48.6047025687993;2.44796397797763,48.6530489895958;;;;polyline;true;true
-bduni-idf-pgr;2.31517860740423,48.7657573206117;1.73853508792818,48.7234391525853;;car;;polyline;true;true
-bduni-idf-pgr;1.89589908793569,48.7866324947681;2.38785015568137,48.4433182034642;;;fastest;polyline;true;true
-bduni-idf-pgr;1.77893240749836,48.4801739969989;2.24767736084759,48.6571313232183;;car;;polyline;true;true
-bduni-idf-pgr;2.38250925689936,48.5080187392654;2.29749291017652,48.7354998544091;;car;;polyline;true;true
-bduni-idf-pgr;2.75157957784832,48.6696816918906;2.6106046397239,48.6184849328361;;car;;polyline;true;true
-bduni-idf-pgr;2.67308412827551,49.0467134487815;1.88871848993003,48.7858450352214;;;;polyline;true;true
-bduni-idf-pgr;2.28414396755397,48.5412525953725;2.26862809471786,48.6602929371409;;;;polyline;true;true
-bduni-idf-pgr;1.76589241586626,48.6122939452063;2.87847086787224,48.8704217498889;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.28558418564498,49.0100721106399;2.61345944292843,48.84184322129;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.97836105301976,48.4586890732171;1.86185560561717,48.7619135329966;;car;;polyline;true;true
-bduni-idf-pgr;3.05286432802677,48.5488145295065;2.24766672290862,48.8326830349863;;;;polyline;true;true
-bduni-idf-pgr;2.29398637488484,48.532341744774;2.03509683050215,49.0130370791303;;;fastest;polyline;true;true
-bduni-idf-pgr;3.155302355811,48.8088112379191;1.79400271475315,48.7254965908127;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.1394589394331,48.655172704393;3.04455347955227,48.4636280691251;;;;polyline;true;true
-bduni-idf-pgr;2.82006553113461,48.5720650034724;2.72786941751838,48.6281849443447;;;;polyline;true;true
-bduni-idf-pgr;2.50881831422448,48.6162664430216;2.52380169704556,48.5565654592123;;;;polyline;true;true
-bduni-idf-pgr;2.80508779771626,48.8314150076825;3.24237989038229,48.9211644186638;;car;;polyline;true;true
-bduni-idf-pgr;2.90736396126449,48.8145677352557;2.95437494143844,48.895003245445;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.76483602523804,48.7834289334947;2.44333230108023,48.6851161454339;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.74138205721974,48.4951852770289;2.05962646864355,48.7131408974528;;car;;polyline;true;true
-bduni-idf-pgr;2.16240077130497,48.9056342708878;2.57546874433756,49.0215309059946;;;;polyline;true;true
-bduni-idf-pgr;2.86805079244077,48.9111416435801;1.96211568191648,48.4904934111983;;;fastest;polyline;true;true
-bduni-idf-pgr;2.39693894758821,48.6177439929219;2.11159228160977,48.6870462149614;;;fastest;polyline;true;true
-bduni-idf-pgr;2.44764026515186,48.7303717983887;1.86678234227002,48.5947005617898;;;fastest;polyline;true;true
-bduni-idf-pgr;2.48838028870523,48.4055102229118;2.87733382321894,48.7122184444452;;;;polyline;true;true
-bduni-idf-pgr;2.03093082383275,48.8598328259774;1.89327391758561,48.9963914602296;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.69736703597009,48.6363132799277;3.182831607759,48.9348469878547;;;fastest;polyline;true;true
-bduni-idf-pgr;3.15717746093869,48.4581351812463;2.41245734393597,48.6886572781252;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.70299930684268,48.4036925303983;2.43869958035648,48.7360838004854;;;fastest;polyline;true;true
-bduni-idf-pgr;2.79737324118614,48.6007891183486;2.99430664107203,48.9486130156089;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.50388777069747,48.8045362858102;2.34645159579813,48.8466877503786;;;;polyline;true;true
-bduni-idf-pgr;2.34890620075166,48.5734699483961;2.16593897081912,49.0283524840139;;;;polyline;true;true
-bduni-idf-pgr;3.12934719100594,48.5202896042028;1.89534109197557,48.5789273653179;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.89886239394546,49.0337235135958;2.92045889385045,48.7608956388664;;;;polyline;true;true
-bduni-idf-pgr;2.65560555048287,48.6464879555162;2.41393017545342,48.943114944757;;car;;polyline;true;true
-bduni-idf-pgr;1.7402398083359,48.7374177104328;2.24627429097891,48.7397860897239;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.76597310937941,48.8385955642443;2.44394816793501,48.9053963240003;;;fastest;polyline;true;true
-bduni-idf-pgr;3.01715762168169,48.6969391793944;3.20263568758965,48.9626127462136;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.54577292092144,48.4032152522588;2.92621581666172,48.8457779747201;;;fastest;polyline;true;true
-bduni-idf-pgr;3.2949625082314,48.9339722776553;2.54716102220118,48.4277711126255;;car;;polyline;true;true
-bduni-idf-pgr;3.13784370422363,48.4485147462459;3.1811253618449,48.7178375440184;;car;;polyline;true;true
-bduni-idf-pgr;2.33329236730933,48.8876486113295;2.14565384984016,48.824415569962;;car;;polyline;true;true
-bduni-idf-pgr;2.20525981336832,48.4524710243102;2.98737781271338,48.733678951324;;car;;polyline;true;true
-bduni-idf-pgr;1.70351696610451,48.6967224117834;2.19678191952407,48.628333799378;;;;polyline;true;true
-bduni-idf-pgr;1.9317928943783,48.9696621822426;2.47072629034519,49.0356613384327;;;fastest;polyline;true;true
-bduni-idf-pgr;2.10365320518613,48.9907704428537;3.29506550841033,49.0098599653458;;car;;polyline;true;true
-bduni-idf-pgr;1.73959526382387,48.907115195808;2.17901276350021,48.7272703210358;;;;polyline;true;true
-bduni-idf-pgr;2.53201073370874,48.7656614233041;2.15153104066849,48.9009692120831;;;;polyline;true;true
-bduni-idf-pgr;3.28023196272552,48.7218059241073;3.26586572155356,48.8291404705029;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.42753846421838,49.0898653692799;3.2305314540863,48.5943622092018;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.06901542656124,48.6345081325853;2.61021210178733,48.8953208891209;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.05548841618001,48.606448809104;1.84710865542293,48.8563449443784;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.74734552763402,48.8885561947245;3.05129791498184,48.7961439184844;;;fastest;polyline;true;true
-bduni-idf-pgr;3.02238834574819,48.5270605054218;1.86672330908477,48.6245439877966;;;fastest;polyline;true;true
-bduni-idf-pgr;2.76956245601177,48.6712490440812;2.40666649341583,48.84756819834;;car;;polyline;true;true
-bduni-idf-pgr;2.46519443653524,48.4101225436898;2.26161520555615,48.7464743186021;;;;polyline;true;true
-bduni-idf-pgr;3.15562987178564,48.5155062379781;3.18331082500517,48.7414217407582;;car;;polyline;true;true
-bduni-idf-pgr;2.45104273669422,48.7872313115979;3.26537883169949,48.4060058250558;;;;polyline;true;true
-bduni-idf-pgr;2.05847477726638,48.5304783798056;1.78662376813591,48.7435751098674;;car;;polyline;true;true
-bduni-idf-pgr;2.44915228784084,48.7143794547766;1.79427379630506,48.5892938267207;;car;;polyline;true;true
-bduni-idf-pgr;2.70950169526041,48.7773852509446;1.70392192415893,48.6924740931252;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.47131392210722,48.5686107953079;2.47563578039408,48.5232675248291;;;fastest;polyline;true;true
-bduni-idf-pgr;3.00200576223433,48.9775314524537;2.61872317120433,48.8471586129162;;car;fastest;polyline;true;true
-bduni-idf-pgr;3.23854403235018,48.802837240696;2.01163341850042,48.8532252323348;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.94985375031829,48.8609381208662;2.14056989103556,48.937168886303;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.98303970173001,48.8078082440421;2.36212318986654,48.6093356524361;;car;;polyline;true;true
-bduni-idf-pgr;1.75505315475166,48.7259683815297;2.53619465194643,48.9744010594208;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.65726837515831,48.5846856117714;2.85868522003293,48.7052039258881;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.91799417063594,48.8083277816419;2.38365162909031,48.8877615066245;;;fastest;polyline;true;true
-bduni-idf-pgr;3.06941128447652,48.8862750092056;1.78778480961919,48.7519670638721;;car;fastest;polyline;true;true
-bduni-idf-pgr;1.84866771772504,48.7393558819313;2.57951624765992,48.6120211988455;;car;fastest;polyline;true;true
-bduni-idf-pgr;2.28624591007829,48.797935621161;1.83973868265748,48.6104129117448;;car;;polyline;true;true
-bduni-idf-pgr;2.15655271187425,48.9793275719276;2.96782912127674,48.7476802977268;;;fastest;polyline;true;true
-bduni-idf-pgr;2.48459296412766,48.480618487997;2.56370316445827,48.6602818151237;;;;polyline;true;true
-bduni-idf-pgr;2.94533781297505,48.97076268401;1.86368526853621,48.6995010352693;;car;fastest;polyline;true;true
diff --git a/test/load/gatling/user-files/resources/routeOsrm.ssv b/test/load/gatling/user-files/resources/routeOsrm.ssv
new file mode 100644
index 0000000..d6b9be0
--- /dev/null
+++ b/test/load/gatling/user-files/resources/routeOsrm.ssv
@@ -0,0 +1,101 @@
+resource;start;end;intermediates;profile;optimization;geometryFormat;getSteps;getBbox
+bduni-idf-osrm;2.44302401952445,48.4137148207752;2.7731701053679,48.868175015063;;;fastest;polyline;true;true
+bduni-idf-osrm;2.7731701053679,48.868175015063;2.56277133412659,48.6960634629475;;;fastest;polyline;true;true
+bduni-idf-osrm;2.35450194738805,49.0751770148287;1.85215365886688,48.4394219123526;;car;;polyline;true;true
+bduni-idf-osrm;2.56277133412659,48.6960634629475;1.74224134907126,48.9479846086819;;car;;polyline;true;true
+bduni-idf-osrm;2.23373788073659,48.6410320689902;2.62949723191559,48.6433561834972;;car;;polyline;true;true
+bduni-idf-osrm;1.85215365886688,48.4394219123526;1.77042682394385,48.6283194552176;;car;;polyline;true;true
+bduni-idf-osrm;2.63650365769863,49.0903410648694;3.14853146634996,48.9014406567905;;;;polyline;true;true
+bduni-idf-osrm;1.74224134907126,48.9479846086819;2.08896000832319,49.0502271274105;;car;fastest;polyline;true;true
+bduni-idf-osrm;1.97092077694833,48.887046989752;2.41960498057306,49.0230359021341;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.62949723191559,48.6433561834972;3.03651972003281,48.6488741465611;;;;polyline;true;true
+bduni-idf-osrm;2.33698104396462,48.5964256068459;1.72928794324398,48.8457934149308;;;fastest;polyline;true;true
+bduni-idf-osrm;1.77042682394385,48.6283194552176;2.29819886684418,48.839445828693;;;fastest;polyline;true;true
+bduni-idf-osrm;2.15232158452272,48.7187696998008;1.94806619845331,48.4511461691232;;;;polyline;true;true
+bduni-idf-osrm;3.14853146634996,48.9014406567905;3.05042917504907,48.5749592368724;;car;;polyline;true;true
+bduni-idf-osrm;3.17251162007451,48.6573443401372;2.33938915580511,49.036685355613;;;;polyline;true;true
+bduni-idf-osrm;2.08896000832319,49.0502271274105;2.82994266860187,49.0329269678332;;car;;polyline;true;true
+bduni-idf-osrm;2.68978281058371,48.8112607997376;3.02433839887381,49.0986915396061;;car;;polyline;true;true
+bduni-idf-osrm;2.41960498057306,49.0230359021341;2.61582909338176,48.7528171760961;;car;fastest;polyline;true;true
+bduni-idf-osrm;3.07776795178652,49.0640629309462;3.29302724190056,48.4269115800736;;;;polyline;true;true
+bduni-idf-osrm;3.03651972003281,48.6488741465611;2.9313952114433,49.0990003583254;;;;polyline;true;true
+bduni-idf-osrm;1.71925774142146,48.551671803114;1.9602685533464,49.0086243897676;;car;;polyline;true;true
+bduni-idf-osrm;1.72928794324398,48.8457934149308;1.87770117819309,48.959950564173;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.28236234672368,48.561669227411;2.80005635507405,48.6121139103547;;;;polyline;true;true
+bduni-idf-osrm;2.29819886684418,48.839445828693;1.80565406046808,48.8567842453951;;;;polyline;true;true
+bduni-idf-osrm;2.65340593419969,48.5115093970904;2.22147331535816,48.7309725905536;;car;;polyline;true;true
+bduni-idf-osrm;1.94806619845331,48.4511461691232;2.21968059018254,48.9512196605792;;;;polyline;true;true
+bduni-idf-osrm;1.79766307622194,49.0639751890674;2.04447524771094,48.604622562998;;;fastest;polyline;true;true
+bduni-idf-osrm;3.05042917504907,48.5749592368724;2.7201017331332,49.03883580931;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.94450366199017,49.0480559564894;2.92997411340475,48.7645577440504;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.33938915580511,49.036685355613;3.13090001307428,49.0978166022105;;car;;polyline;true;true
+bduni-idf-osrm;3.00574745200574,48.6070149338106;2.14300098456442,48.4424930648878;;;fastest;polyline;true;true
+bduni-idf-osrm;2.82994266860187,49.0329269678332;3.03060300946236,48.9548852890963;;;fastest;polyline;true;true
+bduni-idf-osrm;1.75955604799092,48.7252603389323;3.02805497646332,48.7392871859018;;;fastest;polyline;true;true
+bduni-idf-osrm;3.02433839887381,49.0986915396061;3.2080610755831,48.9742621842306;;car;fastest;polyline;true;true
+bduni-idf-osrm;1.86801247894764,48.5516593190609;1.89905630238354,48.9370307860896;;;fastest;polyline;true;true
+bduni-idf-osrm;2.61582909338176,48.7528171760961;2.74377198666334,48.5289590148954;;;;polyline;true;true
+bduni-idf-osrm;3.2478683128953,49.0825153477024;2.52931407950819,48.82735147723;;car;;polyline;true;true
+bduni-idf-osrm;3.29302724190056,48.4269115800736;2.52194954827428,48.7472926355898;;;;polyline;true;true
+bduni-idf-osrm;1.74633691161871,49.0965433740057;2.00636674277484,48.590260257991;;;fastest;polyline;true;true
+bduni-idf-osrm;2.9313952114433,49.0990003583254;2.77043087631464,48.698779434571;;;fastest;polyline;true;true
+bduni-idf-osrm;3.10948592796922,49.0504662042484;2.08577245622873,48.5230459463317;;;;polyline;true;true
+bduni-idf-osrm;1.9602685533464,49.0086243897676;3.00240580327809,49.011906299321;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.28719979822636,48.7777114449535;2.51701880581677,48.4398246585857;;car;;polyline;true;true
+bduni-idf-osrm;1.87770117819309,48.959950564173;3.13924142792821,48.7964165377198;;;fastest;polyline;true;true
+bduni-idf-osrm;2.85333677828312,48.6062430019956;1.85347410105169,48.5623292586068;;;;polyline;true;true
+bduni-idf-osrm;2.80005635507405,48.6121139103547;1.71951768808067,48.4922047724947;;car;;polyline;true;true
+bduni-idf-osrm;2.86846008636057,48.8194918020628;2.65721126645803,49.0341246748343;;car;fastest;polyline;true;true
+bduni-idf-osrm;1.80565406046808,48.8567842453951;3.15767398253083,48.4921172051691;;car;;polyline;true;true
+bduni-idf-osrm;2.21233152970672,49.0853195460746;1.74986352920532,48.4846012684749;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.22147331535816,48.7309725905536;3.24412962421775,48.5043474580627;;;;polyline;true;true
+bduni-idf-osrm;2.46903090253472,48.7825470240787;2.24155541658401,48.924730171659;;car;;polyline;true;true
+bduni-idf-osrm;2.21968059018254,48.9512196605792;2.07961494810879,48.4085965128383;;;;polyline;true;true
+bduni-idf-osrm;2.15995734296739,48.6497260325123;3.08779237866402,48.9104905051412;;;;polyline;true;true
+bduni-idf-osrm;2.04447524771094,48.604622562998;2.26028655618429,48.65906533706;;car;;polyline;true;true
+bduni-idf-osrm;2.63795228265226,48.470772205526;2.10360035635531,48.7667713400209;;car;;polyline;true;true
+bduni-idf-osrm;2.7201017331332,49.03883580931;2.92441692948341,49.0818783620838;;car;;polyline;true;true
+bduni-idf-osrm;3.24241158999503,48.5104270996992;2.68016149103642,48.9174412503606;;;fastest;polyline;true;true
+bduni-idf-osrm;2.92997411340475,48.7645577440504;2.25455458052456,48.5617117720889;;;fastest;polyline;true;true
+bduni-idf-osrm;3.10586747080088,48.8151862436673;2.11147376447916,48.7175056818407;;;;polyline;true;true
+bduni-idf-osrm;3.13090001307428,49.0978166022105;3.06813656724989,49.0666487353155;;;;polyline;true;true
+bduni-idf-osrm;1.75176373198628,48.6717312326888;2.97977443821728,48.5418979424285;;car;;polyline;true;true
+bduni-idf-osrm;2.14300098456442,48.4424930648878;1.77868135385215,48.6940694178222;;;fastest;polyline;true;true
+bduni-idf-osrm;1.77052700333297,48.5874861966819;2.28014034964144,48.4508814013563;;;fastest;polyline;true;true
+bduni-idf-osrm;3.03060300946236,48.9548852890963;2.16519124992192,48.4554131807759;;car;fastest;polyline;true;true
+bduni-idf-osrm;1.82130594663322,48.9569179091603;2.56359329149127,49.0558625487611;;car;fastest;polyline;true;true
+bduni-idf-osrm;3.02805497646332,48.7392871859018;2.20090577974915,48.8656499942997;;;;polyline;true;true
+bduni-idf-osrm;1.77758952975273,48.8166411499027;1.81617962121964,49.029776561656;;;;polyline;true;true
+bduni-idf-osrm;3.2080610755831,48.9742621842306;2.3203807298094,49.0524362850701;;car;;polyline;true;true
+bduni-idf-osrm;1.79864390790462,48.8007683404721;2.40034448355436,49.0499207292916;;;fastest;polyline;true;true
+bduni-idf-osrm;1.89905630238354,48.9370307860896;3.01475152149796,48.7522216537734;;;fastest;polyline;true;true
+bduni-idf-osrm;2.80626571998,48.7127389817731;2.9590084515512,48.7590084518772;;;fastest;polyline;true;true
+bduni-idf-osrm;2.74377198666334,48.5289590148954;2.66359091699123,48.5864080399973;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.62659822516143,49.0045754485996;2.69223699234426,48.781094395183;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.52931407950819,48.82735147723;1.84350316822529,48.7271079975413;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.92537104487419,48.4460248626536;2.06936389505863,48.4106162068434;;car;;polyline;true;true
+bduni-idf-osrm;2.52194954827428,48.7472926355898;2.12147863954306,48.6167812872445;;car;fastest;polyline;true;true
+bduni-idf-osrm;3.00405092947185,48.928900136007;3.05554540157318,48.9368265053024;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.00636674277484,48.590260257991;1.72362964600325,48.8008628757438;;;;polyline;true;true
+bduni-idf-osrm;2.44998060241342,48.9409831087571;2.58977488055825,48.5484650451224;;;fastest;polyline;true;true
+bduni-idf-osrm;2.77043087631464,48.698779434571;2.85722216144204,48.8624128093012;;;;polyline;true;true
+bduni-idf-osrm;2.36744628064334,48.5593186914921;2.24830394499004,48.447400964587;;car;;polyline;true;true
+bduni-idf-osrm;2.08577245622873,48.5230459463317;1.89837341569364,48.5615852880524;;;fastest;polyline;true;true
+bduni-idf-osrm;2.97855033129454,48.4272446077317;1.86097037009895,48.9765269104158;;;fastest;polyline;true;true
+bduni-idf-osrm;3.00240580327809,49.011906299321;1.77136054523289,48.5881791703403;;;;polyline;true;true
+bduni-idf-osrm;2.01686525307596,48.559019746189;2.92506045550108,48.8759416235844;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.51701880581677,48.4398246585857;1.82099920958281,48.9100377754308;;;;polyline;true;true
+bduni-idf-osrm;2.54839190617204,48.508401370002;2.26064089313149,48.600889604562;;;;polyline;true;true
+bduni-idf-osrm;3.13924142792821,48.7964165377198;2.33598023504019,48.9742363027763;;car;fastest;polyline;true;true
+bduni-idf-osrm;3.1219716783613,48.9284332596697;1.93459122255445,48.9302670808276;;;;polyline;true;true
+bduni-idf-osrm;1.85347410105169,48.5623292586068;1.87565202154219,48.8267301582033;;car;fastest;polyline;true;true
+bduni-idf-osrm;2.2769722353667,49.0718624827452;2.48952550180256,48.8390767888166;;;fastest;polyline;true;true
+bduni-idf-osrm;1.71951768808067,48.4922047724947;2.371133909747,48.6451014467282;;;;polyline;true;true
+bduni-idf-osrm;2.27931108362973,48.5834542725701;1.78422989808023,48.6993033653358;;;;polyline;true;true
+bduni-idf-osrm;2.65721126645803,49.0341246748343;2.4685234580189,48.4883759838995;;;fastest;polyline;true;true
+bduni-idf-osrm;1.72670273520052,48.6091325195273;3.18409432508051,48.6388877378544;;car;fastest;polyline;true;true
+bduni-idf-osrm;3.15767398253083,48.4921172051691;2.56231252923608,48.6639785184991;;;fastest;polyline;true;true
+bduni-idf-osrm;2.33809377290308,49.0662992510945;2.64215860851109,48.984148150729;;car;;polyline;true;true
+bduni-idf-osrm;1.74986352920532,48.4846012684749;3.15085980184376,48.600839496241;;;fastest;polyline;true;true
+bduni-idf-osrm;1.88929816000164,48.7471217040671;1.97713369987905,48.791406722297;;car;;polyline;true;true
+bduni-idf-osrm;3.24412962421775,48.5043474580627;1.82923176512122,48.8328967497917;;car;;polyline;true;true
diff --git a/test/load/gatling/user-files/resources/routePgr.ssv b/test/load/gatling/user-files/resources/routePgr.ssv
new file mode 100644
index 0000000..35d9913
--- /dev/null
+++ b/test/load/gatling/user-files/resources/routePgr.ssv
@@ -0,0 +1,101 @@
+resource;start;end;intermediates;profile;optimization;geometryFormat;getSteps;getBbox
+bduni-idf-pgr;2.44302401952445,48.4137148207752;2.7731701053679,48.868175015063;;;fastest;polyline;true;true
+bduni-idf-pgr;2.7731701053679,48.868175015063;2.56277133412659,48.6960634629475;;;fastest;polyline;true;true
+bduni-idf-pgr;2.35450194738805,49.0751770148287;1.85215365886688,48.4394219123526;;car;;polyline;true;true
+bduni-idf-pgr;2.56277133412659,48.6960634629475;1.74224134907126,48.9479846086819;;car;;polyline;true;true
+bduni-idf-pgr;2.23373788073659,48.6410320689902;2.62949723191559,48.6433561834972;;car;;polyline;true;true
+bduni-idf-pgr;1.85215365886688,48.4394219123526;1.77042682394385,48.6283194552176;;car;;polyline;true;true
+bduni-idf-pgr;2.63650365769863,49.0903410648694;3.14853146634996,48.9014406567905;;;;polyline;true;true
+bduni-idf-pgr;1.74224134907126,48.9479846086819;2.08896000832319,49.0502271274105;;car;fastest;polyline;true;true
+bduni-idf-pgr;1.97092077694833,48.887046989752;2.41960498057306,49.0230359021341;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.62949723191559,48.6433561834972;3.03651972003281,48.6488741465611;;;;polyline;true;true
+bduni-idf-pgr;2.33698104396462,48.5964256068459;1.72928794324398,48.8457934149308;;;fastest;polyline;true;true
+bduni-idf-pgr;1.77042682394385,48.6283194552176;2.29819886684418,48.839445828693;;;fastest;polyline;true;true
+bduni-idf-pgr;2.15232158452272,48.7187696998008;1.94806619845331,48.4511461691232;;;;polyline;true;true
+bduni-idf-pgr;3.14853146634996,48.9014406567905;3.05042917504907,48.5749592368724;;car;;polyline;true;true
+bduni-idf-pgr;3.17251162007451,48.6573443401372;2.33938915580511,49.036685355613;;;;polyline;true;true
+bduni-idf-pgr;2.08896000832319,49.0502271274105;2.82994266860187,49.0329269678332;;car;;polyline;true;true
+bduni-idf-pgr;2.68978281058371,48.8112607997376;3.02433839887381,49.0986915396061;;car;;polyline;true;true
+bduni-idf-pgr;2.41960498057306,49.0230359021341;2.61582909338176,48.7528171760961;;car;fastest;polyline;true;true
+bduni-idf-pgr;3.07776795178652,49.0640629309462;3.29302724190056,48.4269115800736;;;;polyline;true;true
+bduni-idf-pgr;3.03651972003281,48.6488741465611;2.9313952114433,49.0990003583254;;;;polyline;true;true
+bduni-idf-pgr;1.71925774142146,48.551671803114;1.9602685533464,49.0086243897676;;car;;polyline;true;true
+bduni-idf-pgr;1.72928794324398,48.8457934149308;1.87770117819309,48.959950564173;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.28236234672368,48.561669227411;2.80005635507405,48.6121139103547;;;;polyline;true;true
+bduni-idf-pgr;2.29819886684418,48.839445828693;1.80565406046808,48.8567842453951;;;;polyline;true;true
+bduni-idf-pgr;2.65340593419969,48.5115093970904;2.22147331535816,48.7309725905536;;car;;polyline;true;true
+bduni-idf-pgr;1.94806619845331,48.4511461691232;2.21968059018254,48.9512196605792;;;;polyline;true;true
+bduni-idf-pgr;1.79766307622194,49.0639751890674;2.04447524771094,48.604622562998;;;fastest;polyline;true;true
+bduni-idf-pgr;3.05042917504907,48.5749592368724;2.7201017331332,49.03883580931;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.94450366199017,49.0480559564894;2.92997411340475,48.7645577440504;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.33938915580511,49.036685355613;3.13090001307428,49.0978166022105;;car;;polyline;true;true
+bduni-idf-pgr;3.00574745200574,48.6070149338106;2.14300098456442,48.4424930648878;;;fastest;polyline;true;true
+bduni-idf-pgr;2.82994266860187,49.0329269678332;3.03060300946236,48.9548852890963;;;fastest;polyline;true;true
+bduni-idf-pgr;1.75955604799092,48.7252603389323;3.02805497646332,48.7392871859018;;;fastest;polyline;true;true
+bduni-idf-pgr;3.02433839887381,49.0986915396061;3.2080610755831,48.9742621842306;;car;fastest;polyline;true;true
+bduni-idf-pgr;1.86801247894764,48.5516593190609;1.89905630238354,48.9370307860896;;;fastest;polyline;true;true
+bduni-idf-pgr;2.61582909338176,48.7528171760961;2.74377198666334,48.5289590148954;;;;polyline;true;true
+bduni-idf-pgr;3.2478683128953,49.0825153477024;2.52931407950819,48.82735147723;;car;;polyline;true;true
+bduni-idf-pgr;3.29302724190056,48.4269115800736;2.52194954827428,48.7472926355898;;;;polyline;true;true
+bduni-idf-pgr;1.74633691161871,49.0965433740057;2.00636674277484,48.590260257991;;;fastest;polyline;true;true
+bduni-idf-pgr;2.9313952114433,49.0990003583254;2.77043087631464,48.698779434571;;;fastest;polyline;true;true
+bduni-idf-pgr;3.10948592796922,49.0504662042484;2.08577245622873,48.5230459463317;;;;polyline;true;true
+bduni-idf-pgr;1.9602685533464,49.0086243897676;3.00240580327809,49.011906299321;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.28719979822636,48.7777114449535;2.51701880581677,48.4398246585857;;car;;polyline;true;true
+bduni-idf-pgr;1.87770117819309,48.959950564173;3.13924142792821,48.7964165377198;;;fastest;polyline;true;true
+bduni-idf-pgr;2.85333677828312,48.6062430019956;1.85347410105169,48.5623292586068;;;;polyline;true;true
+bduni-idf-pgr;2.80005635507405,48.6121139103547;1.71951768808067,48.4922047724947;;car;;polyline;true;true
+bduni-idf-pgr;2.86846008636057,48.8194918020628;2.65721126645803,49.0341246748343;;car;fastest;polyline;true;true
+bduni-idf-pgr;1.80565406046808,48.8567842453951;3.15767398253083,48.4921172051691;;car;;polyline;true;true
+bduni-idf-pgr;2.21233152970672,49.0853195460746;1.74986352920532,48.4846012684749;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.22147331535816,48.7309725905536;3.24412962421775,48.5043474580627;;;;polyline;true;true
+bduni-idf-pgr;2.46903090253472,48.7825470240787;2.24155541658401,48.924730171659;;car;;polyline;true;true
+bduni-idf-pgr;2.21968059018254,48.9512196605792;2.07961494810879,48.4085965128383;;;;polyline;true;true
+bduni-idf-pgr;2.15995734296739,48.6497260325123;3.08779237866402,48.9104905051412;;;;polyline;true;true
+bduni-idf-pgr;2.04447524771094,48.604622562998;2.26028655618429,48.65906533706;;car;;polyline;true;true
+bduni-idf-pgr;2.63795228265226,48.470772205526;2.10360035635531,48.7667713400209;;car;;polyline;true;true
+bduni-idf-pgr;2.7201017331332,49.03883580931;2.92441692948341,49.0818783620838;;car;;polyline;true;true
+bduni-idf-pgr;3.24241158999503,48.5104270996992;2.68016149103642,48.9174412503606;;;fastest;polyline;true;true
+bduni-idf-pgr;2.92997411340475,48.7645577440504;2.25455458052456,48.5617117720889;;;fastest;polyline;true;true
+bduni-idf-pgr;3.10586747080088,48.8151862436673;2.11147376447916,48.7175056818407;;;;polyline;true;true
+bduni-idf-pgr;3.13090001307428,49.0978166022105;3.06813656724989,49.0666487353155;;;;polyline;true;true
+bduni-idf-pgr;1.75176373198628,48.6717312326888;2.97977443821728,48.5418979424285;;car;;polyline;true;true
+bduni-idf-pgr;2.14300098456442,48.4424930648878;1.77868135385215,48.6940694178222;;;fastest;polyline;true;true
+bduni-idf-pgr;1.77052700333297,48.5874861966819;2.28014034964144,48.4508814013563;;;fastest;polyline;true;true
+bduni-idf-pgr;3.03060300946236,48.9548852890963;2.16519124992192,48.4554131807759;;car;fastest;polyline;true;true
+bduni-idf-pgr;1.82130594663322,48.9569179091603;2.56359329149127,49.0558625487611;;car;fastest;polyline;true;true
+bduni-idf-pgr;3.02805497646332,48.7392871859018;2.20090577974915,48.8656499942997;;;;polyline;true;true
+bduni-idf-pgr;1.77758952975273,48.8166411499027;1.81617962121964,49.029776561656;;;;polyline;true;true
+bduni-idf-pgr;3.2080610755831,48.9742621842306;2.3203807298094,49.0524362850701;;car;;polyline;true;true
+bduni-idf-pgr;1.79864390790462,48.8007683404721;2.40034448355436,49.0499207292916;;;fastest;polyline;true;true
+bduni-idf-pgr;1.89905630238354,48.9370307860896;3.01475152149796,48.7522216537734;;;fastest;polyline;true;true
+bduni-idf-pgr;2.80626571998,48.7127389817731;2.9590084515512,48.7590084518772;;;fastest;polyline;true;true
+bduni-idf-pgr;2.74377198666334,48.5289590148954;2.66359091699123,48.5864080399973;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.62659822516143,49.0045754485996;2.69223699234426,48.781094395183;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.52931407950819,48.82735147723;1.84350316822529,48.7271079975413;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.92537104487419,48.4460248626536;2.06936389505863,48.4106162068434;;car;;polyline;true;true
+bduni-idf-pgr;2.52194954827428,48.7472926355898;2.12147863954306,48.6167812872445;;car;fastest;polyline;true;true
+bduni-idf-pgr;3.00405092947185,48.928900136007;3.05554540157318,48.9368265053024;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.00636674277484,48.590260257991;1.72362964600325,48.8008628757438;;;;polyline;true;true
+bduni-idf-pgr;2.44998060241342,48.9409831087571;2.58977488055825,48.5484650451224;;;fastest;polyline;true;true
+bduni-idf-pgr;2.77043087631464,48.698779434571;2.85722216144204,48.8624128093012;;;;polyline;true;true
+bduni-idf-pgr;2.36744628064334,48.5593186914921;2.24830394499004,48.447400964587;;car;;polyline;true;true
+bduni-idf-pgr;2.08577245622873,48.5230459463317;1.89837341569364,48.5615852880524;;;fastest;polyline;true;true
+bduni-idf-pgr;2.97855033129454,48.4272446077317;1.86097037009895,48.9765269104158;;;fastest;polyline;true;true
+bduni-idf-pgr;3.00240580327809,49.011906299321;1.77136054523289,48.5881791703403;;;;polyline;true;true
+bduni-idf-pgr;2.01686525307596,48.559019746189;2.92506045550108,48.8759416235844;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.51701880581677,48.4398246585857;1.82099920958281,48.9100377754308;;;;polyline;true;true
+bduni-idf-pgr;2.54839190617204,48.508401370002;2.26064089313149,48.600889604562;;;;polyline;true;true
+bduni-idf-pgr;3.13924142792821,48.7964165377198;2.33598023504019,48.9742363027763;;car;fastest;polyline;true;true
+bduni-idf-pgr;3.1219716783613,48.9284332596697;1.93459122255445,48.9302670808276;;;;polyline;true;true
+bduni-idf-pgr;1.85347410105169,48.5623292586068;1.87565202154219,48.8267301582033;;car;fastest;polyline;true;true
+bduni-idf-pgr;2.2769722353667,49.0718624827452;2.48952550180256,48.8390767888166;;;fastest;polyline;true;true
+bduni-idf-pgr;1.71951768808067,48.4922047724947;2.371133909747,48.6451014467282;;;;polyline;true;true
+bduni-idf-pgr;2.27931108362973,48.5834542725701;1.78422989808023,48.6993033653358;;;;polyline;true;true
+bduni-idf-pgr;2.65721126645803,49.0341246748343;2.4685234580189,48.4883759838995;;;fastest;polyline;true;true
+bduni-idf-pgr;1.72670273520052,48.6091325195273;3.18409432508051,48.6388877378544;;car;fastest;polyline;true;true
+bduni-idf-pgr;3.15767398253083,48.4921172051691;2.56231252923608,48.6639785184991;;;fastest;polyline;true;true
+bduni-idf-pgr;2.33809377290308,49.0662992510945;2.64215860851109,48.984148150729;;car;;polyline;true;true
+bduni-idf-pgr;1.74986352920532,48.4846012684749;3.15085980184376,48.600839496241;;;fastest;polyline;true;true
+bduni-idf-pgr;1.88929816000164,48.7471217040671;1.97713369987905,48.791406722297;;car;;polyline;true;true
+bduni-idf-pgr;3.24412962421775,48.5043474580627;1.82923176512122,48.8328967497917;;car;;polyline;true;true
diff --git a/test/load/gatling/user-files/simulations/road2_route.scala b/test/load/gatling/user-files/simulations/dataOsm.scala
similarity index 74%
rename from test/load/gatling/user-files/simulations/road2_route.scala
rename to test/load/gatling/user-files/simulations/dataOsm.scala
index 1a00690..d2a731c 100644
--- a/test/load/gatling/user-files/simulations/road2_route.scala
+++ b/test/load/gatling/user-files/simulations/dataOsm.scala
@@ -2,9 +2,9 @@ import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
-class road2RouteLoadTest extends Simulation {
+class dataOsm extends Simulation {
- val urls = ssv("./resources/road2_parameters.ssv").shuffle.circular
+ val urls = ssv("/home/docker/data/road2_parameters.ssv").shuffle.circular
val httpConf = http.baseUrl("http://road2:8080/simple/1.0.0/route?").disableCaching
@@ -17,8 +17,6 @@ class road2RouteLoadTest extends Simulation {
setUp(
scn.inject(
- // nothingFor(5 seconds),
- // rampUsersPerSec (0) to (10) during (60 seconds),
constantUsersPerSec(1) during (100 seconds) randomized
).protocols(httpConf))
diff --git a/test/load/gatling/user-files/simulations/road2_iso.scala b/test/load/gatling/user-files/simulations/isoPgr.scala
similarity index 73%
rename from test/load/gatling/user-files/simulations/road2_iso.scala
rename to test/load/gatling/user-files/simulations/isoPgr.scala
index 9755e2d..a4fad8a 100644
--- a/test/load/gatling/user-files/simulations/road2_iso.scala
+++ b/test/load/gatling/user-files/simulations/isoPgr.scala
@@ -2,9 +2,9 @@ import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
-class road2IsoLoadTest extends Simulation {
+class isoPgr extends Simulation {
- val urls = ssv("./resources/road2_parameters_iso.ssv").shuffle.circular
+ val urls = ssv("./resources/isoPgr.ssv").shuffle.circular
val httpConf = http.baseUrl("http://road2:8080/simple/1.0.0/isochrone?").disableCaching
@@ -17,8 +17,6 @@ class road2IsoLoadTest extends Simulation {
setUp(
scn.inject(
- // nothingFor(5 seconds),
- // rampUsersPerSec (0) to (10) during (60 seconds),
constantUsersPerSec(1) during (60 seconds) randomized
).protocols(httpConf))
diff --git a/test/load/gatling/user-files/simulations/road2_route_pgr.scala b/test/load/gatling/user-files/simulations/routeOsrm.scala
similarity index 65%
rename from test/load/gatling/user-files/simulations/road2_route_pgr.scala
rename to test/load/gatling/user-files/simulations/routeOsrm.scala
index 044b3a5..532ecfb 100644
--- a/test/load/gatling/user-files/simulations/road2_route_pgr.scala
+++ b/test/load/gatling/user-files/simulations/routeOsrm.scala
@@ -2,9 +2,9 @@ import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
-class road2RouteLoadTestPgr extends Simulation {
+class routeOsrm extends Simulation {
- val urls = ssv("./resources/road2_parameters_idf_pgr_wo_int.ssv").shuffle.circular
+ val urls = ssv("./resources/routeOsrm.ssv").shuffle.circular
val httpConf = http.baseUrl("http://road2:8080/simple/1.0.0/route?").disableCaching
@@ -17,9 +17,7 @@ class road2RouteLoadTestPgr extends Simulation {
setUp(
scn.inject(
- // nothingFor(5 seconds),
- // rampUsersPerSec (0) to (10) during (60 seconds),
- constantUsersPerSec(1) during (300 seconds) randomized
+ constantUsersPerSec(1) during (60 seconds) randomized
).protocols(httpConf))
}
diff --git a/test/load/gatling/user-files/simulations/routePgr.scala b/test/load/gatling/user-files/simulations/routePgr.scala
new file mode 100644
index 0000000..b716743
--- /dev/null
+++ b/test/load/gatling/user-files/simulations/routePgr.scala
@@ -0,0 +1,23 @@
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+import scala.concurrent.duration._
+
+class routePgr extends Simulation {
+
+ val urls = ssv("./resources/routePgr.ssv").shuffle.circular
+
+ val httpConf = http.baseUrl("http://road2:8080/simple/1.0.0/route?").disableCaching
+
+ val scn = scenario("road2")
+ .feed(urls).repeat(1){
+ exec(
+ http("compute").get("resource=${resource}&profile=${profile}&optimization=${optimization}&start=${start}&end=${end}&intermediates=${intermediates}&geometryFormat=${geometryFormat}&getSteps=${getSteps}&getBbox=${getBbox}")
+ )
+ }
+
+ setUp(
+ scn.inject(
+ constantUsersPerSec(1) during (60 seconds) randomized
+ ).protocols(httpConf))
+
+}
diff --git a/test/load/readme.md b/test/load/readme.md
index c1771fc..f4ab26d 100644
--- a/test/load/readme.md
+++ b/test/load/readme.md
@@ -6,12 +6,11 @@ Ce dossier contient les scripts utiles aux tests de charges. Ces tests sont effe
Le dossier `gatling` contient le dossier `user-files` nécessaire à Getling pour effectuer les tests. On y retrouve donc la définition des simulations et les ressources nécessaire. En l'état, il est possible de lancer le scénario contenu dans `gatling/user-files/simulations/road2.scala` qui utilise la ressource `gatling/user-files/resources/road2_parameters.ssv`.
-Si Gatling est installé sur la machine, on pourra pointer le dossier `user-files`. De la même manière, il est possible d'utiliser Docker.
+Si Gatling est installé sur la machine, on pourra pointer le dossier `user-files`. Pour plus d'informations, voir le site [officiel](https://gatling.io/).
-Avec le `docker-compose` du repository, il est possible de lancer les tests de charge avec les données déjà disponibles:
-`docker-compose up road2-gatling`
+Autrement, il est possible d'utiliser l'image docker disponible sur [dockerhub](https://hub.docker.com/r/denvazh/gatling).
-Pour utiliser le `docker-compose` avec d'autres données, il suffira de modifier le `.env` associé et ainsi de pointer vers un autre `user-files`. On priviligiera cette approche à celle modifiant les fichiers de ce repository.
+C'est ce qui est fait dans le [docker-compose](../../docker/test/) dédié aux tests dans ce dépôt. Voir le [readme](../../docker/test/readme.md) pour son utilisation.
## random-route-generator
From ae5cc479af272a57965524625741c2f406d73455 Mon Sep 17 00:00:00 2001
From: Loic
Date: Thu, 1 Dec 2022 14:36:07 +0100
Subject: [PATCH 22/93] =?UTF-8?q?[deps]=20maj=20de=20nombreuses=20d=C3=A9p?=
=?UTF-8?q?endances?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
changelog.md | 12 +++
docker/demonstration/Dockerfile | 2 +-
package.json | 18 ++--
readme.md | 2 +-
.../cucumber/features/support/world.js | 2 +-
test/integration/readme.md | 101 +++++++++++++++++-
6 files changed, 124 insertions(+), 13 deletions(-)
diff --git a/changelog.md b/changelog.md
index 42c3f18..bf11cea 100644
--- a/changelog.md
+++ b/changelog.md
@@ -11,6 +11,18 @@ CHANGED:
- Les sources ne sont plus configurées dans le même fichier que les ressources. Chaque source est configurée dans son fichier. L'ensemble est placé dans un dossier de sources. Il peut y en avoir plusieurs.
- Les sources PGRouting et Valhalla ne sont plus configurées de la même manière : chaque source de ces types peut contenir plusieurs coûts.
+UPDATED:
+ - Passage à `osrm` 5.26.0
+ - Passage à `pg` 8.8.0
+ - Passage à `turf` 6.5.0
+ - Passage à `express` 4.18.2
+ - Passage à `helmet` 6.0.1
+ - Passage à `https-proxy-agent` 5.0.1
+ - Passage à `log4js` 6.7.1
+ - Passage à `nconf` 0.12.0
+ - Passage à `proj4` 2.8.0
+ - Utilisation de NodeJS 16 dans docker
+
# 1.1.2
FIXED:
diff --git a/docker/demonstration/Dockerfile b/docker/demonstration/Dockerfile
index 62e9ea0..301bb70 100644
--- a/docker/demonstration/Dockerfile
+++ b/docker/demonstration/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:12-alpine
+FROM node:16-alpine
### Dossier contenant la configuration
WORKDIR /home/docker/config
diff --git a/package.json b/package.json
index 83c4c1b..2582d2c 100644
--- a/package.json
+++ b/package.json
@@ -18,21 +18,21 @@
},
"dependencies": {
"@mapbox/polyline": "1.1.1",
- "@turf/turf": "5.1.6",
+ "@turf/turf": "6.5.0",
"assert": "2.0.0",
"cors": "2.8.5",
- "express": "4.16.4",
+ "express": "4.18.2",
"got": "11.8.2",
- "helmet": "3.21.2",
- "https-proxy-agent": "5.0.0",
- "log4js": "6.1.0",
- "nconf": "0.10.0",
- "proj4": "2.6.0",
+ "helmet": "6.0.1",
+ "https-proxy-agent": "5.0.1",
+ "log4js": "6.7.1",
+ "nconf": "0.12.0",
+ "proj4": "2.8.0",
"wkt": "0.1.1"
},
"optionalDependencies": {
- "osrm": "5.25.0",
- "pg": "7.17.1"
+ "osrm": "5.26.0",
+ "pg": "8.8.0"
},
"devDependencies": {
"sinon": "^7.2.7",
diff --git a/readme.md b/readme.md
index 05ca3ae..ef6fb6a 100644
--- a/readme.md
+++ b/readme.md
@@ -58,7 +58,7 @@ NB : Il y a des dépendances optionnelles pour gérer celles de chaque moteur. P
### Génération de données
Qu'importe la source des données, il est nécessaire de les fournir dans l'un des formats utilisables par Road2. Étant donné que ce dernier peut utiliser plusieurs moteurs les calculs, il accepte plusieurs formats de données:
-- OSRM 5.25.0 rend possible l'utilisation de données OSRM générées avec cette version.
+- OSRM 5.26.0 rend possible l'utilisation de données OSRM générées avec cette version.
- PGRouting 3.1.3 rend possible l'utilisation d'une base de données utilisant cette version. Il sera nécessaire d'y ajouter les procédures du projet [pgrouting-procedures](https://github.com/IGNF/pgrouting-procedures) afin que Road2 puisse communiquer avec la base.
Ces données peuvent donc être générées à partir d'une base de données quelconque, ou de fichiers OSM. Le projet [route-graph-generator](https://github.com/IGNF/route-graph-generator) propose des outils pour générer les graphes à partir de n'importe quelle base de données ou fichier osm. Si la base de données ne correspondant pas au format de la base attendue par route-graph-generator, il suffira de la dériver.
diff --git a/test/functional/configuration/cucumber/features/support/world.js b/test/functional/configuration/cucumber/features/support/world.js
index 50a8c30..9fc42bd 100644
--- a/test/functional/configuration/cucumber/features/support/world.js
+++ b/test/functional/configuration/cucumber/features/support/world.js
@@ -662,7 +662,7 @@ class road2World {
if (this._cleanTmpDirectories) {
- fs.rmdir(this._tmpDirConf, {
+ fs.rm(this._tmpDirConf, {
"recursive": true
}, (err) => { return err;});
diff --git a/test/integration/readme.md b/test/integration/readme.md
index 3d54512..a733d48 100644
--- a/test/integration/readme.md
+++ b/test/integration/readme.md
@@ -1,5 +1,7 @@
# Description des tests d'intégration
+## Tests des classes
+
Pour lancer les tests d'intégration, il est conseillé d'utiliser docker-compose afin de disposer d'un environnement de test plus complet:
```
docker-compose up -d road2
@@ -64,4 +66,101 @@ Autres:
- controller.js de l'api simple 1.0.0
- index.js de l'api simple 1.0.0
- init.js de l'api simple 1.0.0
- - update.js de l'api simple 1.0.0
\ No newline at end of file
+ - update.js de l'api simple 1.0.0
+
+## Tests des dépendances
+
+### Liste des dépendances et de leurs usages
+
+- @mapbox/polyline
+ - geometry/line.js
+ - encode()
+ - toGeoJSON()
+ - fromGeoJSON()
+ - geometry/polygon.js
+ - encode()
+ - toGeoJSON()
+ - fromGeoJSON()
+
+- @turf/turf
+ - apis/simple/1.0.0/controller/controller.js
+ - bbox()
+ - lineSlice()
+ - geometry/polygon.js
+ - polygon()
+ - polygonToLine()
+ - sources/pgrSource.js
+ - point()
+ - truncate()
+ - lineSlice()
+ - nearestPointOnLine()
+ - length()
+ - cleanCoords()
+
+- assert
+ - deepStrictEqual()
+ - equal()
+ - deepEqual()
+
+- cors
+ - service/service.js
+ - ()
+
+- express
+ - administrator/administrator.js
+ - ()
+ - use()
+ - Router()
+ - router.use()
+ - json()
+
+- got
+ - utils/httpQuery.js
+ - ()
+ - post()
+
+- helmet
+ - administrator/administrator.js
+ - ()
+ - service/service.js
+ - ()
+
+- https-proxy-agent
+ - utils/httpQuery.js
+ - ()
+
+- log4js
+ - configure()
+ - getLogger()
+
+- nconf
+ - road2.js
+ - use()
+ - get()
+ - argv().get()
+ - argv().env()
+
+- proj4
+ - geography/projectionManager.js
+ - defs()
+ - ()
+
+- wkt
+ - sources/smartroutingSource.js
+ - parse()
+
+- osrm
+ - sources/sourceManager.js
+ - sources/osrmSource.js
+ - route()
+ - nearest()
+
+- pg {Pool}
+ - base/base.js
+ - ()
+ - connect()
+ - end()
+ - base/baseManager.js
+ - sources/sourcesManager.js
+ - sources/pgrSource.js
+ - query()
\ No newline at end of file
From e0ca4582349ccb6774d7f12acbb1d5007eb20767 Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 5 Dec 2022 10:29:56 +0100
Subject: [PATCH 23/93] [docker] build de valhalla pour les dev
---
docker/demonstration/readme.md | 2 +-
docker/dev/docker-compose.yml | 2 +-
docker/distributions/centos-wo-aws/Dockerfile | 128 ------------------
docker/distributions/centos-wo-aws/readme.md | 69 ----------
docker/distributions/centos/Dockerfile | 91 -------------
docker/distributions/centos/readme.md | 55 --------
docker/distributions/debian/Dockerfile | 115 ++++++----------
docker/readme.md | 4 +-
docker/route-graph-generator | 2 +-
documentation/developers/version.md | 8 +-
src/js/sources/sourceManager.js | 1 +
.../features/req-simple-1.0.0-pgr.feature | 66 +++++++++
12 files changed, 120 insertions(+), 423 deletions(-)
delete mode 100644 docker/distributions/centos-wo-aws/Dockerfile
delete mode 100644 docker/distributions/centos-wo-aws/readme.md
delete mode 100644 docker/distributions/centos/Dockerfile
delete mode 100644 docker/distributions/centos/readme.md
diff --git a/docker/demonstration/readme.md b/docker/demonstration/readme.md
index 9f3cea3..97b88b9 100644
--- a/docker/demonstration/readme.md
+++ b/docker/demonstration/readme.md
@@ -1,6 +1,6 @@
# Démonstration locale de Road2
-Ce fichier décrit les instructions à suivre pour avoir une démonstration locale de Road2.
+Ce fichier décrit les instructions à suivre pour avoir une démonstration locale de Road2 limitée aux moteurs OSRM et PGRouting.
## Principe
diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml
index 7def3fc..a7869ec 100644
--- a/docker/dev/docker-compose.yml
+++ b/docker/dev/docker-compose.yml
@@ -4,7 +4,7 @@ services:
road2:
build:
context: ../..
- dockerfile: ./docker/demonstration/Dockerfile
+ dockerfile: ./docker/distributions/debian/Dockerfile
image: road2
container_name: road2-server
depends_on:
diff --git a/docker/distributions/centos-wo-aws/Dockerfile b/docker/distributions/centos-wo-aws/Dockerfile
deleted file mode 100644
index 5fe080f..0000000
--- a/docker/distributions/centos-wo-aws/Dockerfile
+++ /dev/null
@@ -1,128 +0,0 @@
-FROM centos:7.8.2003
-
-LABEL maintainer="IGN "
-LABEL version="1.2"
-
-### MAJ
-RUN yum -y update && \
- yum -y upgrade && \
- yum install -y yum-utils centos-release-scl epel-release && \
- yum-config-manager --enable rhel-server-rhscl-7-rpms
-
-### Utilitaires et dépendances
-# Pour NodeJS: python-2.7.5
-# Un compilateur pour Boost et GCC 6: gcc-c++
-# Un compilateur c++ plus récent (8) pour NodeJS: devtoolset-8
-# Pour GCC 6.3.0 afin de compiler OSRM: GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+
-# Pour OSRM: boost 1.65.1; expat 2.2.0; lua 5.2.4; bzip2 1.0.6; tbb
-# Pour Boost: openmpi-devel python-devel
-# Pour LUA: readline-devel
-RUN yum -y install wget vim git python-2.7.5 gcc-c++ devtoolset-8 gmp-devel \
- mpfr-devel libmpc-devel flex flex-devel cmake3 zlib zlib-devel tbb tbb-devel \
- expat expat-devel lbzip2 bzip2-devel openmpi-devel python-devel readline-devel
-
-### Installation de NodeJS à partir des sources
-# https://github.com/nodejs/node/blob/v12.x/BUILDING.md
-# https://github.com/nodejs/help/wiki/Installation
-WORKDIR /home/docker/nodejs
-RUN wget -O node-v12.14.0.tar.gz "https://nodejs.org/dist/v12.14.0/node-v12.14.0.tar.gz" && \
- tar -xzf /home/docker/nodejs/node-v12.14.0.tar.gz && \
- scl enable devtoolset-8 bash && export CXX=/opt/rh/devtoolset-8/root/usr/bin/g++ && \
- cd node-v12.14.0 && ./configure && make -j4 && make install && \
- cd .. && rm -rf node-v12.14.0 node-v12.14.0.tar.gz
-
-### Installation de gcc 6.2.0 pour compiler OSRM
-# La compilation est volontairement en dehors des sources de gcc (voir documentation)
-# https://gibsonic.org/tools/2019/08/08/gcc_building.html
-WORKDIR /home/docker/gcc
-RUN git clone -b releases/gcc-6.3.0 --depth 1 https://gcc.gnu.org/git/gcc.git && \
- mkdir /home/docker/gcc/objdir && cd objdir && \
- /home/docker/gcc/gcc/configure --prefix=$(pwd) --disable-multilib --disable-werror --enable-languages=c,c++ && \
- make -j4 && make DESTDIR=/opt/gcc-6/ install && \
- cd .. && rm -rf gcc objdir
-
-### Installation des dépendances de OSRM
-# https://github.com/Project-OSRM/osrm-backend/wiki/Building-OSRM
-
-# Installation de boost 1.65.1 (boost, filesystem, iostreams, program-options, regex, test, date-time, thread, system)
-WORKDIR /home/docker/boost
-RUN wget https://dl.bintray.com/boostorg/release/1.65.1/source/boost_1_65_1.tar.gz && tar -xzf boost_1_65_1.tar.gz && \
- cd boost_1_65_1 && ./bootstrap.sh && ./b2 install && \
- cd .. && rm -rf boost_1_65_1 boost_1_65_1.tar.gz
-
-# Installation de lua 5.2.4
-WORKDIR /home/docker/lua
-RUN wget http://www.lua.org/ftp/lua-5.2.4.tar.gz && tar zxf lua-5.2.4.tar.gz && \
- cd lua-5.2.4 && make linux test && make linux install && \
- cd .. && rm -rf lua-5.2.4 lua-5.2.4.tar.gz
-
-### Installation de OSRM pour utiliser la libosrm dans Road2
-# https://github.com/Project-OSRM/osrm-backend
-# https://github.com/Project-OSRM/osrm-backend/blob/master/docs/nodejs/api.md
-# https://github.com/door2door-io/osrm-express-server-demo
-# https://github.com/Project-OSRM/osrm-backend/blob/master/CMakeLists.txt
-# https://developers.redhat.com/blog/2015/02/05/gcc5-and-the-c11-abi/
-WORKDIR /home/docker/osrm
-RUN wget https://github.com/Project-OSRM/osrm-backend/archive/v5.25.0.zip && unzip v5.25.0.zip -d ./osrm-backend && \
- cd /home/docker/osrm/osrm-backend/osrm-backend-5.25.0/ && \
- npm install --production && \
- mkdir build && cd /home/docker/osrm/osrm-backend/osrm-backend-5.25.0/build && \
- export CC=/opt/gcc-6/home/docker/gcc/objdir/bin/gcc && export CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" && \
- cmake3 .. -DCMAKE_BUILD_TYPE=Release -DENABLE_MASON=OFF -DCMAKE_CXX_COMPILER=/opt/gcc-6/home/docker/gcc/objdir/bin/g++ -DENABLE_NODE_BINDINGS=ON && \
- make -j4 && make install
-# https://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.how_to_set_paths
-ENV LD_LIBRARY_PATH=/opt/gcc-6/home/docker/gcc/objdir/lib64:$LD_LIBRARY_PATH
-
-### Creation du binding NodeJS d'OSRM
-WORKDIR /home/docker/osrm/nodejs-binding/
-# Création du module node osrm et petit nettoyage de ce qui n'est plus utile
-RUN mkdir -p osrm-5.25.0/lib && mkdir -p osrm-5.25.0/node_modules && cp -r ../osrm-backend/osrm-backend-5.25.0/lib/* osrm-5.25.0/lib/ && \
- cp /usr/lib64/libtbb* osrm-5.25.0/lib/binding/ && cp -r ../osrm-backend/osrm-backend-5.25.0/node_modules/* osrm-5.25.0/node_modules && \
- cp ../osrm-backend/osrm-backend-5.25.0/package* osrm-5.25.0/ && cp ../osrm-backend/osrm-backend-5.25.0/taginfo.json osrm-5.25.0/ && \
- tar -cvzf osrm-5.25.0.tgz osrm-5.25.0/ && \
- cd .. && rm -rf v5.25.0.zip osrm-backend nodejs-binding/osrm-5.25.0
-
-### Dossier des données
-WORKDIR /home/docker/internal
-
-### Récupération de données sur la Corse
-RUN wget download.geofabrik.de/europe/france/corse-latest.osm.pbf && osrm-extract corse-latest.osm.pbf -p /usr/local/share/osrm/profiles/car.lua && osrm-contract corse-latest.osrm
-
-### Dossier contenant la configuration
-WORKDIR /home/docker/config
-COPY /docker/config /home/docker/config/
-
-### Dossier de l'application
-WORKDIR /home/docker/app
-
-### Récupération des sources de l'application
-COPY package.json ./
-COPY eslint.json ./
-COPY jsdoc.json ./
-COPY /src ./src/
-COPY /test ./test/
-
-### Installation des dépandences de l'application NodeJS
-# https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
-# https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md
-# https://expressjs.com/fr/starter/installing.html
-RUN sed -i 's/"\s*osrm\s*"\s*:\s*".*",/"osrm":"\/home\/docker\/osrm\/nodejs-binding\/osrm-5\.24\.0\.tgz",/g' package.json
-RUN npm install
-
-### Installation de mocha pour les tests
-# https://mochajs.org/#installation
-RUN npm install mocha -g
-
-### Installation de eslint pour le code
-# https://eslint.org/docs/user-guide/configuring
-RUN npm install eslint -g
-
-### Installation de jsdoc pour la documentation du code
-# http://usejsdoc.org/about-configuring-jsdoc.html
-RUN npm install jsdoc -g
-
-### Volume partagé pour lire les données
-VOLUME ["/home/docker/data"]
-
-### Commande de lancement de l'application
-CMD npm run debug -- --ROAD2_CONF_FILE=/home/docker/config/road2.json
diff --git a/docker/distributions/centos-wo-aws/readme.md b/docker/distributions/centos-wo-aws/readme.md
deleted file mode 100644
index 5099c07..0000000
--- a/docker/distributions/centos-wo-aws/readme.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# Dockerfile pour utiliser Road2 sous CentOS mais sans faire appel à AWS
-
-Il est possible d'installer OSRM, et plus particulièrement le binding NodeJS, depuis les sources sans faire appel aux binaires hébergés sur AWS. Ce dockerfile en est un exemple. Voici la procèdure à suivre:
-
-1. Installer un compilateur pour Boost et GCC 6: gcc-c++
-2. Installer les dépendances pour GCC 6.3.0 afin de compiler OSRM: GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+
-3. Installer les dépendances pour OSRM: boost 1.65.1; expat 2.2.0; lua 5.2.4; bzip2 1.0.6; tbb
-4. Installer les dépendances pour Boost: openmpi-devel python-devel
-5. Installer les dépendances pour LUA: readline-devel
-6. Compiler et installer gcc 6.2.0 pour compiler OSRM
-7. Compiler et installer boost 1.65.1
-8. Compiler et installer lua 5.2.4
-9. Compiler et installer OSRM 5.25.0 (cf Dockerfile)
-10. Ajouter la variable LD_LIBRARY_PATH=/opt/gcc-6/home/docker/gcc/objdir/lib64:$LD_LIBRARY_PATH pour que les binaires trouvent les librairies utilisées lors de la compilation.
-11. Créer le module NodeJS d'OSRM (cf. Dockerfile)
-
-
-# Construction de l'image
-
-Pour construire l'image, il suffit de lancer la commande suivante à la racine du projet Road2:
-```
-docker build -t road2-centos -f docker/centos/Dockerfile .
-```
-
-# Lancer l'application
-
-Pour lancer l'application, il suffit d'utiliser la commande suivante:
-```
-docker run --name road2-centos-server --rm -d -p 8080:8080 road2-centos
-```
-
-## Mode DEBUG
-```
-docker run --name road2-centos-server --rm -it -p 8080:8080 road2-centos /bin/bash
-```
-
-## Pour développer en gardant le code source en local
-```
-docker run --name road2-centos-server --rm -d -p 8080:8080 -v $src:/home/docker/app/src road2-centos
-```
-
-## Pour débugger le mode développement avec les sources en local
-```
-docker run --name road2-centos-server --rm -it -p 8080:8080 -v $src:/home/docker/app/src road2-centos /bin/bash
-```
-# Lancer les tests
-
-Les tests unitaires ont été écrits avec Mocha. Pour les lancer, on utilisera la commande suivante:
-```
-docker run --name road2-centos-server --rm -v $src:/home/docker/app/src -v $test:/home/docker/app/test road2-centos npm run utest
-```
-
-# Lancer eslint
-
-Pour linter le code, il suffit de lancer la commande suivante:
-```
-docker run --name road2-centos-server --rm -v $src:/home/docker/app/src road2-centos npm run lint
-```
-
-# Créer la documentation du code via jsdoc
-
-Le code est documenté via des commentaires. Ces commentaires peuvent être plus ou moins structurés avec des tags. L'outil jsdoc permet de générer un site web à partir de ces commentaires et de ces tags.
-
-Pour créer la documentation, il suffit de lancer la commande suivante:
-```
-docker run --name road2-centos-server --rm -v $doc:/home/docker/app/documentation/code road2-centos npm run jsdoc
-```
-
-La documentation sera alors accessible dans `$doc`.
diff --git a/docker/distributions/centos/Dockerfile b/docker/distributions/centos/Dockerfile
deleted file mode 100644
index a22ebc7..0000000
--- a/docker/distributions/centos/Dockerfile
+++ /dev/null
@@ -1,91 +0,0 @@
-FROM centos:7.5.1804
-
-LABEL maintainer="IGN "
-LABEL version="1.0"
-
-### MAJ
-RUN yum -y update
-RUN yum -y upgrade
-RUN yum install -y yum-utils centos-release-scl epel-release
-RUN yum-config-manager --enable rhel-server-rhscl-7-rpms
-
-### Utilitaires
-RUN yum -y install wget vim
-
-### Installation des dépendances de NodeJS
-RUN yum install -y python-2.7.5
-
-### Installation du compilateur c++
-RUN yum -y install devtoolset-8 gcc gcc-c++
-
-
-
-### Installation de NodeJS à partir des sources
-# https://github.com/nodejs/node/blob/master/BUILDING.md#building-nodejs-on-supported-platforms
-# https://github.com/nodejs/help/wiki/Installation
-WORKDIR /home/docker/nodejs
-RUN wget -O node-v12.14.0.tar.gz "https://nodejs.org/dist/v12.14.0/node-v12.14.0.tar.gz"
-RUN tar -xzf /home/docker/nodejs/node-v12.14.0.tar.gz
-RUN cd node-v12.14.0 && ./configure && make -j4 && make install
-
-### Installation des dépendances de OSRM
-# https://github.com/Project-OSRM/osrm-backend/wiki/Building-OSRM
-RUN scl enable devtoolset-8 bash && yum -y install cmake3 zlib-devel
-
-### Installation de OSRM pour utiliser la libosrm dans Road2
-# https://github.com/Project-OSRM/osrm-backend
-# https://github.com/Project-OSRM/osrm-backend/blob/master/docs/nodejs/api.md
-# https://github.com/door2door-io/osrm-express-server-demo
-# https://github.com/Project-OSRM/osrm-backend/blob/master/CMakeLists.txt
-WORKDIR /home/docker/osrm
-RUN wget https://github.com/Project-OSRM/osrm-backend/archive/v5.25.0.zip
-RUN unzip v5.25.0.zip -d ./osrm-backend
-WORKDIR /home/docker/osrm/osrm-backend/osrm-backend-5.25.0/build
-RUN scl enable devtoolset-8 bash && export CC=/opt/rh/devtoolset-8/root/usr/bin/gcc && cmake3 .. -DCMAKE_BUILD_TYPE=Release -DENABLE_MASON=ON -DCMAKE_CXX_COMPILER=/opt/rh/devtoolset-8/root/usr/bin/g++ && make && make install
-
-### Dossier des données
-WORKDIR /home/docker/internal
-
-### Récupération de données sur la Corse
-# L'objectif est d'avoir un container indépendant du docker-compose
-RUN wget download.geofabrik.de/europe/france/corse-latest.osm.pbf
-RUN osrm-extract corse-latest.osm.pbf -p /usr/local/share/osrm/profiles/car.lua
-RUN osrm-contract corse-latest.osrm
-
-### Dossier contenant la configuration
-WORKDIR /home/docker/config
-COPY /docker/config /home/docker/config/
-
-### Dossier de l'application
-WORKDIR /home/docker/app
-
-### Récupération des sources de l'application
-COPY package.json ./
-COPY eslint.json ./
-COPY jsdoc.json ./
-COPY /src ./src/
-COPY /test ./test/
-
-### Installation des dépandences de l'application NodeJS
-# https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
-# https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md
-# https://expressjs.com/fr/starter/installing.html
-RUN npm install
-
-### Installation de mocha pour les tests
-# https://mochajs.org/#installation
-RUN npm install mocha -g
-
-### Installation de eslint pour le code
-# https://eslint.org/docs/user-guide/configuring
-RUN npm install eslint -g
-
-### Installation de jsdoc pour la documentation du code
-# http://usejsdoc.org/about-configuring-jsdoc.html
-RUN npm install jsdoc -g
-
-### Volume partagé pour lire les données
-VOLUME ["/home/docker/data"]
-
-### Commande de lancement de l'application
-CMD npm run debug -- --ROAD2_CONF_FILE=/home/docker/config/road2.json
diff --git a/docker/distributions/centos/readme.md b/docker/distributions/centos/readme.md
deleted file mode 100644
index 5c4a5f2..0000000
--- a/docker/distributions/centos/readme.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# Dockerfile pour utiliser Road2 sous CentOS
-
-
-# Construction de l'image
-
-Pour construire l'image, il suffit de lancer la commande suivante à la racine du projet Road2:
-```
-docker build -t road2-centos -f docker/centos/Dockerfile .
-```
-
-# Lancer l'application
-
-Pour lancer l'application, il suffit d'utiliser la commande suivante:
-```
-docker run --name road2-centos-server --rm -d -p 8080:8080 road2-centos
-```
-
-## Mode DEBUG
-```
-docker run --name road2-centos-server --rm -it -p 8080:8080 road2-centos /bin/bash
-```
-
-## Pour développer en gardant le code source en local
-```
-docker run --name road2-centos-server --rm -d -p 8080:8080 -v $src:/home/docker/app/src road2-centos
-```
-
-## Pour débugger le mode développement avec les sources en local
-```
-docker run --name road2-centos-server --rm -it -p 8080:8080 -v $src:/home/docker/app/src road2-centos /bin/bash
-```
-# Lancer les tests
-
-Les tests unitaires ont été écrits avec Mocha. Pour les lancer, on utilisera la commande suivante:
-```
-docker run --name road2-centos-server --rm -v $src:/home/docker/app/src -v $test:/home/docker/app/test road2-centos npm run utest
-```
-
-# Lancer eslint
-
-Pour linter le code, il suffit de lancer la commande suivante:
-```
-docker run --name road2-centos-server --rm -v $src:/home/docker/app/src road2-centos npm run lint
-```
-
-# Créer la documentation du code via jsdoc
-
-Le code est documenté via des commentaires. Ces commentaires peuvent être plus ou moins structurés avec des tags. L'outil jsdoc permet de générer un site web à partir de ces commentaires et de ces tags.
-
-Pour créer la documentation, il suffit de lancer la commande suivante:
-```
-docker run --name road2-centos-server --rm -v $doc:/home/docker/app/documentation/code road2-centos npm run jsdoc
-```
-
-La documentation sera alors accessible dans `$doc`.
diff --git a/docker/distributions/debian/Dockerfile b/docker/distributions/debian/Dockerfile
index 5116086..916e07a 100644
--- a/docker/distributions/debian/Dockerfile
+++ b/docker/distributions/debian/Dockerfile
@@ -1,83 +1,56 @@
-FROM debian:buster-20181112
-
-LABEL maintainer="IGN "
-LABEL version="1.0"
-
-### MAJ
-RUN apt-get -y update
-RUN apt-get -y upgrade
-
-### Utilitaires
-RUN apt-get -y install wget vim unzip
-
-### Installation des dépendances de NodeJS
-RUN apt-get install -y python g++ make
-
-### Installation de NodeJS à partir des sources
-# https://github.com/nodejs/node/blob/master/BUILDING.md#building-nodejs-on-supported-platforms
-# https://github.com/nodejs/help/wiki/Installation
-WORKDIR /home/docker/nodejs
-RUN wget -O node-v12.14.0.tar.gz "https://nodejs.org/dist/v12.14.0/node-v12.14.0.tar.gz"
-RUN tar -xzf /home/docker/nodejs/node-v12.14.0.tar.gz
-RUN cd node-v12.14.0 && ./configure && make -j4 && make install
-
-### Installation des dépendances de OSRM
-# https://github.com/Project-OSRM/osrm-backend/wiki/Building-OSRM
-RUN apt-get install -y cmake libboost-dev libboost-filesystem-dev libboost-thread-dev libboost-system-dev libboost-regex-dev libstxxl-dev libxml2-dev libsparsehash-dev libbz2-dev zlib1g-dev libzip-dev libgomp1 liblua5.2-dev pkg-config libgdal-dev libboost-program-options-dev libboost-iostreams-dev libboost-test-dev libtbb-dev libexpat1-dev
-
-### Installation de OSRM pour utiliser la libosrm dans Road2
-# https://github.com/Project-OSRM/osrm-backend
-# https://github.com/Project-OSRM/osrm-backend/blob/master/docs/nodejs/api.md
-# https://github.com/door2door-io/osrm-express-server-demo
-# https://github.com/Project-OSRM/osrm-backend/blob/master/CMakeLists.txt
-WORKDIR /home/docker/osrm
-RUN wget https://github.com/Project-OSRM/osrm-backend/archive/v5.25.0.zip
-RUN unzip v5.25.0.zip -d ./osrm-backend
-RUN cd /home/docker/osrm/osrm-backend/osrm-backend-5.25.0/ && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build . && cmake --build . --target install
-
-### Dossier des données
-WORKDIR /home/docker/internal
-
-### Récupération de données sur la Corse
-# L'objectif est d'avoir un container indépendant du docker-compose
-RUN wget download.geofabrik.de/europe/france/corse-latest.osm.pbf
-RUN osrm-extract corse-latest.osm.pbf -p /usr/local/share/osrm/profiles/car.lua
-RUN osrm-contract corse-latest.osrm
-
-### Dossier contenant la configuration
+### TODO : Supprimer la compilation et l'installation de Valhalla dès que l'on aura un binding NodeJS pour lui et donc repasser sur une image node
+FROM node:16-bullseye as build
+
+### Compilation de Valhalla
+RUN apt-get update && \
+apt-get install -y cmake make libtool pkg-config g++ gcc curl unzip jq lcov protobuf-compiler \
+vim-common locales libcurl4-openssl-dev zlib1g-dev liblz4-dev libprotobuf-dev && \
+apt-get install -y libgeos-dev libgeos++-dev libluajit-5.1-dev libspatialite-dev libsqlite3-dev wget sqlite3 spatialite-bin python3-shapely && \
+apt-get install -y libsqlite3-mod-spatialite python3-pip
+
+WORKDIR /home/prime-server
+RUN apt-get install -y git cmake autoconf automake pkg-config libtool make gcc g++ lcov libcurl4-openssl-dev libzmq3-dev libczmq-dev
+RUN git clone --depth 1 --recursive https://github.com/kevinkreiser/prime_server.git && cd prime_server && \
+cmake -B build . && cmake --build build && make -C build install
+
+WORKDIR /home/valhalla/
+RUN pip install --upgrade conan
+RUN git clone --branch 3.2.0 --depth 1 --recursive https://github.com/valhalla/valhalla.git && cd valhalla && \
+mkdir build && cmake -B build -DCMAKE_BUILD_TYPE=Release && make -C build && make -C build package
+
+FROM node:16-bullseye as road2
+
+### Installation des dépendances pour Valhalla et prime-server
+RUN apt-get update && \
+ apt-get install -y libtool pkg-config curl unzip jq lcov protobuf-compiler \
+ vim-common locales libcurl4-openssl-dev zlib1g-dev liblz4-dev libprotobuf-dev \
+ libgeos-dev libgeos++-dev libluajit-5.1-dev libspatialite-dev libsqlite3-dev wget sqlite3 spatialite-bin python3-shapely \
+ libsqlite3-mod-spatialite libzmq3-dev libczmq-dev
+
+### Installation prime-server
+COPY --from=build /usr/local/lib/libprime_server.so.0.7.0 /usr/lib/libprime_server.so.0.0.0
+COPY --from=build /usr/local/lib/libprime_server.so.0 /usr/lib/libprime_server.so.0
+COPY --from=build /usr/local/lib/libprime_server.so /usr/lib/libprime_server.so
+
+### Installation de valhalla
+COPY --from=build /home/valhalla/valhalla/build/valhalla-3.2.0-Linux.tar.gz ./
+RUN tar -xzvf valhalla-3.2.0-Linux.tar.gz && cd valhalla-3.2.0-Linux && cp -r bin/* /usr/bin/ && cp -r lib/* /usr/lib/ && cp -r include/* /usr/include/ && cp -r share/* /usr/share/
+
+### Dossier contenant la configuration de Road2
WORKDIR /home/docker/config
COPY /docker/config /home/docker/config/
### Dossier de l'application
WORKDIR /home/docker/app
-
-### Récupération des sources de l'application
-COPY package.json ./
-COPY eslint.json ./
-COPY jsdoc.json ./
COPY src ./src/
-COPY /test ./test/
-
-### Installation des dépandences de l'application NodeJS
-# https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
-# https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md
-# https://expressjs.com/fr/starter/installing.html
-RUN npm install
-
-### Installation de mocha pour les tests
-# https://mochajs.org/#installation
-RUN npm install mocha -g
-
-### Installation de eslint pour le code
-# https://eslint.org/docs/user-guide/configuring
-RUN npm install eslint -g
+### Récupération des sources de l'application
+COPY *.json ./
-### Installation de jsdoc pour la documentation du code
-# http://usejsdoc.org/about-configuring-jsdoc.html
-RUN npm install jsdoc -g
+### Installation des dépendances de l'application NodeJS
+RUN npm install && npm install -g mocha eslint jsdoc
### Volume partagé pour lire les données
VOLUME ["/home/docker/data"]
### Commande de lancement de l'application
-CMD npm run debug -- --ROAD2_CONF_FILE=/home/docker/config/road2.json
+CMD npm run debug -- --ROAD2_CONF_FILE=../config/road2.json
diff --git a/docker/readme.md b/docker/readme.md
index 9de92b3..e221985 100644
--- a/docker/readme.md
+++ b/docker/readme.md
@@ -4,10 +4,10 @@ Ce dossier regroupe les différents fichiers permettant d'utiliser Road2 avec do
Il y a un sous-dossier pour les grands usages identifiés :
- [dev](./dev/) : développer Road2
-- [demonstration](./demonstration/) : obtenir une démonstration locale des services proposés par Road2
+- [demonstration](./demonstration/) : obtenir une démonstration locale des services proposés par Road2. Ce Dockerfile est limité aux tests des moteurs OSRM et PGRouting car il n'existe pas de bindings Valhalla pour le moment.
- [test](./test/) : Tester Road2
D'autres sous-dossiers sont ordonnés ainsi pour des raisons pratiques :
- [web](./web/) : Ce dossier regroupe des fichiers utiles pour avoir un petit site web qui contient plusieurs documentations et des pages de tests graphiques pour Road2.
- [config](./config/) : Ce dossier regroupe plusieurs fichiers de configurations qui se trouvent être communs aux autres sous-dossiers.
-- [distributions](./distributions/) : Ce dossier regroupe différents `Dockerfile` qui sont des exemples d'installation sous différentes distributions.
\ No newline at end of file
+- [distributions](./distributions/) : Ce dossier peut regrouper différents `Dockerfile` qui sont des exemples d'installation sous différentes distributions. Actuellement, il ne reste plus qu'un exemple pour Debian. C'est le Dockerfile préconisé pour développer sur Road2 car il contient tous les binaires utiles aux différents moteurs.
\ No newline at end of file
diff --git a/docker/route-graph-generator b/docker/route-graph-generator
index 602f543..3d70be3 160000
--- a/docker/route-graph-generator
+++ b/docker/route-graph-generator
@@ -1 +1 @@
-Subproject commit 602f5432ac37128b1a3069e195ad36b045d471e7
+Subproject commit 3d70be34b11b88b1a06b5c7f0477da010a28f59d
diff --git a/documentation/developers/version.md b/documentation/developers/version.md
index 0a4350d..f114c30 100644
--- a/documentation/developers/version.md
+++ b/documentation/developers/version.md
@@ -44,8 +44,8 @@ Il est conseillé de commencer par gérer les versions de ces deux là. *Ce qui
Démarche à suivre pour chaque projet:
1. Tester `develop` et corriger si nécessaire.
-2. Merge de `develop` sur `master`.
-3. Update de la version sur `master` à 1.0.1.
+2. Update de la version sur `master` à 1.0.1.
+3. Merge de `develop` sur `master`.
4. Update de la version sur `develop` à 1.0.2-DEVELOP.
5. Faire des tests sur `master` et corriger si nécessaire.
6. S'il y a eu des corrections sur `master`, alors faire un merge de `master` sur `develop` et recommencer à 1. en changeant le numéro de version.
@@ -63,8 +63,8 @@ Démarche à suivre pour Road2:
0. Réaliser les montée de version et les merge sur Route Graph Generator et PGRouting Procedures.
1. Tester `develop` avec les `develop` des autres projets, et corriger si nécessaire.
-2. Merge de `develop` sur `master`.
-3. Update de la version sur `master` à 1.0.1.
+2. Update de la version sur `develop` à 1.0.1.
+3. Merge de `develop` sur `master`.
4. Update de la version sur `develop` à 1.0.2-DEVELOP.
5. Faire des tests sur `master` avec les `master` des autres projets, et corriger si nécessaire.
6. S'il y a eu des corrections sur `master`, alors faire un merge de `master` sur `develop` et recommencer à 1. en changeant le numéro de version.
diff --git a/src/js/sources/sourceManager.js b/src/js/sources/sourceManager.js
index fa598af..1956332 100644
--- a/src/js/sources/sourceManager.js
+++ b/src/js/sources/sourceManager.js
@@ -376,6 +376,7 @@ module.exports = class sourceManager {
try {
let osrmTest = require('osrm');
} catch(error) {
+ LOGGER.debug(error);
LOGGER.error("Le module osrm n'est pas disponible mais une source osrm est proposée dans la configuration.");
return false;
}
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
index 490f667..c3eb438 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
@@ -17,6 +17,39 @@ Feature: Road2-PGR
| GET |
| POST |
+ Scenario Outline: [] Route sur l'API simple 1.0.0 avec un autre crs
+ Given an "" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-pgr"
+ And with query parameters:
+ | key | value |
+ | crs | EPSG:2154 |
+ | start | 651475,6826145 |
+ | end | 651475,6826140 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain an attribute "crs" with value "EPSG:2154"
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+ Scenario Outline: [] Route sur l'API simple 1.0.0 avec mauvais crs
+ Given an "" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-pgr"
+ And with query parameters:
+ | key | value |
+ | crs | EPSG:4325 |
+ When I send the request
+ Then the server should send a response with status 400
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain an attribute "error.message" with value "Parameter 'crs' is invalid"
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes sur une ressource pgr
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
@@ -800,6 +833,39 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
| GET |
| POST |
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un autre crs
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone"
+ And with query parameters:
+ | key | value |
+ | crs | EPSG:2154 |
+ | point | 651475,6826145 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain an attribute "crs" with value "EPSG:2154"
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec mauvais crs
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone"
+ And with query parameters:
+ | key | value |
+ | crs | EPSG:4325 |
+ When I send the request
+ Then the server should send a response with status 400
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain an attribute "error.message" with value "Parameter 'crs' is invalid"
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+
Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource pgr
Given an "GET" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
From b7256a928c16af96f418338161642978e33b2d74 Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 5 Dec 2022 12:09:39 +0100
Subject: [PATCH 24/93] [docker] utilisation de notre fork valhalla
---
docker/distributions/debian/Dockerfile | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docker/distributions/debian/Dockerfile b/docker/distributions/debian/Dockerfile
index 916e07a..ab2644b 100644
--- a/docker/distributions/debian/Dockerfile
+++ b/docker/distributions/debian/Dockerfile
@@ -15,7 +15,7 @@ cmake -B build . && cmake --build build && make -C build install
WORKDIR /home/valhalla/
RUN pip install --upgrade conan
-RUN git clone --branch 3.2.0 --depth 1 --recursive https://github.com/valhalla/valhalla.git && cd valhalla && \
+RUN git clone --branch feature-exclude_bridges/tunnels/toll --depth 1 --recursive https://github.com/IGNF/valhalla.git && cd valhalla && \
mkdir build && cmake -B build -DCMAKE_BUILD_TYPE=Release && make -C build && make -C build package
FROM node:16-bullseye as road2
@@ -33,8 +33,8 @@ COPY --from=build /usr/local/lib/libprime_server.so.0 /usr/lib/libprime_server.s
COPY --from=build /usr/local/lib/libprime_server.so /usr/lib/libprime_server.so
### Installation de valhalla
-COPY --from=build /home/valhalla/valhalla/build/valhalla-3.2.0-Linux.tar.gz ./
-RUN tar -xzvf valhalla-3.2.0-Linux.tar.gz && cd valhalla-3.2.0-Linux && cp -r bin/* /usr/bin/ && cp -r lib/* /usr/lib/ && cp -r include/* /usr/include/ && cp -r share/* /usr/share/
+COPY --from=build /home/valhalla/valhalla/build/valhalla-3.1.4-Linux.tar.gz ./
+RUN tar -xzvf valhalla-3.1.4-Linux.tar.gz && cd valhalla-3.1.4-Linux && cp -r bin/* /usr/bin/ && cp -r lib/* /usr/lib/ && cp -r include/* /usr/include/ && cp -r share/* /usr/share/
### Dossier contenant la configuration de Road2
WORKDIR /home/docker/config
From 8eeb766851591b03bbb2ec851180d050496325fd Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 5 Dec 2022 12:15:53 +0100
Subject: [PATCH 25/93] [deps] utilisation de r2gg 1.2.3
---
docker/route-graph-generator | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker/route-graph-generator b/docker/route-graph-generator
index 3d70be3..d403450 160000
--- a/docker/route-graph-generator
+++ b/docker/route-graph-generator
@@ -1 +1 @@
-Subproject commit 3d70be34b11b88b1a06b5c7f0477da010a28f59d
+Subproject commit d403450fda103cc67a97a4be8889d25fe045fbd7
From 525a5b4f6dbb7e8a8a209e0cf971689aebefa8cd Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 5 Dec 2022 16:55:29 +0100
Subject: [PATCH 26/93] [test] maj des tests valhalla
---
.../cucumber/configurations/local-service.json | 4 +++-
.../features/req-simple-1.0.0-valhalla.feature | 12 ++++--------
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/test/functional/request/cucumber/configurations/local-service.json b/test/functional/request/cucumber/configurations/local-service.json
index 2bbd40c..fb332bc 100644
--- a/test/functional/request/cucumber/configurations/local-service.json
+++ b/test/functional/request/cucumber/configurations/local-service.json
@@ -56,7 +56,9 @@
"id": "isochrone-valhalla",
"parameters": {
"resource": "bduni-idf-valhalla",
- "point": "2.333865,48.881989"
+ "point": "2.333865,48.881989",
+ "costValue": "100",
+ "costType": "time"
}
},
{
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
index 562fced..82061f3 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
@@ -7,10 +7,6 @@ Feature: Road2-Valhalla
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource valhalla
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone-valhalla"
- And with query parameters:
- | key | value |
- | costType | distance |
- | costValue | 31000 |
When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
@@ -21,13 +17,13 @@ Feature: Road2-Valhalla
| GET |
| POST |
- Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource valhalla
+ Scenario Outline: [] Isochrone distance sur l'API simple 1.0.0 sur une ressource valhalla
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone-valhalla"
And with query parameters:
- | key | value |
- | costType | distance |
- | costValue | 1000 |
+ | key | value |
+ | costType | distance |
+ | costValue | 1000 |
When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
From 1f8d42a0e876579753c0bb8d006faae1e36a66ea Mon Sep 17 00:00:00 2001
From: Loic
Date: Wed, 7 Dec 2022 13:35:17 +0100
Subject: [PATCH 27/93] [deps] utilisation de pgrouting-procedures 2.0.0
---
docker/motors/pgrouting-procedures | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker/motors/pgrouting-procedures b/docker/motors/pgrouting-procedures
index 4336f8d..f9bee79 160000
--- a/docker/motors/pgrouting-procedures
+++ b/docker/motors/pgrouting-procedures
@@ -1 +1 @@
-Subproject commit 4336f8da74d76ed95971113f4d878525ca3ca2d5
+Subproject commit f9bee79dcafd4820b20132a9361cf86b58bf7264
From 538e971fc377a0827d19e3818e4e1a1a5436c3df Mon Sep 17 00:00:00 2001
From: Loic
Date: Thu, 8 Dec 2022 10:40:01 +0100
Subject: [PATCH 28/93] [fix] reprojection des isochrones
---
changelog.md | 5 +
package.json | 2 +-
.../simple/1.0.0/controller/controller.js | 8 +-
src/js/geometry/polygon.js | 99 +++++++++++++++++++
src/js/requests/isochroneRequest.js | 2 +-
src/js/sources/osrmSource.js | 2 +-
src/js/sources/pgrSource.js | 66 +++++++++----
src/js/sources/smartroutingSource.js | 2 +-
src/js/sources/valhallaSource.js | 50 +++++++---
.../request/cucumber/data/bduni/pgr/3.json | 1 +
.../request/cucumber/data/bduni/pgr/4.json | 1 +
.../features/req-data-bduni-pgr.feature | 35 +++++++
.../features/req-simple-1.0.0-pgr.feature | 2 +-
.../req-simple-1.0.0-valhalla.feature | 19 +++-
.../cucumber/features/support/world.js | 58 +++++++++++
15 files changed, 310 insertions(+), 42 deletions(-)
create mode 100644 test/functional/request/cucumber/data/bduni/pgr/3.json
create mode 100644 test/functional/request/cucumber/data/bduni/pgr/4.json
diff --git a/changelog.md b/changelog.md
index bf11cea..accf6ff 100644
--- a/changelog.md
+++ b/changelog.md
@@ -11,6 +11,9 @@ CHANGED:
- Les sources ne sont plus configurées dans le même fichier que les ressources. Chaque source est configurée dans son fichier. L'ensemble est placé dans un dossier de sources. Il peut y en avoir plusieurs.
- Les sources PGRouting et Valhalla ne sont plus configurées de la même manière : chaque source de ces types peut contenir plusieurs coûts.
+FIXED:
+ - Les reprojections des isochrones fonctionnent
+
UPDATED:
- Passage à `osrm` 5.26.0
- Passage à `pg` 8.8.0
@@ -22,6 +25,8 @@ UPDATED:
- Passage à `nconf` 0.12.0
- Passage à `proj4` 2.8.0
- Utilisation de NodeJS 16 dans docker
+ - Passage à `pgrouting-procedures` 2.0.0
+ - Passage à `route-graph-generator` 1.2.3
# 1.1.2
diff --git a/package.json b/package.json
index 2582d2c..cc8710b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "road2",
- "version": "1.1.3-DEVELOP",
+ "version": "2.0.0-DEVELOP",
"description": "Calcul d'itinéraire",
"author": "RDEV - IGN",
diff --git a/src/js/apis/simple/1.0.0/controller/controller.js b/src/js/apis/simple/1.0.0/controller/controller.js
index 98d99b1..c75bcd0 100644
--- a/src/js/apis/simple/1.0.0/controller/controller.js
+++ b/src/js/apis/simple/1.0.0/controller/controller.js
@@ -714,10 +714,10 @@ module.exports = {
} else {
LOGGER.debug("point valide");
- //TODO: passer par la classe Point
- const tmpStringCoordinates = parameters.point.split(",");
- point.lon = Number(tmpStringCoordinates[0]);
- point.lat = Number(tmpStringCoordinates[1]);
+ let tmpStringCoordinates = parameters.point.split(",");
+ point = new Point(Number(tmpStringCoordinates[0]), Number(tmpStringCoordinates[1]), askedProjection);
+ LOGGER.debug("user point in road2' object:");
+ LOGGER.debug(point);
}
diff --git a/src/js/geometry/polygon.js b/src/js/geometry/polygon.js
index e04c5d0..2c95bbd 100644
--- a/src/js/geometry/polygon.js
+++ b/src/js/geometry/polygon.js
@@ -4,6 +4,7 @@ const errorManager = require('../utils/errorManager');
const turf = require('@turf/turf');
const polyline = require('@mapbox/polyline');
const Geometry = require('../geometry/geometry');
+const proj4 = require('proj4');
/**
*
@@ -42,6 +43,17 @@ module.exports = class Polygon extends Geometry {
return this._geom;
}
+ /**
+ *
+ * @function
+ * @name getGeoJSON
+ * @description Récupérer la représentation geoJSON du polygon
+ *
+ */
+ getGeoJSON () {
+ return this._convertGeometry(this._geom, this._format, 'geojson');
+ }
+
/**
*
* @function
@@ -111,5 +123,92 @@ module.exports = class Polygon extends Geometry {
//TODO: voir si on peut remplacer ce throw par un return {}
throw errorManager.createError("Unsupported geometry conversion");
}
+
+ }
+
+
+ /**
+ *
+ * @function
+ * @name transform
+ * @description Reprojeter un polygon
+ * @param{string} projection - Projection demandée
+ *
+ */
+ transform (projection) {
+
+ if (projection === this._projection) {
+ return true;
+ }
+
+ let geojson = this.getGeoJSON();
+
+ // vérifications sur le geojson à reprojeter
+ if (!geojson.coordinates) {
+ return false;
+ }
+ if (!Array.isArray(geojson.coordinates)) {
+ return false;
+ }
+ if (geojson.coordinates.length === 0) {
+ return false;
+ }
+
+ for (let g = 0; g < geojson.coordinates.length; g++) {
+
+ if (!geojson.coordinates[g]) {
+ return false;
+ }
+ if (!Array.isArray(geojson.coordinates[g])) {
+ return false;
+ }
+ if (geojson.coordinates[g].length === 0) {
+ return false;
+ }
+
+ for (let c = 0; c < geojson.coordinates[g].length; c++) {
+
+ if (!geojson.coordinates[g][c]) {
+ return false;
+ }
+ if (!Array.isArray(geojson.coordinates[g][c])) {
+ return false;
+ }
+ if (geojson.coordinates[g][c].length < 2) {
+ return false;
+ }
+
+ }
+
+ }
+
+ // Reprojection
+ for (let g = 0; g < geojson.coordinates.length; g++) {
+
+ for (let c = 0; c < geojson.coordinates[g].length; c++) {
+
+ let reprojectedPoint = proj4(this.projection, projection, [geojson.coordinates[g][c][0], geojson.coordinates[g][c][1]]);
+
+ if (!Array.isArray(reprojectedPoint)) {
+ return false;
+ }
+ if (reprojectedPoint.length !== 2) {
+ return false;
+ }
+
+ geojson.coordinates[g][c][0] = reprojectedPoint[0];
+ geojson.coordinates[g][c][1] = reprojectedPoint[1];
+
+ }
+
+ }
+
+ // TODO: gérer les différents formats de géométrie
+
+ this._projection = projection;
+
+ return true;
+
}
+
}
diff --git a/src/js/requests/isochroneRequest.js b/src/js/requests/isochroneRequest.js
index f764d28..343ef21 100644
--- a/src/js/requests/isochroneRequest.js
+++ b/src/js/requests/isochroneRequest.js
@@ -18,7 +18,7 @@ module.exports = class isochroneRequest extends Request {
* @name constructor
* @description Constructeur de la classe isochroneRequest
* @param {string} resource - Ressource.
- * @param {string} point - Point de départ.
+ * @param {Point} point - Point de départ ou d'arrivée
* @param {string} costType - Type du coût.
* @param {string} costValue - Valeur du coût.
* @param {string} profile - Profil utilisé pour le calcul.
diff --git a/src/js/sources/osrmSource.js b/src/js/sources/osrmSource.js
index 3115c92..fdad5ea 100644
--- a/src/js/sources/osrmSource.js
+++ b/src/js/sources/osrmSource.js
@@ -567,7 +567,7 @@ module.exports = class osrmSource extends Source {
// Récupération de l'ensemble des points de la réponse d'OSRM
if (osrmResponse.waypoints) {
- console.log(osrmResponse);
+ LOGGER.debug(osrmResponse);
if (osrmResponse.waypoints.length < 1) {
throw errorManager.createError(" OSRM response is invalid: the number of waypoints is lower than 1. ");
} else {
diff --git a/src/js/sources/pgrSource.js b/src/js/sources/pgrSource.js
index 88c71c0..0874a52 100644
--- a/src/js/sources/pgrSource.js
+++ b/src/js/sources/pgrSource.js
@@ -426,7 +426,13 @@ module.exports = class pgrSource extends Source {
LOGGER.debug("type of request is isochroneRequest");
- const point = [request.point.lon, request.point.lat];
+ let point = "";
+ try {
+ point = JSON.stringify(request.point.getCoordinatesIn(super.projection));
+ } catch(error) {
+ LOGGER.error(error);
+ reject(errorManager.createError("Impossible de récupérer les coordonnées du point"));
+ }
let constraints = "";
@@ -446,12 +452,11 @@ module.exports = class pgrSource extends Source {
LOGGER.debug("no constraints asked");
}
- const queryString = `SELECT * FROM ${this._schema}.generateIsochrone(ARRAY ${JSON.stringify(point)}, $1, $2, $3, $4, $5, $6)`;
-
+ const queryString = `SELECT * FROM ${this._schema}.generateIsochrone(ARRAY ${point}, $1, $2, $3, $4, $5)`;
+
const SQLParametersTable = [
request.costValue,
request.direction,
- parseInt(request.askedProjection.split(':')[1]), // e.g. Transformer "EPSG:4326" en 4326 (pour PostGIS).
this._costs[request.profile][request.costType].costColumn,
this._costs[request.profile][request.costType].rcostColumn,
constraints
@@ -489,7 +494,7 @@ module.exports = class pgrSource extends Source {
LOGGER.debug(result);
try {
- resolve(this.writeIsochroneResponse(request, pgrRequest, result));
+ resolve(this.writeIsochroneResponse(request, result));
} catch (error) {
reject(error);
}
@@ -1055,7 +1060,8 @@ module.exports = class pgrSource extends Source {
* @param {pgrResponse} pgrResponse - Objet pgrResponse
*
*/
- writeIsochroneResponse(isochroneRequest, pgrRequest, pgrResponse) {
+ writeIsochroneResponse(isochroneRequest, pgrResponse) {
+
let point = {};
let geometry = {};
@@ -1064,20 +1070,46 @@ module.exports = class pgrSource extends Source {
throw errorManager.createError(" No data found ", 404);
}
- // Création d'un objet Point (utile plus tard).
- point = new Point(isochroneRequest.point.lon, isochroneRequest.point.lat, super.projection);
+ // Projection demandée dans la requête
+ let askedProjection = isochroneRequest.point.projection;
+ LOGGER.debug("asked projection: " + askedProjection);
+
+ LOGGER.debug("data projection: " + super.projection);
- let rawGeometry = JSON.parse(pgrResponse.rows[0].geometry);
- // Cas où il n'y a pas d'isochrone car costValue trop faible
+ // Création d'un objet Point
+ point = isochroneRequest.point;
+ if (!point.transform(askedProjection)) {
+ throw errorManager.createError(" Error during reprojection of point in PGRouting response");
+ } else {
+ LOGGER.debug("point in asked projection:");
+ LOGGER.debug(point);
+ }
+
+ let rawGeometry = null;
+
+ try {
+ rawGeometry = JSON.parse(pgrResponse.rows[0].geometry);
+ } catch(error) {
+ LOGGER.debug(error);
+ throw errorManager.createError("Impossible de parser la réponse de PGRouting");
+ }
+
+ // Création d'un objet Polygon à partir de la géométrie brute
if (rawGeometry === null) {
- rawGeometry = {
- type: 'Point',
- coordinates: [
- isochroneRequest.point.lon,
- isochroneRequest.point.lat
- ]
- };
+ // Potentiellement le cas où il n'y a pas d'isochrone car costValue trop faible
+ geometry = new Polygon({type: 'Point',coordinates: [point.x,point.y]}, "geojson", askedProjection);
+ } else {
+
+ geometry = new Polygon(rawGeometry, "geojson", super.projection);
+
+ if (!geometry.transform(askedProjection)) {
+ throw errorManager.createError(" Error during reprojection of point in PGRouting response");
+ } else {
+ LOGGER.debug("point in asked projection:");
+ LOGGER.debug(point);
+ }
+
}
// Création d'un objet Polygon à partir du GeoJSON reçu.
diff --git a/src/js/sources/smartroutingSource.js b/src/js/sources/smartroutingSource.js
index 31733d3..0d179d0 100644
--- a/src/js/sources/smartroutingSource.js
+++ b/src/js/sources/smartroutingSource.js
@@ -195,7 +195,7 @@ module.exports = class smartroutingSource extends Source {
// Coordonnées
// location
- smartroutingRequest.location = request.point.lon + "," + request.point.lat;
+ smartroutingRequest.location = request.point.x + "," + request.point.y;
// optimization
const mapMethods = {
diff --git a/src/js/sources/valhallaSource.js b/src/js/sources/valhallaSource.js
index 1413082..1336f06 100644
--- a/src/js/sources/valhallaSource.js
+++ b/src/js/sources/valhallaSource.js
@@ -270,11 +270,15 @@ module.exports = class valhallaSource extends Source {
reverse = "true";
}
- const locationsString = `"locations":[{"lat":${request.point.lat},"lon":${request.point.lon}}]`;
+ // Reprojection du point si nécessaire
+ let tmpPoint = request.point.getCoordinatesIn(super.projection);
+
+ const locationsString = `"locations":[{"lat":${tmpPoint[1]},"lon":${tmpPoint[0]}}]`;
const costingString = `"costing":"${this._costs[request.profile][request.costType].costing}"`;
const contoursString = `"contours":[{"${request.costType}":${costValue}}]`;
const reverseString = `"reverse":${reverse}`;
- const commandString = `valhalla_service ${this._configuration.storage.config} isochrone '{${locationsString},${costingString},${contoursString},${reverseString}}' `;
+ const polygonsString = `"polygons":true`;
+ const commandString = `valhalla_service ${this._configuration.storage.config} isochrone '{${locationsString},${costingString},${contoursString},${reverseString},${polygonsString}}' `;
LOGGER.info(commandString);
return new Promise( (resolve, reject) => {
@@ -538,6 +542,7 @@ module.exports = class valhallaSource extends Source {
*
*/
writeIsochroneResponse(isochroneRequest, valhallaResponseStr) {
+
let point = {};
let geometry = {};
let valhallaResponse;
@@ -557,24 +562,39 @@ module.exports = class valhallaSource extends Source {
throw errorManager.createError(" No data found ", 404);
}
- // Création d'un objet Point (utile plus tard).
- point = new Point(isochroneRequest.point.lon, isochroneRequest.point.lat, super.projection);
+ // Projection demandée dans la requête
+ let askedProjection = isochroneRequest.point.projection;
+ LOGGER.debug("asked projection: " + askedProjection);
+
+ LOGGER.debug("data projection: " + super.projection);
+
+ // Création d'un objet Point
+ point = isochroneRequest.point;
+ if (!point.transform(askedProjection)) {
+ throw errorManager.createError(" Error during reprojection of point in Valhalla response");
+ } else {
+ LOGGER.debug("point in asked projection:");
+ LOGGER.debug(point);
+ }
let rawGeometry = valhallaResponse.features[0].geometry;
- // Cas où il n'y a pas d'isochrone car costValue trop faible
+ // Création d'un objet Polygon à partir de la géométrie brute
if (rawGeometry === null) {
- rawGeometry = {
- type: 'Point',
- coordinates: [
- isochroneRequest.point.lon,
- isochroneRequest.point.lat
- ]
- };
- }
+ // Potentiellement le cas où il n'y a pas d'isochrone car costValue trop faible
+ geometry = new Polygon({type: 'Point',coordinates: [point.x,point.y]}, "geojson", askedProjection);
+ } else {
+
+ geometry = new Polygon(rawGeometry, "geojson", super.projection);
+
+ if (!geometry.transform(askedProjection)) {
+ throw errorManager.createError(" Error during reprojection of point in Valhalla response");
+ } else {
+ LOGGER.debug("point in asked projection:");
+ LOGGER.debug(point);
+ }
- // Création d'un objet Polygon à partir du GeoJSON reçu.
- geometry = new Polygon(rawGeometry, "geojson", super.projection);
+ }
/* Envoi de la réponse au proxy. */
return new IsochroneResponse(
diff --git a/test/functional/request/cucumber/data/bduni/pgr/3.json b/test/functional/request/cucumber/data/bduni/pgr/3.json
new file mode 100644
index 0000000..91e4224
--- /dev/null
+++ b/test/functional/request/cucumber/data/bduni/pgr/3.json
@@ -0,0 +1 @@
+{"point":"2.1,48.7","resource":"bduni-idf-pgr","resourceVersion":"2022-11-24","costType":"time","costValue":100,"timeUnit":"second","profile":"car","direction":"departure","crs":"EPSG:4326","geometry":{"type":"Polygon","coordinates":[[[2.093394624,48.701919765],[2.09343569,48.701908761],[2.09343622,48.701908617],[2.093436682,48.70190849],[2.093437221,48.701908339],[2.093466369,48.701900075],[2.09348427,48.701892432],[2.093498626,48.701884004],[2.093514024,48.7018721],[2.093754753,48.70163137],[2.094337538,48.701442596],[2.094470663,48.701478266],[2.094499035,48.701485869],[2.094685301,48.701535779],[2.094695136,48.701537735],[2.094703691,48.701538861],[2.094713698,48.701539517],[2.094721342,48.701539517],[2.09473135,48.701538861],[2.094739904,48.701537735],[2.094749739,48.701535779],[2.094776915,48.701528497],[2.094777446,48.701528353],[2.094777907,48.701528226],[2.094778446,48.701528075],[2.095146237,48.701423799],[2.095164137,48.701416156],[2.095178493,48.701407728],[2.095193891,48.701395824],[2.09543331,48.701156405],[2.095763452,48.701108003],[2.095919343,48.701149774],[2.095948831,48.701157675],[2.095958666,48.701159632],[2.095967221,48.701160758],[2.095977228,48.701161414],[2.095984872,48.701161414],[2.095994879,48.701160758],[2.096003434,48.701159632],[2.096013269,48.701157675],[2.096396591,48.701054965],[2.096406086,48.701051741],[2.096414058,48.701048439],[2.096423053,48.701044004],[2.096429673,48.701040182],[2.096438011,48.70103461],[2.096444856,48.701029358],[2.096452395,48.701022746],[2.096478025,48.700997116],[2.096543099,48.700932042],[2.096666937,48.700965225],[2.096676772,48.700967181],[2.096685327,48.700968307],[2.096695334,48.700968963],[2.096702978,48.700968963],[2.096712986,48.700968307],[2.09672154,48.700967181],[2.096731375,48.700965225],[2.097114697,48.700862514],[2.097124193,48.700859291],[2.097131265,48.700856361],[2.097209849,48.700934946],[2.097124752,48.700957748],[2.097115256,48.700960971],[2.097107284,48.700964273],[2.09709829,48.700968708],[2.097089734,48.700973648],[2.097081395,48.70097922],[2.09707455,48.700984472],[2.09706701,48.700991084],[2.096968677,48.701089418],[2.0967864,48.701271695],[2.096784337,48.701273839],[2.096782595,48.701275722],[2.096780618,48.701277944],[2.096778693,48.701280193],[2.096776803,48.701282491],[2.096775213,48.701284503],[2.096773413,48.701286872],[2.094811931,48.70397616],[2.094811118,48.703977296],[2.094810426,48.703978282],[2.094809634,48.703979433],[2.094552817,48.704359921],[2.094930291,48.705155209],[2.095776453,48.705367512],[2.09578059,48.705360604],[2.095783428,48.70535001],[2.096111177,48.705356264],[2.096119489,48.705355971],[2.096127563,48.705355247],[2.096135794,48.705354056],[2.096155817,48.705350039],[2.09622066,48.705428628],[2.096223057,48.705431396],[2.096225461,48.70543404],[2.096227987,48.705436691],[2.09627863,48.705487333],[2.096282599,48.705494505],[2.096459541,48.7055389],[2.09717789,48.705719135],[2.098991328,48.705535789],[2.099587807,48.70539902],[2.099657249,48.705468462],[2.101672382,48.705264724],[2.1026834,48.705162506],[2.103512697,48.704927926],[2.103513956,48.704909944],[2.103513791,48.704897245],[2.103512607,48.704884949],[2.103510347,48.704872451],[2.103476111,48.704744678],[2.103474606,48.704740245],[2.103541113,48.704492035],[2.103542674,48.704484849],[2.103543857,48.704477779],[2.103544722,48.704470476],[2.103551768,48.704369828],[2.103551602,48.704357129],[2.103550419,48.704344833],[2.103548159,48.704332336],[2.103533579,48.704277922],[2.104247576,48.704083537],[2.104251783,48.704084719],[2.104256536,48.704085887],[2.104261444,48.704086924],[2.104456817,48.704121576],[2.104466784,48.704122678],[2.104476541,48.704123114],[2.104486567,48.704122905],[2.104495799,48.704122107],[2.104505712,48.704120591],[2.104515249,48.704118487],[2.104520489,48.704116965],[2.104520509,48.704117037],[2.105044629,48.703971192],[2.105144203,48.704013419],[2.105148884,48.704015226],[2.105153504,48.704016838],[2.105158293,48.704018334],[2.105162796,48.704019581],[2.105167672,48.704020762],[2.105172464,48.704021757],[2.105177407,48.704022615],[2.105380766,48.704051125],[2.105385754,48.704051659],[2.105390634,48.70405202],[2.105395647,48.704052226],[2.10540032,48.704052265],[2.105405335,48.704052143],[2.105410221,48.704051864],[2.105415218,48.704051414],[2.105604424,48.704028118],[2.106129746,48.704025672],[2.106294665,48.704141],[2.106458636,48.704094618],[2.106896352,48.703970803],[2.107250437,48.703847523],[2.107840677,48.703582989],[2.108126348,48.703174259],[2.108121282,48.703168749],[2.108093144,48.703149386],[2.107978541,48.703103868],[2.107931626,48.703085234],[2.107926906,48.703083536],[2.107922788,48.703082205],[2.107917966,48.703080819],[2.107913874,48.703079787],[2.107908973,48.703078719],[2.107904716,48.703077937],[2.107899755,48.703077192],[2.107818846,48.703067742],[2.107775328,48.703062659],[2.106927424,48.702222709],[2.106893964,48.702153215],[2.106871354,48.702106257],[2.10726513,48.700696292],[2.107266494,48.700695613],[2.107273957,48.700691266],[2.107282273,48.700685662],[2.107288892,48.700680542],[2.107296406,48.700673901],[2.107302489,48.70066777],[2.107309072,48.700660205],[2.107327531,48.700635955],[2.107328156,48.700634536],[2.107411876,48.70052455],[2.107428965,48.700502101],[2.107434504,48.700493741],[2.107438793,48.700486245],[2.107443193,48.700477234],[2.107446295,48.700469664],[2.107449481,48.700460156],[2.107451684,48.700451805],[2.107453603,48.700441962],[2.107463872,48.700361557],[2.108842734,48.69998449],[2.108879287,48.700021042],[2.108926663,48.700068418],[2.108934203,48.70007503],[2.108941054,48.700080288],[2.108949392,48.700085859],[2.108956477,48.700089949],[2.108965471,48.700094385],[2.10897345,48.70009769],[2.108982946,48.700100913],[2.109150807,48.700145891],[2.109337584,48.700195938],[2.109356102,48.700198539],[2.109372119,48.700198815],[2.109390716,48.700196856],[2.10942349,48.700189277],[2.109424777,48.700188967],[2.109425885,48.70018869],[2.109427167,48.700188359],[2.109810489,48.700085648],[2.109825617,48.70007982],[2.109837999,48.700073473],[2.109851564,48.700064594],[2.109974265,48.699964241],[2.109977167,48.699961745],[2.109979616,48.699959529],[2.109982389,48.699956891],[2.109987353,48.699951927],[2.110103845,48.699835435],[2.110151473,48.699787807],[2.110158085,48.699780268],[2.110163342,48.699773416],[2.110168913,48.699765078],[2.110173004,48.699757993],[2.110177439,48.699748999],[2.110180744,48.69974102],[2.110183968,48.699731524],[2.110222569,48.699587462],[2.1102513,48.699480235],[2.110276244,48.699387142],[2.11074869,48.698999107],[2.110787302,48.699002776],[2.110788853,48.699002907],[2.110790192,48.699003007],[2.110791745,48.699003107],[2.110793026,48.699003177],[2.110794581,48.699003245],[2.110795923,48.69900329],[2.110797479,48.699003327],[2.110819442,48.699003625],[2.110819735,48.699003672],[2.110823828,48.699004188],[2.110828823,48.699004653],[2.110833143,48.699004913],[2.110838158,48.699005051],[2.111041056,48.699003967],[2.111129137,48.698877945],[2.111398056,48.698493182],[2.11098788,48.698007504],[2.110944895,48.697995528],[2.110928894,48.697992852],[2.110446836,48.697964035],[2.11043843,48.697963994],[2.110431195,48.697964356],[2.110422835,48.697965236],[2.110198586,48.698001356],[2.110179154,48.698007206],[2.11016334,48.698014367],[2.110146124,48.698025111],[2.110126337,48.698041464],[2.110011697,48.698136206],[2.110004402,48.698143087],[2.10999852,48.69814941],[2.109992185,48.698157184],[2.109987442,48.69816385],[2.109982176,48.698172384],[2.109978131,48.698180014],[2.109974024,48.698189163],[2.109956982,48.698234917],[2.109363022,48.698428662],[2.109024214,48.698519445],[2.108565669,48.698328705],[2.108601073,48.698180713],[2.10860315,48.698160808],[2.108602688,48.698143689],[2.108599541,48.698123925],[2.108543035,48.697933719],[2.10853488,48.697915442],[2.10852592,48.697900848],[2.108513313,48.697885304],[2.108369274,48.697748835],[2.10836162,48.697742472],[2.108354685,48.697737432],[2.10834627,48.697732115],[2.108299006,48.697706383],[2.108289834,48.697702147],[2.108281713,48.697699028],[2.108272064,48.697696035],[2.108129615,48.697661956],[2.108124701,48.697660949],[2.108120435,48.69766022],[2.108115465,48.697659536],[2.108111822,48.697659157],[2.108106818,48.6976588],[2.108102493,48.697658633],[2.108097477,48.697658604],[2.107966969,48.697662126],[2.107961961,48.697662425],[2.107957652,48.697662825],[2.107952674,48.697663451],[2.107949058,48.697664027],[2.107944132,48.697664977],[2.107939912,48.697665936],[2.107938933,48.697666192],[2.107933837,48.697665888],[2.1079252,48.697665938],[2.107915198,48.697666652],[2.107908004,48.697667641],[2.10789818,48.697669655],[2.10788985,48.697671939],[2.107880373,48.697675218],[2.107862025,48.697682943],[2.107841828,48.697688644],[2.10782011,48.697691396],[2.107810265,48.697693305],[2.107801912,48.6976955],[2.107792401,48.697698678],[2.107785678,48.697701424],[2.107776663,48.697705816],[2.107769163,48.697710098],[2.107760798,48.697715629],[2.107757786,48.697717917],[2.107750216,48.697722119],[2.107744853,48.697723713],[2.107735448,48.697727191],[2.107727561,48.69773071],[2.10771869,48.697735386],[2.107712501,48.697739185],[2.107704315,48.69774498],[2.107697608,48.697750421],[2.107695166,48.697752682],[2.107685452,48.697758074],[2.107678706,48.697762292],[2.107673088,48.697766223],[2.107666815,48.697771118],[2.107662445,48.697774908],[2.107656713,48.697780426],[2.107652025,48.697785432],[2.107646896,48.697791514],[2.107645461,48.697793407],[2.10727196,48.697670993],[2.10718659,48.697352389],[2.107183367,48.697342893],[2.107180062,48.697334914],[2.107175627,48.697325921],[2.107171996,48.697319632],[2.107166424,48.697311293],[2.107161167,48.697304441],[2.107154555,48.697296902],[2.106873944,48.697016291],[2.106866404,48.697009679],[2.106859553,48.697004422],[2.106851214,48.69699885],[2.106844925,48.696995219],[2.106835931,48.696990784],[2.106827953,48.696987479],[2.106818456,48.696984255],[2.106592895,48.696923816],[2.106589014,48.696897978],[2.10659278,48.696864124],[2.106577835,48.696740493],[2.106581844,48.696676684],[2.106581817,48.696666656],[2.106581218,48.696657889],[2.106579882,48.69664795],[2.106577916,48.696638205],[2.106575295,48.696628526],[2.106572448,48.696620213],[2.106568585,48.696610958],[2.106504065,48.696481015],[2.106841358,48.695464689],[2.106842271,48.695464379],[2.106954012,48.695426422],[2.106963276,48.695422582],[2.106971156,48.695418694],[2.10697984,48.695413678],[2.106988105,48.695408154],[2.106996059,48.695402047],[2.107002665,48.695396252],[2.107009754,48.69538916],[2.107051176,48.695341907],[2.107051176,48.695341907],[2.107140552,48.695239951],[2.107146655,48.695231994],[2.107151535,48.695224687],[2.107156547,48.695216001],[2.107160942,48.695207084],[2.107164778,48.695197818],[2.107167601,48.695189497],[2.107170194,48.69517981],[2.107208864,48.694985193],[2.107210171,48.69497525],[2.107210744,48.694966482],[2.107210741,48.694956453],[2.107210089,48.694946533],[2.107208778,48.694936591],[2.107207062,48.694927974],[2.107204465,48.694918288],[2.10719541,48.694891633],[2.107156364,48.694776684],[2.107398822,48.694193684],[2.107495528,48.694167772],[2.107505024,48.694164548],[2.107513142,48.694161186],[2.107522136,48.69415675],[2.107530745,48.69415178],[2.107539083,48.694146208],[2.107546055,48.694140859],[2.107553594,48.694134247],[2.107571086,48.694116755],[2.107589104,48.694088247],[2.107615428,48.694014271],[2.107078681,48.693378723],[2.106024417,48.693797191],[2.105269772,48.694096732],[2.104609936,48.695270227],[2.101379131,48.695712306],[2.101376748,48.69571267],[2.10137466,48.695713023],[2.101372289,48.695713462],[2.101369888,48.695713946],[2.101367533,48.69571446],[2.101365471,48.695714943],[2.101363133,48.69571553],[2.101238428,48.695748945],[2.10123776,48.695749124],[2.101232247,48.695750826],[2.10122747,48.6957525],[2.101222101,48.695754612],[2.101110728,48.695803328],[2.100984853,48.695837056],[2.100966363,48.695844715],[2.100951274,48.695853427],[2.100935396,48.695865611],[2.100766016,48.696034991],[2.10059069,48.695988012],[2.100570847,48.6959854],[2.100553424,48.6959854],[2.100533582,48.695988012],[2.100445573,48.696011594],[2.10005244,48.69616764],[2.099820192,48.696399888],[2.099808009,48.696415765],[2.099800984,48.696427933],[2.09972605,48.696407854],[2.099706208,48.696405242],[2.099688784,48.696405242],[2.099668942,48.696407854],[2.09928562,48.696510565],[2.09926713,48.696518224],[2.099252041,48.696526936],[2.099236163,48.696539119],[2.098955553,48.69681973],[2.098943369,48.696835608],[2.098934657,48.696850697],[2.098926999,48.696869187],[2.098824288,48.697252508],[2.098821676,48.697272351],[2.098821676,48.697289774],[2.098824288,48.697309617],[2.098866086,48.697465608],[2.098863945,48.697465889],[2.098548529,48.697550405],[2.098480797,48.697297627],[2.098473139,48.697279137],[2.098464427,48.697264048],[2.098452243,48.69724817],[2.098171632,48.696967559],[2.098155755,48.696955376],[2.098140665,48.696946664],[2.098122175,48.696939005],[2.098114372,48.696936914],[2.096826139,48.697448251],[2.096216213,48.69804028],[2.096217133,48.698041663],[2.096343863,48.698168393],[2.096359692,48.698227466],[2.096367351,48.698245956],[2.096375905,48.698260773],[2.096388089,48.698276651],[2.096604933,48.698493495],[2.096643409,48.698637089],[2.096651067,48.698655579],[2.096659622,48.698670396],[2.096671806,48.698686274],[2.096952416,48.698966884],[2.096964615,48.698976245],[2.097049195,48.699291901],[2.096727553,48.699205717],[2.096707711,48.699203105],[2.096690602,48.699203105],[2.09667076,48.699205717],[2.096620344,48.699219226],[2.096287438,48.699308428],[2.096258903,48.699316075],[2.096240415,48.699323734],[2.096225599,48.699332289],[2.096209723,48.699344471],[2.096137108,48.699417086],[2.096037938,48.699390514],[2.096018095,48.699387901],[2.096000984,48.699387902],[2.09598114,48.699390515],[2.095569327,48.69950088],[2.095568261,48.699501174],[2.095567341,48.699501435],[2.095566275,48.699501745],[2.095536472,48.699510664],[2.095519161,48.699518279],[2.095505264,48.699526572],[2.095490344,48.699538194],[2.095229094,48.699799444],[2.095222482,48.699806983],[2.09521723,48.699813828],[2.095211658,48.699822167],[2.095207836,48.699828787],[2.0952034,48.699837781],[2.095200098,48.699845753],[2.095196875,48.699855249],[2.095186306,48.699894692],[2.095181327,48.699890325],[2.095174481,48.699885072],[2.095166142,48.6998795],[2.095159522,48.699875678],[2.095150528,48.699871243],[2.095142557,48.699867941],[2.095133061,48.699864718],[2.094751722,48.699762538],[2.09473077,48.699759934],[2.09471274,48.699760195],[2.094691871,48.699763405],[2.094329185,48.699871937],[2.093925085,48.700264178],[2.093914323,48.700304342],[2.093890846,48.700391962],[2.093888728,48.700399866],[2.093735045,48.700448642],[2.093555396,48.70062302],[2.093023972,48.70113885],[2.093346794,48.701818993],[2.093394624,48.701919765]]]},"constraints":[]}
\ No newline at end of file
diff --git a/test/functional/request/cucumber/data/bduni/pgr/4.json b/test/functional/request/cucumber/data/bduni/pgr/4.json
new file mode 100644
index 0000000..5ff7d8e
--- /dev/null
+++ b/test/functional/request/cucumber/data/bduni/pgr/4.json
@@ -0,0 +1 @@
+{"point":"2.1,48.7","resource":"bduni-idf-pgr","resourceVersion":"2022-11-24","costType":"time","costValue":100,"timeUnit":"second","profile":"car","direction":"departure","crs":"EPSG:4326","geometry":"_bghHuzwK@I??????@E@A@C@An@o@d@uBGYAEIe@?A???A?A?A?A?A@E??????TiA?A@C@An@o@HaAG_@AE?A?A?A???A?A?ATmA?A??@A?A@A??@ABELKGY?A?A?A???A?A?ATkA?A?AMOEP???@A@?@A@?@A?SRc@b@?@A?????????A@yOfK??????kAr@_DkAi@iD@?@?AaA?A?A@A?COK???AA?II??Ic@c@oCb@iJZwBMMh@qKRiEl@eDB?@?B?@?XD?@p@M@???@?RA@?B?@?HBf@oC??AA??Eg@?A?A?A?A?A?A????\\gBGSAA???A???A???AEg@?A???A???A???ABc@?iBU_@Ha@VwAVeAt@uBpAy@?@BDHT@H@??@???@???@??@N@FfDhDLFFBxGoA??@??A@A@A??@ABC@?TOBC@??A@?@A@?@?@?NAjAsGGGIIA??AAA?A?AA??AIa@Ie@?C?A?C@E???A??RkA@C@A@ARW?A????@ATUHI@A@??A@?@A@?@?ZGTEPElA}A?G???????????A???C?????A??AA@g@VQlAu@~ApA@H@@D~A?@?@A@Ej@AB?BC@ABSV?@A?A@??A@A?A@G@g@vBQbAd@xA\\EB?B?B?d@J@@B?@BZZ@@?@@?BH@@?@?@FZ?@?????@???@???X?@???@???@A????@???@?@?@?@A@?BAB?B?@A@?@??A@?@A@???@?@A??@A@?@?@A???A@?@A@???@A?A@????VjA~@N@@@???@@@?@@?@v@v@@?@@?@?@@??@@@Jl@B?F?V@J?@?@?@?@?@?@@@?XLjEcA??DU@A?A@A?A@A??@AHG??RQ@A@??A@?@?@A@?d@G@?@?@?@?@?@?@@D?TFtBo@BS@A???A@A?A@A@?@CDCNE|BjBsArE{@tCiFbCwAdS???@????????A@EV???@???@ITGX?@ABC@_@`@Fb@?B?B?BCN_@nAm@l@C@A@BL?B?B?BSjAABABA@w@v@CBA@C?kATC?C?C?_@I?@O|@p@LB@B@@@v@v@@@@B@B?@eB~FuBxB??YWKCCAAACAi@i@]GCAAACAw@w@AA}@QN~@@B?BABAHQ`AAD?BA@ABOLDR?B?B?BUpA??????ADABA@ABs@r@A@??A@A?A@A?A?E@?@?@@??@@@?@@@RjA?B?B?BUfAmAnAGBQBA?I\\a@b@gBjBgCaASG","constraints":[]}
\ No newline at end of file
diff --git a/test/functional/request/cucumber/features/req-data-bduni-pgr.feature b/test/functional/request/cucumber/features/req-data-bduni-pgr.feature
index 53ac3e1..8a144b8 100644
--- a/test/functional/request/cucumber/features/req-data-bduni-pgr.feature
+++ b/test/functional/request/cucumber/features/req-data-bduni-pgr.feature
@@ -83,3 +83,38 @@ Feature: Road2 with Bduni data via PGR
| method |
| GET |
| POST |
+
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone"
+ And with query parameters:
+ | key | value |
+ | point | 2.1,48.7 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+ And the iso should be similar to "../../data/bduni/pgr/3.json"
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un geometryFormat polyline
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone"
+ And with query parameters:
+ | key | value |
+ | point | 2.1,48.7 |
+ | geometryFormat | polyline |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+ And the iso should be similar to "../../data/bduni/pgr/4.json"
+
+ Examples:
+ | method |
+ | GET |
+ | POST |
\ No newline at end of file
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
index c3eb438..3a511fa 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
@@ -843,7 +843,7 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
- And the response should contain a complete and valid road
+ And the response should contain a complete and valid iso
And the response should contain an attribute "crs" with value "EPSG:2154"
Examples:
| method |
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
index 82061f3..3cb0a4e 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
@@ -23,7 +23,7 @@ Feature: Road2-Valhalla
And with query parameters:
| key | value |
| costType | distance |
- | costValue | 1000 |
+ | costValue | 2000 |
When I send the request
Then the server should send a response with status 200
And the response should have an header "content-type" with value "application/json"
@@ -34,6 +34,23 @@ Feature: Road2-Valhalla
| GET |
| POST |
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un autre crs
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone-valhalla"
+ And with query parameters:
+ | key | value |
+ | crs | EPSG:2154 |
+ | point | 651475,6826145 |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+ And the response should contain an attribute "crs" with value "EPSG:2154"
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
Scenario Outline: [] Route sur l'API simple 1.0.0 avec valhalla
Given an "" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-valhalla"
diff --git a/test/functional/request/cucumber/features/support/world.js b/test/functional/request/cucumber/features/support/world.js
index 5d40a0c..0f3002c 100644
--- a/test/functional/request/cucumber/features/support/world.js
+++ b/test/functional/request/cucumber/features/support/world.js
@@ -5,6 +5,7 @@ const turf = require('@turf/turf');
const axios = require('axios');
const tunnel = require('tunnel');
const https = require('https');
+const polyline = require('@mapbox/polyline');
/**
@@ -704,7 +705,64 @@ class road2World {
}
+ checkIsoContent(filePath) {
+ let referenceResponse = {};
+ let responseJSON = {};
+
+
+ if (typeof this._response === "string") {
+ responseJSON = JSON.parse(this._response);
+ } else {
+ responseJSON = this._response;
+ }
+
+ try {
+ referenceResponse = JSON.parse(fs.readFileSync(path.resolve(__dirname,filePath)));
+ } catch (error) {
+ return "Can't parse JSON file";
+ }
+
+ let refIso = referenceResponse.geometry;
+ let curIso = this._response.geometry;
+
+ if (typeof(refIso) === "string") {
+
+ if (refIso === curIso) {
+ return true;
+ }
+
+ // On part du principe que c'est du polyline
+ refIso = turf.polygon(polyline.decode(refIso));
+ curIso = turf.polygon(polyline.decode(curIso));
+
+ } else {
+
+ // On part du principe que c'est du GeoJSON
+ if (curIso.coordinates) {
+
+ refIso = turf.polygon(refIso.coordinates);
+ try {
+ curIso = turf.polygon(curIso.coordinates);
+ } catch(error) {
+ return "Can't convert curIso into polygon with turfJS";
+ }
+
+ } else {
+ return "curIso doesn't have coordinates";
+ }
+
+ }
+
+ let buffer = turf.buffer(refIso, 0.1, {units: 'kilometers'});
+
+ if (!turf.booleanWithin(curIso, buffer)) {
+ return "Iso is out of the buffer";
+ } else {
+ return true;
+ }
+
+ }
}
From 532153148a838b23216b7d3232460a8b8d1582a2 Mon Sep 17 00:00:00 2001
From: lgrd
Date: Thu, 8 Dec 2022 14:16:39 +0100
Subject: [PATCH 29/93] Create issue templates
---
.github/ISSUE_TEMPLATE/bug_report.md | 46 ++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..6bdd13a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,46 @@
+---
+name: Bug report
+about: Create a report to help us improve Road2
+title: ''
+labels: bug
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**Type of use (choose between):**
+- `service` provided by Road2 (ex. bug with a request from the API simple/1.0.0)
+- `administration` of the services provided by Road2
+- `other`, please add a helpful description
+
+**Type of bug (choose between):**
+- `request`, for bugs with an API
+- `load`, for bugs during the creation of the server
+- `checkConfig`, for bugs with this option
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Load server with this configuration
+2. Request the server
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Environment (please complete the following information):**
+ - OS: [e.g. Debian]
+ - OS Version: [e.g. 11]
+ - Node version: [e.g. 16]
+ - Road2 commit: [sha]
+
+**Configuration:**
+- the configuration was generated inside the docker image: [eg. yes/no]
+- if no, please, provide us the any differences you find useful
+
+**Data:**
+Type of data: [eg. osrm, pgrouting, valhalla]
+Generation of the data: [eg. docker image of route-graph-generator, other]
+
+**Additional context**
+Add any other context about the problem here.
From 7ea110a4f4283bb4b59522586f566c6a7fdf3e20 Mon Sep 17 00:00:00 2001
From: lgrd
Date: Thu, 8 Dec 2022 15:06:03 +0100
Subject: [PATCH 30/93] Create issue templates
---
.github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..bbcbbe7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
From f58898647dc493a6da0573c858fe56103eb147ee Mon Sep 17 00:00:00 2001
From: Loic
Date: Thu, 8 Dec 2022 16:50:53 +0100
Subject: [PATCH 31/93] [doc] roadmap sur github
---
documentation/developers/roadmap.md | 12 ------------
readme.md | 2 +-
2 files changed, 1 insertion(+), 13 deletions(-)
delete mode 100644 documentation/developers/roadmap.md
diff --git a/documentation/developers/roadmap.md b/documentation/developers/roadmap.md
deleted file mode 100644
index 7138fdb..0000000
--- a/documentation/developers/roadmap.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Roadmap du projet Road2
-
-## Développements en cours
-
-Pour la fin de l'année 2022 :
-
-- Intégration de Valhalla dans Road2 et Route-graph-generator
-- Refactorisation d'une partie du code pour :
- - une meilleure gestion de la configuration
- - la création d'un processus administrateur du service. Ce nouveau processus portera l'API admin sans impacter les requêtes des utilisateurs classiques du service.
-
-
diff --git a/readme.md b/readme.md
index ef6fb6a..5b4c809 100644
--- a/readme.md
+++ b/readme.md
@@ -86,7 +86,7 @@ Les participations à ce projet sont encouragées. Il vous est demandé de réal
On trouvera une documentation dédiée aux développeurs [ici](./documentation/developers/readme.md). Elle indique les concepts utiles pour effectuer des développements sur Road2.
-Pour en savoir plus sur notre roadmap, vous pouvez regarder ce [document](./documentation/developers/roadmap.md).
+Pour en savoir plus sur notre roadmap, vous pouvez regarder le projet [IGNF/Road2 Roadmap](https://github.com/orgs/IGNF/projects/3).
Enfin, il est possible d'utiliser ce [docker-compose](./docker/dev/readme.md) pour avoir un environnement de développement incluant la construction des binaires, des modules et la génération des données.
From 39100c3cc22f806afdc39f93c51a80f6c47d6d57 Mon Sep 17 00:00:00 2001
From: Loic
Date: Wed, 14 Dec 2022 18:01:35 +0100
Subject: [PATCH 32/93] [feat] creation du module wkt interne
---
src/js/geometry/formats/wkt.js | 340 +++++++++++++++++++
test/unit/mocha/geometry/formats/testsWkt.js | 182 ++++++++++
2 files changed, 522 insertions(+)
create mode 100644 src/js/geometry/formats/wkt.js
create mode 100644 test/unit/mocha/geometry/formats/testsWkt.js
diff --git a/src/js/geometry/formats/wkt.js b/src/js/geometry/formats/wkt.js
new file mode 100644
index 0000000..6d01404
--- /dev/null
+++ b/src/js/geometry/formats/wkt.js
@@ -0,0 +1,340 @@
+'use strict';
+
+module.exports = {
+
+
+ /**
+ *
+ * @function
+ * @name validateWKT
+ * @description Vérification d'un WKT
+ * @param {string} wktString - WKT à convertir
+ * @return {boolean|string}
+ *
+ */
+
+ validateWKT: function(wktString) {
+
+ if (!wktString) {
+ return "L'argument est vide";
+ }
+ if (typeof(wktString) !== "string") {
+ return "L'argument n'est pas une chaîne";
+ }
+
+ // Taille minimal d'un WKT (ex. 'POINT(2 2)')
+ if (wktString.length < 10) {
+ return "La chaine est trop courte";
+ }
+
+ // On nettoie la chaîne pour faciliter les vérifications qui suivront
+ let cleanWKT = this.cleanWKT(wktString);
+
+ // On vérifie un mimimum de contenu
+ let splitWkt = cleanWKT.match(/^(SRID:\d+;)?(POINT|LINESTRING|POLYGON|GEOMETRYCOLLECTION)\((.*)\)$/);
+ if (splitWkt === null) {
+ return "La chaine nettoyee ne peut etre splittee";
+ }
+ if (splitWkt.length < 3) {
+ return "Le split de la chaine n'est pas valide: " + splitWkt;
+ }
+
+ // On récupère la partie qu'il reste à analyser
+ let geometryType = "";
+ let geometry = "";
+ if (splitWkt.length === 4) {
+ // il y a un SRID
+ geometryType = splitWkt[2];
+ geometry = splitWkt[3];
+ } else {
+ geometryType = splitWkt[1];
+ geometry = splitWkt[2];
+ }
+
+ if (geometryType === "POINT") {
+ if (this._validatePointGeometry(geometry)) {
+ return true;
+ }
+ } else if (geometryType === "LINESTRING") {
+ if (this._validateLinestringGeometry(geometry)) {
+ return true;
+ }
+ } else if (geometryType === "POLYGON") {
+ if (this._validatePolygonGeometry(geometry)) {
+ return true;
+ }
+ } else if (geometryType === "GEOMETRYCOLLECTION") {
+ return this._validateGeometryCollection(geometry);
+ } else {
+ return "geometryType est inconnu: " + geometryType;
+ }
+
+ return "La validation a echoue";
+
+ },
+
+ /**
+ *
+ * @function
+ * @name cleanWKT
+ * @description Nettoyage d'un WKT
+ * @param {string} wktString - WKT à convertir
+ * @return {string} cleanedWktString - WKT nettoyé
+ *
+ */
+
+ cleanWKT: function(wktString) {
+
+ let tmpWKT = wktString.replaceAll(/\s{2,}/g,' ');
+
+ tmpWKT = tmpWKT.replace(/^\s/,'');
+ tmpWKT = tmpWKT.replace(/\s$/,'');
+ tmpWKT = tmpWKT.replaceAll(/\s,/g,',');
+ tmpWKT = tmpWKT.replaceAll(/,\s/g,',');
+ tmpWKT = tmpWKT.replaceAll(/\(\s/g,'(');
+ tmpWKT = tmpWKT.replaceAll(/\s\(/g,'(');
+ tmpWKT = tmpWKT.replaceAll(/\)\s/g,')');
+ tmpWKT = tmpWKT.replaceAll(/\s\)/g,')');
+
+ return tmpWKT.toUpperCase();
+
+ },
+
+ /**
+ *
+ * @function
+ * @name _validatePointGeometry
+ * @description Validation d'un WKT de type POINT
+ * @param {string} geometry - Partie du WKT qui contient la géométrie (ici une paire de coordonnées est attendu)
+ * @return {boolean}
+ *
+ */
+
+ _validatePointGeometry: function(geometry) {
+
+ let regex = new RegExp(/^-?\d+\.?\d*\s-?\d+\.?\d*\s?-?\d+\.?\d*$/);
+ return regex.test(geometry);
+
+ },
+
+ /**
+ *
+ * @function
+ * @name _validateLinestringGeometry
+ * @description Validation d'un WKT de type LINESTRING
+ * @param {string} geometry - Partie du WKT qui contient la géométrie (ici plusieurs paires de coordonnées séparées par des ',' sont attendues)
+ * @return {boolean}
+ *
+ */
+
+ _validateLinestringGeometry: function(geometry) {
+
+ let regex = new RegExp(/^(-?\d+\.?\d*\s-?\d+\.?\d*(\s-?\d+\.?\d*)?,?){2,}$/);
+ return regex.test(geometry);
+
+ },
+
+ /**
+ *
+ * @function
+ * @name _validatePolygonGeometry
+ * @description Validation d'un WKT de type POLYGON
+ * @param {string} geometry - Partie du WKT qui contient la géométrie (ici plusieurs paires de coordonnées séparées par des ',' et regroupées dans des '()' sont attendues)
+ * @return {boolean}
+ *
+ */
+
+ _validatePolygonGeometry: function(geometry) {
+
+ let regex = new RegExp(/^\((-?\d+\.?\d*\s-?\d+\.?\d*(\s-?\d+\.?\d*)?,?){3,}\)(,\((-?\d+\.?\d*\s-?\d+\.?\d*(\s-?\d+\.?\d*)?,?){3,}\))?$/);
+ return regex.test(geometry);
+
+ },
+
+ /**
+ *
+ * @function
+ * @name _validateGeometryCollectionGeometry
+ * @description Validation d'un WKT de type GEOMETRYCOLLECTION
+ * @param {string} geometry - Partie du WKT qui contient la géométrie (ici plusieurs paires de coordonnées séparées par des ',' et regroupées dans des '()' sont attendues)
+ * @return {boolean}
+ *
+ */
+
+ _validateGeometryCollection: function(geometry) {
+
+ let matches = geometry.matchAll(/([A-Z]+)/g);
+
+ if (matches === null) {
+ return "La gemetrie ne peut etre analysee";
+ }
+
+ matches = Array.from(matches);
+
+ for (let i = 0; i < matches.length; i++) {
+
+ let curGeometry = "";
+ if (i === matches.length-1) {
+ curGeometry = geometry.substring(matches[i]['index']+matches[i][1].length);
+ } else {
+ curGeometry = geometry.substring(matches[i]['index']+matches[i][1].length,matches[i+1]['index']-1);
+ }
+ curGeometry = curGeometry.substring(1,curGeometry.length-1);
+
+ if (matches[i][1] === "POINT") {
+ if (!this._validatePointGeometry(curGeometry)) {
+ return "La gemetrie " + i + " point de la collection est invalide";
+ }
+ } else if (matches[i][1] === "LINESTRING") {
+ if (!this._validateLinestringGeometry(curGeometry)) {
+ return "La gemetrie " + i + " linestring de la collection est invalide";
+ }
+ } else if (matches[i][1] === "POLYGON") {
+ if (!this._validatePolygonGeometry(curGeometry)) {
+ return "La gemetrie " + i + " polygon de la collection est invalide";
+ }
+ } else {
+ return "geometryType est inconnu: " + matches[i][1];
+ }
+
+ }
+
+ return true;
+
+ },
+
+ /**
+ *
+ * @function
+ * @name toGeoJSON
+ * @description Conversion d'un WKT en GeoJSON
+ * @param {string} wktString - WKT à convertir
+ * @return {object|string} JSON
+ *
+ */
+
+ toGeoJSON: function(wktString) {
+
+ let finalGeoJSON = {};
+
+ let splitWkt = this.cleanWKT(wktString).match(/^(SRID:\d+;)?(POINT|LINESTRING|POLYGON|GEOMETRYCOLLECTION)\((.*)\)$/)
+ let geometryType = "";
+ let geometry = "";
+ if (splitWkt.length === 4) {
+ // il y a un SRID
+ geometryType = splitWkt[2];
+ geometry = splitWkt[3];
+ } else {
+ geometryType = splitWkt[1];
+ geometry = splitWkt[2];
+ }
+
+ if (geometryType === "GEOMETRYCOLLECTION") {
+ finalGeoJSON = this._toGeometryCollection(geometry);
+ } else {
+ finalGeoJSON = this._toGeometry(geometryType, geometry);
+ }
+
+ return finalGeoJSON;
+
+ },
+
+ /**
+ *
+ * @function
+ * @name _toGeometry
+ * @description Conversion d'un WKT en géométrie de GeoJSON
+ * @param {string} geometryType - Type de la géométrie (selon le WKT d'origine)
+ * @param {string} geometry - Géométrie à convertir (selon le WKT d'origine)
+ * @return {object|string} JSON
+ *
+ */
+
+ _toGeometry: function(geometryType, geometry) {
+
+ const mapping = {
+ POINT:"Point",
+ LINESTRING:"LineString",
+ POLYGON:"Polygon"
+ };
+
+ geometry = geometry.replaceAll(/(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)/g,"[$1,$2,$3]");
+ geometry = geometry.replaceAll(/(-?\d+\.?\d*)\s(-?\d+\.?\d*)/g,"[$1,$2]");
+ geometry = geometry.replaceAll(/\(/g,"[");
+ geometry = geometry.replaceAll(/\)/g,"]");
+
+ if (geometryType === "LINESTRING") {
+ geometry = "[" + geometry + "]";
+ }
+ if (geometryType === "POLYGON") {
+ geometry = geometry.replaceAll(/\),\(/g,"],[");
+ geometry = "[" + geometry + "]";
+ }
+ geometry = JSON.parse(geometry);
+
+ return {
+ "type": mapping[geometryType],
+ "coordinates": geometry
+ };
+
+ },
+
+ /**
+ *
+ * @function
+ * @name _toGeometryCollection
+ * @description Conversion d'un WKT en GeoJSON
+ * @param {string} geometry - Géométrie à convertir (selon le WKT d'origine)
+ * @return {object|string} JSON
+ *
+ */
+
+ _toGeometryCollection: function(geometry) {
+
+ let geometryCollection = {
+ "type": "GeometryCollection",
+ "geometries": new Array()
+ };
+
+ let matches = Array.from(geometry.matchAll(/([A-Z]+)/g));
+
+ for (let i = 0; i < matches.length; i++) {
+
+ let curGeometry = "";
+ if (i === matches.length-1) {
+ curGeometry = geometry.substring(matches[i]['index']+matches[i][1].length);
+ } else {
+ curGeometry = geometry.substring(matches[i]['index']+matches[i][1].length,matches[i+1]['index']-1);
+ }
+ curGeometry = curGeometry.substring(1,curGeometry.length-1);
+
+ geometryCollection.geometries.push(this._toGeometry(matches[i][1], curGeometry));
+
+ }
+
+ return geometryCollection;
+
+ },
+
+ /**
+ *
+ * @function
+ * @name fromGeoJSON
+ * @description Conversion d'un GeoJSON en WKT
+ * @param {JSON} jsonObject - JSON à convertir
+ * @return {string} wktString
+ *
+ */
+
+ fromGeoJSON: function(jsonObject) {
+
+ let finalWkt = "";
+
+
+
+ return finalWkt;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/test/unit/mocha/geometry/formats/testsWkt.js b/test/unit/mocha/geometry/formats/testsWkt.js
new file mode 100644
index 0000000..6f3dc4b
--- /dev/null
+++ b/test/unit/mocha/geometry/formats/testsWkt.js
@@ -0,0 +1,182 @@
+const assert = require('assert');
+const Wkt = require('../../../../../src/js/geometry/formats/wkt');
+const logManager = require('../../logManager');
+
+const { hrtime } = require('node:process');
+const WKTmodule = require('wkt');
+
+describe('Test de la classe Wkt', function() {
+
+ before(function() {
+ // runs before all tests in this block
+ logManager.manageLogs();
+ });
+
+ let pointWkt = "POINT(2 48)";
+ let linestringWkt = "LINESTRING(2 48,2.1 48.1,2.2 48.2)";
+ let polygonWkt = "POLYGON((2 48,2.1 48.1,2.2 48.2,2 48))";
+ let polygonWkt2 = "POLYGON((2 48,2.1 48.1,2.2 48.2,2 48),(2 48,2.1 48.1,2.2 48.2,2 48))";
+ let geomcollWkt = "GEOMETRYCOLLECTION(POINT(2 48),LINESTRING(2 48,2.1 48.1,2.2 48.2),POLYGON((2 48,2.1 48.1,2.2 48.2,2 48),(2 48,2.1 48.1,2.2 48.2,2 48)))";
+ let spaceWkt = " POLYGON ( (2 48, 2.1 48.1,2.2 48.2) , ( 2 48, 2.1 48.1 ,2.2 48.2 ) ) ";
+ let lowWkt = "polygon((2 48,2.1 48.1,2.2 48.2,2 48))";
+ let eWkt = "SRID:4326;POINT(2 48)";
+ let numberWkt = 1;
+ let objectWkt = {};
+ let emptyWkt = "";
+ let wrongTypeWkt = "TEST(2 48)";
+ let noPointTypeWkt = "(2 48)";
+ let noLinestringTypeWkt = "(2 48,2.1 48.1,2.2 48.2)";
+ let wrongpointWkt = "POINT(2 48";
+ let wrongpointWkt2 = "POINT(2)";
+ let wronglineWkt = "LINESTRING(2 48";
+ let wronglineWkt2 = "LINESTRING(2)";
+ let wronglineWkt3 = "LINESTRING(2 48)";
+ let wronglineWkt4 = "LINESTRING(2 48,2.1)";
+ let wronglineWkt5 = "LINESTRING(2 48,";
+ let wrongeWkt = "SID:4326;POINT(2 48)";
+ let wrongeWkt2 = "SRID:;POINT(2 48)";
+ let wrongeWkt3 = "SRID4326;POINT(2 48)";
+ let loweWkt = "srid:4326;POINT(2 48)";
+ let pointJson = {"type":"Point","coordinates":[2,48]};
+ let linestringJson = {"type":"LineString","coordinates":[[2,48],[2.1,48.1],[2.2,48.2]]};
+ let polygonJson = {"type":"Polygon","coordinates":[[[2,48],[2.1,48.1],[2.2,48.2],[2,48]]]};
+ let polygonJson2 = {"type":"Polygon","coordinates":[[[2,48],[2.1,48.1],[2.2,48.2],[2,48]],[[2,48],[2.1,48.1],[2.2,48.2],[2,48]]]};
+ let geometryCollectionJson = {"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[2,48]},{"type":"LineString","coordinates":[[2,48],[2.1,48.1],[2.2,48.2]]},{"type":"Polygon","coordinates":[[[2,48],[2.1,48.1],[2.2,48.2],[2,48]],[[2,48],[2.1,48.1],[2.2,48.2],[2,48]]]}]};
+
+ describe('Test de la fonction validateWKT()', function() {
+
+ it('Avec un bon wkt (point)', function() {
+ assert.equal(Wkt.validateWKT(pointWkt), true);
+ });
+
+ it('Avec un bon wkt (linestring)', function() {
+ assert.equal(Wkt.validateWKT(linestringWkt), true);
+ });
+
+ it('Avec un bon wkt (polygon)', function() {
+ assert.equal(Wkt.validateWKT(polygonWkt), true);
+ });
+
+ it('Avec un bon wkt (polygon donut)', function() {
+ assert.equal(Wkt.validateWKT(polygonWkt2), true);
+ });
+
+ it('Avec un bon wkt (geometryCollection)', function() {
+ assert.equal(Wkt.validateWKT(geomcollWkt), true);
+ });
+
+ it('Avec un bon ewkt (point)', function() {
+ assert.equal(Wkt.validateWKT(eWkt), true);
+ });
+
+ it('Avec un wkt qui contient des espaces', function() {
+ assert.equal(Wkt.validateWKT(spaceWkt), true);
+ });
+
+ it('Avec un wkt (insensitive case)', function() {
+ assert.equal(Wkt.validateWKT(lowWkt), true);
+ });
+
+ it('Avec un ewkt (insensitive case)', function() {
+ assert.equal(Wkt.validateWKT(loweWkt), true);
+ });
+
+ it('Avec un nombre', function() {
+ assert.equal(Wkt.validateWKT(numberWkt), "L'argument n'est pas une chaîne");
+ });
+
+ it('Avec un objet vide', function() {
+ assert.equal(Wkt.validateWKT(objectWkt), "L'argument n'est pas une chaîne");
+ });
+
+ it('Avec une chaine vide', function() {
+ assert.equal(Wkt.validateWKT(emptyWkt), "L'argument est vide");
+ });
+
+ it('Avec rien', function() {
+ assert.equal(Wkt.validateWKT(), "L'argument est vide");
+ });
+
+ it('Avec un mauvais type', function() {
+ assert.equal(Wkt.validateWKT(wrongTypeWkt), "La chaine nettoyee ne peut etre splittee");
+ });
+
+ it('Linestring sans type', function() {
+ assert.equal(Wkt.validateWKT(noPointTypeWkt), "La chaine est trop courte");
+ });
+
+ it('Linestring sans type', function() {
+ assert.equal(Wkt.validateWKT(noLinestringTypeWkt), "La chaine nettoyee ne peut etre splittee");
+ });
+
+ it('Mauvais wkt (point)', function() {
+ assert.equal(Wkt.validateWKT(wrongpointWkt), "La chaine nettoyee ne peut etre splittee");
+ });
+
+ it('Mauvais wkt (point) 2', function() {
+ assert.equal(Wkt.validateWKT(wrongpointWkt2), "La chaine est trop courte");
+ });
+
+ it('Mauvais wkt (linestring)', function() {
+ assert.equal(Wkt.validateWKT(wronglineWkt), "La chaine nettoyee ne peut etre splittee");
+ });
+
+ it('Mauvais wkt (linestring) 2', function() {
+ assert.equal(Wkt.validateWKT(wronglineWkt2), "La validation a echoue");
+ });
+
+ it('Mauvais wkt (linestring) 3', function() {
+ assert.equal(Wkt.validateWKT(wronglineWkt3), "La validation a echoue");
+ });
+
+ it('Mauvais wkt (linestring) 4', function() {
+ assert.equal(Wkt.validateWKT(wronglineWkt4), "La validation a echoue");
+ });
+
+ it('Mauvais wkt (linestring) 5', function() {
+ assert.equal(Wkt.validateWKT(wronglineWkt5), "La chaine nettoyee ne peut etre splittee");
+ });
+
+ it('Mauvais ewkt (point)', function() {
+ assert.equal(Wkt.validateWKT(wrongeWkt), "La chaine nettoyee ne peut etre splittee");
+ });
+
+ it('Mauvais ewkt (point) 2', function() {
+ assert.equal(Wkt.validateWKT(wrongeWkt2), "La chaine nettoyee ne peut etre splittee");
+ });
+
+ it('Mauvais ewkt (point) 3', function() {
+ assert.equal(Wkt.validateWKT(wrongeWkt3), "La chaine nettoyee ne peut etre splittee");
+ });
+
+ });
+
+ describe('Test de la fonction toGeoJSON()', function() {
+
+ it('Avec un bon wkt (point)', function() {
+ assert.deepStrictEqual(Wkt.toGeoJSON(pointWkt), pointJson);
+ });
+
+ it('Avec un bon wkt (linestring)', function() {
+ assert.deepStrictEqual(Wkt.toGeoJSON(linestringWkt), linestringJson);
+ });
+
+ it('Avec un bon wkt (polygon simple)', function() {
+ assert.deepStrictEqual(Wkt.toGeoJSON(polygonWkt), polygonJson);
+ });
+
+ it('Avec un bon wkt (polygon donuts)', function() {
+ assert.deepStrictEqual(Wkt.toGeoJSON(polygonWkt2), polygonJson2);
+ });
+
+ it('Avec un bon wkt (geometry collection)', function() {
+ assert.deepStrictEqual(Wkt.toGeoJSON(geomcollWkt), geometryCollectionJson);
+ });
+
+ it('Avec un bon ewkt (point)', function() {
+ assert.deepStrictEqual(Wkt.toGeoJSON(eWkt), pointJson);
+ });
+
+ });
+
+});
From 5fafc0d6555320c79c67ff9650b685f24e7be9e3 Mon Sep 17 00:00:00 2001
From: Loic
Date: Thu, 15 Dec 2022 11:48:08 +0100
Subject: [PATCH 33/93] [test] maj des tests unitaires du projectionManager
---
docker/dev/docker-compose.yml | 2 +-
.../mocha/geography/testsProjectionManager.js | 82 +++++++++----------
test/unit/mocha/topology/testsTopology.js | 47 -----------
test/unit/mocha/utils/testsStorageManager.js | 40 ---------
4 files changed, 42 insertions(+), 129 deletions(-)
delete mode 100644 test/unit/mocha/topology/testsTopology.js
delete mode 100644 test/unit/mocha/utils/testsStorageManager.js
diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml
index a7869ec..9c4c2fa 100644
--- a/docker/dev/docker-compose.yml
+++ b/docker/dev/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- pgrouting
environment:
- NODE_ENV=debug
- command : "npm run debug -- --ROAD2_CONF_FILE=../config/road2.json"
+ command : "sleep 60000"
ports:
- 8080:8080
- 9229:9229
diff --git a/test/unit/mocha/geography/testsProjectionManager.js b/test/unit/mocha/geography/testsProjectionManager.js
index 1173859..1f9ad4f 100644
--- a/test/unit/mocha/geography/testsProjectionManager.js
+++ b/test/unit/mocha/geography/testsProjectionManager.js
@@ -9,7 +9,7 @@ describe('Test de la classe ProjectionManager', function() {
logManager.manageLogs();
});
- describe('Test du constructeur et des getters/setters', function() {
+ describe('Test du constructeur', function() {
let projManager = new ProjectionManager();
@@ -33,44 +33,44 @@ describe('Test de la classe ProjectionManager', function() {
});
- describe('Vérification d\'un fichier de projections', function() {
+ describe('Test de isProjectionChecked', function() {
let projManager = new ProjectionManager();
- let file = "/home/docker/app/test/unit/mocha/config/projections/projection.json";
+ let directory = "/home/docker/app/test/unit/mocha/config/projections/";
- it('checkProjectionFile()', function() {
- assert.equal(projManager.checkProjectionFile(file), true);
- assert.equal(projManager.isChecked("EPSG:4326"), true);
- assert.equal(projManager.isChecked("EPSG:2154"), true);
- assert.equal(projManager.isChecked("EPSG:2155"), false);
+ it('isProjectionChecked()', function() {
+ projManager.checkProjectionDirectory(directory);
+ assert.equal(projManager.isProjectionChecked("EPSG:4326"), true);
+ assert.equal(projManager.isProjectionChecked("EPSG:2154"), true);
+ assert.equal(projManager.isProjectionChecked("EPSG:2155"), false);
});
});
- describe('Vérification d\'un dossier de projections', function() {
+ describe('Vérification d\'un fichier de projections', function() {
let projManager = new ProjectionManager();
- let directory = "/home/docker/app/test/unit/mocha/config/projections/";
+ let file = "/home/docker/app/test/unit/mocha/config/projections/projection.json";
- it('checkProjectionDirectory()', function() {
- assert.equal(projManager.checkProjectionDirectory(directory), true);
- assert.equal(projManager.isChecked("EPSG:4326"), true);
- assert.equal(projManager.isChecked("EPSG:2154"), true);
- assert.equal(projManager.isChecked("EPSG:2155"), false);
+ it('checkProjectionFile()', function() {
+ assert.equal(projManager.checkProjectionFile(file), true);
+ assert.equal(projManager.isProjectionChecked("EPSG:4326"), true);
+ assert.equal(projManager.isProjectionChecked("EPSG:2154"), true);
+ assert.equal(projManager.isProjectionChecked("EPSG:2155"), false);
});
});
- describe('Test de isChecked', function() {
+ describe('Vérification d\'un dossier de projections', function() {
let projManager = new ProjectionManager();
let directory = "/home/docker/app/test/unit/mocha/config/projections/";
- it('isChecked()', function() {
- projManager.checkProjectionDirectory(directory);
- assert.equal(projManager.isChecked("EPSG:4326"), true);
- assert.equal(projManager.isChecked("EPSG:2154"), true);
- assert.equal(projManager.isChecked("EPSG:2155"), false);
+ it('checkProjectionDirectory()', function() {
+ assert.equal(projManager.checkProjectionDirectory(directory), true);
+ assert.equal(projManager.isProjectionChecked("EPSG:4326"), true);
+ assert.equal(projManager.isProjectionChecked("EPSG:2154"), true);
+ assert.equal(projManager.isProjectionChecked("EPSG:2155"), false);
});
});
@@ -90,44 +90,44 @@ describe('Test de la classe ProjectionManager', function() {
});
- describe('Chargement d\'un fichier de projections', function() {
+ describe('Test de isProjectionLoaded', function() {
let projManager = new ProjectionManager();
- let file = "/home/docker/app/test/unit/mocha/config/projections/projection.json";
+ let directory = "/home/docker/app/test/unit/mocha/config/projections/";
- it('loadProjectionFile()', function() {
- assert.equal(projManager.loadProjectionFile(file), true);
- assert.equal(projManager.isAvailable("EPSG:4326"), true);
- assert.equal(projManager.isAvailable("EPSG:2154"), true);
- assert.equal(projManager.isAvailable("EPSG:2155"), false);
+ it('isProjectionLoaded()', function() {
+ projManager.loadProjectionDirectory(directory);
+ assert.equal(projManager.isProjectionLoaded("EPSG:4326"), true);
+ assert.equal(projManager.isProjectionLoaded("EPSG:2154"), true);
+ assert.equal(projManager.isProjectionLoaded("EPSG:2155"), false);
});
});
- describe('Chargement d\'un dossier de projections', function() {
+ describe('Chargement d\'un fichier de projections', function() {
let projManager = new ProjectionManager();
- let directory = "/home/docker/app/test/unit/mocha/config/projections/";
+ let file = "/home/docker/app/test/unit/mocha/config/projections/projection.json";
- it('loadProjectionDirectory()', function() {
- assert.equal(projManager.loadProjectionDirectory(directory), true);
- assert.equal(projManager.isAvailable("EPSG:4326"), true);
- assert.equal(projManager.isAvailable("EPSG:2154"), true);
- assert.equal(projManager.isAvailable("EPSG:2155"), false);
+ it('loadProjectionFile()', function() {
+ assert.equal(projManager.loadProjectionFile(file), true);
+ assert.equal(projManager.isProjectionLoaded("EPSG:4326"), true);
+ assert.equal(projManager.isProjectionLoaded("EPSG:2154"), true);
+ assert.equal(projManager.isProjectionLoaded("EPSG:2155"), false);
});
});
- describe('Test de isAvailable', function() {
+ describe('Chargement d\'un dossier de projections', function() {
let projManager = new ProjectionManager();
let directory = "/home/docker/app/test/unit/mocha/config/projections/";
- it('isAvailable()', function() {
- projManager.loadProjectionDirectory(directory);
- assert.equal(projManager.isAvailable("EPSG:4326"), true);
- assert.equal(projManager.isAvailable("EPSG:2154"), true);
- assert.equal(projManager.isAvailable("EPSG:2155"), false);
+ it('loadProjectionDirectory()', function() {
+ assert.equal(projManager.loadProjectionDirectory(directory), true);
+ assert.equal(projManager.isProjectionLoaded("EPSG:4326"), true);
+ assert.equal(projManager.isProjectionLoaded("EPSG:2154"), true);
+ assert.equal(projManager.isProjectionLoaded("EPSG:2155"), false);
});
});
diff --git a/test/unit/mocha/topology/testsTopology.js b/test/unit/mocha/topology/testsTopology.js
deleted file mode 100644
index e877eca..0000000
--- a/test/unit/mocha/topology/testsTopology.js
+++ /dev/null
@@ -1,47 +0,0 @@
-const assert = require('assert');
-const Topology = require('../../../../src/js/topology/topology');
-const logManager = require('../logManager');
-
-describe('Test de la classe Topology', function() {
-
- before(function() {
- // runs before all tests in this block
- logManager.manageLogs();
- });
-
- let configuration = {
- "id": "corse-osm",
- "type": "osm",
- "description": "Corse en version OSM",
- "projection": "EPSG:4326",
- "bbox": "-180,-90,180,90"
- };
-
-
- describe('Test du constructeur et des getters', function() {
-
- let topology = new Topology(configuration.id, configuration.type, configuration.description, configuration.projection, configuration.bbox);
-
- it('Get Id', function() {
- assert.equal(topology.id, configuration.id);
- });
-
- it('Get Type', function() {
- assert.equal(topology.type, configuration.type);
- });
-
- it('Get Description', function() {
- assert.equal(topology.description, configuration.description);
- });
-
- it('Get Projection', function() {
- assert.equal(topology.projection, configuration.projection);
- });
-
- it('Get Bbox', function() {
- assert.equal(topology.bbox, configuration.bbox);
- });
-
- });
-
-});
diff --git a/test/unit/mocha/utils/testsStorageManager.js b/test/unit/mocha/utils/testsStorageManager.js
deleted file mode 100644
index 9db60b0..0000000
--- a/test/unit/mocha/utils/testsStorageManager.js
+++ /dev/null
@@ -1,40 +0,0 @@
-const assert = require('assert');
-const storageManager = require('../../../../src/js/utils/storageManager');
-const logManager = require('../logManager');
-
-describe('Test du storageManager', function() {
-
- before(function() {
- // runs before all tests in this block
- logManager.manageLogs();
- });
-
- describe('Test de la fonction checkJsonStorage()', function() {
-
- let json = {
- "file": "/home/docker/data/bduni-idf-car-fastest/bduni-idf-car-fastest.osrm"
- };
-
- let jsonNoFile = {
- "file": "/home/docker/data/corse-latest.osrm"
- };
-
- let wrongJson = {
- "fil": "/home/docker/data/corse-latest.osrm"
- };
-
- it('checkJsonStorage() should return true when all is correct', function() {
- assert.equal(storageManager.checkJsonStorage(json), true);
- });
-
- it('checkJsonStorage() should return false when no file', function() {
- assert.equal(storageManager.checkJsonStorage(jsonNoFile), false);
- });
-
- it('checkJsonStorage() should return false when the json is incorrect', function() {
- assert.equal(storageManager.checkJsonStorage(wrongJson), false);
- });
-
- });
-
-});
From ebed8ae6a6f87d727e7899e417fbb13e08755b26 Mon Sep 17 00:00:00 2001
From: Loic
Date: Fri, 16 Dec 2022 15:50:18 +0100
Subject: [PATCH 34/93] [feat] conversion geojson vers wkt dans le module
---
src/js/geometry/formats/wkt.js | 66 ++++++++++++++++++--
test/unit/mocha/geometry/formats/testsWkt.js | 24 +++++++
2 files changed, 86 insertions(+), 4 deletions(-)
diff --git a/src/js/geometry/formats/wkt.js b/src/js/geometry/formats/wkt.js
index 6d01404..04d8799 100644
--- a/src/js/geometry/formats/wkt.js
+++ b/src/js/geometry/formats/wkt.js
@@ -326,14 +326,72 @@ module.exports = {
*
*/
- fromGeoJSON: function(jsonObject) {
+ fromGeoJSON: function(jsonObject) {
- let finalWkt = "";
+ if (jsonObject.type === "Point") {
-
+ return this._fromPoint(jsonObject);
+
+ } else if (jsonObject.type === "LineString") {
+
+ return this._internalFrom(jsonObject,"LINESTRING");
+
+ } else if (jsonObject.type === "Polygon") {
+
+ return this._internalFrom(jsonObject,"POLYGON");
- return finalWkt;
+ } else if (jsonObject.type === "GeometryCollection") {
+
+ let arrayWkt = new Array();
+ for(let geometry of jsonObject.geometries) {
+ arrayWkt.push(this.fromGeoJSON(geometry));
+ }
+ return "GEOMETRYCOLLECTION(" + arrayWkt.toString() + ")";
+
+ } else {
+ return "";
+ }
+ },
+
+ /**
+ *
+ * @function
+ * @name _fromPoint
+ * @description Conversion d'un GeoJSON en WKT
+ * @param {JSON} jsonObject - JSON à convertir
+ * @return {string} wktString
+ *
+ */
+
+ _fromPoint: function(jsonObject) {
+
+ let geometry = JSON.stringify(jsonObject.coordinates);
+ geometry = geometry.replaceAll(/\[(-?\d+\.?\d*),(-?\d+\.?\d*),(-?\d+\.?\d*)\]/g,"($1 $2 $3)");
+ geometry = geometry.replaceAll(/\[(-?\d+\.?\d*),(-?\d+\.?\d*)\]/g,"($1 $2)");
+ return "POINT"+geometry;
+
+ },
+
+ /**
+ *
+ * @function
+ * @name _internalFrom
+ * @description Conversion d'un GeoJSON en WKT
+ * @param {JSON} jsonObject - JSON à convertir
+ * @return {string} wktString
+ *
+ */
+
+ _internalFrom: function(jsonObject, type) {
+
+ let geometry = JSON.stringify(jsonObject.coordinates);
+ geometry = geometry.replaceAll(/\[(-?\d+\.?\d*),(-?\d+\.?\d*),(-?\d+\.?\d*)\]/g,"$1 $2 $3");
+ geometry = geometry.replaceAll(/\[(-?\d+\.?\d*),(-?\d+\.?\d*)\]/g,"$1 $2");
+ geometry = geometry.replaceAll(/\[/g,"(");
+ geometry = geometry.replaceAll(/\]/g,")");
+ return type+geometry;
+
}
diff --git a/test/unit/mocha/geometry/formats/testsWkt.js b/test/unit/mocha/geometry/formats/testsWkt.js
index 6f3dc4b..0881545 100644
--- a/test/unit/mocha/geometry/formats/testsWkt.js
+++ b/test/unit/mocha/geometry/formats/testsWkt.js
@@ -179,4 +179,28 @@ describe('Test de la classe Wkt', function() {
});
+ describe('Test de la fonction fromGeoJSON()', function() {
+
+ it('Avec un bon geojson (point)', function() {
+ assert.deepStrictEqual(Wkt.fromGeoJSON(pointJson), pointWkt);
+ });
+
+ it('Avec un bon geojson (linestring)', function() {
+ assert.deepStrictEqual(Wkt.fromGeoJSON(linestringJson), linestringWkt);
+ });
+
+ it('Avec un bon geojson (polygon)', function() {
+ assert.deepStrictEqual(Wkt.fromGeoJSON(polygonJson), polygonWkt);
+ });
+
+ it('Avec un bon geojson (polygon donuts)', function() {
+ assert.deepStrictEqual(Wkt.fromGeoJSON(polygonJson2), polygonWkt2);
+ });
+
+ it('Avec un bon geojson (geometry collection)', function() {
+ assert.deepStrictEqual(Wkt.fromGeoJSON(geometryCollectionJson), geomcollWkt);
+ });
+
+ });
+
});
From 42de23eccd6053d57ed49d81ee8b589277f59671 Mon Sep 17 00:00:00 2001
From: Loic
Date: Fri, 16 Dec 2022 17:31:08 +0100
Subject: [PATCH 35/93] [deps] remplacement du module wkt par la lib interne
---
changelog.md | 1 +
package.json | 4 +---
src/js/sources/smartroutingSource.js | 6 +++---
test/integration/readme.md | 4 ----
test/unit/mocha/geometry/formats/testsWkt.js | 3 ---
test/unit/readme.md | 3 ++-
6 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/changelog.md b/changelog.md
index accf6ff..d2482c9 100644
--- a/changelog.md
+++ b/changelog.md
@@ -4,6 +4,7 @@ ADDED:
- La classe Administrator permet de gérer le service via une API. Notamment la création, la suppression et la modification d'un service seront possible.
- Cette classe est configurée par un nouveau fichier de configuration.
- Ajout du moteur Valhalla pour les itinéraires et les isochrones
+ - Le module `wkt` a été remplacé par une implémentation interne
CHANGED:
- L'option --configCheck au démarrage de Road2 n'a plus exactement le même comportement.
diff --git a/package.json b/package.json
index cc8710b..4ccaf25 100644
--- a/package.json
+++ b/package.json
@@ -27,8 +27,7 @@
"https-proxy-agent": "5.0.1",
"log4js": "6.7.1",
"nconf": "0.12.0",
- "proj4": "2.8.0",
- "wkt": "0.1.1"
+ "proj4": "2.8.0"
},
"optionalDependencies": {
"osrm": "5.26.0",
@@ -53,7 +52,6 @@
"proj4",
"assert",
"helmet",
- "wkt",
"got",
"http-proxy-agent"
]
diff --git a/src/js/sources/smartroutingSource.js b/src/js/sources/smartroutingSource.js
index 0d179d0..be53d34 100644
--- a/src/js/sources/smartroutingSource.js
+++ b/src/js/sources/smartroutingSource.js
@@ -13,7 +13,7 @@ const Distance = require('../geography/distance');
const Duration = require('../time/duration');
const errorManager = require('../utils/errorManager');
const log4js = require('log4js');
-const wkt = require('wkt');
+const wkt = require('../geometry/formats/wkt');
const httpQuery = require('../utils/httpQuery');
@@ -330,7 +330,7 @@ module.exports = class smartroutingSource extends Source {
// ---
// convertion de la geometry
- const wayGeojson = wkt.parse(smartroutingResponse.geometryWkt);
+ const wayGeojson = wkt.toGeoJSON(smartroutingResponse.geometryWkt);
let way = new Line(wayGeojson, 'geojson', askedProjection);
// start et end
@@ -443,7 +443,7 @@ module.exports = class smartroutingSource extends Source {
location = new Point(locationCoords[0], locationCoords[1], projection);
// Geometrie
- const rawGeometry = wkt.parse(smartroutingResponse.wktGeometry);
+ const rawGeometry = wkt.toGeoJSON(smartroutingResponse.wktGeometry);
// Cas où il n'y a pas d'isochrone car costValue trop faible
if (rawGeometry === null) {
diff --git a/test/integration/readme.md b/test/integration/readme.md
index a733d48..3bc24f3 100644
--- a/test/integration/readme.md
+++ b/test/integration/readme.md
@@ -145,10 +145,6 @@ Autres:
- defs()
- ()
-- wkt
- - sources/smartroutingSource.js
- - parse()
-
- osrm
- sources/sourceManager.js
- sources/osrmSource.js
diff --git a/test/unit/mocha/geometry/formats/testsWkt.js b/test/unit/mocha/geometry/formats/testsWkt.js
index 0881545..4b96eaa 100644
--- a/test/unit/mocha/geometry/formats/testsWkt.js
+++ b/test/unit/mocha/geometry/formats/testsWkt.js
@@ -2,9 +2,6 @@ const assert = require('assert');
const Wkt = require('../../../../../src/js/geometry/formats/wkt');
const logManager = require('../../logManager');
-const { hrtime } = require('node:process');
-const WKTmodule = require('wkt');
-
describe('Test de la classe Wkt', function() {
before(function() {
diff --git a/test/unit/readme.md b/test/unit/readme.md
index cf18680..9cd4908 100644
--- a/test/unit/readme.md
+++ b/test/unit/readme.md
@@ -32,4 +32,5 @@ On trouvera donc les classes ou les fichiers suivants:
- processManager (log4js)
- simplify.js //TODO
- storageManager (log4js)
-- validationManager
\ No newline at end of file
+- validationManager
+- wkt
\ No newline at end of file
From b152309466f20b84701414a007450c023b75e128 Mon Sep 17 00:00:00 2001
From: Loic
Date: Mon, 19 Dec 2022 13:42:48 +0100
Subject: [PATCH 36/93] =?UTF-8?q?[feat]=20gestion=20du=20wkt=20dans=20les?=
=?UTF-8?q?=20r=C3=A9ponses?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
documentation/apis/simple/1.0.0/api.yaml | 8 +-
.../configuration/resources/osrm.resource | 3 +-
.../configuration/resources/pgr.resource | 6 +-
.../configuration/resources/smartpgr.resource | 6 +-
.../configuration/resources/valhalla.resource | 6 +-
documentation/developers/functionnalities.md | 4 +-
src/js/geometry/line.js | 51 +++++--------
src/js/geometry/point.js | 10 +--
src/js/geometry/polygon.js | 76 +++++++++++++------
.../features/req-simple-1.0.0-osrm.feature | 16 ++++
.../features/req-simple-1.0.0-pgr.feature | 32 ++++++++
.../req-simple-1.0.0-smartrouting.feature | 18 ++++-
.../req-simple-1.0.0-valhalla.feature | 34 +++++++++
.../mocha/geometry/integrationLine.js | 8 --
14 files changed, 194 insertions(+), 84 deletions(-)
diff --git a/documentation/apis/simple/1.0.0/api.yaml b/documentation/apis/simple/1.0.0/api.yaml
index 24fb6fa..6f115c6 100644
--- a/documentation/apis/simple/1.0.0/api.yaml
+++ b/documentation/apis/simple/1.0.0/api.yaml
@@ -92,7 +92,7 @@ paths:
required: false
schema:
type: "string"
- enum: ["geojson","polyline"]
+ enum: ["geojson","polyline","wkt"]
- name: "constraints"
in: "query"
description: "Contraintes utilisées pour le calcul. Il s'agit d'un objet JSON (voir la version POST de cette opération). Les paramètres disponibles sont présents dans le GetCapabilities."
@@ -377,7 +377,7 @@ paths:
required: false
schema:
type: "string"
- enum: ["geojson","polyline"]
+ enum: ["geojson","polyline","wkt"]
- name: "distanceUnit"
in: "query"
description: "Unité des distances renvoyées. Les valeurs disponibles et la valeur par défaut utilisées sont présentes dans le GetCapabilities."
@@ -526,7 +526,7 @@ components:
type: "boolean"
geometryFormat:
type: "string"
- enum: ["geojson","polyline"]
+ enum: ["geojson","polyline","wkt"]
getBbox:
type: "boolean"
distanceUnit:
@@ -574,7 +574,7 @@ components:
$ref: "#/components/schemas/constraintIso"
geometryFormat:
type: "string"
- enum: ["geojson","polyline"]
+ enum: ["geojson","polyline","wkt"]
distanceUnit:
type: "string"
timeUnit:
diff --git a/documentation/configuration/resources/osrm.resource b/documentation/configuration/resources/osrm.resource
index 7620497..52987c5 100644
--- a/documentation/configuration/resources/osrm.resource
+++ b/documentation/configuration/resources/osrm.resource
@@ -67,7 +67,8 @@
"defaultValueContent": "geojson",
"values": [
"geojson",
- "polyline"
+ "polyline",
+ "wkt"
]
},
{
diff --git a/documentation/configuration/resources/pgr.resource b/documentation/configuration/resources/pgr.resource
index 71d25ab..67b2244 100644
--- a/documentation/configuration/resources/pgr.resource
+++ b/documentation/configuration/resources/pgr.resource
@@ -99,7 +99,8 @@
"defaultValueContent": "geojson",
"values": [
"geojson",
- "polyline"
+ "polyline",
+ "wkt"
]
},
{
@@ -413,7 +414,8 @@
"defaultValueContent": "geojson",
"values": [
"geojson",
- "polyline"
+ "polyline",
+ "wkt"
]
},
{
diff --git a/documentation/configuration/resources/smartpgr.resource b/documentation/configuration/resources/smartpgr.resource
index 5d610ed..d0b3136 100644
--- a/documentation/configuration/resources/smartpgr.resource
+++ b/documentation/configuration/resources/smartpgr.resource
@@ -101,7 +101,8 @@
"defaultValueContent": "geojson",
"values": [
"geojson",
- "polyline"
+ "polyline",
+ "wkt"
]
},
{
@@ -414,7 +415,8 @@
"defaultValueContent": "geojson",
"values": [
"geojson",
- "polyline"
+ "polyline",
+ "wkt"
]
},
{
diff --git a/documentation/configuration/resources/valhalla.resource b/documentation/configuration/resources/valhalla.resource
index ee66b77..2f8d8ee 100644
--- a/documentation/configuration/resources/valhalla.resource
+++ b/documentation/configuration/resources/valhalla.resource
@@ -67,7 +67,8 @@
"defaultValueContent": "geojson",
"values": [
"geojson",
- "polyline"
+ "polyline",
+ "wkt"
]
},
{
@@ -203,7 +204,8 @@
"defaultValueContent": "geojson",
"values": [
"geojson",
- "polyline"
+ "polyline",
+ "wkt"
]
},
{
diff --git a/documentation/developers/functionnalities.md b/documentation/developers/functionnalities.md
index 7ea56ee..14dfe57 100644
--- a/documentation/developers/functionnalities.md
+++ b/documentation/developers/functionnalities.md
@@ -34,7 +34,7 @@ Selon les données présentes dans les graphes, il est possible de choisir les i
Par l'intermédiaire de plusieurs paramètres, il est possible de préciser le contenu de la réponse :
- La présence ou non des étapes du parcours.
-- Le format des géométries dans la réponse. Pour le moment, geojson et polyline sont disponibles.
+- Le format des géométries dans la réponse. Pour le moment, geojson, polyline et wkt sont disponibles.
- La présence ou non d'une bbox dans la réponse.
### 1.8 : Choisir les unités de la requête et de la réponse
@@ -80,7 +80,7 @@ La notion de contrainte est définie dans les [concepts](./concepts.md). Elle es
### 2.8 : Préciser le contenu de la réponse
Par l'intermédiaire de plusieurs paramètres, un seul pour le moment, il est possible de préciser le contenu de la réponse :
-- Le format des géométrie dans la réponse. Pour le moment, geojson et polyline sont disponibles.
+- Le format des géométrie dans la réponse. Pour le moment, geojson, polyline et wkt sont disponibles.
### 2.9 : Choisir les unités de la requête et de la réponse
diff --git a/src/js/geometry/line.js b/src/js/geometry/line.js
index a2076dd..e03f4e2 100644
--- a/src/js/geometry/line.js
+++ b/src/js/geometry/line.js
@@ -2,7 +2,8 @@
const errorManager = require('../utils/errorManager');
const polyline = require('@mapbox/polyline');
-const Geometry = require('../geometry/geometry');
+const wkt = require('./formats/wkt');
+const Geometry = require('./geometry');
const proj4 = require('proj4');
const assert = require('assert');
@@ -30,7 +31,7 @@ module.exports = class Line extends Geometry {
*/
constructor(geom, format, projection, polylinePrecision = 5) {
- super("polyline", projection);
+ super("line", projection);
// Géométrie de la polyline
this._geom = geom;
@@ -38,9 +39,10 @@ module.exports = class Line extends Geometry {
// Format de géométrie (geojson, polyline...)
this._format = format;
- if (polylinePrecision != 5) {
+ if (polylinePrecision != 5 && this._format === "polyline") {
this._geom = polyline.encode(polyline.decode(geom, polylinePrecision));
}
+
}
/**
@@ -54,29 +56,6 @@ module.exports = class Line extends Geometry {
return this._geom;
}
- /**
- *
- * @function
- * @name getGeoJSON
- * @description Récupérer la représentation geoJSON de la ligne
- *
- */
- getGeoJSON () {
- return this._convertGeometry(this._geom, this._format, 'geojson');
- }
-
- /**
- *
- * @function
- * @name getEncodedPolyline
- * @description Récupérer la représentation polyline de la ligne
- *
- */
- getEncodedPolyline () {
- return this._convertGeometry(this._geom, this._format, 'polyline');
- }
-
-
/**
*
* @function
@@ -94,8 +73,8 @@ module.exports = class Line extends Geometry {
* @name convertGeometry
* @description Convertit une géométrie depuis un format vers un autre
* @param {Object|string} geom - Géométrie source
- * @param {string} srcFormat - type de la gémétrie source pour l'instant, dans {geojson, polyline}
- * @param {string} outFormat - type voulu en sortie pour l'instant, dans {geojson, polyline}
+ * @param {string} srcFormat - type de la gémétrie source pour l'instant, dans {geojson, polyline,wkt}
+ * @param {string} outFormat - type voulu en sortie pour l'instant, dans {geojson, polyline,wkt}
* @return {Object|string} out_geom - géométrie convertie
*
*/
@@ -106,6 +85,14 @@ module.exports = class Line extends Geometry {
return polyline.toGeoJSON(geom);
} else if (srcFormat === "geojson" && outFormat === "polyline") {
return polyline.fromGeoJSON(geom);
+ } else if (srcFormat === "wkt" && outFormat === "geojson") {
+ return wkt.toGeoJSON(geom);
+ } else if (srcFormat === "geojson" && outFormat === "wkt") {
+ return wkt.fromGeoJSON(geom);
+ } else if (srcFormat === "polyline" && outFormat === "wkt") {
+ return wkt.fromGeoJSON(polyline.toGeoJSON(geom));
+ } else if (srcFormat === "wkt" && outFormat === "polyline") {
+ return polyline.fromGeoJSON(wkt.toGeoJSON(geom));
} else {
//TODO: voir si on peut remplacer ce throw par un return {}
throw errorManager.createError("Unsupported geometry conversion");
@@ -122,7 +109,7 @@ module.exports = class Line extends Geometry {
*/
transform (projection) {
- if (this.projection !== projection) {
+ if (super.projection !== projection) {
let tmpGeom = this.getLineIn(projection, this._format);
@@ -134,7 +121,7 @@ module.exports = class Line extends Geometry {
} catch (err) {
this._geom = tmpGeom;
- this.projection = projection;
+ super.projection = projection;
return true;
@@ -158,7 +145,7 @@ module.exports = class Line extends Geometry {
*/
getLineIn (projection, format) {
- let geojson = this.getGeoJSON();
+ let geojson = this._convertGeometry(this._geom, this._format, 'geojson');
// vérifications sur le geojson à reprojeter
if (!geojson.coordinates) {
@@ -176,7 +163,7 @@ module.exports = class Line extends Geometry {
for (let i = 0; i < geojson.coordinates.length; i++) {
- let reprojectedPoint = proj4(this.projection, projection, [geojson.coordinates[i][0], geojson.coordinates[i][1]]);
+ let reprojectedPoint = proj4(super.projection, projection, [geojson.coordinates[i][0], geojson.coordinates[i][1]]);
if (!Array.isArray(reprojectedPoint)) {
return {};
diff --git a/src/js/geometry/point.js b/src/js/geometry/point.js
index a06078f..28a0818 100644
--- a/src/js/geometry/point.js
+++ b/src/js/geometry/point.js
@@ -68,8 +68,8 @@ module.exports = class Point extends Geometry {
*/
getCoordinatesIn (projection) {
- if (this.projection !== projection) {
- return proj4(this.projection, projection, [this._x, this._y]);
+ if (super.projection !== projection) {
+ return proj4(super.projection, projection, [this._x, this._y]);
} else {
return [this._x, this._y];
}
@@ -86,9 +86,9 @@ module.exports = class Point extends Geometry {
*/
transform (projection) {
- if (this.projection !== projection) {
+ if (super.projection !== projection) {
- let reprojectedPoint = proj4(this.projection, projection, [this._x, this._y]);
+ let reprojectedPoint = proj4(super.projection, projection, [this._x, this._y]);
if (!Array.isArray(reprojectedPoint)) {
return false;
@@ -99,7 +99,7 @@ module.exports = class Point extends Geometry {
this._x = reprojectedPoint[0];
this._y = reprojectedPoint[1];
- this.projection = projection;
+ super.projection = projection;
return true;
diff --git a/src/js/geometry/polygon.js b/src/js/geometry/polygon.js
index 2c95bbd..a4b1f6e 100644
--- a/src/js/geometry/polygon.js
+++ b/src/js/geometry/polygon.js
@@ -3,6 +3,7 @@
const errorManager = require('../utils/errorManager');
const turf = require('@turf/turf');
const polyline = require('@mapbox/polyline');
+const wkt = require('./formats/wkt');
const Geometry = require('../geometry/geometry');
const proj4 = require('proj4');
@@ -43,17 +44,6 @@ module.exports = class Polygon extends Geometry {
return this._geom;
}
- /**
- *
- * @function
- * @name getGeoJSON
- * @description Récupérer la représentation geoJSON du polygon
- *
- */
- getGeoJSON () {
- return this._convertGeometry(this._geom, this._format, 'geojson');
- }
-
/**
*
* @function
@@ -81,12 +71,54 @@ module.exports = class Polygon extends Geometry {
if (srcFormat === outFormat) {
return geom;
} else if (srcFormat === "polyline" && outFormat === "geojson") {
- let tmpPolygon = polyline.toGeoJSON(geom);
- tmpPolygon.type = "Polygon";
- return tmpPolygon;
+ return this._polyline2GeoJson(geom);
} else if (srcFormat === "geojson" && outFormat === "polyline") {
+ return this._geoJson2Polyline(geom);
+ } else if (srcFormat === "wkt" && outFormat === "geojson") {
+ return wkt.toGeoJSON(geom);
+ } else if (srcFormat === "geojson" && outFormat === "wkt") {
+ return wkt.fromGeoJSON(geom);
+ } else if (srcFormat === "polyline" && outFormat === "wkt") {
+ return wkt.fromGeoJSON(this.__polyline2GeoJson(geom));
+ } else if (srcFormat === "wkt" && outFormat === "polyline") {
+ return this._geoJson2Polyline(wkt.toGeoJSON(geom));
+ } else {
+ //TODO: voir si on peut remplacer ce throw par un return {}
+ throw errorManager.createError("Unsupported geometry conversion");
+ }
+
+ }
- let result = [];
+ /**
+ *
+ * @function
+ * @name _polyline2GeoJson
+ * @description Convertit une géométrie GeoJSON vers Polyline
+ * @param {Object|string} geom - Géométrie source
+ * @return {Object|string} out_geom - géométrie convertie
+ *
+ */
+ _polyline2GeoJson (geom) {
+
+ let tmpGeoJSON = polyline.toGeoJSON(geom);
+ tmpGeoJSON.type = "Polygon";
+ return tmpGeoJSON;
+
+ }
+
+
+ /**
+ *
+ * @function
+ * @name _geoJson2Polyline
+ * @description Convertit une géométrie GeoJSON vers Polyline
+ * @param {Object|string} geom - Géométrie source
+ * @return {Object|string} out_geom - géométrie convertie
+ *
+ */
+ _geoJson2Polyline (geom) {
+
+ let result = [];
if (geom.type === "Point") {
// Cas où l'isochrone est un simple point
@@ -119,11 +151,6 @@ module.exports = class Polygon extends Geometry {
}
- } else {
- //TODO: voir si on peut remplacer ce throw par un return {}
- throw errorManager.createError("Unsupported geometry conversion");
- }
-
}
@@ -141,7 +168,7 @@ module.exports = class Polygon extends Geometry {
return true;
}
- let geojson = this.getGeoJSON();
+ let geojson = this._convertGeometry(this._geom, this._format, 'geojson');
// vérifications sur le geojson à reprojeter
if (!geojson.coordinates) {
@@ -187,7 +214,7 @@ module.exports = class Polygon extends Geometry {
for (let c = 0; c < geojson.coordinates[g].length; c++) {
- let reprojectedPoint = proj4(this.projection, projection, [geojson.coordinates[g][c][0], geojson.coordinates[g][c][1]]);
+ let reprojectedPoint = proj4(super.projection, projection, [geojson.coordinates[g][c][0], geojson.coordinates[g][c][1]]);
if (!Array.isArray(reprojectedPoint)) {
return false;
@@ -203,9 +230,8 @@ module.exports = class Polygon extends Geometry {
}
- // TODO: gérer les différents formats de géométrie
-
- this._projection = projection;
+ this._geom = this._convertGeometry(geojson, 'geojson', this._format);
+ super.projection = projection;
return true;
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
index 225bdbb..8bb2a5a 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-osrm.feature
@@ -599,6 +599,22 @@ Scenario Outline: [] Route sur l'API simple 1.0.0 avec geometryFormat=po
| GET |
| POST |
+ Scenario Outline: [] Route sur l'API simple 1.0.0 avec geometryFormat=wkt
+ Given an "" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-osrm"
+ And with query parameters:
+ | key | value |
+ | geometryFormat | wkt |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain a string attribute "geometry"
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
Scenario Outline: [] Route sur l'API simple 1.0.0 avec mauvais geometryFormat
Given an "" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-osrm"
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
index 3a511fa..8aa32a5 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-pgr.feature
@@ -50,6 +50,22 @@ Feature: Road2-PGR
| GET |
| POST |
+ Scenario Outline: [] Route sur l'API simple 1.0.0 avec geometryFormat=wkt
+ Given an "" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-pgr"
+ And with query parameters:
+ | key | value |
+ | geometryFormat | wkt |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain a string attribute "geometry"
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
Scenario: [GET] Route sur l'API simple 1.0.0 avec deux contraintes sur une ressource pgr
Given an "GET" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-pgr"
@@ -784,6 +800,22 @@ Scenario Outline: [] Isochrone sur l'API simple 1.0.0
| GET |
| POST |
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec geometryFormat=wkt
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone"
+ And with query parameters:
+ | key | value |
+ | geometryFormat | wkt |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+ And the response should contain a string attribute "geometry"
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un mauvais distanceUnit
Given an "" request on operation "isochrone" in api "simple" "1.0.0"
And with default parameters for "isochrone"
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
index 7a08241..5feac4a 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature
@@ -81,4 +81,20 @@ Feature: Road2-SMARTROUTING
Examples:
| method |
| GET |
- | POST |
\ No newline at end of file
+ | POST |
+
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec geometryFormat=wkt
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone-smartpgr"
+ And with query parameters:
+ | key | value |
+ | geometryFormat | wkt |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+ And the response should contain a string attribute "geometry"
+ Examples:
+ | method |
+ | GET |
+ | POST |
\ No newline at end of file
diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
index 3cb0a4e..3a36259 100644
--- a/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
+++ b/test/functional/request/cucumber/features/req-simple-1.0.0-valhalla.feature
@@ -51,6 +51,22 @@ Feature: Road2-Valhalla
| GET |
| POST |
+ Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec geometryFormat=wkt
+ Given an "" request on operation "isochrone" in api "simple" "1.0.0"
+ And with default parameters for "isochrone-valhalla"
+ And with query parameters:
+ | key | value |
+ | geometryFormat | wkt |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid iso
+ And the response should contain a string attribute "geometry"
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
Scenario Outline: [] Route sur l'API simple 1.0.0 avec valhalla
Given an "" request on operation "route" in api "simple" "1.0.0"
And with default parameters for "route-valhalla"
@@ -63,3 +79,21 @@ Scenario Outline: [] Route sur l'API simple 1.0.0 avec valhalla
| method |
| GET |
| POST |
+
+ Scenario Outline: [] Route sur l'API simple 1.0.0 avec geometryFormat=wkt
+ Given an "" request on operation "route" in api "simple" "1.0.0"
+ And with default parameters for "route-valhalla"
+ And with query parameters:
+ | key | value |
+ | geometryFormat | wkt |
+ When I send the request
+ Then the server should send a response with status 200
+ And the response should have an header "content-type" with value "application/json"
+ And the response should contain a complete and valid road
+ And the response should contain a string attribute "geometry"
+ Examples:
+ | method |
+ | GET |
+ | POST |
+
+
diff --git a/test/integration/mocha/geometry/integrationLine.js b/test/integration/mocha/geometry/integrationLine.js
index 8396969..45bf2d9 100644
--- a/test/integration/mocha/geometry/integrationLine.js
+++ b/test/integration/mocha/geometry/integrationLine.js
@@ -55,14 +55,6 @@ describe('Test de la classe Line', function() {
describe('Changement de format', function() {
- it('getGeoJSON()', function() {
- assert.deepEqual(line.getGeoJSON(), refGeojson);
- });
-
- it('getEncodedPolyline()', function() {
- assert.deepEqual(line.getEncodedPolyline(), refPolyline);
- });
-
it('getGeometryWithFormat()', function() {
assert.deepEqual(line.getGeometryWithFormat("geojson"), refGeojson);
});
From 690e1d9de2ff7175eb2949ffa689e6e0ebdc1aa6 Mon Sep 17 00:00:00 2001
From: Loic
Date: Tue, 20 Dec 2022 12:07:52 +0100
Subject: [PATCH 37/93] [test] fix de la conf smartpgr
---
.../request/cucumber/configurations/local-service.json | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/test/functional/request/cucumber/configurations/local-service.json b/test/functional/request/cucumber/configurations/local-service.json
index fb332bc..f40e7ae 100644
--- a/test/functional/request/cucumber/configurations/local-service.json
+++ b/test/functional/request/cucumber/configurations/local-service.json
@@ -42,7 +42,9 @@
"id": "isochrone-smartpgr",
"parameters": {
"resource": "bduni-idf-smartpgr",
- "point": "2.333865,48.881989"
+ "point": "2.333865,48.881989",
+ "costValue": "100",
+ "costType": "time"
}
},
{
From b682c44d156382565283d51fa77496670d6189a9 Mon Sep 17 00:00:00 2001
From: Loic
Date: Tue, 20 Dec 2022 13:08:38 +0100
Subject: [PATCH 38/93] [doc] maj du changelog.md
---
changelog.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/changelog.md b/changelog.md
index d2482c9..e3ee51e 100644
--- a/changelog.md
+++ b/changelog.md
@@ -5,6 +5,7 @@ ADDED:
- Cette classe est configurée par un nouveau fichier de configuration.
- Ajout du moteur Valhalla pour les itinéraires et les isochrones
- Le module `wkt` a été remplacé par une implémentation interne
+ - Le format wkt est disponible pour le paramètre geometryFormat de l'API simple/1.0.0
CHANGED:
- L'option --configCheck au démarrage de Road2 n'a plus exactement le même comportement.
From 4af0ddf7c7dc4da1b9e49466d4f9718b0a4d61f2 Mon Sep 17 00:00:00 2001
From: Loic
Date: Tue, 20 Dec 2022 13:19:52 +0100
Subject: [PATCH 39/93] [fix] docker-compose command pour road2
---
docker/dev/docker-compose.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml
index 9c4c2fa..a7869ec 100644
--- a/docker/dev/docker-compose.yml
+++ b/docker/dev/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- pgrouting
environment:
- NODE_ENV=debug
- command : "sleep 60000"
+ command : "npm run debug -- --ROAD2_CONF_FILE=../config/road2.json"
ports:
- 8080:8080
- 9229:9229
From dabdba688902b6b8ae5c6f1ffd82bc7f863d14aa Mon Sep 17 00:00:00 2001
From: azarz
Date: Mon, 19 Dec 2022 17:28:12 +0100
Subject: [PATCH 40/93] feature(valhalla-source): add contraints to isochrone
---
docker/distributions/debian/Dockerfile | 2 +-
src/js/sources/valhallaSource.js | 16 ++++++++++++----
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/docker/distributions/debian/Dockerfile b/docker/distributions/debian/Dockerfile
index ab2644b..c4374a0 100644
--- a/docker/distributions/debian/Dockerfile
+++ b/docker/distributions/debian/Dockerfile
@@ -15,7 +15,7 @@ cmake -B build . && cmake --build build && make -C build install
WORKDIR /home/valhalla/
RUN pip install --upgrade conan
-RUN git clone --branch feature-exclude_bridges/tunnels/toll --depth 1 --recursive https://github.com/IGNF/valhalla.git && cd valhalla && \
+RUN git clone --branch 3.2.0-with_hard_exclude --depth 1 --recursive https://github.com/IGNF/valhalla.git && cd valhalla && \
mkdir build && cmake -B build -DCMAKE_BUILD_TYPE=Release && make -C build && make -C build package
FROM node:16-bullseye as road2
diff --git a/src/js/sources/valhallaSource.js b/src/js/sources/valhallaSource.js
index 1336f06..b02250d 100644
--- a/src/js/sources/valhallaSource.js
+++ b/src/js/sources/valhallaSource.js
@@ -42,7 +42,7 @@ module.exports = class valhallaSource extends Source {
// Stockage de la configuration
this._configuration = sourceJsonObject;
- // Gestions des coûts disponibles
+ // Gestions des coûts disponibles
this._costs = {};
// Initialisation des coûts
@@ -275,10 +275,18 @@ module.exports = class valhallaSource extends Source {
const locationsString = `"locations":[{"lat":${tmpPoint[1]},"lon":${tmpPoint[0]}}]`;
const costingString = `"costing":"${this._costs[request.profile][request.costType].costing}"`;
+ let costingOptionsString = `"costing_options":{"${this._costs[request.profile][request.costType].costing}":{`;
+ for (let i = 0; i < constraints.length; i++) {
+ costingOptionsString += `"${constraints[i]}": "1"`
+ if (i != constraints.length - 1) {
+ costingOptionsString += ","
+ }
+ }
+ costingOptionsString += "}}"
const contoursString = `"contours":[{"${request.costType}":${costValue}}]`;
const reverseString = `"reverse":${reverse}`;
const polygonsString = `"polygons":true`;
- const commandString = `valhalla_service ${this._configuration.storage.config} isochrone '{${locationsString},${costingString},${contoursString},${reverseString},${polygonsString}}' `;
+ const commandString = `valhalla_service ${this._configuration.storage.config} isochrone '{${locationsString},${costingString},${costingOptionsString},${contoursString},${reverseString},${polygonsString}}' `;
LOGGER.info(commandString);
return new Promise( (resolve, reject) => {
@@ -542,7 +550,7 @@ module.exports = class valhallaSource extends Source {
*
*/
writeIsochroneResponse(isochroneRequest, valhallaResponseStr) {
-
+
let point = {};
let geometry = {};
let valhallaResponse;
@@ -568,7 +576,7 @@ module.exports = class valhallaSource extends Source {
LOGGER.debug("data projection: " + super.projection);
- // Création d'un objet Point
+ // Création d'un objet Point
point = isochroneRequest.point;
if (!point.transform(askedProjection)) {
throw errorManager.createError(" Error during reprojection of point in Valhalla response");
From e1685d3a7bb3a108636de1415479a99a4dc1a0de Mon Sep 17 00:00:00 2001
From: "amaury.zarzelli"
Date: Thu, 22 Dec 2022 17:46:37 +0100
Subject: [PATCH 41/93] (submodules) using develop branch of other projects
---
.gitmodules | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.gitmodules b/.gitmodules
index 3174efe..2d208c3 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,8 +1,8 @@
[submodule "docker/route-graph-generator"]
path = docker/route-graph-generator
url = https://github.com/IGNF/route-graph-generator.git
- branch = master
+ branch = develop
[submodule "docker/motors/pgrouting-procedures"]
path = docker/motors/pgrouting-procedures
url = https://github.com/IGNF/pgrouting-procedures.git
- branch = master
+ branch = develop
From 6a6b7e38421ead01aadac6541e253ce53a352167 Mon Sep 17 00:00:00 2001
From: "amaury.zarzelli"
Date: Mon, 26 Dec 2022 20:23:05 +0100
Subject: [PATCH 42/93] update submodules
---
docker/motors/pgrouting-procedures | 2 +-
docker/route-graph-generator | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docker/motors/pgrouting-procedures b/docker/motors/pgrouting-procedures
index f9bee79..261ca48 160000
--- a/docker/motors/pgrouting-procedures
+++ b/docker/motors/pgrouting-procedures
@@ -1 +1 @@
-Subproject commit f9bee79dcafd4820b20132a9361cf86b58bf7264
+Subproject commit 261ca48c5f13a663dca6e4971e5775e4c9487c47
diff --git a/docker/route-graph-generator b/docker/route-graph-generator
index d403450..d197411 160000
--- a/docker/route-graph-generator
+++ b/docker/route-graph-generator
@@ -1 +1 @@
-Subproject commit d403450fda103cc67a97a4be8889d25fe045fbd7
+Subproject commit d19741120b915d1cf034e099fe5ccad1cbb63e0c
From 87b771099100d7c91b08b54a156c3e90ed91260c Mon Sep 17 00:00:00 2001
From: "amaury.zarzelli"
Date: Tue, 27 Dec 2022 17:27:34 +0100
Subject: [PATCH 43/93] Working dependency in test/www
---
test/www/isochrone.html | 16 ++++---
test/www/itineraire.html | 14 +++---
test/www/js/isochrone.js | 92 ++++++++++++++++++++--------------------
3 files changed, 62 insertions(+), 60 deletions(-)
diff --git a/test/www/isochrone.html b/test/www/isochrone.html
index 98cc43f..7d6e7f8 100644
--- a/test/www/isochrone.html
+++ b/test/www/isochrone.html
@@ -29,7 +29,7 @@
-
+
-
+
@@ -120,7 +122,7 @@
-
+
@@ -131,10 +133,10 @@
-
+
-
+
@@ -150,7 +152,7 @@
-
+