MIFOSX-237: use of jdbcTemplate and SqlRowSet along with refactoring as a result of these changes.
This commit is contained in:
+200
-189
@@ -16,209 +16,220 @@ import javax.xml.bind.annotation.XmlElementWrapper;
|
|||||||
*/
|
*/
|
||||||
public class ApiGlobalErrorResponse {
|
public class ApiGlobalErrorResponse {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A developer friendly plain English description of why the HTTP error response was returned from the API.
|
* A developer friendly plain English description of why the HTTP error
|
||||||
*/
|
* response was returned from the API.
|
||||||
private String developerMessage;
|
*/
|
||||||
|
private String developerMessage;
|
||||||
/**
|
|
||||||
* A link to a URL which provides more information on the details of this type of error.
|
|
||||||
*/
|
|
||||||
private String developerDocLink;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The HTTP status code of the response.
|
|
||||||
*/
|
|
||||||
private String httpStatusCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A user friendly plain English description of why the HTTP error response was returned from the API that can be presented to end users.
|
|
||||||
*/
|
|
||||||
private String defaultUserMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A code that can be used for globalisation support by client applications of the API.
|
|
||||||
*/
|
|
||||||
private String userMessageGlobalisationCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of zero or more of the actual reasons for the HTTP error should they be needed. Typically used to express data validation errors with parameters passed to API.
|
|
||||||
*/
|
|
||||||
private List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
|
||||||
|
|
||||||
public static ApiGlobalErrorResponse unAuthenticated() {
|
/**
|
||||||
|
* A link to a URL which provides more information on the details of this
|
||||||
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
* type of error.
|
||||||
globalErrorResponse.setHttpStatusCode("401");
|
*/
|
||||||
globalErrorResponse.setDeveloperMessage("Invalid authentication details were passed in api request.");
|
private String developerDocLink;
|
||||||
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
|
||||||
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.not.authenticated");
|
|
||||||
globalErrorResponse.setDefaultUserMessage("Unauthenticated. Please login.");
|
|
||||||
|
|
||||||
return globalErrorResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApiGlobalErrorResponse invalidTenantIdentifier() {
|
|
||||||
|
|
||||||
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
|
||||||
globalErrorResponse.setHttpStatusCode("401");
|
|
||||||
globalErrorResponse.setDeveloperMessage("Invalid tenant details were passed in api request.");
|
|
||||||
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
|
||||||
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.invalid.tenant.identifier");
|
|
||||||
globalErrorResponse.setDefaultUserMessage("Invalide tenant identifier provided with request.");
|
|
||||||
|
|
||||||
return globalErrorResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApiGlobalErrorResponse unAuthorized() {
|
/**
|
||||||
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
* The HTTP status code of the response.
|
||||||
globalErrorResponse.setHttpStatusCode("403");
|
*/
|
||||||
globalErrorResponse.setDeveloperMessage("The user associated with credentials passed on this request does not have sufficient privileges to perform this action.");
|
private String httpStatusCode;
|
||||||
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
|
||||||
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.not.authorized");
|
|
||||||
globalErrorResponse.setDefaultUserMessage("Insufficient privileges to perform this action.");
|
|
||||||
|
|
||||||
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
|
||||||
errors.add(ApiParameterError.generalError("error.msg.not.authorized", "Insufficient privileges to perform this action."));
|
|
||||||
globalErrorResponse.setErrors(errors);
|
|
||||||
|
|
||||||
return globalErrorResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApiGlobalErrorResponse domainRuleViolation(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
|
|
||||||
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
|
||||||
globalErrorResponse.setHttpStatusCode("403");
|
|
||||||
globalErrorResponse.setDeveloperMessage("Request was understood but caused a domain rule violation.");
|
|
||||||
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
|
||||||
globalErrorResponse.setUserMessageGlobalisationCode("validation.msg.domain.rule.violation");
|
|
||||||
globalErrorResponse.setDefaultUserMessage("Errors contain reason for domain rule violation.");
|
|
||||||
|
|
||||||
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
|
||||||
errors.add(ApiParameterError.generalError(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs));
|
|
||||||
globalErrorResponse.setErrors(errors);
|
|
||||||
|
|
||||||
return globalErrorResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static ApiGlobalErrorResponse notFound(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
|
/**
|
||||||
|
* A user friendly plain English description of why the HTTP error response
|
||||||
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
* was returned from the API that can be presented to end users.
|
||||||
globalErrorResponse.setHttpStatusCode("404");
|
*/
|
||||||
globalErrorResponse.setDeveloperMessage("The requested resource is not available.");
|
private String defaultUserMessage;
|
||||||
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
|
||||||
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.resource.not.found");
|
|
||||||
globalErrorResponse.setDefaultUserMessage("The requested resource is not available.");
|
|
||||||
|
|
||||||
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
|
||||||
errors.add(ApiParameterError.resourceIdentifierNotFound(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs));
|
|
||||||
globalErrorResponse.setErrors(errors);
|
|
||||||
|
|
||||||
return globalErrorResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApiGlobalErrorResponse dataIntegrityError(final String globalisationMessageCode, final String defaultUserMessage, final String parameterName, final Object... defaultUserMessageArgs) {
|
|
||||||
|
|
||||||
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
|
||||||
globalErrorResponse.setHttpStatusCode("403");
|
|
||||||
globalErrorResponse.setDeveloperMessage("The request caused a data integrity issue to be fired by the database.");
|
|
||||||
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
|
||||||
globalErrorResponse.setUserMessageGlobalisationCode(globalisationMessageCode);
|
|
||||||
globalErrorResponse.setDefaultUserMessage(defaultUserMessage);
|
|
||||||
|
|
||||||
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
|
||||||
errors.add(ApiParameterError.parameterError(globalisationMessageCode, defaultUserMessage, parameterName, defaultUserMessageArgs));
|
|
||||||
globalErrorResponse.setErrors(errors);
|
|
||||||
|
|
||||||
return globalErrorResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApiGlobalErrorResponse badClientRequest(final String globalisationMessageCode, final String defaultUserMessage,
|
|
||||||
List<ApiParameterError> errors) {
|
|
||||||
|
|
||||||
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
|
||||||
globalErrorResponse.setHttpStatusCode("400");
|
|
||||||
globalErrorResponse.setDeveloperMessage("The request was invalid. This typically will happen due to validation errors which are provided.");
|
|
||||||
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
|
||||||
globalErrorResponse.setUserMessageGlobalisationCode(globalisationMessageCode);
|
|
||||||
globalErrorResponse.setDefaultUserMessage(defaultUserMessage);
|
|
||||||
|
|
||||||
globalErrorResponse.setErrors(errors);
|
|
||||||
|
|
||||||
return globalErrorResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApiGlobalErrorResponse serverSideError(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
|
|
||||||
|
|
||||||
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
|
||||||
globalErrorResponse.setHttpStatusCode("500");
|
|
||||||
globalErrorResponse.setDeveloperMessage("An unexpected error occured on the platform server.");
|
|
||||||
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
|
||||||
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.platform.server.side.error");
|
|
||||||
globalErrorResponse.setDefaultUserMessage("An unexpected error occured on the platform server.");
|
|
||||||
|
|
||||||
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
|
||||||
errors.add(ApiParameterError.generalError(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs));
|
|
||||||
globalErrorResponse.setErrors(errors);
|
|
||||||
|
|
||||||
return globalErrorResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ApiGlobalErrorResponse() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
public ApiGlobalErrorResponse(final List<ApiParameterError> errors) {
|
/**
|
||||||
this.errors = errors;
|
* A code that can be used for globalisation support by client applications
|
||||||
}
|
* of the API.
|
||||||
|
*/
|
||||||
|
private String userMessageGlobalisationCode;
|
||||||
|
|
||||||
@XmlElementWrapper(name="errors")
|
/**
|
||||||
@XmlElement(name="errorResponse")
|
* A list of zero or more of the actual reasons for the HTTP error should
|
||||||
public List<ApiParameterError> getErrors() {
|
* they be needed. Typically used to express data validation errors with
|
||||||
return errors;
|
* parameters passed to API.
|
||||||
}
|
*/
|
||||||
|
private List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
||||||
|
|
||||||
public void setErrors(List<ApiParameterError> errors) {
|
public static ApiGlobalErrorResponse unAuthenticated() {
|
||||||
this.errors = errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeveloperMessage() {
|
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
||||||
return developerMessage;
|
globalErrorResponse.setHttpStatusCode("401");
|
||||||
}
|
globalErrorResponse.setDeveloperMessage("Invalid authentication details were passed in api request.");
|
||||||
|
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
||||||
|
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.not.authenticated");
|
||||||
|
globalErrorResponse.setDefaultUserMessage("Unauthenticated. Please login.");
|
||||||
|
|
||||||
public void setDeveloperMessage(String developerMessage) {
|
return globalErrorResponse;
|
||||||
this.developerMessage = developerMessage;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public String getHttpStatusCode() {
|
public static ApiGlobalErrorResponse invalidTenantIdentifier() {
|
||||||
return httpStatusCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHttpStatusCode(String httpStatusCode) {
|
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
||||||
this.httpStatusCode = httpStatusCode;
|
globalErrorResponse.setHttpStatusCode("401");
|
||||||
}
|
globalErrorResponse.setDeveloperMessage("Invalid tenant details were passed in api request.");
|
||||||
|
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
||||||
|
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.invalid.tenant.identifier");
|
||||||
|
globalErrorResponse.setDefaultUserMessage("Invalide tenant identifier provided with request.");
|
||||||
|
|
||||||
public String getDefaultUserMessage() {
|
return globalErrorResponse;
|
||||||
return defaultUserMessage;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaultUserMessage(String defaultUserMessage) {
|
public static ApiGlobalErrorResponse unAuthorized(final String defaultUserMessage) {
|
||||||
this.defaultUserMessage = defaultUserMessage;
|
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
||||||
}
|
globalErrorResponse.setHttpStatusCode("403");
|
||||||
|
globalErrorResponse
|
||||||
|
.setDeveloperMessage("The user associated with credentials passed on this request does not have sufficient privileges to perform this action.");
|
||||||
|
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
||||||
|
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.not.authorized");
|
||||||
|
globalErrorResponse.setDefaultUserMessage("Insufficient privileges to perform this action.");
|
||||||
|
|
||||||
public String getUserMessageGlobalisationCode() {
|
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
||||||
return userMessageGlobalisationCode;
|
errors.add(ApiParameterError.generalError("error.msg.not.authorized", defaultUserMessage));
|
||||||
}
|
globalErrorResponse.setErrors(errors);
|
||||||
|
|
||||||
public void setUserMessageGlobalisationCode(String userMessageGlobalisationCode) {
|
return globalErrorResponse;
|
||||||
this.userMessageGlobalisationCode = userMessageGlobalisationCode;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeveloperDocLink() {
|
public static ApiGlobalErrorResponse domainRuleViolation(final String globalisationMessageCode, final String defaultUserMessage,
|
||||||
return developerDocLink;
|
final Object... defaultUserMessageArgs) {
|
||||||
}
|
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
||||||
|
globalErrorResponse.setHttpStatusCode("403");
|
||||||
|
globalErrorResponse.setDeveloperMessage("Request was understood but caused a domain rule violation.");
|
||||||
|
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
||||||
|
globalErrorResponse.setUserMessageGlobalisationCode("validation.msg.domain.rule.violation");
|
||||||
|
globalErrorResponse.setDefaultUserMessage("Errors contain reason for domain rule violation.");
|
||||||
|
|
||||||
public void setDeveloperDocLink(String developerDocLink) {
|
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
||||||
this.developerDocLink = developerDocLink;
|
errors.add(ApiParameterError.generalError(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs));
|
||||||
}
|
globalErrorResponse.setErrors(errors);
|
||||||
|
|
||||||
|
return globalErrorResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiGlobalErrorResponse notFound(final String globalisationMessageCode, final String defaultUserMessage,
|
||||||
|
final Object... defaultUserMessageArgs) {
|
||||||
|
|
||||||
|
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
||||||
|
globalErrorResponse.setHttpStatusCode("404");
|
||||||
|
globalErrorResponse.setDeveloperMessage("The requested resource is not available.");
|
||||||
|
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
||||||
|
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.resource.not.found");
|
||||||
|
globalErrorResponse.setDefaultUserMessage("The requested resource is not available.");
|
||||||
|
|
||||||
|
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
||||||
|
errors.add(ApiParameterError.resourceIdentifierNotFound(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs));
|
||||||
|
globalErrorResponse.setErrors(errors);
|
||||||
|
|
||||||
|
return globalErrorResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiGlobalErrorResponse dataIntegrityError(final String globalisationMessageCode, final String defaultUserMessage,
|
||||||
|
final String parameterName, final Object... defaultUserMessageArgs) {
|
||||||
|
|
||||||
|
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
||||||
|
globalErrorResponse.setHttpStatusCode("403");
|
||||||
|
globalErrorResponse.setDeveloperMessage("The request caused a data integrity issue to be fired by the database.");
|
||||||
|
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
||||||
|
globalErrorResponse.setUserMessageGlobalisationCode(globalisationMessageCode);
|
||||||
|
globalErrorResponse.setDefaultUserMessage(defaultUserMessage);
|
||||||
|
|
||||||
|
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
||||||
|
errors.add(ApiParameterError.parameterError(globalisationMessageCode, defaultUserMessage, parameterName, defaultUserMessageArgs));
|
||||||
|
globalErrorResponse.setErrors(errors);
|
||||||
|
|
||||||
|
return globalErrorResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiGlobalErrorResponse badClientRequest(final String globalisationMessageCode, final String defaultUserMessage,
|
||||||
|
final List<ApiParameterError> errors) {
|
||||||
|
|
||||||
|
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
||||||
|
globalErrorResponse.setHttpStatusCode("400");
|
||||||
|
globalErrorResponse
|
||||||
|
.setDeveloperMessage("The request was invalid. This typically will happen due to validation errors which are provided.");
|
||||||
|
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
||||||
|
globalErrorResponse.setUserMessageGlobalisationCode(globalisationMessageCode);
|
||||||
|
globalErrorResponse.setDefaultUserMessage(defaultUserMessage);
|
||||||
|
|
||||||
|
globalErrorResponse.setErrors(errors);
|
||||||
|
|
||||||
|
return globalErrorResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiGlobalErrorResponse serverSideError(final String globalisationMessageCode, final String defaultUserMessage,
|
||||||
|
final Object... defaultUserMessageArgs) {
|
||||||
|
|
||||||
|
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
||||||
|
globalErrorResponse.setHttpStatusCode("500");
|
||||||
|
globalErrorResponse.setDeveloperMessage("An unexpected error occured on the platform server.");
|
||||||
|
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
|
||||||
|
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.platform.server.side.error");
|
||||||
|
globalErrorResponse.setDefaultUserMessage("An unexpected error occured on the platform server.");
|
||||||
|
|
||||||
|
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
|
||||||
|
errors.add(ApiParameterError.generalError(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs));
|
||||||
|
globalErrorResponse.setErrors(errors);
|
||||||
|
|
||||||
|
return globalErrorResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ApiGlobalErrorResponse() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApiGlobalErrorResponse(final List<ApiParameterError> errors) {
|
||||||
|
this.errors = errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElementWrapper(name = "errors")
|
||||||
|
@XmlElement(name = "errorResponse")
|
||||||
|
public List<ApiParameterError> getErrors() {
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrors(final List<ApiParameterError> errors) {
|
||||||
|
this.errors = errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeveloperMessage() {
|
||||||
|
return developerMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeveloperMessage(final String developerMessage) {
|
||||||
|
this.developerMessage = developerMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHttpStatusCode() {
|
||||||
|
return httpStatusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHttpStatusCode(final String httpStatusCode) {
|
||||||
|
this.httpStatusCode = httpStatusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultUserMessage() {
|
||||||
|
return defaultUserMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultUserMessage(final String defaultUserMessage) {
|
||||||
|
this.defaultUserMessage = defaultUserMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserMessageGlobalisationCode() {
|
||||||
|
return userMessageGlobalisationCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserMessageGlobalisationCode(final String userMessageGlobalisationCode) {
|
||||||
|
this.userMessageGlobalisationCode = userMessageGlobalisationCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeveloperDocLink() {
|
||||||
|
return developerDocLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeveloperDocLink(final String developerDocLink) {
|
||||||
|
this.developerDocLink = developerDocLink;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+4
-2
@@ -30,9 +30,11 @@ import org.springframework.stereotype.Component;
|
|||||||
public class AccessDeniedExceptionMapper implements ExceptionMapper<AccessDeniedException> {
|
public class AccessDeniedExceptionMapper implements ExceptionMapper<AccessDeniedException> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response toResponse(@SuppressWarnings("unused") AccessDeniedException exception) {
|
public Response toResponse(final AccessDeniedException exception) {
|
||||||
// Status code 403 really reads as:
|
// Status code 403 really reads as:
|
||||||
// "Authenticated - but not authorized":
|
// "Authenticated - but not authorized":
|
||||||
return Response.status(Status.FORBIDDEN).entity(ApiGlobalErrorResponse.unAuthorized()).type(MediaType.APPLICATION_JSON).build();
|
final String defaultUserMessage = exception.getMessage();
|
||||||
|
return Response.status(Status.FORBIDDEN).entity(ApiGlobalErrorResponse.unAuthorized(defaultUserMessage))
|
||||||
|
.type(MediaType.APPLICATION_JSON).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+4
-2
@@ -29,9 +29,11 @@ import org.springframework.stereotype.Component;
|
|||||||
public class NoAuthorizationExceptionMapper implements ExceptionMapper<NoAuthorizationException> {
|
public class NoAuthorizationExceptionMapper implements ExceptionMapper<NoAuthorizationException> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response toResponse(@SuppressWarnings("unused") NoAuthorizationException exception) {
|
public Response toResponse(final NoAuthorizationException exception) {
|
||||||
// Status code 403 really reads as:
|
// Status code 403 really reads as:
|
||||||
// "Authenticated - but not authorized":
|
// "Authenticated - but not authorized":
|
||||||
return Response.status(Status.FORBIDDEN).entity(ApiGlobalErrorResponse.unAuthorized()).type(MediaType.APPLICATION_JSON).build();
|
final String defaultUserMessage = exception.getMessage();
|
||||||
|
return Response.status(Status.FORBIDDEN).entity(ApiGlobalErrorResponse.unAuthorized(defaultUserMessage))
|
||||||
|
.type(MediaType.APPLICATION_JSON).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
@@ -386,6 +386,7 @@ public class JsonParserHelper {
|
|||||||
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.integer.format", "The parameter "
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.integer.format", "The parameter "
|
||||||
+ parameterName + " has value: " + numericalValueFormatted + " which is invalid integer value for provided locale of ["
|
+ parameterName + " has value: " + numericalValueFormatted + " which is invalid integer value for provided locale of ["
|
||||||
+ clientApplicationLocale.toString() + "].", parameterName, numericalValueFormatted, clientApplicationLocale);
|
+ clientApplicationLocale.toString() + "].", parameterName, numericalValueFormatted, clientApplicationLocale);
|
||||||
|
error.setValue(numericalValueFormatted);
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
|
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||||
@@ -408,6 +409,7 @@ public class JsonParserHelper {
|
|||||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.integer", "The parameter " + parameterName
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.integer", "The parameter " + parameterName
|
||||||
+ " has value: " + numericalValueFormatted + " which is invalid integer.", parameterName, numericalValueFormatted);
|
+ " has value: " + numericalValueFormatted + " which is invalid integer.", parameterName, numericalValueFormatted);
|
||||||
|
error.setValue(numericalValueFormatted);
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
|
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||||
@@ -458,6 +460,7 @@ public class JsonParserHelper {
|
|||||||
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.decimal.format", "The parameter "
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.decimal.format", "The parameter "
|
||||||
+ parameterName + " has value: " + numericalValueFormatted + " which is invalid decimal value for provided locale of ["
|
+ parameterName + " has value: " + numericalValueFormatted + " which is invalid decimal value for provided locale of ["
|
||||||
+ clientApplicationLocale.toString() + "].", parameterName, numericalValueFormatted, clientApplicationLocale);
|
+ clientApplicationLocale.toString() + "].", parameterName, numericalValueFormatted, clientApplicationLocale);
|
||||||
|
error.setValue(numericalValueFormatted);
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
|
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||||
|
|||||||
+5
-9
@@ -53,6 +53,7 @@ public class ReportsApiResource {
|
|||||||
this.genericDataService = genericDataService;
|
this.genericDataService = genericDataService;
|
||||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Consumes({ MediaType.APPLICATION_JSON })
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
@Produces({ MediaType.APPLICATION_JSON, "application/x-msdownload" })
|
@Produces({ MediaType.APPLICATION_JSON, "application/x-msdownload" })
|
||||||
@@ -144,10 +145,10 @@ public class ReportsApiResource {
|
|||||||
} else {
|
} else {
|
||||||
json = this.toApiJsonSerializer.serializePretty(prettyPrint, result);
|
json = this.toApiJsonSerializer.serializePretty(prettyPrint, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response.ok().entity(json).type(MediaType.APPLICATION_JSON).build();
|
return Response.ok().entity(json).type(MediaType.APPLICATION_JSON).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSV Export
|
// CSV Export
|
||||||
Map<String, String> reportParams = getReportParams(queryParams, false);
|
Map<String, String> reportParams = getReportParams(queryParams, false);
|
||||||
StreamingOutput result = this.readExtraDataAndReportingService.retrieveReportCSV(reportName, parameterTypeValue, reportParams);
|
StreamingOutput result = this.readExtraDataAndReportingService.retrieveReportCSV(reportName, parameterTypeValue, reportParams);
|
||||||
@@ -160,15 +161,10 @@ public class ReportsApiResource {
|
|||||||
|
|
||||||
// Anyone can run a 'report' that is simply getting possible parameter
|
// Anyone can run a 'report' that is simply getting possible parameter
|
||||||
// (dropdown listbox) values.
|
// (dropdown listbox) values.
|
||||||
|
|
||||||
if (!parameterType) {
|
if (!parameterType) {
|
||||||
AppUser currentUser = context.authenticatedUser();
|
AppUser currentUser = context.authenticatedUser();
|
||||||
if (currentUser.hasNotPermissionForReport(reportName)) {
|
if (currentUser.hasNotPermissionForReport(reportName)) { throw new NoAuthorizationException("Not authorised to run report: "
|
||||||
// FIXME - JW - message isnt passing back the message in the
|
+ reportName); }
|
||||||
// string in
|
|
||||||
// the json just a generalised not authorised message
|
|
||||||
throw new NoAuthorizationException("Not Authorised to Run Report: " + reportName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -15,7 +15,11 @@ public class DatatableData {
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final String registeredTableName;
|
private final String registeredTableName;
|
||||||
|
|
||||||
public DatatableData(final String applicationTableName, final String registeredTableName) {
|
public static DatatableData create(final String applicationTableName, final String registeredTableName) {
|
||||||
|
return new DatatableData(applicationTableName, registeredTableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DatatableData(final String applicationTableName, final String registeredTableName) {
|
||||||
this.applicationTableName = applicationTableName;
|
this.applicationTableName = applicationTableName;
|
||||||
this.registeredTableName = registeredTableName;
|
this.registeredTableName = registeredTableName;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -13,19 +13,19 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class GenericResultsetData {
|
public class GenericResultsetData {
|
||||||
|
|
||||||
private final List<ResultsetColumnHeader> columnHeaders;
|
private final List<ResultsetColumnHeaderData> columnHeaders;
|
||||||
private final List<ResultsetDataRow> data;
|
private final List<ResultsetRowData> data;
|
||||||
|
|
||||||
public GenericResultsetData(final List<ResultsetColumnHeader> columnHeaders, final List<ResultsetDataRow> resultsetDataRows) {
|
public GenericResultsetData(final List<ResultsetColumnHeaderData> columnHeaders, final List<ResultsetRowData> resultsetDataRows) {
|
||||||
this.columnHeaders = columnHeaders;
|
this.columnHeaders = columnHeaders;
|
||||||
this.data = resultsetDataRows;
|
this.data = resultsetDataRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ResultsetColumnHeader> getColumnHeaders() {
|
public List<ResultsetColumnHeaderData> getColumnHeaders() {
|
||||||
return columnHeaders;
|
return columnHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ResultsetDataRow> getData() {
|
public List<ResultsetRowData> getData() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-128
@@ -1,128 +0,0 @@
|
|||||||
/**
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
package org.mifosplatform.infrastructure.dataqueries.data;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
|
||||||
|
|
||||||
public class ResultsetColumnHeader {
|
|
||||||
|
|
||||||
private String columnName;
|
|
||||||
private String columnType;
|
|
||||||
private Long columnLength;
|
|
||||||
private String columnDisplayType;
|
|
||||||
private boolean isColumnNullable;
|
|
||||||
private boolean isColumnPrimaryKey;
|
|
||||||
private List<ResultsetColumnValue> columnValues = new ArrayList<ResultsetColumnValue>();
|
|
||||||
|
|
||||||
public ResultsetColumnHeader() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getColumnName() {
|
|
||||||
return columnName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColumnName(String columnName) {
|
|
||||||
this.columnName = columnName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getColumnType() {
|
|
||||||
return columnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColumnType(String columnType) {
|
|
||||||
this.columnType = columnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getColumnLength() {
|
|
||||||
return columnLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColumnLength(Long columnLength) {
|
|
||||||
this.columnLength = columnLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ResultsetColumnValue> getColumnValues() {
|
|
||||||
return columnValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColumnValues(List<ResultsetColumnValue> columnValues) {
|
|
||||||
this.columnValues = columnValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isColumnNullable() {
|
|
||||||
return isColumnNullable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColumnNullable(boolean isColumnNullable) {
|
|
||||||
this.isColumnNullable = isColumnNullable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isColumnPrimaryKey() {
|
|
||||||
return isColumnPrimaryKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColumnPrimaryKey(boolean isColumnPrimaryKey) {
|
|
||||||
this.isColumnPrimaryKey = isColumnPrimaryKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getColumnDisplayType() {
|
|
||||||
return columnDisplayType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColumnDisplayType() {
|
|
||||||
|
|
||||||
if (this.getColumnValues().size() > 0) {
|
|
||||||
|
|
||||||
if (this.getColumnType().equalsIgnoreCase("int")) {
|
|
||||||
this.columnDisplayType = "CODELOOKUP";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.getColumnType().equalsIgnoreCase("varchar")) {
|
|
||||||
this.columnDisplayType = "CODEVALUE";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.invalid.lookup.type", "Invalid Lookup Type:" + this.getColumnType()
|
|
||||||
+ " - Column Name: " + this.getColumnName());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getColumnType().equalsIgnoreCase("varchar") || this.getColumnType().equalsIgnoreCase("char")) {
|
|
||||||
this.columnDisplayType = "STRING";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getColumnType().equalsIgnoreCase("int") || this.getColumnType().equalsIgnoreCase("bigint")
|
|
||||||
|| this.getColumnType().equalsIgnoreCase("smallint") || this.getColumnType().equalsIgnoreCase("mediumint")
|
|
||||||
|| this.getColumnType().equalsIgnoreCase("tinyint")) {
|
|
||||||
this.columnDisplayType = "INTEGER";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getColumnType().equalsIgnoreCase("date")) {
|
|
||||||
this.columnDisplayType = "DATE";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getColumnType().equalsIgnoreCase("decimal")) {
|
|
||||||
this.columnDisplayType = "DECIMAL";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getColumnType().equalsIgnoreCase("text") || this.getColumnType().equalsIgnoreCase("mediumtext")
|
|
||||||
|| this.getColumnType().equalsIgnoreCase("longtext") || this.getColumnType().equalsIgnoreCase("tinytext")) {
|
|
||||||
this.columnDisplayType = "TEXT";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.unsupported.column.type", "Unsupported Column Type:" + this.getColumnType()
|
|
||||||
+ " - Column Name: " + this.getColumnName());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+218
@@ -0,0 +1,218 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.dataqueries.data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immutable data object representing a resultset column.
|
||||||
|
*/
|
||||||
|
public final class ResultsetColumnHeaderData {
|
||||||
|
|
||||||
|
private final String columnName;
|
||||||
|
private final String columnType;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final Long columnLength;
|
||||||
|
private final String columnDisplayType;
|
||||||
|
private final boolean isColumnNullable;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final boolean isColumnPrimaryKey;
|
||||||
|
|
||||||
|
private final List<ResultsetColumnValueData> columnValues;
|
||||||
|
|
||||||
|
public static ResultsetColumnHeaderData basic(final String columnName, final String columnType) {
|
||||||
|
|
||||||
|
final Long columnLength = null;
|
||||||
|
final boolean columnNullable = false;
|
||||||
|
final boolean columnIsPrimaryKey = false;
|
||||||
|
final List<ResultsetColumnValueData> columnValues = new ArrayList<ResultsetColumnValueData>();
|
||||||
|
return new ResultsetColumnHeaderData(columnName, columnType, columnLength, columnNullable, columnIsPrimaryKey, columnValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResultsetColumnHeaderData detailed(final String columnName, final String columnType, final Long columnLength,
|
||||||
|
final boolean columnNullable, final boolean columnIsPrimaryKey, final List<ResultsetColumnValueData> columnValues) {
|
||||||
|
return new ResultsetColumnHeaderData(columnName, columnType, columnLength, columnNullable, columnIsPrimaryKey, columnValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultsetColumnHeaderData(final String columnName, final String columnType, final Long columnLength,
|
||||||
|
final boolean columnNullable, final boolean columnIsPrimaryKey, final List<ResultsetColumnValueData> columnValues) {
|
||||||
|
this.columnName = columnName;
|
||||||
|
this.columnType = columnType;
|
||||||
|
this.columnLength = columnLength;
|
||||||
|
this.isColumnNullable = columnNullable;
|
||||||
|
this.isColumnPrimaryKey = columnIsPrimaryKey;
|
||||||
|
this.columnValues = columnValues;
|
||||||
|
|
||||||
|
String displayType = null;
|
||||||
|
if (this.columnValues.isEmpty()) {
|
||||||
|
if (isString()) {
|
||||||
|
displayType = "STRING";
|
||||||
|
} else if (isAnyInteger()) {
|
||||||
|
displayType = "INTEGER";
|
||||||
|
} else if (isDate()) {
|
||||||
|
displayType = "DATE";
|
||||||
|
} else if (isDecimal()) {
|
||||||
|
displayType = "DECIMAL";
|
||||||
|
} else if (isAnyText()) {
|
||||||
|
displayType = "TEXT";
|
||||||
|
} else {
|
||||||
|
throw new PlatformDataIntegrityException("error.msg.invalid.lookup.type", "Invalid Lookup Type:" + this.columnType
|
||||||
|
+ " - Column Name: " + this.columnName);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (isInt()) {
|
||||||
|
displayType = "CODELOOKUP";
|
||||||
|
} else if (isVarchar()) {
|
||||||
|
displayType = "CODEVALUE";
|
||||||
|
} else {
|
||||||
|
throw new PlatformDataIntegrityException("error.msg.invalid.lookup.type", "Invalid Lookup Type:" + this.columnType
|
||||||
|
+ " - Column Name: " + this.columnName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.columnDisplayType = displayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAnyText() {
|
||||||
|
return isText() || isTinyText() || isMediumText() || isLongText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isText() {
|
||||||
|
return "text".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTinyText() {
|
||||||
|
return "tinytext".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMediumText() {
|
||||||
|
return "mediumtext".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLongText() {
|
||||||
|
return "longtext".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDecimal() {
|
||||||
|
return "decimal".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDate() {
|
||||||
|
return "date".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isString() {
|
||||||
|
return isVarchar() || isChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isChar() {
|
||||||
|
return "char".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVarchar() {
|
||||||
|
return "varchar".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAnyInteger() {
|
||||||
|
return isInt() || isSmallInt() || isTinyInt() || isMediumInt() || isBigInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInt() {
|
||||||
|
return "int".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSmallInt() {
|
||||||
|
return "smallint".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTinyInt() {
|
||||||
|
return "tinyint".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMediumInt() {
|
||||||
|
return "mediumint".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBigInt() {
|
||||||
|
return "bigint".equalsIgnoreCase(this.columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnName() {
|
||||||
|
return this.columnName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnType() {
|
||||||
|
return this.columnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnDisplayType() {
|
||||||
|
return this.columnDisplayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDateDisplayType() {
|
||||||
|
return "DATE".equalsIgnoreCase(this.columnDisplayType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIntegerDisplayType() {
|
||||||
|
return "INTEGER".equalsIgnoreCase(this.columnDisplayType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDecimalDisplayType() {
|
||||||
|
return "DECIMAL".equalsIgnoreCase(this.columnDisplayType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCodeValueDisplayType() {
|
||||||
|
return "CODEVALUE".equalsIgnoreCase(this.columnDisplayType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCodeLookupDisplayType() {
|
||||||
|
return "CODELOOKUP".equalsIgnoreCase(this.columnDisplayType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMandatory() {
|
||||||
|
return !isOptional();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOptional() {
|
||||||
|
return this.isColumnNullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasColumnValues() {
|
||||||
|
return !this.columnValues.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isColumnValueAllowed(final String match) {
|
||||||
|
boolean allowed = false;
|
||||||
|
for (ResultsetColumnValueData allowedValue : this.columnValues) {
|
||||||
|
if (allowedValue.matches(match)) {
|
||||||
|
allowed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isColumnValueNotAllowed(final String match) {
|
||||||
|
return !isColumnValueAllowed(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isColumnCodeNotAllowed(final Integer match) {
|
||||||
|
return !isColumnCodeAllowed(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isColumnCodeAllowed(final Integer match) {
|
||||||
|
boolean allowed = false;
|
||||||
|
for (ResultsetColumnValueData allowedValue : this.columnValues) {
|
||||||
|
if (allowedValue.codeMatches(match)) {
|
||||||
|
allowed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
-33
@@ -1,33 +0,0 @@
|
|||||||
/**
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
package org.mifosplatform.infrastructure.dataqueries.data;
|
|
||||||
|
|
||||||
public class ResultsetColumnValue {
|
|
||||||
|
|
||||||
private int id;
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
public ResultsetColumnValue(int id, String value) {
|
|
||||||
this.id = id;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.dataqueries.data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immutable data object representing a possible value for a given resultset
|
||||||
|
* column.
|
||||||
|
*/
|
||||||
|
public class ResultsetColumnValueData {
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
public ResultsetColumnValueData(final int id, final String value) {
|
||||||
|
this.id = id;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(final String match) {
|
||||||
|
return match.equalsIgnoreCase(this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean codeMatches(final Integer match) {
|
||||||
|
return match.intValue() == this.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-8
@@ -5,22 +5,21 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.dataqueries.data;
|
package org.mifosplatform.infrastructure.dataqueries.data;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ResultsetDataRow {
|
public class ResultsetRowData {
|
||||||
|
|
||||||
private List<String> row = new ArrayList<String>();
|
private final List<String> row;
|
||||||
|
|
||||||
public ResultsetDataRow() {
|
public static ResultsetRowData create(final List<String> rowValues) {
|
||||||
|
return new ResultsetRowData(rowValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultsetRowData(final List<String> rowValues) {
|
||||||
|
this.row = rowValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getRow() {
|
public List<String> getRow() {
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRow(List<String> row) {
|
|
||||||
this.row = row;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+3
-5
@@ -5,16 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.dataqueries.service;
|
package org.mifosplatform.infrastructure.dataqueries.service;
|
||||||
|
|
||||||
import javax.sql.rowset.CachedRowSet;
|
import java.util.List;
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
||||||
|
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
|
||||||
|
|
||||||
public interface GenericDataService {
|
public interface GenericDataService {
|
||||||
|
|
||||||
CachedRowSet getCachedResultSet(String sql, String errorMsg);
|
|
||||||
|
|
||||||
void updateSQL(String sql, String sqlErrorMsg);
|
|
||||||
|
|
||||||
GenericResultsetData fillGenericResultSet(final String sql);
|
GenericResultsetData fillGenericResultSet(final String sql);
|
||||||
|
|
||||||
String generateJsonFromGenericResultsetData(GenericResultsetData grs);
|
String generateJsonFromGenericResultsetData(GenericResultsetData grs);
|
||||||
@@ -25,4 +22,5 @@ public interface GenericDataService {
|
|||||||
|
|
||||||
String getDatabaseName();
|
String getDatabaseName();
|
||||||
|
|
||||||
|
List<ResultsetColumnHeaderData> fillResultsetColumnHeaders(String datatable);
|
||||||
}
|
}
|
||||||
+113
-116
@@ -5,128 +5,70 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.dataqueries.service;
|
package org.mifosplatform.infrastructure.dataqueries.service;
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.ResultSetMetaData;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import javax.sql.rowset.CachedRowSet;
|
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeader;
|
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetDataRow;
|
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnValueData;
|
||||||
|
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetRowData;
|
||||||
|
import org.mifosplatform.infrastructure.dataqueries.exception.DataTableNotFoundException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.support.rowset.SqlRowSet;
|
||||||
|
import org.springframework.jdbc.support.rowset.SqlRowSetMetaData;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.sun.rowset.CachedRowSetImpl;
|
|
||||||
|
|
||||||
//TODO - JW - Performance Item - most items (code values etc) can be cached but not doing that yet
|
|
||||||
@Service
|
@Service
|
||||||
public class GenericDataServiceImpl implements GenericDataService {
|
public class GenericDataServiceImpl implements GenericDataService {
|
||||||
|
|
||||||
|
private final JdbcTemplate jdbcTemplate;
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public GenericDataServiceImpl(final TenantAwareRoutingDataSource dataSource) {
|
public GenericDataServiceImpl(final TenantAwareRoutingDataSource dataSource) {
|
||||||
|
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
}
|
this.jdbcTemplate = new JdbcTemplate(this.dataSource);
|
||||||
|
|
||||||
@Override
|
|
||||||
public CachedRowSet getCachedResultSet(final String sql, final String sqlErrorMsg) {
|
|
||||||
// FIXME - KW - Need to reimplement this away from Sun library - could
|
|
||||||
// be mixture of Lists and jdbcTemplate.query
|
|
||||||
|
|
||||||
// long startTime = System.currentTimeMillis();
|
|
||||||
Connection db_connection = null;
|
|
||||||
Statement db_statement = null;
|
|
||||||
CachedRowSet crs = null;
|
|
||||||
try {
|
|
||||||
db_connection = dataSource.getConnection();
|
|
||||||
db_statement = db_connection.createStatement();
|
|
||||||
ResultSet rs = db_statement.executeQuery(sql);
|
|
||||||
crs = new CachedRowSetImpl();
|
|
||||||
|
|
||||||
crs.populate(rs);
|
|
||||||
// logger.info("RS Size: " + crs.size() +
|
|
||||||
// " getCachedResultSet sql: " + sql);
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), sqlErrorMsg);
|
|
||||||
} finally {
|
|
||||||
dbClose(db_statement, db_connection);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// long elapsed = System.currentTimeMillis() - startTime;
|
|
||||||
// logger.info("Elapsed Time: " + elapsed + " SQL: " + sql);
|
|
||||||
return crs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateSQL(final String sql, final String sqlErrorMsg) {
|
|
||||||
|
|
||||||
// long startTime = System.currentTimeMillis();
|
|
||||||
Connection db_connection = null;
|
|
||||||
Statement db_statement = null;
|
|
||||||
try {
|
|
||||||
db_connection = dataSource.getConnection();
|
|
||||||
db_statement = db_connection.createStatement();
|
|
||||||
db_statement.executeUpdate(sql);
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), sqlErrorMsg);
|
|
||||||
} finally {
|
|
||||||
dbClose(db_statement, db_connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// long elapsed = System.currentTimeMillis() - startTime;
|
|
||||||
// logger.info("Elapsed Time: " + elapsed + " SQL: " + sql);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GenericResultsetData fillGenericResultSet(final String sql) {
|
public GenericResultsetData fillGenericResultSet(final String sql) {
|
||||||
|
|
||||||
String sqlErrorMsg = "Sql: " + sql;
|
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sql);
|
||||||
CachedRowSet rs = getCachedResultSet(sql, sqlErrorMsg);
|
|
||||||
|
|
||||||
List<ResultsetColumnHeader> columnHeaders = new ArrayList<ResultsetColumnHeader>();
|
final List<ResultsetColumnHeaderData> columnHeaders = new ArrayList<ResultsetColumnHeaderData>();
|
||||||
List<ResultsetDataRow> resultsetDataRows = new ArrayList<ResultsetDataRow>();
|
final List<ResultsetRowData> resultsetDataRows = new ArrayList<ResultsetRowData>();
|
||||||
|
|
||||||
try {
|
final SqlRowSetMetaData rsmd = rs.getMetaData();
|
||||||
|
|
||||||
ResultSetMetaData rsmd = rs.getMetaData();
|
for (int i = 0; i < rsmd.getColumnCount(); i++) {
|
||||||
String columnName = null;
|
|
||||||
String columnValue = null;
|
|
||||||
for (int i = 0; i < rsmd.getColumnCount(); i++) {
|
|
||||||
ResultsetColumnHeader rsch = new ResultsetColumnHeader();
|
|
||||||
rsch.setColumnName(rsmd.getColumnName(i + 1));
|
|
||||||
rsch.setColumnType(rsmd.getColumnTypeName(i + 1));
|
|
||||||
columnHeaders.add(rsch);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultsetDataRow resultsetDataRow;
|
final String columnName = rsmd.getColumnName(i + 1);
|
||||||
while (rs.next()) {
|
final String columnType = rsmd.getColumnTypeName(i + 1);
|
||||||
resultsetDataRow = new ResultsetDataRow();
|
|
||||||
List<String> columnValues = new ArrayList<String>();
|
|
||||||
for (int i = 0; i < rsmd.getColumnCount(); i++) {
|
|
||||||
columnName = rsmd.getColumnName(i + 1);
|
|
||||||
columnValue = rs.getString(columnName);
|
|
||||||
columnValues.add(columnValue);
|
|
||||||
}
|
|
||||||
resultsetDataRow.setRow(columnValues);
|
|
||||||
resultsetDataRows.add(resultsetDataRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GenericResultsetData(columnHeaders, resultsetDataRows);
|
final ResultsetColumnHeaderData columnHeader = ResultsetColumnHeaderData.basic(columnName, columnType);
|
||||||
} catch (SQLException e) {
|
columnHeaders.add(columnHeader);
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), sqlErrorMsg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (rs.next()) {
|
||||||
|
final List<String> columnValues = new ArrayList<String>();
|
||||||
|
for (int i = 0; i < rsmd.getColumnCount(); i++) {
|
||||||
|
final String columnName = rsmd.getColumnName(i + 1);
|
||||||
|
final String columnValue = rs.getString(columnName);
|
||||||
|
columnValues.add(columnValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
final ResultsetRowData resultsetDataRow = ResultsetRowData.create(columnValues);
|
||||||
|
resultsetDataRows.add(resultsetDataRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GenericResultsetData(columnHeaders, resultsetDataRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -165,17 +107,16 @@ public class GenericDataServiceImpl implements GenericDataService {
|
|||||||
|
|
||||||
writer.append("[");
|
writer.append("[");
|
||||||
|
|
||||||
List<ResultsetColumnHeader> columnHeaders = grs.getColumnHeaders();
|
final List<ResultsetColumnHeaderData> columnHeaders = grs.getColumnHeaders();
|
||||||
// logger.info("NO. of Columns: " + columnHeaders.size());
|
|
||||||
|
|
||||||
List<ResultsetDataRow> data = grs.getData();
|
List<ResultsetRowData> data = grs.getData();
|
||||||
List<String> row;
|
List<String> row;
|
||||||
Integer rSize;
|
Integer rSize;
|
||||||
String doubleQuote = "\"";
|
String doubleQuote = "\"";
|
||||||
String slashDoubleQuote = "\\\"";
|
String slashDoubleQuote = "\\\"";
|
||||||
String currColType;
|
String currColType;
|
||||||
String currVal;
|
String currVal;
|
||||||
// logger.info("NO. of Rows: " + data.size());
|
|
||||||
for (int i = 0; i < data.size(); i++) {
|
for (int i = 0; i < data.size(); i++) {
|
||||||
writer.append("\n{");
|
writer.append("\n{");
|
||||||
|
|
||||||
@@ -205,8 +146,8 @@ public class GenericDataServiceImpl implements GenericDataService {
|
|||||||
writer.append("[" + localDate.getYear() + ", " + localDate.getMonthOfYear() + ", " + localDate.getDayOfMonth()
|
writer.append("[" + localDate.getYear() + ", " + localDate.getMonthOfYear() + ", " + localDate.getDayOfMonth()
|
||||||
+ "]");
|
+ "]");
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
writer.append(doubleQuote + replace(currVal, doubleQuote,slashDoubleQuote) + doubleQuote);
|
writer.append(doubleQuote + replace(currVal, doubleQuote, slashDoubleQuote) + doubleQuote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -217,8 +158,7 @@ public class GenericDataServiceImpl implements GenericDataService {
|
|||||||
|
|
||||||
if (i < (data.size() - 1)) {
|
if (i < (data.size() - 1)) {
|
||||||
writer.append("},");
|
writer.append("},");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
writer.append("}");
|
writer.append("}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,24 +167,6 @@ public class GenericDataServiceImpl implements GenericDataService {
|
|||||||
return writer.toString();
|
return writer.toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dbClose(Statement db_statement, Connection db_connection) {
|
|
||||||
// logger.debug("dbClose");
|
|
||||||
try {
|
|
||||||
if (db_statement != null) {
|
|
||||||
db_statement.close();
|
|
||||||
// parameter assignment in this case is ok.
|
|
||||||
db_statement = null;
|
|
||||||
}
|
|
||||||
if (db_connection != null) {
|
|
||||||
db_connection.close();
|
|
||||||
// parameter assignment in this case is ok.
|
|
||||||
db_connection = null;
|
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), "Error closing database connection");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDatabaseName() {
|
public String getDatabaseName() {
|
||||||
@@ -254,4 +176,79 @@ public class GenericDataServiceImpl implements GenericDataService {
|
|||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), "Error Accessing Database Name");
|
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), "Error Accessing Database Name");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ResultsetColumnHeaderData> fillResultsetColumnHeaders(final String datatable) {
|
||||||
|
|
||||||
|
final SqlRowSet columnDefinitions = getDatatableMetaData(datatable);
|
||||||
|
|
||||||
|
final List<ResultsetColumnHeaderData> columnHeaders = new ArrayList<ResultsetColumnHeaderData>();
|
||||||
|
|
||||||
|
columnDefinitions.beforeFirst();
|
||||||
|
while (columnDefinitions.next()) {
|
||||||
|
final String columnName = columnDefinitions.getString("COLUMN_NAME");
|
||||||
|
final String isNullable = columnDefinitions.getString("IS_NULLABLE");
|
||||||
|
final String isPrimaryKey = columnDefinitions.getString("COLUMN_KEY");
|
||||||
|
final String columnType = columnDefinitions.getString("DATA_TYPE");
|
||||||
|
final Long columnLength = columnDefinitions.getLong("CHARACTER_MAXIMUM_LENGTH");
|
||||||
|
|
||||||
|
boolean columnNullable = "YES".equalsIgnoreCase(isNullable);
|
||||||
|
boolean columnIsPrimaryKey = "PRI".equalsIgnoreCase(isPrimaryKey);
|
||||||
|
|
||||||
|
List<ResultsetColumnValueData> columnValues = new ArrayList<ResultsetColumnValueData>();
|
||||||
|
if ("varchar".equalsIgnoreCase(columnType)) {
|
||||||
|
columnValues = retreiveColumnValues(columnName, "_cv");
|
||||||
|
} else if ("int".equalsIgnoreCase(columnType)) {
|
||||||
|
columnValues = retreiveColumnValues(columnName, "_cd");
|
||||||
|
}
|
||||||
|
|
||||||
|
final ResultsetColumnHeaderData rsch = ResultsetColumnHeaderData.detailed(columnName, columnType, columnLength, columnNullable,
|
||||||
|
columnIsPrimaryKey, columnValues);
|
||||||
|
|
||||||
|
columnHeaders.add(rsch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return columnHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Candidate for using caching there to get allowed 'column values' from
|
||||||
|
* code/codevalue tables
|
||||||
|
*/
|
||||||
|
private List<ResultsetColumnValueData> retreiveColumnValues(final String columnName, final String code_suffix) {
|
||||||
|
|
||||||
|
final List<ResultsetColumnValueData> columnValues = new ArrayList<ResultsetColumnValueData>();
|
||||||
|
|
||||||
|
int codePosition = columnName.indexOf(code_suffix);
|
||||||
|
if (codePosition > 0) {
|
||||||
|
final String codeName = columnName.substring(0, codePosition);
|
||||||
|
|
||||||
|
final String sql = "select v.id, v.code_value from m_code m " + " join m_code_value v on v.code_id = m.id "
|
||||||
|
+ " where m.code_name = '" + codeName + "' order by v.order_position, v.id";
|
||||||
|
|
||||||
|
final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql);
|
||||||
|
|
||||||
|
rsValues.beforeFirst();
|
||||||
|
while (rsValues.next()) {
|
||||||
|
final Integer id = rsValues.getInt("id");
|
||||||
|
final String codeValue = rsValues.getString("code_value");
|
||||||
|
|
||||||
|
columnValues.add(new ResultsetColumnValueData(id, codeValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return columnValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqlRowSet getDatatableMetaData(final String datatable) {
|
||||||
|
|
||||||
|
final String sql = "select COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMN_KEY"
|
||||||
|
+ " from INFORMATION_SCHEMA.COLUMNS " + " where TABLE_SCHEMA = schema() and TABLE_NAME = '" + datatable
|
||||||
|
+ "'order by ORDINAL_POSITION";
|
||||||
|
|
||||||
|
final SqlRowSet columnDefinitions = this.jdbcTemplate.queryForRowSet(sql);
|
||||||
|
if (columnDefinitions.next()) { return columnDefinitions; }
|
||||||
|
|
||||||
|
throw new DataTableNotFoundException(datatable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+373
-467
@@ -13,13 +13,11 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.sql.Date;
|
import java.sql.Date;
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import javax.sql.rowset.CachedRowSet;
|
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.StreamingOutput;
|
import javax.ws.rs.core.StreamingOutput;
|
||||||
|
|
||||||
@@ -28,8 +26,8 @@ import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityExce
|
|||||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
||||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeader;
|
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetDataRow;
|
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetRowData;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.exception.ReportNotFoundException;
|
import org.mifosplatform.infrastructure.dataqueries.exception.ReportNotFoundException;
|
||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.mifosplatform.useradministration.domain.AppUser;
|
import org.mifosplatform.useradministration.domain.AppUser;
|
||||||
@@ -49,6 +47,8 @@ import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.support.rowset.SqlRowSet;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.lowagie.text.Document;
|
import com.lowagie.text.Document;
|
||||||
@@ -59,467 +59,373 @@ import com.lowagie.text.pdf.PdfWriter;
|
|||||||
@Service
|
@Service
|
||||||
public class ReadReportingServiceImpl implements ReadReportingService {
|
public class ReadReportingServiceImpl implements ReadReportingService {
|
||||||
|
|
||||||
private final DataSource dataSource;
|
private final static Logger logger = LoggerFactory.getLogger(ReadReportingServiceImpl.class);
|
||||||
private final PlatformSecurityContext context;
|
|
||||||
|
private final JdbcTemplate jdbcTemplate;
|
||||||
private final static Logger logger = LoggerFactory
|
private final DataSource dataSource;
|
||||||
.getLogger(ReadReportingServiceImpl.class);
|
private final PlatformSecurityContext context;
|
||||||
|
private final GenericDataService genericDataService;
|
||||||
private Boolean noPentaho = false;
|
private boolean noPentaho = false;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ReadReportingServiceImpl(final PlatformSecurityContext context,
|
public ReadReportingServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
|
||||||
final TenantAwareRoutingDataSource dataSource) {
|
final GenericDataService genericDataService) {
|
||||||
// kick off pentaho reports server
|
// kick off pentaho reports server
|
||||||
ClassicEngineBoot.getInstance().start();
|
ClassicEngineBoot.getInstance().start();
|
||||||
noPentaho = false;
|
noPentaho = false;
|
||||||
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
}
|
this.jdbcTemplate = new JdbcTemplate(this.dataSource);
|
||||||
|
this.genericDataService = genericDataService;
|
||||||
@Autowired
|
}
|
||||||
private GenericDataService genericDataService;
|
|
||||||
|
@Override
|
||||||
@Override
|
public StreamingOutput retrieveReportCSV(final String name, final String type, final Map<String, String> queryParams) {
|
||||||
public StreamingOutput retrieveReportCSV(final String name,
|
|
||||||
final String type, final Map<String, String> queryParams) {
|
return new StreamingOutput() {
|
||||||
|
|
||||||
return new StreamingOutput() {
|
@Override
|
||||||
|
public void write(final OutputStream out) {
|
||||||
@Override
|
try {
|
||||||
public void write(final OutputStream out) {
|
|
||||||
try {
|
GenericResultsetData result = retrieveGenericResultset(name, type, queryParams);
|
||||||
|
StringBuffer sb = generateCsvFileBuffer(result);
|
||||||
GenericResultsetData result = retrieveGenericResultset(
|
|
||||||
name, type, queryParams);
|
InputStream in = new ByteArrayInputStream(sb.toString().getBytes("UTF-8"));
|
||||||
StringBuffer sb = generateCsvFileBuffer(result);
|
|
||||||
|
byte[] outputByte = new byte[4096];
|
||||||
InputStream in = new ByteArrayInputStream(sb.toString()
|
Integer readLen = in.read(outputByte, 0, 4096);
|
||||||
.getBytes("UTF-8"));
|
|
||||||
|
while (readLen != -1) {
|
||||||
byte[] outputByte = new byte[4096];
|
out.write(outputByte, 0, readLen);
|
||||||
Integer readLen = in.read(outputByte, 0, 4096);
|
readLen = in.read(outputByte, 0, 4096);
|
||||||
|
}
|
||||||
while (readLen != -1) {
|
// in.close();
|
||||||
out.write(outputByte, 0, readLen);
|
// out.flush();
|
||||||
readLen = in.read(outputByte, 0, 4096);
|
// out.close();
|
||||||
}
|
} catch (Exception e) {
|
||||||
// in.close();
|
throw new PlatformDataIntegrityException("error.msg.exception.error", e.getMessage());
|
||||||
// out.flush();
|
}
|
||||||
// out.close();
|
}
|
||||||
} catch (Exception e) {
|
};
|
||||||
throw new PlatformDataIntegrityException(
|
|
||||||
"error.msg.exception.error", e.getMessage());
|
}
|
||||||
}
|
|
||||||
}
|
private StringBuffer generateCsvFileBuffer(final GenericResultsetData result) {
|
||||||
};
|
StringBuffer writer = new StringBuffer();
|
||||||
|
|
||||||
}
|
List<ResultsetColumnHeaderData> columnHeaders = result.getColumnHeaders();
|
||||||
|
logger.info("NO. of Columns: " + columnHeaders.size());
|
||||||
private StringBuffer generateCsvFileBuffer(final GenericResultsetData result) {
|
Integer chSize = columnHeaders.size();
|
||||||
StringBuffer writer = new StringBuffer();
|
for (int i = 0; i < chSize; i++) {
|
||||||
|
writer.append('"' + columnHeaders.get(i).getColumnName() + '"');
|
||||||
List<ResultsetColumnHeader> columnHeaders = result.getColumnHeaders();
|
if (i < (chSize - 1)) writer.append(",");
|
||||||
logger.info("NO. of Columns: " + columnHeaders.size());
|
}
|
||||||
Integer chSize = columnHeaders.size();
|
writer.append('\n');
|
||||||
for (int i = 0; i < chSize; i++) {
|
|
||||||
writer.append('"' + columnHeaders.get(i).getColumnName() + '"');
|
List<ResultsetRowData> data = result.getData();
|
||||||
if (i < (chSize - 1))
|
List<String> row;
|
||||||
writer.append(",");
|
Integer rSize;
|
||||||
}
|
// String currCol;
|
||||||
writer.append('\n');
|
String currColType;
|
||||||
|
String currVal;
|
||||||
List<ResultsetDataRow> data = result.getData();
|
String doubleQuote = "\"";
|
||||||
List<String> row;
|
String twoDoubleQuotes = doubleQuote + doubleQuote;
|
||||||
Integer rSize;
|
logger.info("NO. of Rows: " + data.size());
|
||||||
// String currCol;
|
for (int i = 0; i < data.size(); i++) {
|
||||||
String currColType;
|
row = data.get(i).getRow();
|
||||||
String currVal;
|
rSize = row.size();
|
||||||
String doubleQuote = "\"";
|
for (int j = 0; j < rSize; j++) {
|
||||||
String twoDoubleQuotes = doubleQuote + doubleQuote;
|
// currCol = columnHeaders.get(j).getColumnName();
|
||||||
logger.info("NO. of Rows: " + data.size());
|
currColType = columnHeaders.get(j).getColumnType();
|
||||||
for (int i = 0; i < data.size(); i++) {
|
currVal = row.get(j);
|
||||||
row = data.get(i).getRow();
|
if (currVal != null) {
|
||||||
rSize = row.size();
|
if (currColType.equals("DECIMAL") || currColType.equals("DOUBLE") || currColType.equals("BIGINT")
|
||||||
for (int j = 0; j < rSize; j++) {
|
|| currColType.equals("SMALLINT") || currColType.equals("INT"))
|
||||||
// currCol = columnHeaders.get(j).getColumnName();
|
writer.append(currVal);
|
||||||
currColType = columnHeaders.get(j).getColumnType();
|
else
|
||||||
currVal = row.get(j);
|
writer.append('"' + genericDataService.replace(currVal, doubleQuote, twoDoubleQuotes) + '"');
|
||||||
if (currVal != null) {
|
|
||||||
if (currColType.equals("DECIMAL")
|
}
|
||||||
|| currColType.equals("DOUBLE")
|
if (j < (rSize - 1)) writer.append(",");
|
||||||
|| currColType.equals("BIGINT")
|
}
|
||||||
|| currColType.equals("SMALLINT")
|
writer.append('\n');
|
||||||
|| currColType.equals("INT"))
|
}
|
||||||
writer.append(currVal);
|
|
||||||
else
|
return writer;
|
||||||
writer.append('"' + genericDataService.replace(currVal,
|
}
|
||||||
doubleQuote, twoDoubleQuotes) + '"');
|
|
||||||
|
@Override
|
||||||
}
|
public GenericResultsetData retrieveGenericResultset(final String name, final String type, final Map<String, String> queryParams) {
|
||||||
if (j < (rSize - 1))
|
|
||||||
writer.append(",");
|
long startTime = System.currentTimeMillis();
|
||||||
}
|
logger.info("STARTING REPORT: " + name + " Type: " + type);
|
||||||
writer.append('\n');
|
|
||||||
}
|
String sql;
|
||||||
|
if (name.equals(".")) {
|
||||||
return writer;
|
// this is to support api /reports - which isn't an important
|
||||||
}
|
// call. It isn't used in the default reporting UI. But there is a
|
||||||
|
// need to provide an api that does bring back 'permitted' reports
|
||||||
@Override
|
// PERMITTED REPORTS SQL
|
||||||
public GenericResultsetData retrieveGenericResultset(final String name,
|
sql = "select r.report_id, r.report_name, r.report_type, r.report_subtype, r.report_category,"
|
||||||
final String type, final Map<String, String> queryParams) {
|
+ " rp.parameter_id, rp.report_parameter_name, p.parameter_name" + " from stretchy_report r"
|
||||||
|
+ " left join stretchy_report_parameter rp on rp.report_id = r.report_id"
|
||||||
long startTime = System.currentTimeMillis();
|
+ " left join stretchy_parameter p on p.parameter_id = rp.parameter_id" + " where exists" + " (select 'f'"
|
||||||
logger.info("STARTING REPORT: " + name + " Type: " + type);
|
+ " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
|
||||||
|
+ " left join m_role_permission rp on rp.role_id = r.id" + " left join m_permission p on p.id = rp.permission_id"
|
||||||
String sql;
|
+ " where ur.appuser_id = " + context.authenticatedUser().getId()
|
||||||
if (name.equals(".")) {
|
+ " and (p.code in ('ALL_FUNCTIONS', 'ALL_FUNCTIONS_READ') or p.code = concat('READ_', r.report_name))) "
|
||||||
// this is to support api /reports - which isn't an important
|
+ " order by r.report_name, rp.parameter_id";
|
||||||
// call. It isn't used in the default reporting UI. But there is a
|
} else {
|
||||||
// need to provide an api that does bring back 'permitted' reports
|
sql = getSQLtoRun(name, type, queryParams);
|
||||||
// PERMITTED REPORTS SQL
|
}
|
||||||
sql = "select r.report_id, r.report_name, r.report_type, r.report_subtype, r.report_category,"
|
|
||||||
+ " rp.parameter_id, rp.report_parameter_name, p.parameter_name"
|
GenericResultsetData result = genericDataService.fillGenericResultSet(sql);
|
||||||
+ " from stretchy_report r"
|
|
||||||
+ " left join stretchy_report_parameter rp on rp.report_id = r.report_id"
|
long elapsed = System.currentTimeMillis() - startTime;
|
||||||
+ " left join stretchy_parameter p on p.parameter_id = rp.parameter_id"
|
logger.info("FINISHING Report/Request Name: " + name + " - " + type + " Elapsed Time: " + elapsed);
|
||||||
+ " where exists"
|
return result;
|
||||||
+ " (select 'f'"
|
}
|
||||||
+ " from m_appuser_role ur "
|
|
||||||
+ " join m_role r on r.id = ur.role_id"
|
private String getSQLtoRun(final String name, final String type, final Map<String, String> queryParams) {
|
||||||
+ " left join m_role_permission rp on rp.role_id = r.id"
|
|
||||||
+ " left join m_permission p on p.id = rp.permission_id"
|
String sql = getSql(name, type);
|
||||||
+ " where ur.appuser_id = "
|
|
||||||
+ context.authenticatedUser().getId()
|
Set<String> keys = queryParams.keySet();
|
||||||
+ " and (p.code in ('ALL_FUNCTIONS', 'ALL_FUNCTIONS_READ') or p.code = concat('READ_', r.report_name))) "
|
for (String key : keys) {
|
||||||
+ " order by r.report_name, rp.parameter_id";
|
String pValue = queryParams.get(key);
|
||||||
} else {
|
// logger.info("(" + key + " : " + pValue + ")");
|
||||||
sql = getSQLtoRun(name, type, queryParams);
|
sql = genericDataService.replace(sql, key, pValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericResultsetData result = genericDataService
|
AppUser currentUser = context.authenticatedUser();
|
||||||
.fillGenericResultSet(sql);
|
// Allows sql query to restrict data by office hierarchy if required
|
||||||
|
sql = genericDataService.replace(sql, "${currentUserHierarchy}", currentUser.getOffice().getHierarchy());
|
||||||
long elapsed = System.currentTimeMillis() - startTime;
|
// Allows sql query to restrict data by current user Id if required
|
||||||
logger.info("FINISHING Report/Request Name: " + name + " - " + type
|
// (typically used to return report lists containing only reports
|
||||||
+ " Elapsed Time: " + elapsed);
|
// permitted to be run by the user
|
||||||
return result;
|
sql = genericDataService.replace(sql, "${currentUserId}", currentUser.getId().toString());
|
||||||
}
|
|
||||||
|
sql = genericDataService.wrapSQL(sql);
|
||||||
private String getSQLtoRun(final String name, final String type,
|
|
||||||
final Map<String, String> queryParams) {
|
return sql;
|
||||||
|
|
||||||
String sql = getSql(name, type);
|
}
|
||||||
|
|
||||||
Set<String> keys = queryParams.keySet();
|
private String getSql(final String name, final String type) {
|
||||||
for (String key : keys) {
|
|
||||||
String pValue = queryParams.get(key);
|
final String inputSql = "select " + type + "_sql as the_sql from stretchy_" + type + " where " + type + "_name = '" + name + "'";
|
||||||
// logger.info("(" + key + " : " + pValue + ")");
|
final String inputSqlWrapped = genericDataService.wrapSQL(inputSql);
|
||||||
sql = genericDataService.replace(sql, key, pValue);
|
|
||||||
}
|
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(inputSqlWrapped);
|
||||||
|
|
||||||
AppUser currentUser = context.authenticatedUser();
|
if (rs.next()) { return rs.getString("the_sql"); }
|
||||||
// Allows sql query to restrict data by office hierarchy if required
|
throw new ReportNotFoundException(inputSql);
|
||||||
sql = genericDataService.replace(sql, "${currentUserHierarchy}",
|
}
|
||||||
currentUser.getOffice().getHierarchy());
|
|
||||||
// Allows sql query to restrict data by current user Id if required
|
@Override
|
||||||
// (typically used to return report lists containing only reports
|
public String getReportType(final String reportName) {
|
||||||
// permitted to be run by the user
|
|
||||||
sql = genericDataService.replace(sql, "${currentUserId}", currentUser
|
final String sql = "SELECT ifnull(report_type,'') as report_type FROM `stretchy_report` where report_name = '" + reportName + "'";
|
||||||
.getId().toString());
|
|
||||||
|
final String sqlWrapped = genericDataService.wrapSQL(sql);
|
||||||
sql = genericDataService.wrapSQL(sql);
|
|
||||||
|
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sqlWrapped);
|
||||||
return sql;
|
|
||||||
|
if (rs.next()) { return rs.getString("report_type"); }
|
||||||
}
|
throw new ReportNotFoundException(sql);
|
||||||
|
}
|
||||||
private String getSql(final String name, final String type) {
|
|
||||||
|
@Override
|
||||||
String inputSql = "select " + type + "_sql as the_sql from stretchy_"
|
public Response processPentahoRequest(final String reportName, final String outputTypeParam, final Map<String, String> queryParams) {
|
||||||
+ type + " where " + type + "_name = '" + name + "'";
|
|
||||||
inputSql = genericDataService.wrapSQL(inputSql);
|
String outputType = "HTML";
|
||||||
|
if (StringUtils.isNotBlank(outputTypeParam)) outputType = outputTypeParam;
|
||||||
String sqlErrorMsg = "Sql: " + inputSql;
|
|
||||||
CachedRowSet rs = genericDataService.getCachedResultSet(inputSql,
|
if (!(outputType.equalsIgnoreCase("HTML") || outputType.equalsIgnoreCase("PDF") || outputType.equalsIgnoreCase("XLS") || outputType
|
||||||
sqlErrorMsg);
|
.equalsIgnoreCase("CSV")))
|
||||||
|
throw new PlatformDataIntegrityException("error.msg.invalid.outputType", "No matching Output Type: " + outputType);
|
||||||
try {
|
|
||||||
if (rs.next()) {
|
if (noPentaho) { throw new PlatformDataIntegrityException("error.msg.no.pentaho", "Pentaho is not enabled",
|
||||||
return rs.getString("the_sql");
|
"Pentaho is not enabled"); }
|
||||||
}
|
|
||||||
throw new ReportNotFoundException(inputSql);
|
// TODO - JW - use pentaho location finder like Pawel does in Mifos
|
||||||
|
// String reportPath =
|
||||||
} catch (SQLException e) {
|
// "C:\\dev\\apache-tomcat-7.0.25\\webapps\\ROOT\\PentahoReports\\"
|
||||||
logger.info("msg: " + e.getMessage() + " sql: " + inputSql);
|
// + reportName + ".prpt";
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error",
|
/*
|
||||||
e.getMessage(), sqlErrorMsg);
|
* String reportPath = FileUtils.MIFOSX_BASE_DIR + File.separator +
|
||||||
}
|
* ThreadLocalContextUtil.getTenant().getName() .replaceAll(" ",
|
||||||
|
* "").trim() + File.separator + "reports" + File.separator + reportName
|
||||||
}
|
* + ".prpt";
|
||||||
|
*/
|
||||||
@Override
|
final String reportPath = FileUtils.MIFOSX_BASE_DIR + File.separator + "reports" + File.separator + reportName + ".prpt";
|
||||||
public String getReportType(final String reportName) {
|
logger.info("Report path: " + reportPath);
|
||||||
String sql = "SELECT ifnull(report_type,'') as report_type FROM `stretchy_report` where report_name = '"
|
|
||||||
+ reportName + "'";
|
// load report definition
|
||||||
|
ResourceManager manager = new ResourceManager();
|
||||||
sql = genericDataService.wrapSQL(sql);
|
manager.registerDefaults();
|
||||||
|
Resource res;
|
||||||
String sqlErrorMsg = "Report Name: " + reportName + " Sql: " + sql;
|
|
||||||
CachedRowSet rs = genericDataService.getCachedResultSet(sql,
|
try {
|
||||||
sqlErrorMsg);
|
res = manager.createDirectly(reportPath, MasterReport.class);
|
||||||
|
MasterReport masterReport = (MasterReport) res.getResource();
|
||||||
try {
|
|
||||||
|
addParametersToReport(masterReport, queryParams);
|
||||||
if (rs.next()) {
|
|
||||||
return rs.getString("report_type");
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
}
|
|
||||||
throw new ReportNotFoundException(sql);
|
if ("PDF".equalsIgnoreCase(outputType)) {
|
||||||
|
PdfReportUtil.createPDF(masterReport, baos);
|
||||||
} catch (SQLException e) {
|
return Response.ok().entity(baos.toByteArray()).type("application/pdf").build();
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error",
|
}
|
||||||
e.getMessage(), sqlErrorMsg);
|
|
||||||
}
|
if ("XLS".equalsIgnoreCase(outputType)) {
|
||||||
|
ExcelReportUtil.createXLS(masterReport, baos);
|
||||||
}
|
return Response.ok().entity(baos.toByteArray()).type("application/vnd.ms-excel")
|
||||||
|
.header("Content-Disposition", "attachment;filename=" + reportName.replaceAll(" ", "") + ".xls").build();
|
||||||
@Override
|
}
|
||||||
public Response processPentahoRequest(final String reportName,
|
|
||||||
final String outputTypeParam, final Map<String, String> queryParams) {
|
if ("CSV".equalsIgnoreCase(outputType)) {
|
||||||
|
CSVReportUtil.createCSV(masterReport, baos, "UTF-8");
|
||||||
String outputType = "HTML";
|
return Response.ok().entity(baos.toByteArray()).type("application/x-msdownload")
|
||||||
if (StringUtils.isNotBlank(outputTypeParam))
|
.header("Content-Disposition", "attachment;filename=" + reportName.replaceAll(" ", "") + ".csv").build();
|
||||||
outputType = outputTypeParam;
|
}
|
||||||
|
|
||||||
if (!(outputType.equalsIgnoreCase("HTML")
|
if ("HTML".equalsIgnoreCase(outputType)) {
|
||||||
|| outputType.equalsIgnoreCase("PDF")
|
HtmlReportUtil.createStreamHTML(masterReport, baos);
|
||||||
|| outputType.equalsIgnoreCase("XLS") || outputType
|
return Response.ok().entity(baos.toByteArray()).type("text/html").build();
|
||||||
.equalsIgnoreCase("CSV")))
|
}
|
||||||
throw new PlatformDataIntegrityException(
|
} catch (ResourceException e) {
|
||||||
"error.msg.invalid.outputType", "No matching Output Type: "
|
throw new PlatformDataIntegrityException("error.msg.reporting.error", e.getMessage());
|
||||||
+ outputType);
|
} catch (ReportProcessingException e) {
|
||||||
|
throw new PlatformDataIntegrityException("error.msg.reporting.error", e.getMessage());
|
||||||
if (noPentaho)
|
} catch (IOException e) {
|
||||||
throw new PlatformDataIntegrityException("error.msg.no.pentaho",
|
throw new PlatformDataIntegrityException("error.msg.reporting.error", e.getMessage());
|
||||||
"Pentaho is not enabled", "Pentaho is not enabled");
|
}
|
||||||
|
|
||||||
// TODO - JW - use pentaho location finder like Pawel does in Mifos
|
throw new PlatformDataIntegrityException("error.msg.invalid.outputType", "No matching Output Type: " + outputType);
|
||||||
// String reportPath =
|
}
|
||||||
// "C:\\dev\\apache-tomcat-7.0.25\\webapps\\ROOT\\PentahoReports\\"
|
|
||||||
// + reportName + ".prpt";
|
private void addParametersToReport(final MasterReport report, final Map<String, String> queryParams) {
|
||||||
/*String reportPath = FileUtils.MIFOSX_BASE_DIR
|
|
||||||
+ File.separator
|
AppUser currentUser = context.authenticatedUser();
|
||||||
+ ThreadLocalContextUtil.getTenant().getName()
|
|
||||||
.replaceAll(" ", "").trim() + File.separator
|
try {
|
||||||
+ "reports" + File.separator + reportName + ".prpt";*/
|
|
||||||
String reportPath = FileUtils.MIFOSX_BASE_DIR
|
logger.info("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||||||
+ File.separator
|
ReportParameterValues rptParamValues = report.getParameterValues();
|
||||||
+ "reports" + File.separator + reportName + ".prpt";
|
ReportParameterDefinition paramsDefinition = report.getParameterDefinition();
|
||||||
logger.info("Report path: " + reportPath);
|
|
||||||
|
/*
|
||||||
// load report definition
|
* only allow integer, long, date and string parameter types and
|
||||||
ResourceManager manager = new ResourceManager();
|
* assume all mandatory - could go more detailed like Pawel did in
|
||||||
manager.registerDefaults();
|
* Mifos later and could match incoming and pentaho parameters
|
||||||
Resource res;
|
* better... currently assuming they come in ok... and if not an
|
||||||
|
* error
|
||||||
try {
|
*/
|
||||||
res = manager.createDirectly(reportPath, MasterReport.class);
|
for (ParameterDefinitionEntry paramDefEntry : paramsDefinition.getParameterDefinitions()) {
|
||||||
MasterReport masterReport = (MasterReport) res.getResource();
|
String paramName = paramDefEntry.getName();
|
||||||
|
if (!((paramName.equals("tenantdb")) || (paramName.equals("userhierarchy")))) {
|
||||||
addParametersToReport(masterReport, queryParams);
|
logger.info("paramName:" + paramName);
|
||||||
|
String pValue = queryParams.get(paramName);
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
if (StringUtils.isBlank(pValue))
|
||||||
|
throw new PlatformDataIntegrityException("error.msg.reporting.error", "Pentaho Parameter: " + paramName
|
||||||
if ("PDF".equalsIgnoreCase(outputType)) {
|
+ " - not Provided");
|
||||||
PdfReportUtil.createPDF(masterReport, baos);
|
|
||||||
return Response.ok().entity(baos.toByteArray())
|
Class<?> clazz = paramDefEntry.getValueType();
|
||||||
.type("application/pdf").build();
|
logger.info("addParametersToReport(" + paramName + " : " + pValue + " : " + clazz.getCanonicalName() + ")");
|
||||||
}
|
if (clazz.getCanonicalName().equalsIgnoreCase("java.lang.Integer"))
|
||||||
|
rptParamValues.put(paramName, Integer.parseInt(pValue));
|
||||||
if ("XLS".equalsIgnoreCase(outputType)) {
|
else if (clazz.getCanonicalName().equalsIgnoreCase("java.lang.Long"))
|
||||||
ExcelReportUtil.createXLS(masterReport, baos);
|
rptParamValues.put(paramName, Long.parseLong(pValue));
|
||||||
return Response
|
else if (clazz.getCanonicalName().equalsIgnoreCase("java.sql.Date"))
|
||||||
.ok()
|
rptParamValues.put(paramName, Date.valueOf(pValue));
|
||||||
.entity(baos.toByteArray())
|
else
|
||||||
.type("application/vnd.ms-excel")
|
rptParamValues.put(paramName, pValue);
|
||||||
.header("Content-Disposition",
|
}
|
||||||
"attachment;filename="
|
|
||||||
+ reportName.replaceAll(" ", "")
|
// tenant database name and current user's office hierarchy
|
||||||
+ ".xls").build();
|
// passed as parameters to allow multitenant penaho reporting
|
||||||
}
|
// and
|
||||||
|
// data scoping
|
||||||
if ("CSV".equalsIgnoreCase(outputType)) {
|
String tenantdb = dataSource.getConnection().getCatalog();
|
||||||
CSVReportUtil.createCSV(masterReport, baos, "UTF-8");
|
String userhierarchy = currentUser.getOffice().getHierarchy();
|
||||||
return Response
|
logger.info("db name:" + tenantdb + " userhierarchy:" + userhierarchy);
|
||||||
.ok()
|
rptParamValues.put("tenantdb", tenantdb);
|
||||||
.entity(baos.toByteArray())
|
rptParamValues.put("userhierarchy", userhierarchy);
|
||||||
.type("application/x-msdownload")
|
}
|
||||||
.header("Content-Disposition",
|
|
||||||
"attachment;filename="
|
} catch (Exception e) {
|
||||||
+ reportName.replaceAll(" ", "")
|
logger.error("error.msg.reporting.error:" + e.getMessage());
|
||||||
+ ".csv").build();
|
throw new PlatformDataIntegrityException("error.msg.reporting.error", e.getMessage());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ("HTML".equalsIgnoreCase(outputType)) {
|
|
||||||
HtmlReportUtil.createStreamHTML(masterReport, baos);
|
@Override
|
||||||
return Response.ok().entity(baos.toByteArray())
|
public String retrieveReportPDF(final String reportName, final String type, final Map<String, String> queryParams) {
|
||||||
.type("text/html").build();
|
|
||||||
}
|
String fileLocation = FileUtils.MIFOSX_BASE_DIR + File.separator + "";
|
||||||
} catch (ResourceException e) {
|
if (!new File(fileLocation).isDirectory()) {
|
||||||
throw new PlatformDataIntegrityException(
|
new File(fileLocation).mkdirs();
|
||||||
"error.msg.reporting.error", e.getMessage());
|
}
|
||||||
} catch (ReportProcessingException e) {
|
|
||||||
throw new PlatformDataIntegrityException(
|
String genaratePdf = fileLocation + File.separator + reportName + ".pdf";
|
||||||
"error.msg.reporting.error", e.getMessage());
|
|
||||||
} catch (IOException e) {
|
try {
|
||||||
throw new PlatformDataIntegrityException(
|
GenericResultsetData result = retrieveGenericResultset(reportName, type, queryParams);
|
||||||
"error.msg.reporting.error", e.getMessage());
|
|
||||||
}
|
List<ResultsetColumnHeaderData> columnHeaders = result.getColumnHeaders();
|
||||||
|
List<ResultsetRowData> data = result.getData();
|
||||||
throw new PlatformDataIntegrityException(
|
List<String> row;
|
||||||
"error.msg.invalid.outputType", "No matching Output Type: "
|
|
||||||
+ outputType);
|
logger.info("NO. of Columns: " + columnHeaders.size());
|
||||||
|
Integer chSize = columnHeaders.size();
|
||||||
}
|
|
||||||
|
Document document = new Document(PageSize.B0.rotate());
|
||||||
private void addParametersToReport(final MasterReport report,
|
|
||||||
final Map<String, String> queryParams) {
|
PdfWriter.getInstance(document, new FileOutputStream(new File(fileLocation + reportName + ".pdf")));
|
||||||
|
document.open();
|
||||||
AppUser currentUser = context.authenticatedUser();
|
|
||||||
|
PdfPTable table = new PdfPTable(chSize);
|
||||||
try {
|
table.setWidthPercentage(100);
|
||||||
|
|
||||||
logger.info("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
for (int i = 0; i < chSize; i++) {
|
||||||
ReportParameterValues rptParamValues = report.getParameterValues();
|
|
||||||
ReportParameterDefinition paramsDefinition = report
|
table.addCell(columnHeaders.get(i).getColumnName());
|
||||||
.getParameterDefinition();
|
|
||||||
|
}
|
||||||
/*
|
table.completeRow();
|
||||||
* only allow integer, long, date and string parameter types and
|
|
||||||
* assume all mandatory - could go more detailed like Pawel did in
|
Integer rSize;
|
||||||
* Mifos later and could match incoming and pentaho parameters
|
String currColType;
|
||||||
* better... currently assuming they come in ok... and if not an
|
String currVal;
|
||||||
* error
|
logger.info("NO. of Rows: " + data.size());
|
||||||
*/
|
for (int i = 0; i < data.size(); i++) {
|
||||||
for (ParameterDefinitionEntry paramDefEntry : paramsDefinition
|
row = data.get(i).getRow();
|
||||||
.getParameterDefinitions()) {
|
rSize = row.size();
|
||||||
String paramName = paramDefEntry.getName();
|
for (int j = 0; j < rSize; j++) {
|
||||||
if (!((paramName.equals("tenantdb")) || (paramName.equals("userhierarchy")))) {
|
currColType = columnHeaders.get(j).getColumnType();
|
||||||
logger.info("paramName:" + paramName);
|
currVal = row.get(j);
|
||||||
String pValue = queryParams.get(paramName);
|
if (currVal != null) {
|
||||||
if (StringUtils.isBlank(pValue))
|
if (currColType.equals("DECIMAL") || currColType.equals("DOUBLE") || currColType.equals("BIGINT")
|
||||||
throw new PlatformDataIntegrityException(
|
|| currColType.equals("SMALLINT") || currColType.equals("INT")) {
|
||||||
"error.msg.reporting.error",
|
|
||||||
"Pentaho Parameter: " + paramName
|
table.addCell(currVal.toString());
|
||||||
+ " - not Provided");
|
} else {
|
||||||
|
table.addCell(currVal.toString());
|
||||||
Class<?> clazz = paramDefEntry.getValueType();
|
}
|
||||||
logger.info("addParametersToReport(" + paramName + " : "
|
}
|
||||||
+ pValue + " : " + clazz.getCanonicalName() + ")");
|
}
|
||||||
if (clazz.getCanonicalName().equalsIgnoreCase(
|
}
|
||||||
"java.lang.Integer"))
|
table.completeRow();
|
||||||
rptParamValues.put(paramName, Integer.parseInt(pValue));
|
document.add(table);
|
||||||
else if (clazz.getCanonicalName().equalsIgnoreCase(
|
document.close();
|
||||||
"java.lang.Long"))
|
return genaratePdf;
|
||||||
rptParamValues.put(paramName, Long.parseLong(pValue));
|
} catch (Exception e) {
|
||||||
else if (clazz.getCanonicalName().equalsIgnoreCase(
|
logger.error("error.msg.reporting.error:" + e.getMessage());
|
||||||
"java.sql.Date"))
|
throw new PlatformDataIntegrityException("error.msg.exception.error", e.getMessage());
|
||||||
rptParamValues.put(paramName, Date.valueOf(pValue));
|
}
|
||||||
else
|
}
|
||||||
rptParamValues.put(paramName, pValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tenant database name and current user's office hierarchy
|
|
||||||
// passed as parameters to allow multitenant penaho reporting and
|
|
||||||
// data scoping
|
|
||||||
String tenantdb = dataSource.getConnection().getCatalog();
|
|
||||||
String userhierarchy = currentUser.getOffice().getHierarchy();
|
|
||||||
logger.info("db name:" + tenantdb + " userhierarchy:" + userhierarchy);
|
|
||||||
rptParamValues.put("tenantdb", tenantdb);
|
|
||||||
rptParamValues.put("userhierarchy", userhierarchy);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
logger.info("error.msg.reporting.error:" + e.getMessage());
|
|
||||||
throw new PlatformDataIntegrityException(
|
|
||||||
"error.msg.reporting.error", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String retrieveReportPDF(final String reportName, final String type,
|
|
||||||
final Map<String, String> queryParams) {
|
|
||||||
|
|
||||||
String fileLocation = FileUtils.MIFOSX_BASE_DIR + File.separator + "";
|
|
||||||
if (!new File(fileLocation).isDirectory()) {
|
|
||||||
new File(fileLocation).mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
String genaratePdf = fileLocation + File.separator + reportName
|
|
||||||
+ ".pdf";
|
|
||||||
|
|
||||||
try {
|
|
||||||
GenericResultsetData result = retrieveGenericResultset(reportName,
|
|
||||||
type, queryParams);
|
|
||||||
|
|
||||||
List<ResultsetColumnHeader> columnHeaders = result
|
|
||||||
.getColumnHeaders();
|
|
||||||
List<ResultsetDataRow> data = result.getData();
|
|
||||||
List<String> row;
|
|
||||||
|
|
||||||
logger.info("NO. of Columns: " + columnHeaders.size());
|
|
||||||
Integer chSize = columnHeaders.size();
|
|
||||||
|
|
||||||
Document document = new Document(PageSize.B0.rotate());
|
|
||||||
|
|
||||||
PdfWriter.getInstance(document, new FileOutputStream(new File(
|
|
||||||
fileLocation + reportName + ".pdf")));
|
|
||||||
document.open();
|
|
||||||
|
|
||||||
PdfPTable table = new PdfPTable(chSize);
|
|
||||||
table.setWidthPercentage(100);
|
|
||||||
|
|
||||||
for (int i = 0; i < chSize; i++) {
|
|
||||||
|
|
||||||
table.addCell(columnHeaders.get(i).getColumnName());
|
|
||||||
|
|
||||||
}
|
|
||||||
table.completeRow();
|
|
||||||
|
|
||||||
Integer rSize;
|
|
||||||
String currColType;
|
|
||||||
String currVal;
|
|
||||||
logger.info("NO. of Rows: " + data.size());
|
|
||||||
for (int i = 0; i < data.size(); i++) {
|
|
||||||
row = data.get(i).getRow();
|
|
||||||
rSize = row.size();
|
|
||||||
for (int j = 0; j < rSize; j++) {
|
|
||||||
currColType = columnHeaders.get(j).getColumnType();
|
|
||||||
currVal = row.get(j);
|
|
||||||
if (currVal != null) {
|
|
||||||
if (currColType.equals("DECIMAL")
|
|
||||||
|| currColType.equals("DOUBLE")
|
|
||||||
|| currColType.equals("BIGINT")
|
|
||||||
|| currColType.equals("SMALLINT")
|
|
||||||
|| currColType.equals("INT")) {
|
|
||||||
|
|
||||||
table.addCell(currVal.toString());
|
|
||||||
} else {
|
|
||||||
table.addCell(currVal.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
table.completeRow();
|
|
||||||
document.add(table);
|
|
||||||
document.close();
|
|
||||||
return genaratePdf;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new PlatformDataIntegrityException(
|
|
||||||
"error.msg.exception.error", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+190
-255
@@ -7,8 +7,6 @@ package org.mifosplatform.infrastructure.dataqueries.service;
|
|||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.sql.ResultSetMetaData;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -16,7 +14,7 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.sql.rowset.CachedRowSet;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
@@ -26,17 +24,20 @@ import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidation
|
|||||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.JsonParserHelper;
|
import org.mifosplatform.infrastructure.core.serialization.JsonParserHelper;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.DatatableData;
|
import org.mifosplatform.infrastructure.dataqueries.data.DatatableData;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeader;
|
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnValue;
|
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetRowData;
|
||||||
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetDataRow;
|
|
||||||
import org.mifosplatform.infrastructure.dataqueries.exception.DataTableNotFoundException;
|
import org.mifosplatform.infrastructure.dataqueries.exception.DataTableNotFoundException;
|
||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.mifosplatform.useradministration.domain.AppUser;
|
import org.mifosplatform.useradministration.domain.AppUser;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.support.rowset.SqlRowSet;
|
||||||
|
import org.springframework.jdbc.support.rowset.SqlRowSetMetaData;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
@@ -46,18 +47,24 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(ReadWriteNonCoreDataServiceImpl.class);
|
private final static Logger logger = LoggerFactory.getLogger(ReadWriteNonCoreDataServiceImpl.class);
|
||||||
|
|
||||||
|
private final JdbcTemplate jdbcTemplate;
|
||||||
|
private final DataSource dataSource;
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
private final FromJsonHelper fromJsonHelper;
|
private final FromJsonHelper fromJsonHelper;
|
||||||
|
private final JsonParserHelper helper;
|
||||||
|
private final GenericDataService genericDataService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ReadWriteNonCoreDataServiceImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper) {
|
public ReadWriteNonCoreDataServiceImpl(final TenantAwareRoutingDataSource dataSource, final PlatformSecurityContext context,
|
||||||
|
final FromJsonHelper fromJsonHelper, final GenericDataService genericDataService) {
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
this.jdbcTemplate = new JdbcTemplate(this.dataSource);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.fromJsonHelper = fromJsonHelper;
|
this.fromJsonHelper = fromJsonHelper;
|
||||||
|
this.helper = new JsonParserHelper();
|
||||||
|
this.genericDataService = genericDataService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private GenericDataService genericDataService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DatatableData> retrieveDatatableNames(final String appTable) {
|
public List<DatatableData> retrieveDatatableNames(final String appTable) {
|
||||||
|
|
||||||
@@ -67,25 +74,23 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
} else {
|
} else {
|
||||||
andClause = " and application_table_name = '" + appTable + "'";
|
andClause = " and application_table_name = '" + appTable + "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
// PERMITTED datatables
|
// PERMITTED datatables
|
||||||
String sql = "select application_table_name, registered_table_name" + " from x_registered_table " + " where exists"
|
final String sql = "select application_table_name, registered_table_name" + " from x_registered_table " + " where exists"
|
||||||
+ " (select 'f'" + " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
|
+ " (select 'f'" + " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
|
||||||
+ " left join m_role_permission rp on rp.role_id = r.id" + " left join m_permission p on p.id = rp.permission_id"
|
+ " left join m_role_permission rp on rp.role_id = r.id" + " left join m_permission p on p.id = rp.permission_id"
|
||||||
+ " where ur.appuser_id = " + context.authenticatedUser().getId()
|
+ " where ur.appuser_id = " + context.authenticatedUser().getId()
|
||||||
+ " and (p.code in ('ALL_FUNCTIONS', 'ALL_FUNCTIONS_READ') or p.code = concat('READ_', registered_table_name))) "
|
+ " and (p.code in ('ALL_FUNCTIONS', 'ALL_FUNCTIONS_READ') or p.code = concat('READ_', registered_table_name))) "
|
||||||
+ andClause + " order by application_table_name, registered_table_name";
|
+ andClause + " order by application_table_name, registered_table_name";
|
||||||
|
|
||||||
String sqlErrorMsg = "Application Table Name: " + appTable + " sql: " + sql;
|
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sql);
|
||||||
CachedRowSet rs = genericDataService.getCachedResultSet(sql, sqlErrorMsg);
|
|
||||||
|
|
||||||
List<DatatableData> datatables = new ArrayList<DatatableData>();
|
final List<DatatableData> datatables = new ArrayList<DatatableData>();
|
||||||
try {
|
while (rs.next()) {
|
||||||
while (rs.next()) {
|
final String appTableName = rs.getString("application_table_name");
|
||||||
datatables.add(new DatatableData(rs.getString("application_table_name"), rs.getString("registered_table_name")));
|
final String registeredDatatableName = rs.getString("registered_table_name");
|
||||||
}
|
|
||||||
|
|
||||||
} catch (SQLException e) {
|
datatables.add(DatatableData.create(appTableName, registeredDatatableName));
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), sqlErrorMsg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return datatables;
|
return datatables;
|
||||||
@@ -96,63 +101,89 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
|
|
||||||
validateAppTable(appTable);
|
validateAppTable(appTable);
|
||||||
|
|
||||||
String createPermission = "'CREATE_" + datatable + "'";
|
final String createPermission = "'CREATE_" + datatable + "'";
|
||||||
String createPermissionChecker = "'CREATE_" + datatable + "_CHECKER'";
|
final String createPermissionChecker = "'CREATE_" + datatable + "_CHECKER'";
|
||||||
String readPermission = "'READ_" + datatable + "'";
|
final String readPermission = "'READ_" + datatable + "'";
|
||||||
String updatePermission = "'UPDATE_" + datatable + "'";
|
final String updatePermission = "'UPDATE_" + datatable + "'";
|
||||||
String updatePermissionChecker = "'UPDATE_" + datatable + "_CHECKER'";
|
final String updatePermissionChecker = "'UPDATE_" + datatable + "_CHECKER'";
|
||||||
String deletePermission = "'DELETE_" + datatable + "'";
|
final String deletePermission = "'DELETE_" + datatable + "'";
|
||||||
String deletePermissionChecker = "'DELETE_" + datatable + "_CHECKER'";
|
final String deletePermissionChecker = "'DELETE_" + datatable + "_CHECKER'";
|
||||||
// TODO - JW - put in batch command later
|
|
||||||
String sql = "insert into x_registered_table (registered_table_name, application_table_name) values ('" + datatable + "', '"
|
|
||||||
+ appTable + "')";
|
|
||||||
|
|
||||||
genericDataService.updateSQL(sql, "SQL: " + sql);
|
// TODO - JW - put in batch command later
|
||||||
/*
|
final String registerDatatableSql = "insert into x_registered_table (registered_table_name, application_table_name) values ('"
|
||||||
* add all permissions, including checker permissions for maintenance
|
+ datatable + "', '" + appTable + "')";
|
||||||
* tasks
|
|
||||||
*/
|
this.jdbcTemplate.update(registerDatatableSql);
|
||||||
sql = "insert into m_permission (grouping, code, action_name, entity_name, can_maker_checker) values " + "('datatable', "
|
|
||||||
+ createPermission + ", 'CREATE', '" + datatable + "', true)," + "('datatable', " + createPermissionChecker
|
final String permissionsSql = "insert into m_permission (grouping, code, action_name, entity_name, can_maker_checker) values "
|
||||||
+ ", 'CREATE', '" + datatable + "', false)," + "('datatable', " + readPermission + ", 'READ', '" + datatable + "', false),"
|
+ "('datatable', "
|
||||||
+ "('datatable', " + updatePermission + ", 'UPDATE', '" + datatable + "', true)," + "('datatable', "
|
+ createPermission
|
||||||
+ updatePermissionChecker + ", 'UPDATE', '" + datatable + "', false)," + "('datatable', " + deletePermission
|
+ ", 'CREATE', '"
|
||||||
+ ", 'DELETE', '" + datatable + "', true)," + "('datatable', " + deletePermissionChecker + ", 'DELETE', '" + datatable
|
+ datatable
|
||||||
|
+ "', true),"
|
||||||
|
+ "('datatable', "
|
||||||
|
+ createPermissionChecker
|
||||||
|
+ ", 'CREATE', '"
|
||||||
|
+ datatable
|
||||||
|
+ "', false),"
|
||||||
|
+ "('datatable', "
|
||||||
|
+ readPermission
|
||||||
|
+ ", 'READ', '"
|
||||||
|
+ datatable
|
||||||
|
+ "', false),"
|
||||||
|
+ "('datatable', "
|
||||||
|
+ updatePermission
|
||||||
|
+ ", 'UPDATE', '"
|
||||||
|
+ datatable
|
||||||
|
+ "', true),"
|
||||||
|
+ "('datatable', "
|
||||||
|
+ updatePermissionChecker
|
||||||
|
+ ", 'UPDATE', '"
|
||||||
|
+ datatable
|
||||||
|
+ "', false),"
|
||||||
|
+ "('datatable', "
|
||||||
|
+ deletePermission
|
||||||
|
+ ", 'DELETE', '"
|
||||||
|
+ datatable
|
||||||
|
+ "', true),"
|
||||||
|
+ "('datatable', "
|
||||||
|
+ deletePermissionChecker
|
||||||
|
+ ", 'DELETE', '"
|
||||||
|
+ datatable
|
||||||
+ "', false)";
|
+ "', false)";
|
||||||
|
|
||||||
genericDataService.updateSQL(sql, "SQL: " + sql);
|
this.jdbcTemplate.update(permissionsSql);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deregisterDatatable(final String datatable) {
|
public void deregisterDatatable(final String datatable) {
|
||||||
// TODO - JW - put in batch command later
|
// TODO - JW - put in batch command later
|
||||||
|
final String permissionList = "('CREATE_" + datatable + "', 'CREATE_" + datatable + "_CHECKER', 'READ_" + datatable + "', 'UPDATE_"
|
||||||
String permissionList = "('CREATE_" + datatable + "', 'CREATE_" + datatable + "_CHECKER', 'READ_" + datatable + "', 'UPDATE_"
|
|
||||||
+ datatable + "', 'UPDATE_" + datatable + "_CHECKER', 'DELETE_" + datatable + "', 'DELETE_" + datatable + "_CHECKER')";
|
+ datatable + "', 'UPDATE_" + datatable + "_CHECKER', 'DELETE_" + datatable + "', 'DELETE_" + datatable + "_CHECKER')";
|
||||||
|
|
||||||
String sql = "delete from m_role_permission where m_role_permission.permission_id in (select id from m_permission where code in "
|
String sql = "delete from m_role_permission where m_role_permission.permission_id in (select id from m_permission where code in "
|
||||||
+ permissionList + ")";
|
+ permissionList + ")";
|
||||||
genericDataService.updateSQL(sql, "SQL: " + sql);
|
this.jdbcTemplate.update(sql);
|
||||||
|
|
||||||
sql = "delete from m_permission where code in " + permissionList;
|
sql = "delete from m_permission where code in " + permissionList;
|
||||||
genericDataService.updateSQL(sql, "SQL: " + sql);
|
this.jdbcTemplate.update(sql);
|
||||||
|
|
||||||
sql = "delete from x_registered_table where registered_table_name = '" + datatable + "'";
|
sql = "delete from x_registered_table where registered_table_name = '" + datatable + "'";
|
||||||
genericDataService.updateSQL(sql, "SQL: " + sql);
|
this.jdbcTemplate.update(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void newDatatableEntry(final String datatable, final Long appTableId, final JsonCommand command) {
|
public void newDatatableEntry(final String datatable, final Long appTableId, final JsonCommand command) {
|
||||||
String appTable = getWithinScopeApplicationTableName(datatable, appTableId);
|
String appTable = getWithinScopeApplicationTableName(datatable, appTableId);
|
||||||
|
|
||||||
List<ResultsetColumnHeader> columnHeaders = getDatatableResultsetColumnHeaders(datatable);
|
final List<ResultsetColumnHeaderData> columnHeaders = this.genericDataService.fillResultsetColumnHeaders(datatable);
|
||||||
|
|
||||||
final Type typeOfMap = new TypeToken<Map<String, String>>() {}.getType();
|
final Type typeOfMap = new TypeToken<Map<String, String>>() {}.getType();
|
||||||
Map<String, String> dataParams = this.fromJsonHelper.extractDataMap(typeOfMap, command.json());
|
final Map<String, String> dataParams = this.fromJsonHelper.extractDataMap(typeOfMap, command.json());
|
||||||
|
|
||||||
String sql = getAddSql(columnHeaders, datatable, getFKField(appTable), appTableId, dataParams);
|
final String sql = getAddSql(columnHeaders, datatable, getFKField(appTable), appTableId, dataParams);
|
||||||
|
|
||||||
genericDataService.updateSQL(sql, "SQL: " + sql);
|
this.jdbcTemplate.update(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -166,7 +197,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
throw new PlatformDataIntegrityException("error.msg.attempting.multiple.update", "Application Table: " + datatable
|
throw new PlatformDataIntegrityException("error.msg.attempting.multiple.update", "Application Table: " + datatable
|
||||||
+ " Foreign Key Id: " + appTableId);
|
+ " Foreign Key Id: " + appTableId);
|
||||||
|
|
||||||
String fkName = getFKField(getApplicationTableName(datatable));
|
String fkName = getFKField(queryForApplicationTableName(datatable));
|
||||||
|
|
||||||
final Type typeOfMap = new TypeToken<Map<String, String>>() {}.getType();
|
final Type typeOfMap = new TypeToken<Map<String, String>>() {}.getType();
|
||||||
Map<String, String> dataParams = this.fromJsonHelper.extractDataMap(typeOfMap, command.json());
|
Map<String, String> dataParams = this.fromJsonHelper.extractDataMap(typeOfMap, command.json());
|
||||||
@@ -175,10 +206,10 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
|
|
||||||
if (changes.size() == 0) return changes;
|
if (changes.size() == 0) return changes;
|
||||||
|
|
||||||
String sql = getUpdateSql(datatable, fkName, appTableId, changes);
|
final String sql = getUpdateSql(datatable, fkName, appTableId, changes);
|
||||||
|
|
||||||
if (sql != null) {
|
if (StringUtils.isNotBlank(sql)) {
|
||||||
genericDataService.updateSQL(sql, "SQL: " + sql);
|
this.jdbcTemplate.update(sql);
|
||||||
} else {
|
} else {
|
||||||
logger.info("No Changes");
|
logger.info("No Changes");
|
||||||
}
|
}
|
||||||
@@ -190,21 +221,21 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
public Map<String, Object> updateDatatableEntryOneToMany(final String datatable, final Long appTableId, final Long datatableId,
|
public Map<String, Object> updateDatatableEntryOneToMany(final String datatable, final Long appTableId, final Long datatableId,
|
||||||
final JsonCommand command) {
|
final JsonCommand command) {
|
||||||
|
|
||||||
GenericResultsetData grs = retrieveDataTableGenericResultSet(datatable, appTableId, null, datatableId);
|
final GenericResultsetData grs = retrieveDataTableGenericResultSet(datatable, appTableId, null, datatableId);
|
||||||
|
|
||||||
if (grs.getData().size() == 0) throw new DataTableNotFoundException(datatable, appTableId);
|
if (grs.getData().size() == 0) throw new DataTableNotFoundException(datatable, appTableId);
|
||||||
|
|
||||||
final Type typeOfMap = new TypeToken<Map<String, String>>() {}.getType();
|
final Type typeOfMap = new TypeToken<Map<String, String>>() {}.getType();
|
||||||
Map<String, String> dataParams = this.fromJsonHelper.extractDataMap(typeOfMap, command.json());
|
final Map<String, String> dataParams = this.fromJsonHelper.extractDataMap(typeOfMap, command.json());
|
||||||
|
|
||||||
final Map<String, Object> changes = getAffectedAndChangedColumns(grs, dataParams, "id");
|
final Map<String, Object> changes = getAffectedAndChangedColumns(grs, dataParams, "id");
|
||||||
|
|
||||||
if (changes.size() == 0) return changes;
|
if (changes.size() == 0) return changes;
|
||||||
|
|
||||||
String sql = getUpdateSql(datatable, "id", datatableId, changes);
|
final String sql = getUpdateSql(datatable, "id", datatableId, changes);
|
||||||
|
|
||||||
if (sql != null) {
|
if (StringUtils.isNotBlank(sql)) {
|
||||||
genericDataService.updateSQL(sql, "SQL: " + sql);
|
this.jdbcTemplate.update(sql);
|
||||||
} else {
|
} else {
|
||||||
logger.info("No Changes");
|
logger.info("No Changes");
|
||||||
}
|
}
|
||||||
@@ -215,11 +246,11 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
@Override
|
@Override
|
||||||
public void deleteDatatableEntries(final String datatable, final Long appTableId) {
|
public void deleteDatatableEntries(final String datatable, final Long appTableId) {
|
||||||
|
|
||||||
String appTable = getWithinScopeApplicationTableName(datatable, appTableId);
|
final String appTable = getWithinScopeApplicationTableName(datatable, appTableId);
|
||||||
|
|
||||||
String sql = getDeleteEntriesSql(datatable, getFKField(appTable), appTableId);
|
final String sql = getDeleteEntriesSql(datatable, getFKField(appTable), appTableId);
|
||||||
|
|
||||||
genericDataService.updateSQL(sql, "SQL: " + sql);
|
this.jdbcTemplate.update(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -227,18 +258,18 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
|
|
||||||
getWithinScopeApplicationTableName(datatable, appTableId);
|
getWithinScopeApplicationTableName(datatable, appTableId);
|
||||||
|
|
||||||
String sql = getDeleteEntrySql(datatable, datatableId);
|
final String sql = getDeleteEntrySql(datatable, datatableId);
|
||||||
|
|
||||||
genericDataService.updateSQL(sql, "SQL: " + sql);
|
this.jdbcTemplate.update(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GenericResultsetData retrieveDataTableGenericResultSet(final String datatable, final Long appTableId, final String order,
|
public GenericResultsetData retrieveDataTableGenericResultSet(final String datatable, final Long appTableId, final String order,
|
||||||
final Long id) {
|
final Long id) {
|
||||||
|
|
||||||
String appTable = getWithinScopeApplicationTableName(datatable, appTableId);
|
final String appTable = getWithinScopeApplicationTableName(datatable, appTableId);
|
||||||
|
|
||||||
List<ResultsetColumnHeader> columnHeaders = getDatatableResultsetColumnHeaders(datatable);
|
final List<ResultsetColumnHeaderData> columnHeaders = this.genericDataService.fillResultsetColumnHeaders(datatable);
|
||||||
|
|
||||||
String sql = "";
|
String sql = "";
|
||||||
|
|
||||||
@@ -252,20 +283,20 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
|
|
||||||
if (order != null) sql = sql + " order by " + order;
|
if (order != null) sql = sql + " order by " + order;
|
||||||
|
|
||||||
List<ResultsetDataRow> result = fillDatatableResultSetDataRows(sql);
|
List<ResultsetRowData> result = fillDatatableResultSetDataRows(sql);
|
||||||
|
|
||||||
return new GenericResultsetData(columnHeaders, result);
|
return new GenericResultsetData(columnHeaders, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkMainResourceExistsWithinScope(final String appTable, final Long appTableId) {
|
private void checkMainResourceExistsWithinScope(final String appTable, final Long appTableId) {
|
||||||
|
|
||||||
String unscopedSql = "select t.id from `" + appTable + "` t ${dataScopeCriteria} where t.id = " + appTableId;
|
final String unscopedSql = "select t.id from `" + appTable + "` t ${dataScopeCriteria} where t.id = " + appTableId;
|
||||||
|
|
||||||
String sql = dataScopedSQL(unscopedSql, appTable);
|
final String sql = dataScopedSQL(unscopedSql, appTable);
|
||||||
|
|
||||||
CachedRowSet rs = genericDataService.getCachedResultSet(sql, "SQL : " + sql);
|
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sql);
|
||||||
|
|
||||||
if (rs.size() == 0) throw new DataTableNotFoundException(appTable, appTableId);
|
if (!rs.next()) { throw new DataTableNotFoundException(appTable, appTableId); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private String dataScopedSQL(final String unscopedSQL, final String appTable) {
|
private String dataScopedSQL(final String unscopedSQL, final String appTable) {
|
||||||
@@ -303,74 +334,50 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
throw new PlatformDataIntegrityException("error.msg.invalid.application.table", "Invalid Application Table: " + appTable);
|
throw new PlatformDataIntegrityException("error.msg.invalid.application.table", "Invalid Application Table: " + appTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ResultsetDataRow> fillDatatableResultSetDataRows(final String sql) {
|
private List<ResultsetRowData> fillDatatableResultSetDataRows(final String sql) {
|
||||||
|
|
||||||
String sqlErrorMsg = "Sql: " + sql;
|
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sql);
|
||||||
CachedRowSet rs = genericDataService.getCachedResultSet(sql, sqlErrorMsg);
|
|
||||||
|
|
||||||
List<ResultsetDataRow> resultsetDataRows = new ArrayList<ResultsetDataRow>();
|
final List<ResultsetRowData> resultsetDataRows = new ArrayList<ResultsetRowData>();
|
||||||
|
|
||||||
try {
|
final SqlRowSetMetaData rsmd = rs.getMetaData();
|
||||||
|
|
||||||
ResultSetMetaData rsmd = rs.getMetaData();
|
while (rs.next()) {
|
||||||
int columnCount = rsmd.getColumnCount();
|
final List<String> columnValues = new ArrayList<String>();
|
||||||
|
for (int i = 0; i < rsmd.getColumnCount(); i++) {
|
||||||
ResultsetDataRow resultsetDataRow;
|
final String columnName = rsmd.getColumnName(i + 1);
|
||||||
String columnName = null;
|
final String columnValue = rs.getString(columnName);
|
||||||
String columnValue = null;
|
columnValues.add(columnValue);
|
||||||
while (rs.next()) {
|
|
||||||
resultsetDataRow = new ResultsetDataRow();
|
|
||||||
List<String> columnValues = new ArrayList<String>();
|
|
||||||
for (int i = 0; i < columnCount; i++) {
|
|
||||||
columnName = rsmd.getColumnName(i + 1);
|
|
||||||
columnValue = rs.getString(columnName);
|
|
||||||
columnValues.add(columnValue);
|
|
||||||
}
|
|
||||||
resultsetDataRow.setRow(columnValues);
|
|
||||||
resultsetDataRows.add(resultsetDataRow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultsetDataRows;
|
final ResultsetRowData resultsetDataRow = ResultsetRowData.create(columnValues);
|
||||||
} catch (SQLException e) {
|
resultsetDataRows.add(resultsetDataRow);
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), sqlErrorMsg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return resultsetDataRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getWithinScopeApplicationTableName(final String datatable, final Long appTableId) {
|
private String getWithinScopeApplicationTableName(final String datatable, final Long appTableId) {
|
||||||
String sql = "SELECT application_table_name FROM x_registered_table where registered_table_name = '" + datatable + "'";
|
|
||||||
|
|
||||||
CachedRowSet rs = genericDataService.getCachedResultSet(sql, "SQL : " + sql);
|
final String applicationTableName = queryForApplicationTableName(datatable);
|
||||||
|
checkMainResourceExistsWithinScope(applicationTableName, appTableId);
|
||||||
|
|
||||||
if (rs.size() == 0) throw new DataTableNotFoundException(datatable);
|
return applicationTableName;
|
||||||
|
|
||||||
try {
|
|
||||||
rs.next();
|
|
||||||
String appTable = rs.getString("application_table_name");
|
|
||||||
|
|
||||||
checkMainResourceExistsWithinScope(appTable, appTableId);
|
|
||||||
|
|
||||||
return appTable;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getApplicationTableName(final String datatable) {
|
private String queryForApplicationTableName(final String datatable) {
|
||||||
// TODO - JW - only used for update... can probably remove this after as
|
final String sql = "SELECT application_table_name FROM x_registered_table where registered_table_name = '" + datatable + "'";
|
||||||
// its
|
|
||||||
// a reread
|
|
||||||
String sql = "SELECT application_table_name FROM x_registered_table where registered_table_name = '" + datatable + "'";
|
|
||||||
|
|
||||||
CachedRowSet rs = genericDataService.getCachedResultSet(sql, "SQL : " + sql);
|
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sql);
|
||||||
|
|
||||||
if (rs.size() == 0) throw new DataTableNotFoundException(datatable);
|
String applicationTableName = null;
|
||||||
|
if (rs.next()) {
|
||||||
try {
|
applicationTableName = rs.getString("application_table_name");
|
||||||
rs.next();
|
} else {
|
||||||
return rs.getString("application_table_name");
|
throw new DataTableNotFoundException(datatable);
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return applicationTableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFKField(final String applicationTableName) {
|
private String getFKField(final String applicationTableName) {
|
||||||
@@ -378,89 +385,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
return applicationTableName.substring(2) + "_id";
|
return applicationTableName.substring(2) + "_id";
|
||||||
}
|
}
|
||||||
|
|
||||||
private CachedRowSet getDatatableMetaData(final String datatable) {
|
private String getAddSql(final List<ResultsetColumnHeaderData> columnHeaders, final String datatable, final String fkName,
|
||||||
|
|
||||||
String sql = "select COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMN_KEY"
|
|
||||||
+ " from INFORMATION_SCHEMA.COLUMNS " + " where TABLE_SCHEMA = schema() and TABLE_NAME = '" + datatable
|
|
||||||
+ "'order by ORDINAL_POSITION";
|
|
||||||
|
|
||||||
CachedRowSet columnDefinitions = genericDataService.getCachedResultSet(sql, "SQL: " + sql);
|
|
||||||
|
|
||||||
if (columnDefinitions.size() > 0) return columnDefinitions;
|
|
||||||
|
|
||||||
throw new DataTableNotFoundException(datatable);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ResultsetColumnHeader> getDatatableResultsetColumnHeaders(final String datatable) {
|
|
||||||
|
|
||||||
CachedRowSet columnDefinitions = getDatatableMetaData(datatable);
|
|
||||||
|
|
||||||
List<ResultsetColumnHeader> columnHeaders = new ArrayList<ResultsetColumnHeader>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
while (columnDefinitions.next()) {
|
|
||||||
ResultsetColumnHeader rsch = new ResultsetColumnHeader();
|
|
||||||
|
|
||||||
rsch.setColumnName(columnDefinitions.getString("COLUMN_NAME"));
|
|
||||||
|
|
||||||
String isNullable = columnDefinitions.getString("IS_NULLABLE");
|
|
||||||
if (isNullable.equalsIgnoreCase("YES"))
|
|
||||||
rsch.setColumnNullable(true);
|
|
||||||
else
|
|
||||||
rsch.setColumnNullable(false);
|
|
||||||
|
|
||||||
String isPrimaryKey = columnDefinitions.getString("COLUMN_KEY");
|
|
||||||
if (isPrimaryKey.equalsIgnoreCase("PRI"))
|
|
||||||
rsch.setColumnPrimaryKey(true);
|
|
||||||
else
|
|
||||||
rsch.setColumnPrimaryKey(false);
|
|
||||||
|
|
||||||
Long columnLength = columnDefinitions.getLong("CHARACTER_MAXIMUM_LENGTH");
|
|
||||||
if (columnLength > 0) rsch.setColumnLength(columnDefinitions.getLong("CHARACTER_MAXIMUM_LENGTH"));
|
|
||||||
|
|
||||||
rsch.setColumnType(columnDefinitions.getString("DATA_TYPE"));
|
|
||||||
|
|
||||||
/* look for codes */
|
|
||||||
if (rsch.getColumnType().equalsIgnoreCase("varchar")) addCodesValueIfNecessary(rsch, "_cv");
|
|
||||||
|
|
||||||
if (rsch.getColumnType().equalsIgnoreCase("int")) addCodesValueIfNecessary(rsch, "_cd");
|
|
||||||
|
|
||||||
rsch.setColumnDisplayType();
|
|
||||||
|
|
||||||
columnHeaders.add(rsch);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
return columnHeaders;
|
|
||||||
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addCodesValueIfNecessary(final ResultsetColumnHeader rsch, final String code_suffix) {
|
|
||||||
int codePosition = rsch.getColumnName().indexOf(code_suffix);
|
|
||||||
if (codePosition > 0) {
|
|
||||||
String codeName = rsch.getColumnName().substring(0, codePosition);
|
|
||||||
|
|
||||||
String sql = "select v.id, v.code_value from m_code m " + " join m_code_value v on v.code_id = m.id "
|
|
||||||
+ " where m.code_name = '" + codeName + "' order by v.order_position, v.id";
|
|
||||||
|
|
||||||
CachedRowSet rsValues = genericDataService.getCachedResultSet(sql, "SQL: " + sql);
|
|
||||||
|
|
||||||
try {
|
|
||||||
while (rsValues.next()) {
|
|
||||||
rsch.getColumnValues().add(new ResultsetColumnValue(rsValues.getInt("id"), rsValues.getString("code_value")));
|
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getAddSql(final List<ResultsetColumnHeader> columnHeaders, final String datatable, final String fkName,
|
|
||||||
final Long appTableId, final Map<String, String> queryParams) {
|
final Long appTableId, final Map<String, String> queryParams) {
|
||||||
|
|
||||||
final Map<String, String> affectedColumns = getAffectedColumns(columnHeaders, queryParams, fkName);
|
final Map<String, String> affectedColumns = getAffectedColumns(columnHeaders, queryParams, fkName);
|
||||||
@@ -573,8 +498,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
throw new PlatformDataIntegrityException("error.msg.invalid.columnName", "Parameter Column Name: " + key + " not found");
|
throw new PlatformDataIntegrityException("error.msg.invalid.columnName", "Parameter Column Name: " + key + " not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> getAffectedColumns(final List<ResultsetColumnHeader> columnHeaders, final Map<String, String> queryParams,
|
private Map<String, String> getAffectedColumns(final List<ResultsetColumnHeaderData> columnHeaders,
|
||||||
final String keyFieldName) {
|
final Map<String, String> queryParams, final String keyFieldName) {
|
||||||
|
|
||||||
String dateFormat = queryParams.get("dateFormat");
|
String dateFormat = queryParams.get("dateFormat");
|
||||||
Locale clientApplicationLocale = null;
|
Locale clientApplicationLocale = null;
|
||||||
@@ -600,7 +525,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
// matches incoming fields with and without underscores (spaces
|
// matches incoming fields with and without underscores (spaces
|
||||||
// and underscores considered the same)
|
// and underscores considered the same)
|
||||||
queryParamColumnUnderscored = genericDataService.replace(key, space, underscore);
|
queryParamColumnUnderscored = genericDataService.replace(key, space, underscore);
|
||||||
for (ResultsetColumnHeader columnHeader : columnHeaders) {
|
for (ResultsetColumnHeaderData columnHeader : columnHeaders) {
|
||||||
if (notFound) {
|
if (notFound) {
|
||||||
columnHeaderUnderscored = genericDataService.replace(columnHeader.getColumnName(), space, underscore);
|
columnHeaderUnderscored = genericDataService.replace(columnHeader.getColumnName(), space, underscore);
|
||||||
if (queryParamColumnUnderscored.equalsIgnoreCase(columnHeaderUnderscored)) {
|
if (queryParamColumnUnderscored.equalsIgnoreCase(columnHeaderUnderscored)) {
|
||||||
@@ -618,74 +543,84 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
|||||||
return affectedColumns;
|
return affectedColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String validateColumn(final ResultsetColumnHeader columnHeader, final String pValue, final String dateFormat,
|
private String validateColumn(final ResultsetColumnHeaderData columnHeader, final String pValue, final String dateFormat,
|
||||||
final Locale clientApplicationLocale) {
|
final Locale clientApplicationLocale) {
|
||||||
|
|
||||||
String paramValue = pValue;
|
String paramValue = pValue;
|
||||||
if ((columnHeader.getColumnDisplayType().equals("DATE")) || (columnHeader.getColumnDisplayType().equals("INTEGER"))
|
if (columnHeader.isDateDisplayType() || columnHeader.isIntegerDisplayType() || columnHeader.isDecimalDisplayType()) {
|
||||||
|| (columnHeader.getColumnDisplayType().equals("DECIMAL"))) paramValue = paramValue.trim();
|
paramValue = paramValue.trim();
|
||||||
|
}
|
||||||
|
|
||||||
if ((StringUtils.isEmpty(paramValue)) && (!(columnHeader.isColumnNullable()))) {
|
if (StringUtils.isEmpty(paramValue) && columnHeader.isMandatory()) {
|
||||||
|
|
||||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
ApiParameterError error = ApiParameterError.parameterError("error.msg.column.mandatory", "Mandatory",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.column.mandatory", "Mandatory",
|
||||||
columnHeader.getColumnName());
|
columnHeader.getColumnName());
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||||
dataValidationErrors);
|
dataValidationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!StringUtils.isEmpty(paramValue)) {
|
if (StringUtils.isNotEmpty(paramValue)) {
|
||||||
|
|
||||||
if (columnHeader.getColumnValues().size() > 0) {
|
if (columnHeader.hasColumnValues()) {
|
||||||
// match code value or id
|
if (columnHeader.isCodeValueDisplayType()) {
|
||||||
List<ResultsetColumnValue> allowedValues = columnHeader.getColumnValues();
|
|
||||||
if (columnHeader.getColumnDisplayType().equals("CODEVALUE")) {
|
if (columnHeader.isColumnValueNotAllowed(paramValue)) {
|
||||||
for (ResultsetColumnValue allowedValue : allowedValues) {
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
if (paramValue.equalsIgnoreCase(allowedValue.getValue())) return paramValue;
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.invalid.columnValue",
|
||||||
|
"Value not found in Allowed Value list", columnHeader.getColumnName(), paramValue);
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||||
|
dataValidationErrors);
|
||||||
}
|
}
|
||||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
|
||||||
ApiParameterError error = ApiParameterError.parameterError("error.msg.invalid.columnValue",
|
|
||||||
"Value not found in Allowed Value list", columnHeader.getColumnName(), paramValue);
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
|
||||||
dataValidationErrors);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (columnHeader.getColumnDisplayType().equals("CODELOOKUP")) {
|
return paramValue;
|
||||||
for (ResultsetColumnValue allowedValue : allowedValues) {
|
} else if (columnHeader.isCodeLookupDisplayType()) {
|
||||||
if (paramValue.equals(Integer.toString(allowedValue.getId()))) return paramValue;
|
|
||||||
|
final Integer codeLookup = Integer.valueOf(paramValue);
|
||||||
|
if (columnHeader.isColumnCodeNotAllowed(codeLookup)) {
|
||||||
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.invalid.columnValue",
|
||||||
|
"Value not found in Allowed Value list", columnHeader.getColumnName(), paramValue);
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||||
|
dataValidationErrors);
|
||||||
}
|
}
|
||||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
|
||||||
ApiParameterError error = ApiParameterError.parameterError("error.msg.invalid.columnValue",
|
|
||||||
"Value not found in Allowed Value list", columnHeader.getColumnName(), paramValue);
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
|
||||||
dataValidationErrors);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.invalid.columnType.", "Code: " + columnHeader.getColumnName()
|
return paramValue;
|
||||||
+ " - Invalid Type " + columnHeader.getColumnType() + " (neither varchar nor int)");
|
} else {
|
||||||
|
throw new PlatformDataIntegrityException("error.msg.invalid.columnType.", "Code: " + columnHeader.getColumnName()
|
||||||
|
+ " - Invalid Type " + columnHeader.getColumnType() + " (neither varchar nor int)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonParserHelper helper = new JsonParserHelper();
|
if (columnHeader.isDateDisplayType()) {
|
||||||
|
final LocalDate tmpDate = helper.convertFrom(paramValue, columnHeader.getColumnName(), dateFormat, clientApplicationLocale);
|
||||||
if (columnHeader.getColumnDisplayType().equals("DATE")) {
|
if (tmpDate == null) {
|
||||||
LocalDate tmpDate = helper.convertFrom(paramValue, columnHeader.getColumnName(), dateFormat, clientApplicationLocale);
|
paramValue = null;
|
||||||
if (tmpDate == null) return null;
|
} else {
|
||||||
return tmpDate.toString();
|
paramValue = tmpDate.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (columnHeader.getColumnDisplayType().equals("INTEGER")) {
|
|
||||||
|
if (columnHeader.isIntegerDisplayType()) {
|
||||||
Integer tmpInt = helper.convertToInteger(paramValue, columnHeader.getColumnName(), clientApplicationLocale);
|
Integer tmpInt = helper.convertToInteger(paramValue, columnHeader.getColumnName(), clientApplicationLocale);
|
||||||
if (tmpInt == null) return null;
|
if (tmpInt == null) {
|
||||||
return tmpInt.toString();
|
paramValue = null;
|
||||||
}
|
} else {
|
||||||
if (columnHeader.getColumnDisplayType().equals("DECIMAL")) {
|
paramValue = tmpInt.toString();
|
||||||
BigDecimal tmpDecimal = helper.convertFrom(paramValue, columnHeader.getColumnName(), clientApplicationLocale);
|
}
|
||||||
if (tmpDecimal == null) return null;
|
|
||||||
return tmpDecimal.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (columnHeader.isDecimalDisplayType()) {
|
||||||
|
BigDecimal tmpDecimal = helper.convertFrom(paramValue, columnHeader.getColumnName(), clientApplicationLocale);
|
||||||
|
if (tmpDecimal == null) {
|
||||||
|
paramValue = null;
|
||||||
|
} else {
|
||||||
|
paramValue = tmpDecimal.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return paramValue;
|
return paramValue;
|
||||||
|
|||||||
Reference in New Issue
Block a user