Split validation and import.

Added validation for unused fields.
This commit is contained in:
Erik C. Thauvin 2016-08-27 17:25:15 -07:00
parent c9de7a0754
commit fa05584827
3 changed files with 85 additions and 67 deletions

View file

@ -72,10 +72,42 @@ class MainActivity : AppCompatActivity(), AnkoLogger {
val PAUSE = ',' val PAUSE = ','
} }
@NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
fun importConfig(intent: Intent) {
val errors = StringBuilder()
val tmp: Config? = try {
Gson().fromJson(InputStreamReader(contentResolver.openInputStream(intent.data)),
Config::class.java)
} catch (jse: JsonSyntaxException) {
val cause = jse.cause
if (cause != null) {
errors.append(cause.message)
} else {
errors.append(jse.message)
}
null
}
if (tmp != null && validateConfig(tmp, errors)) {
config = tmp
saveConfig()
recreate()
}
if (errors.length > 0) {
alert {
title(R.string.alert_config_error)
message(Html.fromHtml("$errors"))
cancelButton { }
}.show()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == read_request_code && resultCode == Activity.RESULT_OK) { if (requestCode == read_request_code && resultCode == Activity.RESULT_OK) {
if (data != null) { if (data != null) {
MainActivityPermissionsDispatcher.validateConfigWithCheck(this, data) MainActivityPermissionsDispatcher.importConfigWithCheck(this, data)
} }
} }
} }
@ -271,6 +303,12 @@ class MainActivity : AppCompatActivity(), AnkoLogger {
defaultConfigs.forEach { defaultConfigs.forEach {
config = Gson().fromJson(InputStreamReader(resources.openRawResource(it)), config = Gson().fromJson(InputStreamReader(resources.openRawResource(it)),
Config::class.java) Config::class.java)
// val errors = StringBuilder()
// if (!validateConfig(config, errors)) {
// info("${config.params.name}: $errors")
// }
confs.configs.put(config.params.name, config) confs.configs.put(config.params.name, config)
} }
@ -297,25 +335,10 @@ class MainActivity : AppCompatActivity(), AnkoLogger {
} }
} }
@NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) fun validateConfig(config: Config, errors: StringBuilder): Boolean {
fun validateConfig(intent: Intent) { val len = errors.length
val errors = StringBuilder()
val tmp: Config? = try { with(config) {
Gson().fromJson(InputStreamReader(contentResolver.openInputStream(intent.data)),
Config::class.java)
} catch (jse: JsonSyntaxException) {
val cause = jse.cause
if (cause != null) {
errors.append(cause.message)
} else {
errors.append(jse.message)
}
null
}
if (tmp != null) {
with(tmp) {
if (params.name.isBlank()) { if (params.name.isBlank()) {
errors.append(getString(R.string.validate_missing_param, "name")) errors.append(getString(R.string.validate_missing_param, "name"))
} }
@ -341,6 +364,10 @@ class MainActivity : AppCompatActivity(), AnkoLogger {
errors.append(getString(R.string.validate_invalid_option, i + 1, "nodial/nosteps")) errors.append(getString(R.string.validate_invalid_option, i + 1, "nodial/nosteps"))
} }
if (option.dtmf.isBlank()) {
errors.append(getString(R.string.validate_invalid_dtmf, i + 1, "''"))
}
option.fields.forEachIndexed { j, field -> option.fields.forEachIndexed { j, field ->
if (field.size <= 0) { if (field.size <= 0) {
errors.append(getString(R.string.validate_invalid_attr, i + 1, j + 1, "size")) errors.append(getString(R.string.validate_invalid_attr, i + 1, j + 1, "size"))
@ -357,31 +384,21 @@ class MainActivity : AppCompatActivity(), AnkoLogger {
} }
} }
} }
if (!option.dtmf.contains(Dtmf.DTMF_FIELD.format(j + 1))) {
errors.append(getString(R.string.validate_unused_field, i + 1, j + 1))
}
} }
val blank = "\\0" val blank = "\\0"
val dtmf = Dtmf.mock(option, blank) val dtmf = Dtmf.mock(option, blank)
if (!Dtmf.validate(dtmf, "${MainActivity.PAUSE}${params.star}${params.hash}$blank")) { if (!Dtmf.validate(dtmf, "${MainActivity.Companion.PAUSE}${params.star}${params.hash}$blank")) {
errors.append(getString(R.string.validate_invalid_dtmf, i + 1, dtmf.replace(blank, "&#10003;"))) errors.append(getString(R.string.validate_invalid_dtmf, i + 1, dtmf.replace(blank, "&#10003;")))
} }
} }
} }
if (errors.length == 0) { return errors.length == len
config = tmp
saveConfig()
recreate()
}
}
if (errors.length > 0) {
alert {
title(R.string.alert_config_error)
message(Html.fromHtml("$errors"))
cancelButton { }
}.show()
}
} }
fun validateFields(fields: ArrayList<EditText>, size: Int): Boolean { fun validateFields(fields: ArrayList<EditText>, size: Int): Boolean {

View file

@ -24,8 +24,8 @@ import java.util.*
class Dtmf { class Dtmf {
companion object { companion object {
private val DTMF_MASTER = "[MASTER]" val DTMF_MASTER = "[MASTER]"
private val DTMF_FIELD = "[FIELD:%1\$d]" val DTMF_FIELD = "[FIELD:%1\$d]"
private fun alphaToDigits(text: String, star: String): String { private fun alphaToDigits(text: String, star: String): String {
val result = StringBuffer() val result = StringBuffer()

View file

@ -21,4 +21,5 @@
<string name="validate_missing_fields">&lt;p>&lt;b>opts[<xliff:g id="opts">%1$d</xliff:g>]&lt;/b>: &lt;font color=\"red\">fields&lt;/font> missing</string> <string name="validate_missing_fields">&lt;p>&lt;b>opts[<xliff:g id="opts">%1$d</xliff:g>]&lt;/b>: &lt;font color=\"red\">fields&lt;/font> missing</string>
<string name="validate_missing_param">&lt;p>&lt;p>&lt;b>params&lt;/b>: &lt;font color=\"red\"><xliff:g id="param">%1$s</xliff:g>&lt;/font> missing&lt;/p></string> <string name="validate_missing_param">&lt;p>&lt;p>&lt;b>params&lt;/b>: &lt;font color=\"red\"><xliff:g id="param">%1$s</xliff:g>&lt;/font> missing&lt;/p></string>
<string name="validate_missing_opts">&lt;font color=\"red\">opts&lt;/font> missing.</string> <string name="validate_missing_opts">&lt;font color=\"red\">opts&lt;/font> missing.</string>
<string name="validate_unused_field">&lt;b>opts[<xliff:g id="opts">%1$d</xliff:g>]&lt;/b>, &lt;font color=\"red\">fields[<xliff:g id="field">%2$d</xliff:g>]&lt;/font>: unused</string>
</resources> </resources>