Merge remote-tracking branch 'lech/MIFOSX-365' into develop
This commit is contained in:
+28
-8
@@ -16,6 +16,8 @@ import net.fortuna.ical4j.model.property.RRule;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
|
||||
public class DataValidatorBuilder {
|
||||
|
||||
private final List<ApiParameterError> dataValidationErrors;
|
||||
@@ -206,12 +208,13 @@ public class DataValidatorBuilder {
|
||||
|
||||
if (value != null) {
|
||||
List<Object> valuesList = Arrays.asList(values);
|
||||
String valuesListStr = StringUtils.join(valuesList, ", ");
|
||||
|
||||
if (!valuesList.contains(this.value)) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
.append(".is.not.one.of.expected.enumerations");
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter).append(" must be one of [ ")
|
||||
.append(values).append(" ] ").append(".");
|
||||
.append(valuesListStr).append(" ] ").append(".");
|
||||
|
||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||
defaultEnglishMessage.toString(), parameter, this.value, values);
|
||||
@@ -227,12 +230,13 @@ public class DataValidatorBuilder {
|
||||
|
||||
if (value != null) {
|
||||
List<Object> valuesList = Arrays.asList(values);
|
||||
String valuesListStr = StringUtils.join(valuesList, ", ");
|
||||
|
||||
if (valuesList.contains(this.value)) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
.append(".is.one.of.expected.enumerations");
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter).append(" must not be one of [ ")
|
||||
.append(values).append(" ] ").append(".");
|
||||
.append(".is.one.of.unwanted.enumerations");
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter).append(" must not be any of [ ")
|
||||
.append(valuesListStr).append(" ] ").append(".");
|
||||
|
||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||
defaultEnglishMessage.toString(), parameter, this.value, values);
|
||||
@@ -330,6 +334,22 @@ public class DataValidatorBuilder {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataValidatorBuilder jsonArrayNotEmpty() {
|
||||
if (value == null && ignoreNullValue) { return this; }
|
||||
|
||||
JsonArray array = (JsonArray)value;
|
||||
if (value != null && !array.iterator().hasNext()) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
.append(".cannot.be.empty");
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter).append(
|
||||
" cannot be empty. You must select at least one.");
|
||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
|
||||
parameter);
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public void expectedArrayButIsNot() {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
@@ -406,7 +426,7 @@ public class DataValidatorBuilder {
|
||||
}
|
||||
|
||||
public DataValidatorBuilder cantBeBlankWhenParameterProvidedIs(final String parameterName, final Object parameterValue) {
|
||||
if (StringUtils.isNotBlank(value.toString())) { return this; }
|
||||
if (value != null && StringUtils.isNotBlank(value.toString())) { return this; }
|
||||
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
.append(".must.be.provided.when.").append(parameterName).append(".is.").append(parameterValue);
|
||||
@@ -557,12 +577,12 @@ public class DataValidatorBuilder {
|
||||
|
||||
public DataValidatorBuilder matchesRegularExpression(final String expression) {
|
||||
if (value == null && ignoreNullValue) { return this; }
|
||||
|
||||
if (!value.toString().matches(expression)) {
|
||||
|
||||
if (value != null && !value.toString().matches(expression)) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
.append(".does.not.match.regexp");
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter)
|
||||
.append(" must match the provided regular expression ")
|
||||
.append(" must match the provided regular expression [ ")
|
||||
.append(expression).append(" ] ").append(".");
|
||||
|
||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||
|
||||
+92
-61
@@ -44,7 +44,8 @@ public class DatatableCommandFromApiJsonDeserializer {
|
||||
"name", "newName", "type", "length", "mandatory", "after"));
|
||||
private final Set<String> supportedParametersForDropColumns = new HashSet<String>(Arrays.asList(
|
||||
"name"));
|
||||
private final Object[] supportedColumnTypes = { "String", "Number", "Decimal", "Date" };
|
||||
private final Object[] supportedColumnTypes = { "String", "Number", "Decimal", "Date", "Text" };
|
||||
private final Object[] supportedApptableNames = { "m_loan", "m_savings_account", "m_client", "m_group", "m_office" };
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@@ -64,40 +65,50 @@ public class DatatableCommandFromApiJsonDeserializer {
|
||||
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
final String apptableName = fromApiJsonHelper.extractStringNamed("apptableName", element);
|
||||
final String fkColumnName = apptableName.substring(2) + "_id";
|
||||
baseDataValidator.reset().parameter("apptableName").value(apptableName).notNull().notBlank().notExceedingLengthOf(50);
|
||||
baseDataValidator.reset().parameter("apptableName").value(apptableName).notBlank().notExceedingLengthOf(50)
|
||||
.isOneOfTheseValues(supportedApptableNames);
|
||||
final String fkColumnName = (apptableName != null) ? apptableName.substring(2) + "_id" : "";
|
||||
|
||||
final String datatableName = fromApiJsonHelper.extractStringNamed("datatableName", element);
|
||||
baseDataValidator.reset().parameter("datatableName").value(datatableName).notNull().notBlank().notExceedingLengthOf(50)
|
||||
baseDataValidator.reset().parameter("datatableName").value(datatableName).notBlank().notExceedingLengthOf(50)
|
||||
.matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
|
||||
final Boolean multiRow = fromApiJsonHelper.extractBooleanNamed("multiRow", element);
|
||||
baseDataValidator.reset().parameter("multiRow").value(multiRow).ignoreIfNull().trueOrFalseRequired(multiRow);
|
||||
baseDataValidator.reset().parameter("multiRow").value(multiRow).ignoreIfNull().notBlank()
|
||||
.isOneOfTheseValues(true, false);
|
||||
|
||||
final JsonArray columns = fromApiJsonHelper.extractJsonArrayNamed("columns", element);
|
||||
baseDataValidator.reset().parameter("columns").value(columns).notNull();
|
||||
baseDataValidator.reset().parameter("columns").value(columns).notNull().jsonArrayNotEmpty();
|
||||
|
||||
for (JsonElement column : columns) {
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(column.getAsJsonObject(), supportedParametersForCreateColumns);
|
||||
|
||||
final String name = fromApiJsonHelper.extractStringNamed("name", column);
|
||||
baseDataValidator.reset().parameter("name").value(name).notNull().notBlank().notExceedingLengthOf(50)
|
||||
.isNotOneOfTheseValues("id", fkColumnName).matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
|
||||
final String type = fromApiJsonHelper.extractStringNamed("type", column);
|
||||
baseDataValidator.reset().parameter("type").value(type).notNull().notBlank().isOneOfTheseValues(supportedColumnTypes);
|
||||
|
||||
final Integer length = fromApiJsonHelper.extractIntegerSansLocaleNamed("length", column);
|
||||
if (type.equals("String")) {
|
||||
baseDataValidator.reset().parameter("length").value(length).notNull().notBlank()
|
||||
.zeroOrPositiveAmount();
|
||||
} else {
|
||||
baseDataValidator.reset().parameter("length").value(length).ignoreIfNull().notBlank()
|
||||
.zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
final Boolean mandatory = fromApiJsonHelper.extractBooleanNamed("mandatory", column);
|
||||
baseDataValidator.reset().parameter("mandatory").value(mandatory).ignoreIfNull().trueOrFalseRequired(mandatory);
|
||||
if (columns != null) {
|
||||
for (JsonElement column : columns) {
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(column.getAsJsonObject(), supportedParametersForCreateColumns);
|
||||
|
||||
final String name = fromApiJsonHelper.extractStringNamed("name", column);
|
||||
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(50)
|
||||
.isNotOneOfTheseValues("id", fkColumnName).matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
|
||||
final String type = fromApiJsonHelper.extractStringNamed("type", column);
|
||||
baseDataValidator.reset().parameter("type").value(type).notBlank().isOneOfTheseValues(supportedColumnTypes);
|
||||
|
||||
final Integer length = fromApiJsonHelper.extractIntegerSansLocaleNamed("length", column);
|
||||
if (type != null && (type.equals("String") || type.equals("Text"))) {
|
||||
if (length != null) {
|
||||
baseDataValidator.reset().parameter("length").value(length).notBlank()
|
||||
.zeroOrPositiveAmount();
|
||||
} else if (!type.equals("Text")) {
|
||||
baseDataValidator.reset().parameter("length").value(length)
|
||||
.cantBeBlankWhenParameterProvidedIs("type", type);
|
||||
}
|
||||
} else if (type != null && length != null) {
|
||||
baseDataValidator.reset().parameter("length").value(length)
|
||||
.mustBeBlankWhenParameterProvidedIs("type", type);
|
||||
}
|
||||
|
||||
final Boolean mandatory = fromApiJsonHelper.extractBooleanNamed("mandatory", column);
|
||||
baseDataValidator.reset().parameter("mandatory").value(mandatory).ignoreIfNull().notBlank()
|
||||
.isOneOfTheseValues(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
@@ -105,6 +116,9 @@ public class DatatableCommandFromApiJsonDeserializer {
|
||||
|
||||
public void validateForUpdate(final String json) {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
// Because all parameters are optional, a check to see if at least one parameter
|
||||
// has been specified is necessary in order to avoid JSON requests with no parameters
|
||||
if (!json.matches("(?s)\\A\\{.*?(\\\".*?\\\"\\s*?:\\s*?)+.*?\\}\\z")) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParametersForUpdate);
|
||||
@@ -114,18 +128,19 @@ public class DatatableCommandFromApiJsonDeserializer {
|
||||
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
final String apptableName = fromApiJsonHelper.extractStringNamed("apptableName", element);
|
||||
final String fkColumnName = apptableName.substring(2) + "_id";
|
||||
baseDataValidator.reset().parameter("apptableName").value(apptableName).notBlank().notExceedingLengthOf(50);
|
||||
baseDataValidator.reset().parameter("apptableName").value(apptableName).ignoreIfNull().notBlank()
|
||||
.notExceedingLengthOf(50).isOneOfTheseValues(supportedApptableNames);
|
||||
final String fkColumnName = (apptableName != null) ? apptableName.substring(2) + "_id" : "";
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("changeColumns", element)) {
|
||||
final JsonArray changeColumns = fromApiJsonHelper.extractJsonArrayNamed("changeColumns", element);
|
||||
baseDataValidator.reset().parameter("changeColumns").value(changeColumns).ignoreIfNull();
|
||||
final JsonArray changeColumns = fromApiJsonHelper.extractJsonArrayNamed("changeColumns", element);
|
||||
baseDataValidator.reset().parameter("changeColumns").value(changeColumns).ignoreIfNull().jsonArrayNotEmpty();
|
||||
|
||||
if (changeColumns != null) {
|
||||
for (JsonElement column : changeColumns) {
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(column.getAsJsonObject(), supportedParametersForChangeColumns);
|
||||
|
||||
final String name = fromApiJsonHelper.extractStringNamed("name", column);
|
||||
baseDataValidator.reset().parameter("name").value(name).notNull().notBlank().notExceedingLengthOf(50)
|
||||
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(50)
|
||||
.isNotOneOfTheseValues("id", fkColumnName).matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
|
||||
final String newName = fromApiJsonHelper.extractStringNamed("newName", column);
|
||||
@@ -134,65 +149,81 @@ public class DatatableCommandFromApiJsonDeserializer {
|
||||
.matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
|
||||
final String type = fromApiJsonHelper.extractStringNamed("type", column);
|
||||
baseDataValidator.reset().parameter("type").value(type).notNull().notBlank()
|
||||
baseDataValidator.reset().parameter("type").value(type).notBlank()
|
||||
.isOneOfTheseValues(supportedColumnTypes);
|
||||
|
||||
final Integer length = fromApiJsonHelper.extractIntegerSansLocaleNamed("length", column);
|
||||
if (type.equals("String")) {
|
||||
baseDataValidator.reset().parameter("length").value(length).notNull().notBlank()
|
||||
.zeroOrPositiveAmount();
|
||||
} else {
|
||||
baseDataValidator.reset().parameter("length").value(length).ignoreIfNull().notBlank()
|
||||
.zeroOrPositiveAmount();
|
||||
if (type != null && (type.equals("String") || type.equals("Text"))) {
|
||||
if (length != null) {
|
||||
baseDataValidator.reset().parameter("length").value(length).notBlank()
|
||||
.zeroOrPositiveAmount();
|
||||
} else if (!type.equals("Text")) {
|
||||
baseDataValidator.reset().parameter("length").value(length)
|
||||
.cantBeBlankWhenParameterProvidedIs("type", type);
|
||||
}
|
||||
} else if (type != null && length != null) {
|
||||
baseDataValidator.reset().parameter("length").value(length)
|
||||
.mustBeBlankWhenParameterProvidedIs("type", type);
|
||||
}
|
||||
|
||||
final Boolean mandatory = fromApiJsonHelper.extractBooleanNamed("mandatory", column);
|
||||
baseDataValidator.reset().parameter("mandatory").value(mandatory).ignoreIfNull().trueOrFalseRequired(mandatory);
|
||||
|
||||
baseDataValidator.reset().parameter("mandatory").value(mandatory).ignoreIfNull().notBlank()
|
||||
.isOneOfTheseValues(true, false);
|
||||
|
||||
final Boolean after = fromApiJsonHelper.extractBooleanNamed("after", column);
|
||||
baseDataValidator.reset().parameter("after").value(after).ignoreIfNull().notBlank();
|
||||
baseDataValidator.reset().parameter("after").value(after).ignoreIfNull().notBlank()
|
||||
.isOneOfTheseValues(true, false);
|
||||
}
|
||||
}
|
||||
if (fromApiJsonHelper.parameterExists("addColumns", element)) {
|
||||
final JsonArray addColumns = fromApiJsonHelper.extractJsonArrayNamed("addColumns", element);
|
||||
baseDataValidator.reset().parameter("addColumns").value(addColumns).ignoreIfNull();
|
||||
|
||||
|
||||
final JsonArray addColumns = fromApiJsonHelper.extractJsonArrayNamed("addColumns", element);
|
||||
baseDataValidator.reset().parameter("addColumns").value(addColumns).ignoreIfNull().jsonArrayNotEmpty();
|
||||
|
||||
if (addColumns != null) {
|
||||
for (JsonElement column : addColumns) {
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(column.getAsJsonObject(), supportedParametersForAddColumns);
|
||||
|
||||
final String name = fromApiJsonHelper.extractStringNamed("name", column);
|
||||
baseDataValidator.reset().parameter("name").value(name).notNull().notBlank().notExceedingLengthOf(50)
|
||||
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(50)
|
||||
.isNotOneOfTheseValues("id", fkColumnName).matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
|
||||
final String type = fromApiJsonHelper.extractStringNamed("type", column);
|
||||
baseDataValidator.reset().parameter("type").value(type).notNull().notBlank()
|
||||
baseDataValidator.reset().parameter("type").value(type).notBlank()
|
||||
.isOneOfTheseValues(supportedColumnTypes);
|
||||
|
||||
final Integer length = fromApiJsonHelper.extractIntegerSansLocaleNamed("length", column);
|
||||
if (type.equals("String")) {
|
||||
baseDataValidator.reset().parameter("length").value(length).notNull().notBlank()
|
||||
.zeroOrPositiveAmount();
|
||||
} else {
|
||||
baseDataValidator.reset().parameter("length").value(length).ignoreIfNull().notBlank()
|
||||
.zeroOrPositiveAmount();
|
||||
if (type != null && (type.equals("String") || type.equals("Text"))) {
|
||||
if (length != null) {
|
||||
baseDataValidator.reset().parameter("length").value(length).notBlank()
|
||||
.zeroOrPositiveAmount();
|
||||
} else if (!type.equals("Text")) {
|
||||
baseDataValidator.reset().parameter("length").value(length)
|
||||
.cantBeBlankWhenParameterProvidedIs("type", type);
|
||||
}
|
||||
} else if (type != null && length != null) {
|
||||
baseDataValidator.reset().parameter("length").value(length)
|
||||
.mustBeBlankWhenParameterProvidedIs("type", type);
|
||||
}
|
||||
|
||||
final Boolean mandatory = fromApiJsonHelper.extractBooleanNamed("mandatory", column);
|
||||
baseDataValidator.reset().parameter("mandatory").value(mandatory).ignoreIfNull().trueOrFalseRequired(mandatory);
|
||||
baseDataValidator.reset().parameter("mandatory").value(mandatory).ignoreIfNull().notBlank()
|
||||
.isOneOfTheseValues(true, false);
|
||||
|
||||
final Boolean after = fromApiJsonHelper.extractBooleanNamed("after", column);
|
||||
baseDataValidator.reset().parameter("after").value(after).ignoreIfNull().notBlank();
|
||||
baseDataValidator.reset().parameter("after").value(after).ignoreIfNull().notBlank()
|
||||
.isOneOfTheseValues(true, false);
|
||||
}
|
||||
}
|
||||
if (fromApiJsonHelper.parameterExists("dropColumns", element)) {
|
||||
final JsonArray dropColumns = fromApiJsonHelper.extractJsonArrayNamed("dropColumns", element);
|
||||
baseDataValidator.reset().parameter("dropColumns").value(dropColumns).ignoreIfNull();
|
||||
|
||||
final JsonArray dropColumns = fromApiJsonHelper.extractJsonArrayNamed("dropColumns", element);
|
||||
baseDataValidator.reset().parameter("dropColumns").value(dropColumns).ignoreIfNull().jsonArrayNotEmpty();
|
||||
|
||||
if (dropColumns != null) {
|
||||
for (JsonElement column : dropColumns) {
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(column.getAsJsonObject(), supportedParametersForDropColumns);
|
||||
|
||||
final String name = fromApiJsonHelper.extractStringNamed("name", column);
|
||||
baseDataValidator.reset().parameter("name").value(name).notNull().notBlank().notExceedingLengthOf(50)
|
||||
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(50)
|
||||
.isNotOneOfTheseValues("id", fkColumnName).matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -27,14 +27,14 @@ public class UpdateDatatableCommandHandler implements NewCommandSourceHandler {
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
final String datatableName = command.getUrl().replaceAll("/datatables/", "");
|
||||
|
||||
|
||||
final String datatableName = command.getUrl().replaceAll("/datatables/", "");
|
||||
|
||||
this.writePlatformService.updateDatatable(datatableName, command);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withResourceIdAsString(datatableName) //
|
||||
.build();
|
||||
return new CommandProcessingResultBuilder()
|
||||
.withCommandId(command.commandId())
|
||||
.withResourceIdAsString(datatableName)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+246
-205
@@ -18,6 +18,7 @@ import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.SQLGrammarException;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
@@ -56,18 +57,13 @@ import com.google.gson.reflect.TypeToken;
|
||||
@Service
|
||||
public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataService {
|
||||
|
||||
private final static String DATATABLE_NAME_REGEX_PATTERN = "^[a-zA-Z][a-zA-Z0-9\\-_\\s]{0,48}[a-zA-Z0-9]$";
|
||||
private final static String DATATABLE_NAME_REGEX_PATTERN = "^[a-zA-Z][a-zA-Z0-9\\-_\\s]{0,48}[a-zA-Z0-9]$";
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ReadWriteNonCoreDataServiceImpl.class);
|
||||
private final static HashMap<String, String> apiTypeToMySQL = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
put("String", "VARCHAR");
|
||||
put("Number", "INT");
|
||||
put("Decimal", "DECIMAL");
|
||||
put("Date", "DATE");
|
||||
}
|
||||
};
|
||||
private final static HashMap<String, String> apiTypeToMySQL = new HashMap<String, String>() {{
|
||||
put("String", "VARCHAR"); put("Number", "INT"); put("Decimal", "DECIMAL"); put("Date", "DATE");
|
||||
put("Text", "TEXT");
|
||||
}};
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final DataSource dataSource;
|
||||
@@ -285,232 +281,277 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean datatableExists(final String datatable) {
|
||||
|
||||
String sql = "SELECT COUNT(*) FROM `x_registered_table` WHERE `registered_table_name`='" + datatable + "'";
|
||||
Integer rowCount = this.jdbcTemplate.queryForInt(sql);
|
||||
|
||||
return (rowCount > 0);
|
||||
}
|
||||
|
||||
private void validateDatatableExists(final String name) {
|
||||
|
||||
if (!datatableExists(name)) { throw new PlatformDataIntegrityException("error.msg.datatables.missing.table.name", "Table '" + name
|
||||
+ "' does not exist.", name); }
|
||||
}
|
||||
|
||||
private void validateDatatableNotExists(final String name) {
|
||||
|
||||
if (datatableExists(name)) { throw new PlatformDataIntegrityException("error.msg.datatables.duplicate.table.name", "Table '" + name
|
||||
+ "' already exists.", name); }
|
||||
}
|
||||
|
||||
private void validateDatatableName(final String name) {
|
||||
|
||||
if (name == null || name.isEmpty()) {
|
||||
throw new PlatformDataIntegrityException("error.msg.datatables.datatable.null.name", "Data table name must not be blank.");
|
||||
} else if (!name.matches(DATATABLE_NAME_REGEX_PATTERN)) { throw new PlatformDataIntegrityException(
|
||||
"error.msg.datatables.datatable.invalid.name.regex", "Invalid data table name.", name); }
|
||||
|
||||
if (name == null || name.isEmpty()) {
|
||||
throw new PlatformDataIntegrityException("error.msg.datatables.datatable.null.name",
|
||||
"Data table name must not be blank.");
|
||||
} else if (!name.matches(DATATABLE_NAME_REGEX_PATTERN)) {
|
||||
throw new PlatformDataIntegrityException("error.msg.datatables.datatable.invalid.name.regex",
|
||||
"Invalid data table name.", name);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseDatatableColumnObjectForCreate(final JsonObject column, StringBuilder sqlBuilder) {
|
||||
|
||||
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||
String type = (column.has("type")) ? column.get("type").getAsString() : null;
|
||||
Integer length = (column.has("length")) ? column.get("length").getAsInt() : null;
|
||||
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
|
||||
|
||||
String mysqlType = apiTypeToMySQL.get(type);
|
||||
sqlBuilder = sqlBuilder.append("`" + name + "` " + mysqlType);
|
||||
|
||||
if (type != null) {
|
||||
if (type.equals("String")) {
|
||||
sqlBuilder = sqlBuilder.append("(" + length + ")");
|
||||
} else if (type.equals("Decimal")) {
|
||||
sqlBuilder = sqlBuilder.append("(19,6)");
|
||||
}
|
||||
}
|
||||
if (mandatory != null) {
|
||||
if (mandatory) {
|
||||
sqlBuilder = sqlBuilder.append(" NOT NULL");
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
|
||||
}
|
||||
}
|
||||
|
||||
sqlBuilder = sqlBuilder.append(", ");
|
||||
|
||||
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||
String type = (column.has("type")) ? column.get("type").getAsString() : null;
|
||||
Integer length = (column.has("length")) ? column.get("length").getAsInt() : null;
|
||||
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
|
||||
|
||||
String mysqlType = apiTypeToMySQL.get(type);
|
||||
sqlBuilder = sqlBuilder.append("`" + name + "` " + mysqlType);
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
if (type.equals("String")) {
|
||||
sqlBuilder = sqlBuilder.append("(" + length + ")");
|
||||
} else if (type.equals("Decimal")) {
|
||||
sqlBuilder = sqlBuilder.append("(19,6)");
|
||||
}
|
||||
}
|
||||
if (mandatory != null) {
|
||||
if (mandatory) {
|
||||
sqlBuilder = sqlBuilder.append(" NOT NULL");
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
|
||||
}
|
||||
}
|
||||
|
||||
sqlBuilder = sqlBuilder.append(", ");
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult createDatatable(final JsonCommand command) {
|
||||
|
||||
context.authenticatedUser();
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||
String datatableName = null;
|
||||
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||
|
||||
JsonElement element = this.fromJsonHelper.parse(command.json());
|
||||
JsonArray columns = this.fromJsonHelper.extractJsonArrayNamed("columns", element);
|
||||
datatableName = this.fromJsonHelper.extractStringNamed("datatableName", element);
|
||||
String apptableName = this.fromJsonHelper.extractStringNamed("apptableName", element);
|
||||
Boolean multiRow = this.fromJsonHelper.extractBooleanNamed("multiRow", element);
|
||||
|
||||
if (multiRow == null) {
|
||||
multiRow = false;
|
||||
}
|
||||
|
||||
validateDatatableName(datatableName);
|
||||
validateAppTable(apptableName);
|
||||
|
||||
String fkColumnName = apptableName.substring(2) + "_id";
|
||||
String fkName = datatableName.toLowerCase().replaceAll("\\s", "_");
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder = sqlBuilder.append("CREATE TABLE `" + datatableName + "` (");
|
||||
|
||||
if (multiRow) {
|
||||
sqlBuilder = sqlBuilder
|
||||
.append("`id` BIGINT(20) NOT NULL AUTO_INCREMENT, ")
|
||||
.append("`" + fkColumnName + "` BIGINT(20) NOT NULL, ");
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder
|
||||
.append("`" + fkColumnName + "` BIGINT(20) NOT NULL, ");
|
||||
}
|
||||
|
||||
for (JsonElement column : columns) {
|
||||
parseDatatableColumnObjectForCreate(column.getAsJsonObject(), sqlBuilder);
|
||||
}
|
||||
|
||||
// Remove trailing comma and space
|
||||
sqlBuilder = sqlBuilder.delete(sqlBuilder.length() - 2, sqlBuilder.length());
|
||||
|
||||
if (multiRow) {
|
||||
sqlBuilder = sqlBuilder
|
||||
.append(", PRIMARY KEY (`id`)")
|
||||
.append(", KEY `fk_" + apptableName + "` (`" + fkColumnName + "`)")
|
||||
.append(", CONSTRAINT `fk_" + fkName + "` ")
|
||||
.append("FOREIGN KEY (`" + fkColumnName + "`) ")
|
||||
.append("REFERENCES `" + apptableName + "` (`id`)");
|
||||
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder
|
||||
.append(", PRIMARY KEY (`" + fkColumnName + "`)")
|
||||
.append(", CONSTRAINT `fk_" + fkName + "` ")
|
||||
.append("FOREIGN KEY (`" + fkColumnName + "`) ")
|
||||
.append("REFERENCES `" + apptableName + "` (`id`)");
|
||||
}
|
||||
|
||||
sqlBuilder = sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
|
||||
this.jdbcTemplate.execute(sqlBuilder.toString());
|
||||
|
||||
registerDatatable(datatableName, apptableName);
|
||||
} catch (SQLGrammarException e) {
|
||||
Throwable realCause = e.getCause();
|
||||
|
||||
JsonElement element = this.fromJsonHelper.parse(command.json());
|
||||
JsonArray columns = this.fromJsonHelper.extractJsonArrayNamed("columns", element);
|
||||
String datatableName = this.fromJsonHelper.extractStringNamed("datatableName", element);
|
||||
String apptable = this.fromJsonHelper.extractStringNamed("apptableName", element);
|
||||
Boolean multiRow = this.fromJsonHelper.extractBooleanNamed("multiRow", element);
|
||||
if (realCause.getMessage().contains("Table") && realCause.getMessage().contains("already exists")) {
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.datatable.already.exists", realCause.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (multiRow == null) {
|
||||
multiRow = false;
|
||||
}
|
||||
|
||||
validateDatatableName(datatableName);
|
||||
validateDatatableName(apptable);
|
||||
validateDatatableNotExists(datatableName);
|
||||
|
||||
String fkColumnName = apptable.substring(2) + "_id";
|
||||
String fkName = datatableName.toLowerCase().replaceAll("\\s", "_");
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder = sqlBuilder.append("CREATE TABLE `" + datatableName + "` (");
|
||||
|
||||
if (multiRow) {
|
||||
sqlBuilder = sqlBuilder.append("`id` BIGINT(20) NOT NULL AUTO_INCREMENT, ").append(
|
||||
"`" + fkColumnName + "` BIGINT(20) NOT NULL, ");
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder.append("`" + fkColumnName + "` BIGINT(20) NOT NULL, ");
|
||||
}
|
||||
|
||||
for (JsonElement column : columns) {
|
||||
parseDatatableColumnObjectForCreate(column.getAsJsonObject(), sqlBuilder);
|
||||
}
|
||||
|
||||
// Remove trailing comma and space
|
||||
sqlBuilder = sqlBuilder.delete(sqlBuilder.length() - 2, sqlBuilder.length());
|
||||
|
||||
if (multiRow) {
|
||||
sqlBuilder = sqlBuilder.append(", PRIMARY KEY (`id`)").append(", KEY `fk_" + apptable + "` (`" + fkColumnName + "`)")
|
||||
.append(", CONSTRAINT `fk_" + fkName + "` ").append("FOREIGN KEY (`" + fkColumnName + "`) ")
|
||||
.append("REFERENCES `" + apptable + "` (`id`)");
|
||||
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder.append(", PRIMARY KEY (`" + fkColumnName + "`)").append(", CONSTRAINT `fk_" + fkName + "` ")
|
||||
.append("FOREIGN KEY (`" + fkColumnName + "`) ").append("REFERENCES `" + apptable + "` (`id`)");
|
||||
}
|
||||
|
||||
sqlBuilder = sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
|
||||
this.jdbcTemplate.execute(sqlBuilder.toString());
|
||||
|
||||
registerDatatable(datatableName, apptable);
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withResourceIdAsString(datatableName).build();
|
||||
return new CommandProcessingResultBuilder()
|
||||
.withCommandId(command.commandId())
|
||||
.withResourceIdAsString(datatableName)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void parseDatatableColumnForUpdate(final JsonObject column, StringBuilder sqlBuilder) {
|
||||
|
||||
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||
String newName = (column.has("newName")) ? column.get("newName").getAsString() : name;
|
||||
String type = (column.has("type")) ? column.get("type").getAsString() : null;
|
||||
Integer length = (column.has("length")) ? column.get("length").getAsInt() : null;
|
||||
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
|
||||
String after = (column.has("after")) ? column.get("after").getAsString() : null;
|
||||
|
||||
String mysqlType = apiTypeToMySQL.get(type);
|
||||
sqlBuilder = sqlBuilder.append(", CHANGE `" + name + "` `" + newName + "` " + mysqlType);
|
||||
|
||||
if (type != null) {
|
||||
if (type.equals("String") && length != null) {
|
||||
sqlBuilder = sqlBuilder.append("(" + length + ")");
|
||||
} else if (type.equals("Decimal")) {
|
||||
sqlBuilder = sqlBuilder.append("(19,6)");
|
||||
}
|
||||
}
|
||||
if (mandatory != null) {
|
||||
if (mandatory) {
|
||||
sqlBuilder = sqlBuilder.append(" NOT NULL");
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
|
||||
}
|
||||
}
|
||||
if (after != null) {
|
||||
sqlBuilder = sqlBuilder.append(" AFTER `" + after + "`");
|
||||
}
|
||||
|
||||
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||
String newName = (column.has("newName")) ? column.get("newName").getAsString() : name;
|
||||
String type = (column.has("type")) ? column.get("type").getAsString() : null;
|
||||
Integer length = (column.has("length")) ? column.get("length").getAsInt() : null;
|
||||
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
|
||||
String after = (column.has("after")) ? column.get("after").getAsString() : null;
|
||||
|
||||
String mysqlType = apiTypeToMySQL.get(type);
|
||||
sqlBuilder = sqlBuilder.append(", CHANGE `" + name + "` `" + newName + "` " + mysqlType);
|
||||
|
||||
if (type != null) {
|
||||
if (type.equals("String") && length != null) {
|
||||
sqlBuilder = sqlBuilder.append("(" + length + ")");
|
||||
} else if (type.equals("Decimal")) {
|
||||
sqlBuilder = sqlBuilder.append("(19,6)");
|
||||
}
|
||||
}
|
||||
if (mandatory != null) {
|
||||
if (mandatory) {
|
||||
sqlBuilder = sqlBuilder.append(" NOT NULL");
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
|
||||
}
|
||||
}
|
||||
if (after != null) {
|
||||
sqlBuilder = sqlBuilder.append(" AFTER `" + after + "`");
|
||||
}
|
||||
}
|
||||
|
||||
private void parseDatatableColumnForAdd(final JsonObject column, StringBuilder sqlBuilder) {
|
||||
|
||||
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||
String type = (column.has("type")) ? column.get("type").getAsString() : null;
|
||||
Integer length = (column.has("length")) ? column.get("length").getAsInt() : null;
|
||||
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
|
||||
String after = (column.has("after")) ? column.get("after").getAsString() : null;
|
||||
|
||||
String mysqlType = apiTypeToMySQL.get(type);
|
||||
sqlBuilder = sqlBuilder.append(", ADD `" + name + "` " + mysqlType);
|
||||
|
||||
if (type != null) {
|
||||
if (type.equals("String") && length != null) {
|
||||
sqlBuilder = sqlBuilder.append("(" + length + ")");
|
||||
} else if (type.equals("Decimal")) {
|
||||
sqlBuilder = sqlBuilder.append("(19,6)");
|
||||
}
|
||||
}
|
||||
if (mandatory != null) {
|
||||
if (mandatory) {
|
||||
sqlBuilder = sqlBuilder.append(" NOT NULL");
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
|
||||
}
|
||||
}
|
||||
if (after != null) {
|
||||
sqlBuilder = sqlBuilder.append(" AFTER `" + after + "`");
|
||||
}
|
||||
|
||||
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||
String type = (column.has("type")) ? column.get("type").getAsString() : null;
|
||||
Integer length = (column.has("length")) ? column.get("length").getAsInt() : null;
|
||||
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
|
||||
String after = (column.has("after")) ? column.get("after").getAsString() : null;
|
||||
|
||||
String mysqlType = apiTypeToMySQL.get(type);
|
||||
sqlBuilder = sqlBuilder.append(", ADD `" + name + "` " + mysqlType);
|
||||
|
||||
if (type != null) {
|
||||
if (type.equals("String") && length != null) {
|
||||
sqlBuilder = sqlBuilder.append("(" + length + ")");
|
||||
} else if (type.equals("Decimal")) {
|
||||
sqlBuilder = sqlBuilder.append("(19,6)");
|
||||
}
|
||||
}
|
||||
if (mandatory != null) {
|
||||
if (mandatory) {
|
||||
sqlBuilder = sqlBuilder.append(" NOT NULL");
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
|
||||
}
|
||||
}
|
||||
if (after != null) {
|
||||
sqlBuilder = sqlBuilder.append(" AFTER `" + after + "`");
|
||||
}
|
||||
}
|
||||
|
||||
private void parseDatatableColumnForDrop(final JsonObject column, StringBuilder sqlBuilder) {
|
||||
|
||||
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||
|
||||
sqlBuilder = sqlBuilder.append(", DROP COLUMN `" + name + "`");
|
||||
}
|
||||
private void parseDatatableColumnForDrop(final JsonObject column, StringBuilder sqlBuilder) {
|
||||
|
||||
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||
|
||||
sqlBuilder = sqlBuilder.append(", DROP COLUMN `" + name + "`");
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void updateDatatable(final String datatableName, final JsonCommand command) {
|
||||
|
||||
context.authenticatedUser();
|
||||
this.fromApiJsonDeserializer.validateForUpdate(command.json());
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
this.fromApiJsonDeserializer.validateForUpdate(command.json());
|
||||
|
||||
JsonElement element = this.fromJsonHelper.parse(command.json());
|
||||
JsonArray changeColumns = this.fromJsonHelper.extractJsonArrayNamed("changeColumns", element);
|
||||
JsonArray addColumns = this.fromJsonHelper.extractJsonArrayNamed("addColumns", element);
|
||||
JsonArray dropColumns = this.fromJsonHelper.extractJsonArrayNamed("dropColumns", element);
|
||||
String apptableName = this.fromJsonHelper.extractStringNamed("apptableName", element);
|
||||
|
||||
validateDatatableName(datatableName);
|
||||
|
||||
if (!StringUtils.isBlank(apptableName)) {
|
||||
validateAppTable(apptableName);
|
||||
|
||||
String oldApptableName = this.queryForApplicationTableName(datatableName);
|
||||
if (!StringUtils.equals(oldApptableName, apptableName)) {
|
||||
deregisterDatatable(datatableName);
|
||||
registerDatatable(datatableName, apptableName);
|
||||
}
|
||||
}
|
||||
|
||||
if (changeColumns == null && addColumns == null && dropColumns == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`");
|
||||
|
||||
if (changeColumns != null) {
|
||||
for (JsonElement column : changeColumns) {
|
||||
parseDatatableColumnForUpdate(column.getAsJsonObject(), sqlBuilder);
|
||||
}
|
||||
}
|
||||
if (addColumns != null) {
|
||||
for (JsonElement column : addColumns) {
|
||||
parseDatatableColumnForAdd(column.getAsJsonObject(), sqlBuilder);
|
||||
}
|
||||
}
|
||||
if (dropColumns != null) {
|
||||
for (JsonElement column : dropColumns) {
|
||||
parseDatatableColumnForDrop(column.getAsJsonObject(), sqlBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the first comma, right after ALTER TABLE `datatable`
|
||||
int indexOfFirstComma = sqlBuilder.indexOf(",");
|
||||
if (indexOfFirstComma != -1) {
|
||||
sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma);
|
||||
}
|
||||
this.jdbcTemplate.execute(sqlBuilder.toString());
|
||||
} catch (SQLGrammarException e) {
|
||||
Throwable realCause = e.getCause();
|
||||
|
||||
JsonElement element = this.fromJsonHelper.parse(command.json());
|
||||
JsonArray changeColumns = this.fromJsonHelper.extractJsonArrayNamed("changeColumns", element);
|
||||
JsonArray addColumns = this.fromJsonHelper.extractJsonArrayNamed("addColumns", element);
|
||||
JsonArray dropColumns = this.fromJsonHelper.extractJsonArrayNamed("dropColumns", element);
|
||||
|
||||
validateDatatableName(datatableName);
|
||||
validateDatatableExists(datatableName);
|
||||
|
||||
StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`");
|
||||
|
||||
for (JsonElement column : changeColumns) {
|
||||
parseDatatableColumnForUpdate(column.getAsJsonObject(), sqlBuilder);
|
||||
}
|
||||
for (JsonElement column : addColumns) {
|
||||
parseDatatableColumnForAdd(column.getAsJsonObject(), sqlBuilder);
|
||||
}
|
||||
for (JsonElement column : dropColumns) {
|
||||
parseDatatableColumnForDrop(column.getAsJsonObject(), sqlBuilder);
|
||||
}
|
||||
|
||||
// Remove the first comma, right after ALTER TABLE `datatable`
|
||||
sqlBuilder = sqlBuilder.deleteCharAt(sqlBuilder.indexOf(","));
|
||||
this.jdbcTemplate.execute(sqlBuilder.toString());
|
||||
if (realCause.getMessage().contains("Unknown column")) {
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.datatable.column.missing", realCause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void deleteDatatable(final String datatableName) {
|
||||
|
||||
context.authenticatedUser();
|
||||
|
||||
validateDatatableName(datatableName);
|
||||
validateDatatableExists(datatableName);
|
||||
deregisterDatatable(datatableName);
|
||||
|
||||
String sql = "DROP TABLE `" + datatableName + "`";
|
||||
this.jdbcTemplate.execute(sql);
|
||||
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
|
||||
validateDatatableName(datatableName);
|
||||
deregisterDatatable(datatableName);
|
||||
|
||||
String sql = "DROP TABLE `" + datatableName + "`";
|
||||
this.jdbcTemplate.execute(sql);
|
||||
} catch (SQLGrammarException e) {
|
||||
Throwable realCause = e.getCause();
|
||||
|
||||
if (realCause.getMessage().contains("Unknown table")) {
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.datatable.missing", realCause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
Reference in New Issue
Block a user