diff options
| -rw-r--r-- | icespider/common/routes.ice | 8 | ||||
| -rw-r--r-- | icespider/compile/routeCompiler.cpp | 68 | ||||
| -rw-r--r-- | icespider/unittests/testCompile.cpp | 44 | ||||
| -rw-r--r-- | icespider/unittests/testRoutes.json | 218 | 
4 files changed, 160 insertions, 178 deletions
| diff --git a/icespider/common/routes.ice b/icespider/common/routes.ice index e238664..e77fed4 100644 --- a/icespider/common/routes.ice +++ b/icespider/common/routes.ice @@ -23,12 +23,12 @@ module IceSpider {  	dictionary<string, Parameter> Parameters;  	class OutputSerializer { -		string contentType;  		string serializer;  		StringSeq params;  	}; -	sequence<OutputSerializer> OutputSerializers; +	["slicer:json:object"] +	dictionary<string, OutputSerializer> OutputSerializers;  	class Operation {  		string operation; @@ -39,7 +39,6 @@ module IceSpider {  	dictionary<string, Operation> Operations;  	class Route { -		string name;  		string path;  		HttpMethod method = GET;  		optional(0) string operation; @@ -49,7 +48,8 @@ module IceSpider {  		OutputSerializers outputSerializers;  	}; -	sequence<Route> Routes; +	["slicer:json:object"] +	dictionary<string, Route> Routes;  	class RouteConfiguration {  		string name; diff --git a/icespider/compile/routeCompiler.cpp b/icespider/compile/routeCompiler.cpp index 0f603f5..b8b89db 100644 --- a/icespider/compile/routeCompiler.cpp +++ b/icespider/compile/routeCompiler.cpp @@ -97,7 +97,7 @@ namespace IceSpider {  			for (const auto & o : r->operations) {  				auto op = findOperation(o.second->operation, us);  				if (!op) { -					throw std::runtime_error("Find operator failed for " + r->name); +					throw std::runtime_error("Find operator failed for " + r->path);  				}  				for (const auto & p : op->parameters()) {  					auto po = o.second->paramOverrides.find(p->name()); @@ -116,21 +116,21 @@ namespace IceSpider {  		RouteCompiler::applyDefaults(RouteConfigurationPtr c, const Units & u) const  		{  			for (const auto & r : c->routes) { -				if (r->operation) { -					r->operations[std::string()] = new Operation(*r->operation, {}); +				if (r.second->operation) { +					r.second->operations[std::string()] = new Operation(*r.second->operation, {});  				} -				auto ps = findParameters(r, u); +				auto ps = findParameters(r.second, u);  				for (const auto & p : ps) { -					auto defined = r->params.find(p.first); -					if (defined != r->params.end()) { +					auto defined = r.second->params.find(p.first); +					if (defined != r.second->params.end()) {  						if (!defined->second->key) defined->second->key = defined->first;  					}  					else { -						defined = r->params.insert({ p.first, new Parameter(ParameterSource::URL, p.first, false, IceUtil::Optional<std::string>(), false) }).first; +						defined = r.second->params.insert({ p.first, new Parameter(ParameterSource::URL, p.first, false, IceUtil::Optional<std::string>(), false) }).first;  					}  					auto d = defined->second;  					if (d->source == ParameterSource::URL) { -						Path path(r->path); +						Path path(r.second->path);  						d->hasUserSource = std::find_if(path.parts.begin(), path.parts.end(), [d](const auto & pp) {  							if (auto par = dynamic_cast<PathParameter *>(pp.get())) {  								return par->name == d->key; @@ -232,12 +232,12 @@ namespace IceSpider {  		RouteCompiler::registerOutputSerializers(FILE * output, RoutePtr r) const  		{  			for (const auto & os : r->outputSerializers) { -				auto bs = boost::algorithm::replace_all_copy(os->serializer, ".", "::"); -				auto slash = os->contentType.find('/'); +				auto bs = boost::algorithm::replace_all_copy(os.second->serializer, ".", "::"); +				auto slash = os.first.find('/');  				fprintbf(4, output, "addRouteSerializer({ \"%s\", \"%s\" }, new %s::IceSpiderFactory(", -						os->contentType.substr(0, slash), os->contentType.substr(slash + 1), bs); -				for (auto p = os->params.begin(); p != os->params.end(); ++p) { -					if (p != os->params.begin()) { +						os.first.substr(0, slash), os.first.substr(slash + 1), bs); +				for (auto p = os.second->params.begin(); p != os.second->params.end(); ++p) { +					if (p != os.second->params.begin()) {  						fprintf(output, ", ");  					}  					fputs(p->c_str(), output); @@ -250,9 +250,9 @@ namespace IceSpider {  		RouteCompiler::releaseOutputSerializers(FILE * output, RoutePtr r) const  		{  			for (const auto & os : r->outputSerializers) { -				auto slash = os->contentType.find('/'); +				auto slash = os.first.find('/');  				fprintbf(4, output, "removeRouteSerializer({ \"%s\", \"%s\" });\n", -						os->contentType.substr(0, slash), os->contentType.substr(slash + 1)); +						os.first.substr(0, slash), os.first.substr(slash + 1));  			}  		} @@ -285,20 +285,20 @@ namespace IceSpider {  			fprintbf(output, "namespace %s {\n", c->name);  			fprintbf(1, output, "// Implementation classes.\n\n");  			for (const auto & r : c->routes) { -				std::string methodName = getEnumString(r->method); +				std::string methodName = getEnumString(r.second->method); -				fprintbf(1, output, "// Route name: %s\n", r->name); -				fprintbf(1, output, "//       path: %s\n", r->path); -				fprintbf(1, output, "class %s : public IceSpider::IRouteHandler {\n", r->name); +				fprintbf(1, output, "// Route name: %s\n", r.first); +				fprintbf(1, output, "//       path: %s\n", r.second->path); +				fprintbf(1, output, "class %s : public IceSpider::IRouteHandler {\n", r.first);  				fprintbf(2, output, "public:\n"); -				fprintbf(3, output, "%s(const IceSpider::Core * core) :\n", r->name); -				fprintbf(4, output, "IceSpider::IRouteHandler(IceSpider::HttpMethod::%s, \"%s\")", methodName, r->path); -				auto proxies = initializeProxies(output, r); -				for (const auto & p : r->params) { +				fprintbf(3, output, "%s(const IceSpider::Core * core) :\n", r.first); +				fprintbf(4, output, "IceSpider::IRouteHandler(IceSpider::HttpMethod::%s, \"%s\")", methodName, r.second->path); +				auto proxies = initializeProxies(output, r.second); +				for (const auto & p : r.second->params) {  					if (p.second->hasUserSource) {  						fprintf(output, ",\n");  						if (p.second->source == ParameterSource::URL) { -							Path path(r->path); +							Path path(r.second->path);  							unsigned int idx = -1;  							for (const auto & pp : path.parts) {  								if (auto par = dynamic_cast<PathParameter *>(pp.get())) { @@ -321,16 +321,16 @@ namespace IceSpider {  				}  				fprintf(output, "\n");  				fprintbf(3, output, "{\n"); -				registerOutputSerializers(output, r); +				registerOutputSerializers(output, r.second);  				fprintbf(3, output, "}\n\n"); -				fprintbf(3, output, "~%s()\n", r->name); +				fprintbf(3, output, "~%s()\n", r.first);  				fprintbf(3, output, "{\n"); -				releaseOutputSerializers(output, r); +				releaseOutputSerializers(output, r.second);  				fprintbf(3, output, "}\n\n");  				fprintbf(3, output, "void execute(IceSpider::IHttpRequest * request) const\n");  				fprintbf(3, output, "{\n"); -				auto ps = findParameters(r, units); -				for (const auto & p : r->params) { +				auto ps = findParameters(r.second, units); +				for (const auto & p : r.second->params) {  					if (p.second->hasUserSource) {  						auto ip = ps.find(p.first)->second;  						fprintbf(4, output, "auto _p_%s(request->get%sParam<%s>(_p%c_%s)", @@ -351,16 +351,16 @@ namespace IceSpider {  						fprintbf(0, output, ");\n");  					}  				} -				if (r->operation) { -					addSingleOperation(output, r, findOperation(*r->operation, units)); +				if (r.second->operation) { +					addSingleOperation(output, r.second, findOperation(*r.second->operation, units));  				}  				else { -					addMashupOperations(output, r, proxies, units); +					addMashupOperations(output, r.second, proxies, units);  				}  				fprintbf(3, output, "}\n\n");  				fprintbf(2, output, "private:\n");  				declareProxies(output, proxies); -				for (const auto & p : r->params) { +				for (const auto & p : r.second->params) {  					if (p.second->hasUserSource) {  						if (p.second->source == ParameterSource::URL) {  							fprintbf(3, output, "const unsigned int _pi_%s;\n", p.first); @@ -381,7 +381,7 @@ namespace IceSpider {  			fprintbf(output, "} // namespace %s\n\n", c->name);  			fprintf(output, "// Register route handlers.\n");  			for (const auto & r : c->routes) { -				fprintbf(output, "FACTORY(%s::%s, IceSpider::RouteHandlerFactory);\n", c->name, r->name); +				fprintbf(output, "FACTORY(%s::%s, IceSpider::RouteHandlerFactory);\n", c->name, r.first);  			}  			fprintf(output, "\n// End generated code.\n");  		} diff --git a/icespider/unittests/testCompile.cpp b/icespider/unittests/testCompile.cpp index 063d691..4fb7827 100644 --- a/icespider/unittests/testCompile.cpp +++ b/icespider/unittests/testCompile.cpp @@ -38,31 +38,25 @@ BOOST_AUTO_TEST_CASE( testLoadConfiguration )  	BOOST_REQUIRE_EQUAL("common", cfg->name);  	BOOST_REQUIRE_EQUAL(10, cfg->routes.size()); -	BOOST_REQUIRE_EQUAL("index", cfg->routes[0]->name); -	BOOST_REQUIRE_EQUAL("/", cfg->routes[0]->path); -	BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes[0]->method); -	BOOST_REQUIRE_EQUAL("TestIceSpider.TestApi.index", cfg->routes[0]->operation); -	BOOST_REQUIRE_EQUAL(0, cfg->routes[0]->params.size()); - -	BOOST_REQUIRE_EQUAL("item", cfg->routes[1]->name); -	BOOST_REQUIRE_EQUAL("/view/{s}/{i}", cfg->routes[1]->path); -	BOOST_REQUIRE_EQUAL(2, cfg->routes[1]->params.size()); - -	BOOST_REQUIRE_EQUAL("del", cfg->routes[2]->name); -	BOOST_REQUIRE_EQUAL(HttpMethod::DELETE, cfg->routes[2]->method); -	BOOST_REQUIRE_EQUAL(1, cfg->routes[2]->params.size()); - -	BOOST_REQUIRE_EQUAL("update", cfg->routes[3]->name); -	BOOST_REQUIRE_EQUAL(HttpMethod::POST, cfg->routes[3]->method); -	BOOST_REQUIRE_EQUAL(2, cfg->routes[3]->params.size()); - -	BOOST_REQUIRE_EQUAL("mashStruct", cfg->routes[6]->name); -	BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes[6]->method); -	BOOST_REQUIRE_EQUAL(3, cfg->routes[6]->params.size()); - -	BOOST_REQUIRE_EQUAL("mashClass", cfg->routes[7]->name); -	BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes[7]->method); -	BOOST_REQUIRE_EQUAL(3, cfg->routes[7]->params.size()); +	BOOST_REQUIRE_EQUAL("/", cfg->routes["index"]->path); +	BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes["index"]->method); +	BOOST_REQUIRE_EQUAL("TestIceSpider.TestApi.index", cfg->routes["index"]->operation); +	BOOST_REQUIRE_EQUAL(0, cfg->routes["index"]->params.size()); + +	BOOST_REQUIRE_EQUAL("/view/{s}/{i}", cfg->routes["item"]->path); +	BOOST_REQUIRE_EQUAL(2, cfg->routes["item"]->params.size()); + +	BOOST_REQUIRE_EQUAL(HttpMethod::DELETE, cfg->routes["del"]->method); +	BOOST_REQUIRE_EQUAL(1, cfg->routes["del"]->params.size()); + +	BOOST_REQUIRE_EQUAL(HttpMethod::POST, cfg->routes["update"]->method); +	BOOST_REQUIRE_EQUAL(2, cfg->routes["update"]->params.size()); + +	BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes["mashStruct"]->method); +	BOOST_REQUIRE_EQUAL(3, cfg->routes["mashStruct"]->params.size()); + +	BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes["mashClass"]->method); +	BOOST_REQUIRE_EQUAL(3, cfg->routes["mashClass"]->params.size());  	BOOST_REQUIRE_EQUAL(1, cfg->slices.size());  	BOOST_REQUIRE_EQUAL("test-api.ice", cfg->slices[0]); diff --git a/icespider/unittests/testRoutes.json b/icespider/unittests/testRoutes.json index 52add90..13a6806 100644 --- a/icespider/unittests/testRoutes.json +++ b/icespider/unittests/testRoutes.json @@ -1,132 +1,120 @@  {  	"name": "common",  	"headers": [ "xsltStreamSerializer.h" ], -	"routes": [ -	{ -		"name": "index", -		"path": "/", -		"method": "GET", -		"outputSerializers": [ -		{ -			"contentType": "text/html", -			"serializer": "IceSpider.XsltStreamSerializer", -			"params": [ "\"xslt/transform.xslt\"" ] -		} -		], -		"operation": "TestIceSpider.TestApi.index" -	}, -	{ -		"name": "item", -		"path": "/view/{s}/{i}", -		"method": "GET", -		"operation": "TestIceSpider.TestApi.withParams" -	}, -	{ -		"name": "del", -		"path": "/{s}", -		"method": "DELETE", -		"operation": "TestIceSpider.TestApi.returnNothing" -	}, -	{ -		"name": "update", -		"path": "/{id}", -		"method": "POST", -		"operation": "TestIceSpider.TestApi.complexParam", -		"params": { -			"s": { -				"source": "URL", -				"key": "id", -				"isOptional": true +	"routes": { +		"index": { +			"path": "/", +			"method": "GET", +			"outputSerializers": { +				"text/html": { +					"serializer": "IceSpider.XsltStreamSerializer", +					"params": [ "\"xslt/transform.xslt\"" ] +				}  			}, -			"m": { -				"source": "Body" +			"operation": "TestIceSpider.TestApi.index" +		}, +		"item": { +			"path": "/view/{s}/{i}", +			"method": "GET", +			"operation": "TestIceSpider.TestApi.withParams" +		}, +		"del": { +			"path": "/{s}", +			"method": "DELETE", +			"operation": "TestIceSpider.TestApi.returnNothing" +		}, +		"update": { +			"path": "/{id}", +			"method": "POST", +			"operation": "TestIceSpider.TestApi.complexParam", +			"params": { +				"s": { +					"source": "URL", +					"key": "id", +					"isOptional": true +				}, +				"m": { +					"source": "Body" +				}  			} -		} -	}, -	{ -		"name": "defaultItem", -		"path": "/item/{s}", -		"method": "GET", -		"operation": "TestIceSpider.TestApi.withParams", -		"params": { -			"i": { -				"default": "1234" +		}, +		"defaultItem": { +			"path": "/item/{s}", +			"method": "GET", +			"operation": "TestIceSpider.TestApi.withParams", +			"params": { +				"i": { +					"default": "1234" +				}  			} -		} -	}, -	{ -		"name": "itemWithDefault", -		"path": "/item/{s}/{i}", -		"method": "GET", -		"operation": "TestIceSpider.TestApi.withParams", -		"params": { -			"i": { -				"default": "1234" +		}, +		"itemWithDefault":{ +			"path": "/item/{s}/{i}", +			"method": "GET", +			"operation": "TestIceSpider.TestApi.withParams", +			"params": { +				"i": { +					"default": "1234" +				}  			} -		} -	}, -	{ -		"name": "mashStruct", -		"path": "/mashS/{s}/{t}/{i}", -		"method": "GET", -		"type": "TestIceSpider.Mash1", -		"operations": { -			"a": { -				"operation": "TestIceSpider.TestApi.withParams" -			}, -			"b": { -				"operation": "TestIceSpider.TestApi.withParams", -				"paramOverrides": { -					"s": "t" +		}, +		"mashStruct": { +			"path": "/mashS/{s}/{t}/{i}", +			"method": "GET", +			"type": "TestIceSpider.Mash1", +			"operations": { +				"a": { +					"operation": "TestIceSpider.TestApi.withParams" +				}, +				"b": { +					"operation": "TestIceSpider.TestApi.withParams", +					"paramOverrides": { +						"s": "t" +					}  				}  			} -		} -	}, -	{ -		"name": "mashClass", -		"path": "/mashC/{s}/{t}/{i}", -		"method": "GET", -		"type": "TestIceSpider.Mash2", -		"operations": { -			"a": { -				"operation": "TestIceSpider.TestApi.withParams" -			}, -			"b": { -				"operation": "TestIceSpider.TestApi.withParams", -				"paramOverrides": { -					"s": "t" +		}, +		"mashClass": { +			"path": "/mashC/{s}/{t}/{i}", +			"method": "GET", +			"type": "TestIceSpider.Mash2", +			"operations": { +				"a": { +					"operation": "TestIceSpider.TestApi.withParams" +				}, +				"b": { +					"operation": "TestIceSpider.TestApi.withParams", +					"paramOverrides": { +						"s": "t" +					}  				}  			} -		} -	}, -	{ -		"name": "override", -		"path": "/override", -		"method": "GET", -		"outputSerializers": [ -		{ -			"contentType": "application/xml", -			"serializer": "IceSpider.XsltStreamSerializer", -			"params": [ "\"xslt/transform.xslt\"" ] -		} -		], -		"operation": "TestIceSpider.TestApi.index" -	}, -	{ -		"name": "search", -		"path": "/search", -		"method": "GET", -		"operation": "TestIceSpider.TestApi.withParams", -		"params": { -			"s": { -				"source": "QueryString" +		}, +		"override": { +			"path": "/override", +			"method": "GET", +			"outputSerializers": { +				"application/xml": { +					"serializer": "IceSpider.XsltStreamSerializer", +					"params": [ "\"xslt/transform.xslt\"" ] +				}  			}, -			"i": { -				"source": "QueryString" +			"operation": "TestIceSpider.TestApi.index" +		}, +		"search": { +			"path": "/search", +			"method": "GET", +			"operation": "TestIceSpider.TestApi.withParams", +			"params": { +				"s": { +					"source": "QueryString" +				}, +				"i": { +					"source": "QueryString" +				}  			}  		} -	} -	], +	},  	"slices": [  		"test-api.ice"  	] | 
