Details
diff --git a/util/src/main/java/com/ning/billing/util/validation/ColumnInfo.java b/util/src/main/java/com/ning/billing/util/validation/ColumnInfo.java
index 31d8bf0..545425b 100644
--- a/util/src/main/java/com/ning/billing/util/validation/ColumnInfo.java
+++ b/util/src/main/java/com/ning/billing/util/validation/ColumnInfo.java
@@ -22,13 +22,18 @@ public class ColumnInfo {
private final int scale;
private final int precision;
private final boolean isNullable;
+ private final int maximumLength;
+ private final String dataType;
- public ColumnInfo(String tableName, String columnName, int scale, int precision, boolean nullable) {
+ public ColumnInfo(String tableName, String columnName, int scale, int precision,
+ boolean nullable, int maximumLength, String dataType) {
this.tableName = tableName;
this.columnName = columnName;
this.scale = scale;
this.precision = precision;
isNullable = nullable;
+ this.maximumLength = maximumLength;
+ this.dataType = dataType;
}
public String getTableName() {
@@ -50,4 +55,12 @@ public class ColumnInfo {
public boolean getIsNullable() {
return isNullable;
}
+
+ public int getMaximumLength() {
+ return maximumLength;
+ }
+
+ public String getDataType() {
+ return dataType;
+ }
}
\ No newline at end of file
diff --git a/util/src/main/java/com/ning/billing/util/validation/dao/DatabaseSchemaSqlDao.java b/util/src/main/java/com/ning/billing/util/validation/dao/DatabaseSchemaSqlDao.java
index 250ecce..53fccf7 100644
--- a/util/src/main/java/com/ning/billing/util/validation/dao/DatabaseSchemaSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/validation/dao/DatabaseSchemaSqlDao.java
@@ -42,8 +42,10 @@ public interface DatabaseSchemaSqlDao {
final Integer scale = r.getInt("numeric_scale");
final Integer precision = r.getInt("numeric_precision");
final boolean isNullable = r.getBoolean("is_nullable");
+ final Integer maximumLength = r.getInt("character_maximum_length");
+ final String dataType = r.getString("data_type");
- return new ColumnInfo(tableName, columnName, scale, precision, isNullable);
+ return new ColumnInfo(tableName, columnName, scale, precision, isNullable, maximumLength, dataType);
}
}
}
diff --git a/util/src/main/java/com/ning/billing/util/validation/ValidationManager.java b/util/src/main/java/com/ning/billing/util/validation/ValidationManager.java
index 4bd8e8e..cac7736 100644
--- a/util/src/main/java/com/ning/billing/util/validation/ValidationManager.java
+++ b/util/src/main/java/com/ning/billing/util/validation/ValidationManager.java
@@ -20,6 +20,7 @@ import com.google.inject.Inject;
import com.ning.billing.util.validation.dao.DatabaseSchemaDao;
import java.lang.reflect.Field;
+import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -84,9 +85,11 @@ public class ValidationManager {
return true;
}
- if (!columnInfo.getIsNullable()) {
- if (value == null) {return false;}
- }
+ if (!hasValidNullability(columnInfo, value)) {return false;}
+ if (!isValidLengthString(columnInfo, value)) {return false;}
+ if (!isValidLengthChar(columnInfo, value)) {return false;}
+ if (!hasValidPrecision(columnInfo, value)) {return false;}
+ if (!hasValidScale(columnInfo, value)) {return false;}
} catch (NoSuchFieldException e) {
// if the field doesn't exist, assume the configuration is faulty and skip this property
} catch (IllegalAccessException e) {
@@ -98,6 +101,66 @@ public class ValidationManager {
return true;
}
+ private boolean hasValidNullability(final ColumnInfo columnInfo, final Object value) {
+ if (!columnInfo.getIsNullable()) {
+ if (value == null) {return false;}
+ }
+
+ return true;
+ }
+
+ private boolean isValidLengthString(final ColumnInfo columnInfo, final Object value) {
+ if (columnInfo.getMaximumLength() != 0) {
+ if (value != null) {
+ if (value.toString().length() > columnInfo.getMaximumLength()) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private boolean isValidLengthChar(final ColumnInfo columnInfo, final Object value) {
+ if (columnInfo.getDataType().equals("char")) {
+ if (value== null) {
+ return false;
+ } else {
+ if (value.toString().length() != columnInfo.getMaximumLength()) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private boolean hasValidPrecision(final ColumnInfo columnInfo, final Object value) {
+ if (columnInfo.getPrecision() != 0) {
+ if (value != null) {
+ BigDecimal bigDecimalValue = new BigDecimal(value.toString());
+ if (bigDecimalValue.precision() > columnInfo.getPrecision()) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private boolean hasValidScale(final ColumnInfo columnInfo, final Object value) {
+ if (columnInfo.getScale() != 0) {
+ if (value != null) {
+ BigDecimal bigDecimalValue = new BigDecimal(value.toString());
+ if (bigDecimalValue.scale() > columnInfo.getScale()) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
public boolean hasConfiguration(Class clazz) {
return configurations.containsKey(clazz);
}
diff --git a/util/src/test/java/com/ning/billing/util/validation/TestValidationManager.java b/util/src/test/java/com/ning/billing/util/validation/TestValidationManager.java
index f664da3..b7e5bc6 100644
--- a/util/src/test/java/com/ning/billing/util/validation/TestValidationManager.java
+++ b/util/src/test/java/com/ning/billing/util/validation/TestValidationManager.java
@@ -56,7 +56,7 @@ public class TestValidationManager {
helper.startMysql();
StringBuilder ddl = new StringBuilder();
ddl.append(String.format("DROP TABLE IF EXISTS %s;", TABLE_NAME));
- ddl.append(String.format("CREATE TABLE %s (column1 varchar(1), column2 char(2) NOT NULL, column3 numeric(10,4), column4 datetime) ENGINE = innodb;", TABLE_NAME));
+ ddl.append(String.format("CREATE TABLE %s (column1 varchar(25), column2 char(2) NOT NULL, column3 numeric(10,4), column4 datetime) ENGINE = innodb;", TABLE_NAME));
helper.initDb(ddl.toString());
}
@@ -87,7 +87,7 @@ public class TestValidationManager {
String STRING_FIELD_2 = "column2";
String STRING_FIELD_2_PROPERTY = "stringField2";
- SimpleTestClass testObject = new SimpleTestClass("a", null, 7.9, new DateTime());
+ SimpleTestClass testObject = new SimpleTestClass(null, null, 7.9, new DateTime());
vm.setConfiguration(testObject.getClass(), STRING_FIELD_2_PROPERTY, vm.getColumnInfo(TABLE_NAME, STRING_FIELD_2));
@@ -98,10 +98,57 @@ public class TestValidationManager {
assertNotNull(configuration);
assertTrue(configuration.hasMapping(STRING_FIELD_2_PROPERTY));
+ // set char field to value that is too short
assertFalse(vm.validate(testObject));
+ testObject.setStringField2("a");
+ assertFalse(vm.validate(testObject));
+
+ // set char to excessively long string
+ testObject.setStringField2("abc");
+ assertFalse(vm.validate(testObject));
+
+ // set char to proper length
testObject.setStringField2("ab");
assertTrue(vm.validate(testObject));
+ // add the first string field and add a string that exceeds the length
+ final String STRING_FIELD_1 = "column1";
+ final String STRING_FIELD_1_PROPERTY = "stringField1";
+ vm.setConfiguration(testObject.getClass(), STRING_FIELD_1_PROPERTY, vm.getColumnInfo(TABLE_NAME, STRING_FIELD_1));
+
+ assertTrue(vm.validate(testObject));
+ testObject.setStringField1("This is a long string that exceeds the length limit for column 1.");
+ assertFalse(vm.validate(testObject));
+ testObject.setStringField1("This is a short string.");
+ assertTrue(vm.validate(testObject));
+
+ // verify numeric values
+ final String NUMERIC_FIELD = "column3";
+ final String NUMERIC_FIELD_PROPERTY = "numericField1";
+ vm.setConfiguration(testObject.getClass(), NUMERIC_FIELD_PROPERTY, vm.getColumnInfo(TABLE_NAME, NUMERIC_FIELD));
+ assertTrue(vm.validate(testObject));
+
+ // set the value to have more than 4 decimal places
+ testObject.setNumericField1(0.123456);
+ assertFalse(vm.validate(testObject));
+
+ // set the value to have more than 10 digits
+ testObject.setNumericField1(12345678901234D);
+ assertFalse(vm.validate(testObject));
+
+ // set to a valid value
+ testObject.setNumericField1(1234567890);
+ assertTrue(vm.validate(testObject));
+
+ // check another valid number
+ testObject.setNumericField1(123456.7891);
+ assertTrue(vm.validate(testObject));
+
+ // check another valid number
+ testObject.setNumericField1(12345678.91);
+ assertTrue(vm.validate(testObject));
+
+
}
private class SimpleTestClass {