in core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java [1096:1315]
private void addRouteDefinition(
CamelContext camelContext, List<VerbDefinition> verbs, List<RouteDefinition> answer,
String component, String producerComponent) {
for (VerbDefinition verb : verbs) {
// use a route as facade for this REST service
RouteDefinition route = new RouteDefinition();
if (verb.getTo() == null) {
throw new IllegalArgumentException("Rest service: " + verb + " must have to endpoint configured.");
}
if (verb.getRouteId() != null) {
route.routeId(parseText(camelContext, verb.getRouteId()));
}
if (verb.getStreamCache() != null) {
route.streamCache(parseText(camelContext, verb.getStreamCache()));
}
route.getOutputs().add(verb.getTo());
// add the binding
RestBindingDefinition binding = new RestBindingDefinition();
binding.setComponent(component);
binding.setType(parseText(camelContext, verb.getType()));
binding.setTypeClass(verb.getTypeClass());
binding.setOutType(parseText(camelContext, verb.getOutType()));
binding.setOutTypeClass(verb.getOutTypeClass());
// verb takes precedence over configuration on rest
if (verb.getBindingMode() != null) {
binding.setBindingMode(parseText(camelContext, verb.getBindingMode()));
} else {
binding.setBindingMode(getBindingMode());
}
if (verb.getConsumes() != null) {
binding.setConsumes(parseText(camelContext, verb.getConsumes()));
} else {
binding.setConsumes(getConsumes());
}
if (verb.getProduces() != null) {
binding.setProduces(parseText(camelContext, verb.getProduces()));
} else {
binding.setProduces(getProduces());
}
if (binding.getType() != null || binding.getOutType() != null && binding.getBindingMode() != null) {
// okay we have binding mode and in/out type defined - then we can infer consume/produces
String mode = binding.getBindingMode();
if ("json".equals(mode)) {
if (binding.getConsumes() == null && binding.getType() != null) {
binding.setConsumes("application/json");
}
if (binding.getProduces() == null && binding.getOutType() != null) {
binding.setProduces("application/json");
}
} else if ("xml".equals(mode)) {
if (binding.getConsumes() == null && binding.getType() != null) {
binding.setConsumes("application/xml");
}
if (binding.getProduces() == null && binding.getOutType() != null) {
binding.setProduces("application/xml");
}
} else if ("json_xml".equals(mode)) {
if (binding.getConsumes() == null && binding.getType() != null) {
binding.setConsumes("application/json;application/xml");
}
if (binding.getProduces() == null && binding.getOutType() != null) {
binding.setProduces("application/json;application/xml");
}
}
}
if (verb.getSkipBindingOnErrorCode() != null) {
binding.setSkipBindingOnErrorCode(parseText(camelContext, verb.getSkipBindingOnErrorCode()));
} else {
binding.setSkipBindingOnErrorCode(getSkipBindingOnErrorCode());
}
if (verb.getClientRequestValidation() != null) {
binding.setClientRequestValidation(parseText(camelContext, verb.getClientRequestValidation()));
} else {
binding.setClientRequestValidation(getClientRequestValidation());
}
if (verb.getEnableCORS() != null) {
binding.setEnableCORS(parseText(camelContext, verb.getEnableCORS()));
} else {
binding.setEnableCORS(getEnableCORS());
}
if (verb.getEnableNoContentResponse() != null) {
binding.setEnableNoContentResponse(parseText(camelContext, verb.getEnableNoContentResponse()));
} else {
binding.setEnableNoContentResponse(getEnableNoContentResponse());
}
for (ParamDefinition param : verb.getParams()) {
// register all the default values for the query and header parameters
RestParamType type = param.getType();
if ((RestParamType.query == type || RestParamType.header == type)
&& ObjectHelper.isNotEmpty(param.getDefaultValue())) {
binding.addDefaultValue(param.getName(), parseText(camelContext, param.getDefaultValue()));
}
// register all allowed values for the query and header parameters
if ((RestParamType.query == type || RestParamType.header == type)
&& param.getAllowableValues() != null) {
binding.addAllowedValue(param.getName(), parseText(camelContext, param.getAllowableValuesAsCommaString()));
}
// register which parameters are required
Boolean required = param.getRequired();
if (required != null && required) {
if (RestParamType.query == type) {
binding.addRequiredQueryParameter(param.getName());
} else if (RestParamType.header == type) {
binding.addRequiredHeader(param.getName());
} else if (RestParamType.body == type) {
binding.setRequiredBody(true);
}
}
}
route.setRestBindingDefinition(binding);
// append options
Map<String, Object> options = new HashMap<>();
if (binding.getConsumes() != null) {
options.put("consumes", binding.getConsumes());
}
if (binding.getProduces() != null) {
options.put("produces", binding.getProduces());
}
// append optional type binding information
String inType = binding.getType();
if (inType != null) {
options.put("inType", inType);
}
String outType = binding.getOutType();
if (outType != null) {
options.put("outType", outType);
}
if (component != null && !component.isEmpty()) {
options.put("consumerComponentName", component);
}
if (producerComponent != null && !producerComponent.isEmpty()) {
options.put("producerComponentName", producerComponent);
}
// include optional description, which we favor from 1) to/route
// description 2) verb description 3) rest description
// this allows end users to define general descriptions and override
// then per to/route or verb
final String description = getDescription(verb, route);
if (description != null) {
options.put("description", parseText(camelContext, description));
}
String path = parseText(camelContext, getPath());
String s1 = FileUtil.stripTrailingSeparator(path);
String s2 = FileUtil.stripLeadingSeparator(parseText(camelContext, verb.getPath()));
String allPath;
if (s1 != null && s2 != null) {
allPath = s1 + "/" + s2;
} else if (path != null) {
allPath = path;
} else {
allPath = parseText(camelContext, verb.getPath());
}
// each {} is a parameter (url templating)
Set<String> toRemove = null;
if (allPath != null && allPath.contains("?")) {
// special when having query parameters
String path1 = StringHelper.before(allPath, "?");
uriTemplating(camelContext, verb, path1, false);
String path2 = StringHelper.after(allPath, "?");
// there may be some query parameters that are templates which we then must remove
toRemove = uriTemplating(camelContext, verb, path2, true);
} else {
// no query parameters
uriTemplating(camelContext, verb, allPath, false);
}
if (verb.getType() != null) {
String bodyType = parseText(camelContext, verb.getType());
ParamDefinition param = findParam(verb, RestParamType.body.name());
if (param == null) {
// must be body type and set the model class as data type
param(verb).name(RestParamType.body.name()).type(RestParamType.body).dataType(bodyType).endParam();
} else {
// must be body type and set the model class as data type
param.type(RestParamType.body).dataType(bodyType);
}
}
// create the from endpoint uri which is using the rest component
String from = buildFromUri(camelContext, verb);
// rebuild uri without these query parameters
if (toRemove != null && !toRemove.isEmpty()) {
try {
Map<String, Object> query = URISupport.parseQuery(URISupport.extractQuery(from));
// remove if the value matches, eg: auth={myAuth}
toRemove.forEach(v -> {
query.values().removeIf(qv -> qv.toString().equals(v));
});
from = URISupport.stripQuery(from);
if (!query.isEmpty()) {
String q = URISupport.createQueryString(query);
from = URISupport.stripQuery(from) + "?" + q;
}
} catch (Exception e) {
throw RuntimeCamelException.wrapRuntimeCamelException(e);
}
}
// append additional options
if (!options.isEmpty()) {
try {
from = URISupport.appendParametersToURI(from, options);
} catch (Exception e) {
throw RuntimeCamelException.wrapRuntimeCamelException(e);
}
}
// the route should be from this rest endpoint
route.fromRest(from);
route.setRestDefinition(this);
answer.add(route);
}
}