I wrote a string validator to check username/password. I pass a string, a min required length. The length of the first string i pass is 4 (username) and the second time 8 (password).
I then store these values in a companion object and let my return variable, an Enum with a string value, use the min length variable reference from the companion object to specify min length in the string message.
The problem is the first time it works as intended and the string writes 4 as min length. The second time however, when I bump the length to 8, the output still says 4.
Code:
//Calling from somewhere else
val usernameStrengthResult = StringStrengthValidator.evaluateStrength(registrationUserData.fullName,8)
val passwordStrengthResult = StringStrengthValidator.evaluateStrength(registrationUserData.password,8)
-------------------------------------------------------------------
companion object {
//--------REQUIREMENTS--------
var REQUIRED_LENGTH = 0
fun evaluateStrength(clientString: String, requiredLength: Int?= null){
//Setting companion value to the new length limit
requiredLength?.let { REQUIRED_LENGTH = it }
return when {
clientString.length < REQUIRED_LENGTH -> StringStrengthReport.TO_SHORT
}
}
-------------------------------------------------------------------
//I use REQUIRED_LENGTH to construct a message
enum class StringStrengthReport(val message: String){
TO_SHORT("is to short. ${StringStrengthValidator.REQUIRED_LENGTH} characters are required")
}
The weirdest part is that when im debugging the value is shown as 8 (the second time) but the string still gets constructed with the 4.
It seams that once the value have been read one, it will not change. Has anyone else had a similar problem?
EDIT: Full code
class StringStrengthValidator {
companion object {
//--------REQUIREMENTS--------
var REQUIRED_LENGTH = 8
var MAXIMUM_LENGTH = 32
private var REQUIRE_SPECIAL_CHARACTERS = false
private var REQUIRE_DIGITS = false
private var REQUIRE_LOWER_CASE = false
private var REQUIRE_UPPER_CASE = false
fun evaluateStrength(clientString: String,
requiredLength: Int?= null,
maxLength: Int? = null,
requireSpecial: Boolean? = null,
requireDigits: Boolean?= null,
requireLowerCase: Boolean? = null,
requireUpperCase:Boolean? =null)
: StringStrengthReport {
requiredLength?.let { REQUIRED_LENGTH = it }
maxLength?.let { MAXIMUM_LENGTH = it }
requireSpecial?.let { REQUIRE_SPECIAL_CHARACTERS = it }
requireDigits?.let { REQUIRE_DIGITS = it }
requireLowerCase?.let { REQUIRE_LOWER_CASE = it }
requireUpperCase?.let { REQUIRE_UPPER_CASE = it }
var hasUpper = false
var hasLower = false
var hasDigit = false
var hasSpecial = false
for (i in 0 until clientString.length) {
val c = clientString[i]
when {
isSpecialCharacter(hasSpecial, c) -> hasSpecial = true
isDigit(hasDigit, c) -> hasDigit = true
isUpperCase(hasUpper, c) -> hasUpper = true
else -> hasLower = true
}
}
return when {
clientString.length < REQUIRED_LENGTH -> StringStrengthReport.TO_SHORT
REQUIRE_LOWER_CASE && !hasLower -> StringStrengthReport.LOWER_CASE_REQUIRED
REQUIRE_UPPER_CASE && !hasUpper -> StringStrengthReport.UPPER_CASE_REQUIRED
REQUIRE_DIGITS && !hasDigit -> StringStrengthReport.DIGIT_REQUIRED
REQUIRE_SPECIAL_CHARACTERS && !hasSpecial -> StringStrengthReport.SPECIAL_CHARACTER_REQUIRED
clientString.length > MAXIMUM_LENGTH ->StringStrengthReport.MAX_LENGTH_EXCEEDED
else -> StringStrengthReport.VALID_STRING
}
}
private fun isUpperCase(hasUpper: Boolean, c: Char) =
!hasUpper && Character.isUpperCase(c)
private fun isDigit(hasDigit: Boolean, c: Char) = !hasDigit && Character.isDigit(c)
private fun isSpecialCharacter(hasSpecial: Boolean, c: Char) =
!hasSpecial && !Character.isLetterOrDigit(c)
fun validateEmail(email: String):Boolean {
return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()
}
fun validateRegisterCredentials(registrationUserData: RegistrationUserData): CredentialStrengthReport {
val isEmailValid = StringStrengthValidator.validateEmail(registrationUserData.email)
val usernameStrengthResult = StringStrengthValidator.evaluateStrength(registrationUserData.fullName,8,32)
val passwordStrengthResult = StringStrengthValidator.evaluateStrength(registrationUserData.password,8,32)
var reportMessage = ""
if (!isEmailValid) reportMessage += "Incorrect Email format\n"
val isUsernameValid = usernameStrengthResult == StringStrengthReport.VALID_STRING
if (!isUsernameValid) reportMessage += "Username ${usernameStrengthResult.message}\n"
val isPasswordValid = passwordStrengthResult == StringStrengthReport.VALID_STRING
if (!isPasswordValid)reportMessage += "Password ${passwordStrengthResult.message}\n"
return CredentialStrengthReport(isEmailValid, isUsernameValid, isPasswordValid, reportMessage)
}
}
}
enum class StringStrengthReport(val message: String){
TO_SHORT("is to short. ${StringStrengthValidator.REQUIRED_LENGTH} characters are required"),
LOWER_CASE_REQUIRED("requires at least one lower case character"),
UPPER_CASE_REQUIRED("requires at least one upper case character"),
DIGIT_REQUIRED("requires at least one digit"),
SPECIAL_CHARACTER_REQUIRED("requires at least one special character (i.e !&?#%)"),
MAX_LENGTH_EXCEEDED("is to long. Maximum length is ${StringStrengthValidator.MAXIMUM_LENGTH} characters"),
VALID_STRING("is valid")
}
class CredentialStrengthReport(val isEmailValid: Boolean,
val isUsernameValid:Boolean,
val isPasswordValid: Boolean,
val resultMessage: String){
val isCredentialsValid:Boolean
get() {return isEmailValid && isUsernameValid && isPasswordValid}
}