use of org.folio.rest.tools.utils.AsyncResponseResult in project raml-module-builder by folio-org.
the class RestVerticle method parseParams.
private void parseParams(RoutingContext rc, Iterator<Map.Entry<String, Object>> paramList, boolean[] validRequest, JsonArray consumes, Object[] paramArray, String[] pathParams, Map<String, String> okapiHeaders) {
HttpServerRequest request = rc.request();
MultiMap queryParams = request.params();
int[] pathParamsIndex = new int[] { pathParams.length };
paramList.forEachRemaining(entry -> {
if (validRequest[0]) {
String valueName = ((JsonObject) entry.getValue()).getString("value");
String valueType = ((JsonObject) entry.getValue()).getString("type");
String paramType = ((JsonObject) entry.getValue()).getString("param_type");
int order = ((JsonObject) entry.getValue()).getInteger("order");
Object defaultVal = ((JsonObject) entry.getValue()).getValue("default_value");
boolean emptyNumeircParam = false;
// to their async upload - so explicitly skip them
if (AnnotationGrabber.NON_ANNOTATED_PARAM.equals(paramType) && !FILE_UPLOAD_PARAM.equals(valueType)) {
try {
// this will also validate the json against the pojo created from the schema
Class<?> entityClazz = Class.forName(valueType);
if (!valueType.equals("io.vertx.core.Handler") && !valueType.equals("io.vertx.core.Context") && !valueType.equals("java.util.Map") && !valueType.equals("java.io.InputStream") && !valueType.equals("io.vertx.ext.web.RoutingContext")) {
// we have special handling for the Result Handler and context, it is also assumed that
// an inputsteam parameter occurs when application/octet is declared in the raml
// in which case the content will be streamed to he function
String bodyContent = rc.getBodyAsString();
log.debug(rc.request().path() + " -------- bodyContent -------- " + bodyContent);
if (bodyContent != null) {
if ("java.io.Reader".equals(valueType)) {
paramArray[order] = new StringReader(bodyContent);
} else if (bodyContent.length() > 0) {
try {
paramArray[order] = MAPPER.readValue(bodyContent, entityClazz);
} catch (UnrecognizedPropertyException e) {
log.error(e.getMessage(), e);
endRequestWithError(rc, RTFConsts.VALIDATION_ERROR_HTTP_CODE, true, JsonUtils.entity2String(ValidationHelper.createValidationErrorMessage("", "", e.getMessage())), validRequest);
return;
}
}
}
Errors errorResp = new Errors();
if (!allowEmptyObject(entityClazz, bodyContent)) {
// right now - because no way in raml to make body optional - do not validate
// TenantAttributes object as it may be empty
// is this request only to validate a field value and not an actual
// request for additional processing
List<String> field2validate = request.params().getAll("validate_field");
Object[] resp = isValidRequest(rc, paramArray[order], errorResp, validRequest, field2validate, entityClazz);
boolean isValid = (boolean) resp[0];
paramArray[order] = resp[1];
if (!isValid) {
endRequestWithError(rc, RTFConsts.VALIDATION_ERROR_HTTP_CODE, true, JsonUtils.entity2String(errorResp), validRequest);
return;
} else if (isValid && !field2validate.isEmpty()) {
// valid request for the field to validate request made
AsyncResponseResult arr = new AsyncResponseResult();
ResponseImpl ri = new ResponseImpl();
ri.setStatus(200);
arr.setResult(ri);
// right now this is the only flag available to stop
// any additional respones for this request. to fix
validRequest[0] = false;
sendResponse(rc, arr, 0, null);
return;
}
}
// complex rules validation here (drools) - after simpler validation rules pass -
Error error = new Error();
FactHandle handle = null;
FactHandle handleError = null;
try {
// if no /rules exist then drools session will be null
if (droolsSession != null && paramArray[order] != null && validRequest[0]) {
// add object to validate to session
handle = droolsSession.insert(paramArray[order]);
handleError = droolsSession.insert(error);
// run all rules in session on object
droolsSession.fireAllRules();
}
} catch (Exception e) {
error.setCode("-1");
error.setType(RTFConsts.VALIDATION_FIELD_ERROR);
errorResp.getErrors().add(error);
endRequestWithError(rc, RTFConsts.VALIDATION_ERROR_HTTP_CODE, true, JsonUtils.entity2String(errorResp), validRequest);
} finally {
// remove the object from the session
if (handle != null) {
droolsSession.delete(handle);
droolsSession.delete(handleError);
}
}
populateMetaData(paramArray[order], okapiHeaders, rc.request().path());
}
} catch (Exception e) {
log.error(e);
endRequestWithError(rc, 400, true, "Json content error " + e.getMessage(), validRequest);
}
} else if (AnnotationGrabber.HEADER_PARAM.equals(paramType)) {
// handle header params - read the header field from the
// header (valueName) and get its value
String value = request.getHeader(valueName);
// set the value passed from the header as a param to the function
paramArray[order] = value;
} else if (AnnotationGrabber.PATH_PARAM.equals(paramType)) {
// these are placeholder values in the path - for example
// /patrons/{patronid} - this would be the patronid value
paramArray[order] = pathParams[pathParamsIndex[0] - 1];
pathParamsIndex[0] = pathParamsIndex[0] - 1;
} else if (AnnotationGrabber.QUERY_PARAM.equals(paramType)) {
String param = queryParams.get(valueName);
// support enum, numbers or strings as query parameters
try {
if (valueType.contains("String")) {
// regular string param in query string - just push value
if (param == null && defaultVal != null) {
// no value passed - check if there is a default value
paramArray[order] = defaultVal;
} else {
paramArray[order] = param;
}
} else if (valueType.contains("int") || valueType.contains("Integer")) {
// cant pass null to an int type
if (param == null) {
if (defaultVal != null) {
paramArray[order] = Integer.valueOf((String) defaultVal);
} else {
paramArray[order] = 0;
}
} else if ("".equals(param)) {
emptyNumeircParam = true;
} else {
paramArray[order] = Integer.valueOf(param);
}
} else if (valueType.contains("boolean") || valueType.contains("Boolean")) {
if (param == null) {
if (defaultVal != null) {
paramArray[order] = Boolean.valueOf((String) defaultVal);
}
} else {
paramArray[order] = Boolean.valueOf(param);
}
} else if (valueType.contains("List")) {
List<String> vals = queryParams.getAll(valueName);
if (vals == null) {
paramArray[order] = null;
} else {
paramArray[order] = vals;
}
} else if (valueType.contains("BigDecimal")) {
if (param == null) {
if (defaultVal != null) {
paramArray[order] = new BigDecimal((String) defaultVal);
} else {
paramArray[order] = null;
}
} else if ("".equals(param)) {
emptyNumeircParam = true;
} else {
// big decimal can contain ","
paramArray[order] = new BigDecimal(param.replaceAll(",", ""));
}
} else {
// enum object type
try {
String enumClazz = replaceLast(valueType, ".", "$");
Class<?> enumClazz1 = Class.forName(enumClazz);
if (enumClazz1.isEnum()) {
Object defaultEnum = null;
Object[] vals = enumClazz1.getEnumConstants();
for (int i = 0; i < vals.length; i++) {
if (vals[i].toString().equals(defaultVal)) {
defaultEnum = vals[i];
}
// in case no value was passed in the request
if (param == null && defaultEnum != null) {
paramArray[order] = defaultEnum;
break;
} else // make sure enum value is valid by converting the string to an enum
if (vals[i].toString().equals(param)) {
paramArray[order] = vals[i];
break;
}
if (i == vals.length - 1) {
// if enum passed is not valid, replace with default value
paramArray[order] = defaultEnum;
}
}
}
} catch (Exception ee) {
log.error(ee.getMessage(), ee);
endRequestWithError(rc, 400, true, ee.getMessage(), validRequest);
}
}
if (emptyNumeircParam) {
endRequestWithError(rc, 400, true, valueName + " does not have a default value in the RAML and has been passed empty", validRequest);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
endRequestWithError(rc, 400, true, e.getMessage(), validRequest);
}
}
}
});
}
Aggregations