wip data tables

This commit is contained in:
John Woodlock
2012-09-23 17:38:56 +10:00
parent 1a83d07c1c
commit 4ef70d0d78
2 changed files with 305 additions and 45 deletions
@@ -32,7 +32,6 @@ import org.mifosng.platform.api.infrastructure.ApiParameterHelper;
import org.mifosng.platform.exceptions.NoAuthorizationException; import org.mifosng.platform.exceptions.NoAuthorizationException;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException; import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.mifosng.platform.noncore.AdditionalFieldsService; import org.mifosng.platform.noncore.AdditionalFieldsService;
import org.mifosng.platform.noncore.ReadWriteNonCoreDataService;
import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.security.PlatformSecurityContext;
import org.mifosng.platform.user.domain.AppUser; import org.mifosng.platform.user.domain.AppUser;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -1,16 +1,24 @@
package org.mifosng.platform.noncore; package org.mifosng.platform.noncore;
import java.math.BigDecimal;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
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.rowset.CachedRowSet;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.mifosng.platform.api.data.ApiParameterError; import org.mifosng.platform.api.data.ApiParameterError;
import org.mifosng.platform.api.data.DatatableData; import org.mifosng.platform.api.data.DatatableData;
import org.mifosng.platform.api.data.GenericResultsetData; import org.mifosng.platform.api.data.GenericResultsetData;
@@ -25,6 +33,7 @@ import org.mifosng.platform.user.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.format.number.NumberFormatter;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
@@ -537,6 +546,7 @@ public class ReadWriteNonCoreDataServiceImpl implements
|| currColType.equals("DOUBLE") || currColType.equals("DOUBLE")
|| currColType.equals("BIGINT") || currColType.equals("BIGINT")
|| currColType.equals("SMALLINT") || currColType.equals("SMALLINT")
|| currColType.equals("TINYINT")
|| currColType.equals("INT")) || currColType.equals("INT"))
writer.append(currVal); writer.append(currVal);
else else
@@ -693,6 +703,12 @@ public class ReadWriteNonCoreDataServiceImpl implements
List<ResultsetColumnHeader> columnHeaders, List<ResultsetColumnHeader> columnHeaders,
Map<String, String> queryParams, String keyFieldName) { Map<String, String> queryParams, String keyFieldName) {
String dateFormat = queryParams.get("dateFormat");
Locale clientApplicationLocale = null;
String localeQueryParam = queryParams.get("locale");
if (!(StringUtils.isBlank(localeQueryParam)))
clientApplicationLocale = new Locale(queryParams.get("locale"));
String underscore = "_"; String underscore = "_";
String space = " "; String space = " ";
String pValue = null; String pValue = null;
@@ -708,8 +724,7 @@ public class ReadWriteNonCoreDataServiceImpl implements
// validating numeric and date data // validating numeric and date data
if (!((key.equalsIgnoreCase("id")) if (!((key.equalsIgnoreCase("id"))
|| (key.equalsIgnoreCase(keyFieldName)) || (key.equalsIgnoreCase(keyFieldName))
|| (key.equalsIgnoreCase("locale")) || (key || (key.equals("locale")) || (key.equals("dateFormat")))) {
.equalsIgnoreCase("dateformat")))) {
notFound = true; notFound = true;
// 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)
@@ -723,7 +738,8 @@ public class ReadWriteNonCoreDataServiceImpl implements
if (queryParamColumnUnderscored if (queryParamColumnUnderscored
.equalsIgnoreCase(columnHeaderUnderscored)) { .equalsIgnoreCase(columnHeaderUnderscored)) {
pValue = queryParams.get(key); pValue = queryParams.get(key);
validateColumn(columnHeader, pValue); pValue = validateColumn(columnHeader, pValue,
dateFormat, clientApplicationLocale);
affectedColumns.put(columnHeader.getColumnName(), affectedColumns.put(columnHeader.getColumnName(),
pValue); pValue);
notFound = false; notFound = false;
@@ -741,10 +757,12 @@ public class ReadWriteNonCoreDataServiceImpl implements
return affectedColumns; return affectedColumns;
} }
private void validateColumn(ResultsetColumnHeader columnHeader, private String validateColumn(ResultsetColumnHeader columnHeader,
String pValue) { String pValue, String dateFormat, Locale clientApplicationLocale) {
if ((StringUtils.isEmpty(pValue)) String paramValue = pValue;
if ((StringUtils.isEmpty(paramValue))
&& (!(columnHeader.isColumnNullable()))) { && (!(columnHeader.isColumnNullable()))) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
@@ -757,51 +775,80 @@ public class ReadWriteNonCoreDataServiceImpl implements
"Validation errors exist.", dataValidationErrors); "Validation errors exist.", dataValidationErrors);
} }
// check allowed values if (!StringUtils.isEmpty(paramValue)) {
if ((!StringUtils.isEmpty(pValue))
&& columnHeader.getColumnValuesNew().size() > 0) {
List<ResultsetColumnValue> allowedValues = columnHeader if (columnHeader.getColumnValuesNew().size() > 0) {
.getColumnValuesNew(); // match code value or id
if (columnHeader.getColumnType().equalsIgnoreCase("varchar")) { List<ResultsetColumnValue> allowedValues = columnHeader
for (ResultsetColumnValue allowedValue : allowedValues) { .getColumnValuesNew();
if (pValue.equalsIgnoreCase(allowedValue.getValue())) if (columnHeader.getColumnType().equalsIgnoreCase("varchar")) {
return; for (ResultsetColumnValue allowedValue : allowedValues) {
if (paramValue
.equalsIgnoreCase(allowedValue.getValue()))
return paramValue;
}
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError(
"error.msg.invalid.columnValue",
columnHeader.getColumnName(), "Value :"
+ paramValue
+ "' not found in Allowed Value list");
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( if (columnHeader.getColumnType().equalsIgnoreCase("int")) {
"error.msg.invalid.columnValue", for (ResultsetColumnValue allowedValue : allowedValues) {
columnHeader.getColumnName(), "Value :" + pValue if (paramValue.equals(Integer.toString(allowedValue
+ "' not found in Allowed Value list"); .getId())))
dataValidationErrors.add(error); return paramValue;
throw new PlatformApiDataValidationException( }
"validation.msg.validation.errors.exist", List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
"Validation errors exist.", dataValidationErrors); ApiParameterError error = ApiParameterError.parameterError(
"error.msg.invalid.columnValue",
columnHeader.getColumnName(), "Value :"
+ paramValue
+ "' not found in Allowed Value list");
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()
+ " - Invalid Type "
+ columnHeader.getColumnType()
+ " (neither varchar nor int)");
} }
if (columnHeader.getColumnType().equalsIgnoreCase("int")) { if (columnHeader.getColumnType().equalsIgnoreCase("date"))
for (ResultsetColumnValue allowedValue : allowedValues) { paramValue = convertFrom(paramValue,
if (pValue.equals(Integer.toString(allowedValue.getId()))) columnHeader.getColumnName(), dateFormat,
return; clientApplicationLocale).toString();
}
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); if (columnHeader.getColumnType().equalsIgnoreCase("bigint")
ApiParameterError error = ApiParameterError.parameterError( || columnHeader.getColumnType()
"error.msg.invalid.columnValue", .equalsIgnoreCase("smallint")
columnHeader.getColumnName(), "Value :" + pValue || columnHeader.getColumnType().equalsIgnoreCase("tinyint")
+ "' not found in Allowed Value list"); || columnHeader.getColumnType().equalsIgnoreCase("int"))
dataValidationErrors.add(error); paramValue = convertToInteger(paramValue,
throw new PlatformApiDataValidationException( columnHeader.getColumnName(), clientApplicationLocale)
"validation.msg.validation.errors.exist", .toString();
"Validation errors exist.", dataValidationErrors);
} if (columnHeader.getColumnType().equalsIgnoreCase("decimal")
|| columnHeader.getColumnType().equalsIgnoreCase("long"))
paramValue = convertFrom(paramValue,
columnHeader.getColumnName(), clientApplicationLocale)
.toString();
logger.info("Converted Value: " + paramValue + " - was: " + pValue);
throw new PlatformDataIntegrityException(
"error.msg.invalid.columnType.", "Code: "
+ columnHeader.getColumnName() + " - Invalid Type "
+ columnHeader.getColumnType()
+ " (neither varchar nor int)");
} }
return paramValue;
} }
private String getDeleteEntriesSql(String datatable, String FKField, private String getDeleteEntriesSql(String datatable, String FKField,
@@ -833,4 +880,218 @@ public class ReadWriteNonCoreDataServiceImpl implements
return true; return true;
} }
private LocalDate convertFrom(final String dateAsString,
final String parameterName, final String dateFormat,
final Locale clientApplicationLocale) {
if (StringUtils.isBlank(dateFormat) || clientApplicationLocale == null) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
if (StringUtils.isBlank(dateFormat)) {
String defaultMessage = new StringBuilder(
"The parameter '"
+ parameterName
+ "' requires a 'dateFormat' parameter to be passed with it.")
.toString();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.missing.dateFormat.parameter",
defaultMessage, parameterName);
dataValidationErrors.add(error);
}
if (clientApplicationLocale == null) {
String defaultMessage = new StringBuilder(
"The parameter '"
+ parameterName
+ "' requires a 'locale' parameter to be passed with it.")
.toString();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.missing.locale.parameter",
defaultMessage, parameterName);
dataValidationErrors.add(error);
}
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
LocalDate eventLocalDate = null;
if (StringUtils.isNotBlank(dateAsString)) {
try {
// Locale locale = LocaleContextHolder.getLocale();
eventLocalDate = DateTimeFormat
.forPattern(dateFormat)
.withLocale(clientApplicationLocale)
.parseLocalDate(
dateAsString
.toLowerCase(clientApplicationLocale));
} catch (IllegalArgumentException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.invalid.date.format", "The parameter "
+ parameterName
+ " is invalid based on the dateFormat: '"
+ dateFormat + "' and locale: '"
+ clientApplicationLocale + "' provided:",
parameterName, dateAsString, dateFormat);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
}
return eventLocalDate;
}
private Integer convertToInteger(final String numericalValueFormatted,
final String parameterName, final Locale clientApplicationLocale) {
if (clientApplicationLocale == null) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
String defaultMessage = new StringBuilder("The parameter '"
+ parameterName
+ "' requires a 'locale' parameter to be passed with it.")
.toString();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.missing.locale.parameter", defaultMessage,
parameterName);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
try {
Integer number = null;
if (StringUtils.isNotBlank(numericalValueFormatted)) {
String source = numericalValueFormatted.trim();
NumberFormat format = NumberFormat
.getInstance(clientApplicationLocale);
DecimalFormat df = (DecimalFormat) format;
DecimalFormatSymbols symbols = df.getDecimalFormatSymbols();
df.setParseBigDecimal(true);
// http://bugs.sun.com/view_bug.do?bug_id=4510618
char groupingSeparator = symbols.getGroupingSeparator();
if (groupingSeparator == '\u00a0') {
source = source.replaceAll(" ",
Character.toString('\u00a0'));
}
Number parsedNumber = df.parse(source);
double parsedNumberDouble = parsedNumber.doubleValue();
int parsedNumberInteger = parsedNumber.intValue();
if (source.contains(Character.toString(symbols
.getDecimalSeparator()))) {
throw new ParseException(source, 0);
}
if (!Double.valueOf(parsedNumberDouble).equals(
Double.valueOf(Integer.valueOf(parsedNumberInteger)))) {
throw new ParseException(source, 0);
}
number = parsedNumber.intValue();
}
return number;
} catch (ParseException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError
.parameterError(
"validation.msg.invalid.integer.format",
"The parameter "
+ parameterName
+ " has value: "
+ numericalValueFormatted
+ " which is invalid integer value for provided locale of ["
+ clientApplicationLocale.toString() + "].",
parameterName, numericalValueFormatted,
clientApplicationLocale);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
}
private BigDecimal convertFrom(final String numericalValueFormatted,
final String parameterName, final Locale clientApplicationLocale) {
if (clientApplicationLocale == null) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
String defaultMessage = new StringBuilder("The parameter '"
+ parameterName
+ "' requires a 'locale' parameter to be passed with it.")
.toString();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.missing.locale.parameter", defaultMessage,
parameterName);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
try {
BigDecimal number = null;
if (StringUtils.isNotBlank(numericalValueFormatted)) {
String source = numericalValueFormatted.trim();
NumberFormat format = NumberFormat
.getNumberInstance(clientApplicationLocale);
DecimalFormat df = (DecimalFormat) format;
DecimalFormatSymbols symbols = df.getDecimalFormatSymbols();
// http://bugs.sun.com/view_bug.do?bug_id=4510618
char groupingSeparator = symbols.getGroupingSeparator();
if (groupingSeparator == '\u00a0') {
source = source.replaceAll(" ",
Character.toString('\u00a0'));
}
NumberFormatter numberFormatter = new NumberFormatter();
Number parsedNumber = numberFormatter.parse(source,
clientApplicationLocale);
number = BigDecimal.valueOf(Double.valueOf(parsedNumber
.doubleValue()));
}
return number;
} catch (ParseException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError
.parameterError(
"validation.msg.invalid.decimal.format",
"The parameter "
+ parameterName
+ " has value: "
+ numericalValueFormatted
+ " which is invalid decimal value for provided locale of ["
+ clientApplicationLocale.toString() + "].",
parameterName, numericalValueFormatted,
clientApplicationLocale);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
}
} }