├── sample ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── layout │ │ │ └── activity_main.xml │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ └── drawable │ │ │ └── ic_launcher_background.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── io │ │ └── github │ │ └── anderscheow │ │ └── validator │ │ └── sample │ │ └── MainActivity.kt ├── proguard-rules.pro └── build.gradle ├── jitpack.yml ├── library ├── .gitignore ├── src │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── res │ │ │ └── values │ │ │ │ └── strings.xml │ │ └── java │ │ │ └── io │ │ │ └── github │ │ │ └── anderscheow │ │ │ └── validator │ │ │ ├── constant │ │ │ └── Mode.java │ │ │ ├── interfaces │ │ │ ├── Validate.kt │ │ │ └── ErrorImpl.kt │ │ │ ├── rules │ │ │ ├── Rule.kt │ │ │ ├── common │ │ │ │ ├── NotNullRule.kt │ │ │ │ ├── NotBlankRule.kt │ │ │ │ ├── NotEmptyRule.kt │ │ │ │ ├── RegexRule.kt │ │ │ │ ├── EqualRule.kt │ │ │ │ ├── NotEqualRule.kt │ │ │ │ ├── MinRule.kt │ │ │ │ ├── MaxRule.kt │ │ │ │ ├── AllLowerCaseRule.kt │ │ │ │ ├── AllUpperCaseRule.kt │ │ │ │ ├── PastRule.kt │ │ │ │ ├── ContainRule.kt │ │ │ │ ├── EndsWithRule.kt │ │ │ │ ├── NotContainRule.kt │ │ │ │ ├── StartsWithRule.kt │ │ │ │ ├── FutureRule.kt │ │ │ │ └── LengthRule.kt │ │ │ └── regex │ │ │ │ ├── DigitsRule.kt │ │ │ │ ├── AlphabetRule.kt │ │ │ │ ├── EmailRule.kt │ │ │ │ ├── SymbolRule.kt │ │ │ │ ├── AlphanumericRule.kt │ │ │ │ ├── PasswordRule.kt │ │ │ │ └── CreditCardRule.kt │ │ │ ├── conditions │ │ │ ├── common │ │ │ │ ├── Or.kt │ │ │ │ └── And.kt │ │ │ └── Condition.kt │ │ │ ├── Validation.kt │ │ │ └── Validator.kt │ └── test │ │ └── java │ │ └── io │ │ └── github │ │ └── anderscheow │ │ └── validator │ │ ├── rules │ │ ├── common │ │ │ ├── NotNullRuleTest.kt │ │ │ ├── EqualRuleTest.kt │ │ │ ├── RegexRuleTest.kt │ │ │ ├── NotEqualRuleTest.kt │ │ │ ├── NotContainRuleTest.kt │ │ │ ├── NotBlankRuleTest.kt │ │ │ ├── NotEmptyRuleTest.kt │ │ │ ├── MaxRuleTest.kt │ │ │ ├── MinRuleTest.kt │ │ │ ├── AllLowerCaseRuleTest.kt │ │ │ ├── AllUpperCaseRuleTest.kt │ │ │ ├── EndsWithRuleTest.kt │ │ │ ├── ContainRuleTest.kt │ │ │ ├── StartsWithRuleTest.kt │ │ │ ├── PastRuleTest.kt │ │ │ ├── FutureRuleTest.kt │ │ │ └── LengthRuleTest.kt │ │ ├── RuleTest.kt │ │ └── regex │ │ │ ├── EmailRuleTest.kt │ │ │ ├── DigitsRuleTest.kt │ │ │ ├── SymbolRuleTest.kt │ │ │ ├── AlphabetRuleTest.kt │ │ │ ├── AlphanumericRuleTest.kt │ │ │ ├── CreditCardRuleTest.kt │ │ │ └── PasswordRuleTest.kt │ │ └── conditions │ │ ├── ConditionTest.kt │ │ └── common │ │ ├── OrTest.kt │ │ └── AndTest.kt ├── proguard-rules.pro ├── gradle.properties └── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── caches │ └── build_file_checksums.ser └── misc.xml ├── settings.gradle ├── gradle.properties ├── LICENSE ├── .gitignore ├── gradlew.bat ├── dependencies.gradle ├── CHANGELOG.md ├── README.md └── gradlew /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - openjdk11 -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Validator 3 | 4 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/sample/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/sample/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/sample/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderscheow/Validator/HEAD/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/constant/Mode.java: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.constant; 2 | 3 | public enum Mode { 4 | SINGLE, 5 | CONTINUOUS 6 | } 7 | -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/interfaces/Validate.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.interfaces 2 | 3 | interface Validate { 4 | 5 | fun validate(value: String?): Boolean 6 | } 7 | -------------------------------------------------------------------------------- /sample/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Validator 3 | Filed is required 4 | Password is too short 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jul 09 10:16:52 MYT 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip 7 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':sample', ':library' 2 | 3 | dependencyResolutionManagement { 4 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 5 | repositories { 6 | google() 7 | mavenCentral() 8 | maven { url 'https://jitpack.io' } 9 | } 10 | } -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sample/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/Rule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.interfaces.ErrorImpl 5 | import io.github.anderscheow.validator.interfaces.Validate 6 | 7 | abstract class Rule : ErrorImpl, Validate { 8 | 9 | constructor(@StringRes errorRes: Int) : super(errorRes) 10 | 11 | constructor(errorString: String) : super(errorString) 12 | } 13 | 14 | class RulesBuilder { 15 | val ruleList = arrayListOf() 16 | 17 | operator fun Rule.unaryPlus() { 18 | ruleList.add(this) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/NotNullRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class NotNullRule : Rule { 7 | 8 | constructor(@StringRes errorRes: Int) : super(errorRes) 9 | 10 | constructor(errorMessage: String) : super(errorMessage) 11 | 12 | override fun validate(value: String?): Boolean { 13 | return value != null 14 | } 15 | } 16 | 17 | fun notNull(@StringRes errorRes: Int): NotNullRule = NotNullRule(errorRes) 18 | 19 | fun notNull(errorMessage: String): NotNullRule = NotNullRule(errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/regex/DigitsRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.regex 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.common.RegexRule 5 | 6 | class DigitsRule : RegexRule { 7 | 8 | constructor(@StringRes errorRes: Int) : super(DIGITS_REGEX, errorRes) 9 | 10 | constructor(errorMessage: String) : super(DIGITS_REGEX, errorMessage) 11 | 12 | companion object { 13 | private const val DIGITS_REGEX = "\\d+" 14 | } 15 | } 16 | 17 | fun digitsOnly(@StringRes errorRes: Int): DigitsRule = DigitsRule(errorRes) 18 | 19 | fun digitsOnly(errorMessage: String): DigitsRule = DigitsRule(errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/regex/AlphabetRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.regex 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.common.RegexRule 5 | 6 | class AlphabetRule : RegexRule { 7 | 8 | constructor(@StringRes errorRes: Int) : super(ALPHABET_REGEX, errorRes) 9 | 10 | constructor(errorMessage: String) : super(ALPHABET_REGEX, errorMessage) 11 | 12 | companion object { 13 | private const val ALPHABET_REGEX = "^[a-zA-Z]*$" 14 | } 15 | } 16 | 17 | fun alphabetOnly(@StringRes errorRes: Int): AlphabetRule = AlphabetRule(errorRes) 18 | 19 | fun alphabetOnly(errorMessage: String): AlphabetRule = AlphabetRule(errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/regex/EmailRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.regex 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.common.RegexRule 5 | 6 | class EmailRule : RegexRule { 7 | 8 | constructor(@StringRes errorRes: Int) : super(EMAIL_REGEX, errorRes) 9 | 10 | constructor(errorMessage: String) : super(EMAIL_REGEX, errorMessage) 11 | 12 | companion object { 13 | private const val EMAIL_REGEX = "\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b" 14 | } 15 | } 16 | 17 | fun email(@StringRes errorRes: Int): EmailRule = EmailRule(errorRes) 18 | 19 | fun email(errorMessage: String): EmailRule = EmailRule(errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/regex/SymbolRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.regex 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.common.RegexRule 5 | 6 | class SymbolRule : RegexRule { 7 | 8 | constructor(@StringRes errorRes: Int) : super(ALPHABET_REGEX, errorRes) 9 | 10 | constructor(errorMessage: String) : super(ALPHABET_REGEX, errorMessage) 11 | 12 | companion object { 13 | private const val ALPHABET_REGEX = "^[-!@#\$%^&*()_+|~=`{}\\[\\]:\";'<>?,.\\/]*\$" 14 | } 15 | } 16 | 17 | fun symbolsOnly(@StringRes errorRes: Int): SymbolRule = SymbolRule(errorRes) 18 | 19 | fun symbolsOnly(errorMessage: String): SymbolRule = SymbolRule(errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/regex/AlphanumericRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.regex 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.common.RegexRule 5 | 6 | class AlphanumericRule : RegexRule { 7 | 8 | constructor(@StringRes errorRes: Int) : super(ALPHANUMERIC_REGEX, errorRes) 9 | 10 | constructor(errorMessage: String) : super(ALPHANUMERIC_REGEX, errorMessage) 11 | 12 | companion object { 13 | private const val ALPHANUMERIC_REGEX = "^[a-zA-Z0-9]*$" 14 | } 15 | } 16 | 17 | fun alphanumericOnly(@StringRes errorRes: Int): AlphanumericRule = AlphanumericRule(errorRes) 18 | 19 | fun alphanumericOnly(errorMessage: String): AlphanumericRule = AlphanumericRule(errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/NotBlankRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class NotBlankRule : Rule { 7 | 8 | constructor(@StringRes errorRes: Int) : super(errorRes) 9 | 10 | constructor(errorMessage: String) : super(errorMessage) 11 | 12 | override fun validate(value: String?): Boolean { 13 | if (value == null) { 14 | throw NullPointerException() 15 | } else { 16 | return value.isNotBlank() 17 | } 18 | } 19 | } 20 | 21 | fun notBlank(@StringRes errorRes: Int): NotBlankRule = NotBlankRule(errorRes) 22 | 23 | fun notBlank(errorMessage: String): NotBlankRule = NotBlankRule(errorMessage) 24 | -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/NotEmptyRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class NotEmptyRule : Rule { 7 | 8 | constructor(@StringRes errorRes: Int) : super(errorRes) 9 | 10 | constructor(errorMessage: String) : super(errorMessage) 11 | 12 | override fun validate(value: String?): Boolean { 13 | if (value == null) { 14 | throw NullPointerException() 15 | } else { 16 | return value.isNotEmpty() 17 | } 18 | } 19 | } 20 | 21 | fun notEmpty(@StringRes errorRes: Int): NotEmptyRule = NotEmptyRule(errorRes) 22 | 23 | fun notEmpty(errorMessage: String): NotEmptyRule = NotEmptyRule(errorMessage) 24 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /library/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /sample/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | rootProject.sampleModulePlugins.each { 2 | apply plugin: it 3 | } 4 | 5 | android { 6 | def ext = rootProject.extensions.ext 7 | compileSdkVersion ext.android.compileSdkVersion 8 | defaultConfig { 9 | applicationId "io.github.anderscheow.validator" 10 | minSdkVersion ext.android.minSdkVersion 11 | targetSdkVersion ext.android.targetSdkVersion 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | rootProject.sampleModuleDependencies.each { 24 | add(it.configuration, it.dependency, it.options) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | android.useAndroidX=true 20 | android.enableJetifier=true -------------------------------------------------------------------------------- /library/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Settings specified in this file will override any Gradle settings 4 | # configured through the IDE. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 10 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 11 | # When configured, Gradle will run in incubating parallel mode. 12 | # This option should only be used with decoupled projects. More details, visit 13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 14 | # org.gradle.parallel=true 15 | POM_NAME=Validator 16 | POM_ARTIFACT_ID=validator 17 | POM_PACKAGING=aar 18 | -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/RegexRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | open class RegexRule : Rule { 7 | 8 | private var regex: String 9 | 10 | constructor(regex: String, @StringRes errorRes: Int) : super(errorRes) { 11 | this.regex = regex 12 | } 13 | 14 | constructor(regex: String, errorMessage: String) : super(errorMessage) { 15 | this.regex = regex 16 | } 17 | 18 | override fun validate(value: String?): Boolean { 19 | if (value == null) { 20 | throw NullPointerException() 21 | } else { 22 | return value.matches(regex.toRegex()) 23 | } 24 | } 25 | } 26 | 27 | fun regex(regex: String, @StringRes errorRes: Int): RegexRule = RegexRule(regex, errorRes) 28 | 29 | fun regex(regex: String, errorMessage: String): RegexRule = RegexRule(regex, errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/EqualRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class EqualRule : Rule { 7 | 8 | private var keyword: Any 9 | 10 | constructor(keyword: Any, @StringRes errorRes: Int) : 11 | super(errorRes) { 12 | this.keyword = keyword 13 | } 14 | 15 | constructor(keyword: Any, errorMessage: String) : 16 | super(errorMessage) { 17 | this.keyword = keyword 18 | } 19 | 20 | override fun validate(value: String?): Boolean { 21 | if (value == null) { 22 | throw NullPointerException() 23 | } else { 24 | return value == keyword 25 | } 26 | } 27 | } 28 | 29 | fun equalTo(keyword: String, @StringRes errorRes: Int): EqualRule = EqualRule(keyword, errorRes) 30 | 31 | fun equalTo(keyword: String, errorMessage: String): EqualRule = EqualRule(keyword, errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/NotEqualRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class NotEqualRule : Rule { 7 | 8 | private var keyword: Any 9 | 10 | constructor(keyword: Any, @StringRes errorRes: Int) : super(errorRes) { 11 | this.keyword = keyword 12 | } 13 | 14 | constructor(keyword: Any, errorMessage: String) : super(errorMessage) { 15 | this.keyword = keyword 16 | } 17 | 18 | override fun validate(value: String?): Boolean { 19 | if (value == null) { 20 | throw NullPointerException() 21 | } else { 22 | return value != keyword 23 | } 24 | } 25 | } 26 | 27 | fun notEqualTo(keyword: String, @StringRes errorRes: Int): NotEqualRule = 28 | NotEqualRule(keyword, errorRes) 29 | 30 | fun notEqualTo(keyword: String, errorMessage: String): NotEqualRule = 31 | NotEqualRule(keyword, errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/MinRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class MinRule : Rule { 7 | 8 | private var minLength: Int 9 | 10 | constructor(minLength: Int, @StringRes errorRes: Int) : 11 | super(errorRes) { 12 | this.minLength = minLength 13 | } 14 | 15 | constructor(minLength: Int, errorMessage: String) : 16 | super(errorMessage) { 17 | this.minLength = minLength 18 | } 19 | 20 | override fun validate(value: String?): Boolean { 21 | if (value == null) { 22 | throw NullPointerException() 23 | } else { 24 | return value.length >= minLength 25 | } 26 | } 27 | } 28 | 29 | fun minimumLength(minLength: Int, @StringRes errorRes: Int): MinRule = MinRule(minLength, errorRes) 30 | 31 | fun minimumLength(minLength: Int, errorMessage: String): MinRule = MinRule(minLength, errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/MaxRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class MaxRule : Rule { 7 | 8 | private var maxLength: Int 9 | 10 | constructor(maxLength: Int, @StringRes errorRes: Int) : 11 | super(errorRes) { 12 | this.maxLength = maxLength 13 | } 14 | 15 | constructor(maxLength: Int, errorMessage: String) : 16 | super(errorMessage) { 17 | this.maxLength = maxLength 18 | } 19 | 20 | override fun validate(value: String?): Boolean { 21 | if (value == null) { 22 | throw NullPointerException() 23 | } else { 24 | return value.length <= maxLength 25 | } 26 | } 27 | } 28 | 29 | fun maximumLength(maxLength: Int, @StringRes errorRes: Int): MaxRule = MaxRule(maxLength, errorRes) 30 | 31 | fun maximumLength(maxLength: Int, errorMessage: String): MaxRule = MaxRule(maxLength, errorMessage) 32 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | rootProject.libraryModulePlugins.each { 2 | apply plugin: it 3 | } 4 | 5 | android { 6 | def ext = rootProject.extensions.ext 7 | compileSdkVersion ext.android.compileSdkVersion 8 | defaultConfig { 9 | minSdkVersion ext.android.minSdkVersion 10 | targetSdkVersion ext.android.targetSdkVersion 11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | rootProject.libraryModuleDependencies.each { 23 | add(it.configuration, it.dependency, it.options) 24 | } 25 | } 26 | 27 | afterEvaluate { 28 | publishing { 29 | publications { 30 | release(MavenPublication) { 31 | from components.release 32 | groupId = "io.github.anderscheow" 33 | artifactId = "validator" 34 | version = "3.0.3" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2017-2018 Anders Cheow 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/android,mac 2 | 3 | ### Android ### 4 | # Built application files 5 | *.apk 6 | *.ap_ 7 | 8 | # Files for the ART/Dalvik VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # Generated files 15 | bin/ 16 | gen/ 17 | out/ 18 | 19 | # Gradle files 20 | .gradle/ 21 | build/ 22 | 23 | # Local configuration file (sdk path, etc) 24 | local.properties 25 | 26 | # Proguard folder generated by Eclipse 27 | proguard/ 28 | 29 | # Log Files 30 | *.log 31 | 32 | # Android Studio Navigation editor temp files 33 | .navigation/ 34 | 35 | # Android Studio captures folder 36 | captures/ 37 | 38 | # Intellij 39 | *.iml 40 | .idea/workspace.xml 41 | .idea/tasks.xml 42 | .idea/gradle.xml 43 | .idea/dictionaries 44 | .idea/libraries 45 | 46 | # External native build folder generated in Android Studio 2.2 and later 47 | .externalNativeBuild 48 | 49 | # Freeline 50 | freeline.py 51 | freeline/ 52 | freeline_project_description.json 53 | 54 | ### Android Patch ### 55 | gen-external-apklibs 56 | 57 | #!! ERROR: mac is undefined. Use list command to see defined gitignore types !!# 58 | 59 | # End of https://www.gitignore.io/api/android,mac 60 | .idea 61 | -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/AllLowerCaseRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | import java.util.* 6 | 7 | class AllLowerCaseRule : Rule { 8 | 9 | private var locale: Locale 10 | 11 | constructor(@StringRes errorRes: Int, locale: Locale = Locale.getDefault()) 12 | : super(errorRes) { 13 | this.locale = locale 14 | } 15 | 16 | constructor(errorMessage: String, locale: Locale = Locale.getDefault()) 17 | : super(errorMessage) { 18 | this.locale = locale 19 | } 20 | 21 | override fun validate(value: String?): Boolean { 22 | if (value == null) { 23 | throw NullPointerException() 24 | } else { 25 | return value.lowercase(locale) == value 26 | } 27 | } 28 | } 29 | 30 | fun allLowercase( 31 | @StringRes errorRes: Int, 32 | locale: Locale = Locale.getDefault() 33 | ): AllLowerCaseRule = AllLowerCaseRule(errorRes, locale) 34 | 35 | fun allLowercase( 36 | errorMessage: String, 37 | locale: Locale = Locale.getDefault() 38 | ): AllLowerCaseRule = AllLowerCaseRule(errorMessage, locale) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/AllUpperCaseRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | import java.util.* 6 | 7 | class AllUpperCaseRule : Rule { 8 | 9 | private var locale: Locale 10 | 11 | constructor(@StringRes errorRes: Int, locale: Locale = Locale.getDefault()) 12 | : super(errorRes) { 13 | this.locale = locale 14 | } 15 | 16 | constructor(errorMessage: String, locale: Locale = Locale.getDefault()) 17 | : super(errorMessage) { 18 | this.locale = locale 19 | } 20 | 21 | override fun validate(value: String?): Boolean { 22 | if (value == null) { 23 | throw NullPointerException() 24 | } else { 25 | return value.uppercase(locale) == value 26 | } 27 | } 28 | } 29 | 30 | fun allUppercase( 31 | @StringRes errorRes: Int, 32 | locale: Locale = Locale.getDefault() 33 | ): AllUpperCaseRule = AllUpperCaseRule(errorRes, locale) 34 | 35 | fun allUppercase( 36 | errorMessage: String, 37 | locale: Locale = Locale.getDefault() 38 | ): AllUpperCaseRule = AllUpperCaseRule(errorMessage, locale) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/regex/PasswordRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.regex 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.common.RegexRule 5 | 6 | class PasswordRule : RegexRule { 7 | 8 | enum class PasswordRegex constructor(private val value: String) { 9 | ANY(".+"), 10 | ALPHA("\\w+"), 11 | ALPHA_MIXED_CASE("(?=.*[a-z])(?=.*[A-Z]).+"), 12 | NUMERIC("\\d+"), 13 | ALPHA_NUMERIC("(?=.*[a-zA-Z])(?=.*[\\d]).+"), 14 | ALPHA_NUMERIC_SYMBOLS("(?=.*[a-zA-Z])(?=.*[\\d])(?=.*([^\\w])).+"); 15 | 16 | override fun toString(): String { 17 | return value 18 | } 19 | } 20 | 21 | constructor(regex: PasswordRegex, @StringRes errorRes: Int) : super(regex.toString(), errorRes) 22 | 23 | constructor(regex: PasswordRegex, errorMessage: String) : super(regex.toString(), errorMessage) 24 | } 25 | 26 | fun withPassword( 27 | regex: PasswordRule.PasswordRegex, 28 | @StringRes errorRes: Int 29 | ): PasswordRule = PasswordRule(regex, errorRes) 30 | 31 | fun withPassword(regex: PasswordRule.PasswordRegex, errorMessage: String): PasswordRule = 32 | PasswordRule(regex, errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/interfaces/ErrorImpl.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.interfaces 2 | 3 | import android.content.Context 4 | import androidx.annotation.StringRes 5 | 6 | abstract class ErrorImpl { 7 | 8 | @StringRes 9 | var errorRes: Int = -1 10 | private set 11 | 12 | var errorString: String = "Invalid input" 13 | private set 14 | 15 | val isErrorAvailable: Boolean 16 | get() = isErrorResAvailable || isErrorMessageAvailable 17 | 18 | val isErrorResAvailable: Boolean 19 | get() = errorRes != -1 20 | 21 | val isErrorMessageAvailable: Boolean 22 | get() = errorString.isNotBlank() 23 | 24 | constructor(errorRes: Int) { 25 | this.errorRes = errorRes 26 | } 27 | 28 | constructor(errorString: String) { 29 | this.errorString = errorString 30 | } 31 | 32 | fun getErrorMessage(context: Context): String { 33 | return when { 34 | isErrorResAvailable -> { 35 | context.getString(errorRes) 36 | } 37 | isErrorMessageAvailable -> { 38 | errorString 39 | } 40 | else -> { 41 | throw IllegalStateException("Please either use errorRes or errorMessage as your error output") 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/PastRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | import java.text.DateFormat 6 | import java.text.ParseException 7 | import java.util.* 8 | 9 | class PastRule : Rule { 10 | 11 | private var dateFormat: DateFormat 12 | 13 | constructor(dateFormat: DateFormat, @StringRes errorRes: Int) : super(errorRes) { 14 | this.dateFormat = dateFormat 15 | } 16 | 17 | constructor(dateFormat: DateFormat, errorMessage: String) : super(errorMessage) { 18 | this.dateFormat = dateFormat 19 | } 20 | 21 | override fun validate(value: String?): Boolean { 22 | if (value == null) { 23 | throw NullPointerException() 24 | } else { 25 | var parsedDate: Date? = null 26 | 27 | try { 28 | parsedDate = dateFormat.parse(value) 29 | } catch (ignored: ParseException) { 30 | } 31 | 32 | return parsedDate != null && parsedDate.before(Date()) 33 | } 34 | } 35 | } 36 | 37 | fun past(dateFormat: DateFormat, @StringRes errorRes: Int): PastRule = 38 | PastRule(dateFormat, errorRes) 39 | 40 | fun past(dateFormat: DateFormat, errorMessage: String): PastRule = 41 | PastRule(dateFormat, errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/ContainRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class ContainRule : Rule { 7 | 8 | private var keyword: String 9 | 10 | private var ignoreCase = false 11 | 12 | constructor(keyword: String, @StringRes errorRes: Int, ignoreCase: Boolean = false) : 13 | super(errorRes) { 14 | this.keyword = keyword 15 | this.ignoreCase = ignoreCase 16 | } 17 | 18 | constructor(keyword: String, errorMessage: String, ignoreCase: Boolean = false) : 19 | super(errorMessage) { 20 | this.keyword = keyword 21 | this.ignoreCase = ignoreCase 22 | } 23 | 24 | override fun validate(value: String?): Boolean { 25 | if (value == null) { 26 | throw NullPointerException() 27 | } else { 28 | return value.contains(keyword, ignoreCase) 29 | } 30 | } 31 | } 32 | 33 | fun contain( 34 | keyword: String, 35 | @StringRes errorRes: Int, 36 | ignoreCase: Boolean = false 37 | ): ContainRule = ContainRule(keyword, errorRes, ignoreCase) 38 | 39 | fun contain( 40 | keyword: String, 41 | errorMessage: String, 42 | ignoreCase: Boolean = false 43 | ): ContainRule = ContainRule(keyword, errorMessage, ignoreCase) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/EndsWithRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class EndsWithRule : Rule { 7 | 8 | private var keyword: String 9 | 10 | private var ignoreCase = false 11 | 12 | constructor(keyword: String, @StringRes errorRes: Int, ignoreCase: Boolean = false) : 13 | super(errorRes) { 14 | this.keyword = keyword 15 | this.ignoreCase = ignoreCase 16 | } 17 | 18 | constructor(keyword: String, errorMessage: String, ignoreCase: Boolean = false) : 19 | super(errorMessage) { 20 | this.keyword = keyword 21 | this.ignoreCase = ignoreCase 22 | } 23 | 24 | override fun validate(value: String?): Boolean { 25 | if (value == null) { 26 | throw NullPointerException() 27 | } else { 28 | return value.endsWith(keyword, ignoreCase) 29 | } 30 | } 31 | } 32 | 33 | fun endsWith( 34 | keyword: String, 35 | @StringRes errorRes: Int, 36 | ignoreCase: Boolean = false 37 | ): EndsWithRule = EndsWithRule(keyword, errorRes, ignoreCase) 38 | 39 | fun endsWith( 40 | keyword: String, 41 | errorMessage: String, 42 | ignoreCase: Boolean = false 43 | ): EndsWithRule = EndsWithRule(keyword, errorMessage, ignoreCase) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/NotContainRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class NotContainRule : Rule { 7 | 8 | private var keyword: String 9 | 10 | private var ignoreCase = false 11 | 12 | constructor(keyword: String, @StringRes errorRes: Int, ignoreCase: Boolean = false) : 13 | super(errorRes) { 14 | this.keyword = keyword 15 | this.ignoreCase = ignoreCase 16 | } 17 | 18 | constructor(keyword: String, errorMessage: String, ignoreCase: Boolean = false) : 19 | super(errorMessage) { 20 | this.keyword = keyword 21 | this.ignoreCase = ignoreCase 22 | } 23 | 24 | override fun validate(value: String?): Boolean { 25 | if (value == null) { 26 | throw NullPointerException() 27 | } else { 28 | return !value.contains(keyword, ignoreCase) 29 | } 30 | } 31 | } 32 | 33 | fun notContain( 34 | keyword: String, 35 | @StringRes errorRes: Int, 36 | ignoreCase: Boolean = false 37 | ): NotContainRule = NotContainRule(keyword, errorRes, ignoreCase) 38 | 39 | fun notContain( 40 | keyword: String, 41 | errorMessage: String, 42 | ignoreCase: Boolean = false 43 | ): NotContainRule = NotContainRule(keyword, errorMessage, ignoreCase) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/StartsWithRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | 6 | class StartsWithRule : Rule { 7 | 8 | private var keyword: String 9 | 10 | private var ignoreCase = false 11 | 12 | constructor(keyword: String, @StringRes errorRes: Int, ignoreCase: Boolean = false) : 13 | super(errorRes) { 14 | this.keyword = keyword 15 | this.ignoreCase = ignoreCase 16 | } 17 | 18 | constructor(keyword: String, errorMessage: String, ignoreCase: Boolean = false) : 19 | super(errorMessage) { 20 | this.keyword = keyword 21 | this.ignoreCase = ignoreCase 22 | } 23 | 24 | override fun validate(value: String?): Boolean { 25 | if (value == null) { 26 | throw NullPointerException() 27 | } else { 28 | return value.startsWith(keyword, ignoreCase) 29 | } 30 | } 31 | } 32 | 33 | fun startsWith( 34 | keyword: String, 35 | @StringRes errorRes: Int, 36 | ignoreCase: Boolean = false 37 | ): StartsWithRule = StartsWithRule(keyword, errorRes, ignoreCase) 38 | 39 | fun startsWith( 40 | keyword: String, 41 | errorMessage: String, 42 | ignoreCase: Boolean = false 43 | ): StartsWithRule = StartsWithRule(keyword, errorMessage, ignoreCase) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/regex/CreditCardRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.regex 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.common.RegexRule 5 | 6 | class CreditCardRule : RegexRule { 7 | 8 | enum class CreditCardRegex(private val value: String) { 9 | VISA("^4[0-9]{12}(?:[0-9]{3})?$"), 10 | MASTERCARD("^5[1-5][0-9]{14}$"), 11 | AMERICAN_EXPRESS("^3[47][0-9]{13}$"), 12 | DINERS_CLUB("^3(?:0[0-5]|[68][0-9])[0-9]{11}$"), 13 | DISCOVER("^6(?:011|5[0-9]{2})[0-9]{12}$"), 14 | JCB("^(?:2131|1800|35\\d{3})\\d{11}$"), 15 | CHINA_UNION_PAY("^62[0-9]{14,17}$"); 16 | 17 | override fun toString(): String { 18 | return value 19 | } 20 | } 21 | 22 | constructor(regex: CreditCardRegex, @StringRes errorRes: Int) : super( 23 | regex.toString(), 24 | errorRes 25 | ) 26 | 27 | constructor(regex: CreditCardRegex, errorMessage: String) : super( 28 | regex.toString(), 29 | errorMessage 30 | ) 31 | } 32 | 33 | fun withCreditCard( 34 | regex: CreditCardRule.CreditCardRegex, 35 | @StringRes errorRes: Int 36 | ): CreditCardRule = CreditCardRule(regex, errorRes) 37 | 38 | fun withCreditCard(regex: CreditCardRule.CreditCardRegex, errorMessage: String): CreditCardRule = 39 | CreditCardRule(regex, errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/rules/common/FutureRule.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.rules.Rule 5 | import java.text.DateFormat 6 | import java.text.ParseException 7 | import java.util.* 8 | 9 | class FutureRule : Rule { 10 | 11 | private var dateFormat: DateFormat 12 | 13 | constructor(dateFormat: DateFormat, @StringRes errorRes: Int) : 14 | super(errorRes) { 15 | this.dateFormat = dateFormat 16 | } 17 | 18 | constructor(dateFormat: DateFormat, errorMessage: String) : 19 | super(errorMessage) { 20 | this.dateFormat = dateFormat 21 | } 22 | 23 | override fun validate(value: String?): Boolean { 24 | if (value == null) { 25 | throw NullPointerException() 26 | } else { 27 | var parsedDate: Date? = null 28 | 29 | try { 30 | parsedDate = dateFormat.parse(value) 31 | } catch (ignored: ParseException) { 32 | } 33 | 34 | return parsedDate != null && parsedDate.after(Date()) 35 | } 36 | } 37 | } 38 | 39 | fun future(dateFormat: DateFormat, @StringRes errorRes: Int): FutureRule = 40 | FutureRule(dateFormat, errorRes) 41 | 42 | fun future(dateFormat: DateFormat, errorMessage: String): FutureRule = 43 | FutureRule(dateFormat, errorMessage) -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/conditions/common/Or.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.conditions.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.conditions.Condition 5 | import io.github.anderscheow.validator.conditions.ConditionBuilder 6 | import io.github.anderscheow.validator.conditions.ConditionsBuilder 7 | import io.github.anderscheow.validator.rules.Rule 8 | 9 | class Or : Condition { 10 | 11 | constructor(rules: List, @StringRes errorRes: Int) : super(rules, errorRes) 12 | 13 | constructor(rules: List, errorMessage: String) : super(rules, errorMessage) 14 | 15 | constructor(rule: Rule, @StringRes errorRes: Int) : super(listOf(rule), errorRes) 16 | 17 | constructor(rule: Rule, errorMessage: String) : super(listOf(rule), errorMessage) 18 | 19 | override fun validate(value: String?): Boolean { 20 | for (baseRule in rules) { 21 | if (baseRule.validate(value)) { 22 | return true 23 | } 24 | } 25 | return false 26 | } 27 | } 28 | 29 | class OrBuilder : ConditionBuilder() { 30 | } 31 | 32 | fun ConditionsBuilder.or( 33 | @StringRes errorRes: Int, 34 | init: OrBuilder.() -> Unit 35 | ): Or { 36 | val or = OrBuilder() 37 | or.init() 38 | return Or(or.ruleList, errorRes) 39 | } 40 | 41 | fun ConditionsBuilder.or( 42 | errorMessage: String, 43 | init: OrBuilder.() -> Unit 44 | ): Or { 45 | val or = OrBuilder() 46 | or.init() 47 | return Or(or.ruleList, errorMessage) 48 | } -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/conditions/common/And.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.conditions.common 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.conditions.Condition 5 | import io.github.anderscheow.validator.conditions.ConditionBuilder 6 | import io.github.anderscheow.validator.conditions.ConditionsBuilder 7 | import io.github.anderscheow.validator.rules.Rule 8 | 9 | class And : Condition { 10 | 11 | constructor(rules: List, @StringRes errorRes: Int) : super(rules, errorRes) 12 | 13 | constructor(rules: List, errorMessage: String) : super(rules, errorMessage) 14 | 15 | constructor(rule: Rule, @StringRes errorRes: Int) : super(listOf(rule), errorRes) 16 | 17 | constructor(rule: Rule, errorMessage: String) : super(listOf(rule), errorMessage) 18 | 19 | override fun validate(value: String?): Boolean { 20 | for (baseRule in rules) { 21 | if (baseRule.validate(value).not()) { 22 | return false 23 | } 24 | } 25 | return true 26 | } 27 | } 28 | 29 | class AndBuilder : ConditionBuilder() { 30 | } 31 | 32 | fun ConditionsBuilder.and( 33 | @StringRes errorRes: Int, 34 | init: AndBuilder.() -> Unit 35 | ): And { 36 | val and = AndBuilder() 37 | and.init() 38 | return And(and.ruleList, errorRes) 39 | } 40 | 41 | fun ConditionsBuilder.and( 42 | errorMessage: String, 43 | init: AndBuilder.() -> Unit 44 | ): And { 45 | val and = AndBuilder() 46 | and.init() 47 | return And(and.ruleList, errorMessage) 48 | } -------------------------------------------------------------------------------- /library/src/test/java/io/github/anderscheow/validator/rules/common/NotNullRuleTest.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules.common 2 | 3 | import androidx.annotation.StringRes 4 | import org.junit.After 5 | import org.junit.Assert.* 6 | import org.junit.Before 7 | import org.junit.Test 8 | 9 | class NotNullRuleTest { 10 | 11 | private lateinit var notNullRule: NotNullRule 12 | 13 | @Before 14 | @Throws(Exception::class) 15 | fun setUp() { 16 | } 17 | 18 | @After 19 | @Throws(Exception::class) 20 | fun tearDown() { 21 | } 22 | 23 | @Test 24 | @Throws(Exception::class) 25 | fun validate_ValidSample_ReturnTrue() { 26 | notNullRule = NotNullRule("") 27 | 28 | val sample = "test" 29 | 30 | assertTrue(notNullRule.validate(sample)) 31 | } 32 | 33 | @Test 34 | @Throws(Exception::class) 35 | fun validate_InvalidSample_ReturnFalse() { 36 | notNullRule = NotNullRule("") 37 | 38 | assertFalse(notNullRule.validate(null)) 39 | } 40 | 41 | @Test 42 | @Throws(Exception::class) 43 | fun errorMessage_CustomErrorMessage() { 44 | val errorMessage = "This is a custom error message" 45 | 46 | notNullRule = NotNullRule(errorMessage) 47 | 48 | assertEquals(errorMessage, notNullRule.errorString) 49 | } 50 | 51 | @Test 52 | @Throws(Exception::class) 53 | fun errorMessage_CustomErrorRes() { 54 | @StringRes val errorRes = 0 55 | 56 | notNullRule = NotNullRule(errorRes) 57 | 58 | assertEquals(errorRes, notNullRule.errorRes) 59 | } 60 | } -------------------------------------------------------------------------------- /library/src/main/java/io/github/anderscheow/validator/conditions/Condition.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.conditions 2 | 3 | import androidx.annotation.StringRes 4 | import io.github.anderscheow.validator.interfaces.ErrorImpl 5 | import io.github.anderscheow.validator.interfaces.Validate 6 | import io.github.anderscheow.validator.rules.Rule 7 | import io.github.anderscheow.validator.rules.RulesBuilder 8 | 9 | abstract class Condition : ErrorImpl, Validate { 10 | 11 | val rules: List 12 | 13 | constructor(rules: List, @StringRes errorRes: Int) : super(errorRes) { 14 | this.rules = rules 15 | } 16 | 17 | constructor(rules: List, errorString: String) : super(errorString) { 18 | this.rules = rules 19 | } 20 | 21 | constructor(rule: Rule, @StringRes errorRes: Int) : super(errorRes) { 22 | this.rules = listOf(rule) 23 | } 24 | 25 | constructor(rule: Rule, errorString: String) : super(errorString) { 26 | this.rules = listOf(rule) 27 | } 28 | } 29 | 30 | class ConditionsBuilder { 31 | val conditionList = arrayListOf() 32 | 33 | operator fun Condition.unaryPlus() { 34 | conditionList.add(this) 35 | } 36 | } 37 | 38 | open class ConditionBuilder { 39 | val ruleList = arrayListOf() 40 | 41 | fun rules(init: RulesBuilder.() -> Unit) { 42 | ruleList.addAll(RulesBuilder().apply(init).ruleList) 43 | } 44 | 45 | operator fun Rule.unaryPlus() { 46 | ruleList.add(this) 47 | } 48 | 49 | operator fun List.unaryPlus() { 50 | ruleList.addAll(this) 51 | } 52 | } -------------------------------------------------------------------------------- /library/src/test/java/io/github/anderscheow/validator/rules/RuleTest.kt: -------------------------------------------------------------------------------- 1 | package io.github.anderscheow.validator.rules 2 | 3 | import androidx.annotation.StringRes 4 | import org.junit.After 5 | import org.junit.Assert.* 6 | import org.junit.Before 7 | import org.junit.Test 8 | 9 | class RuleTest { 10 | 11 | private lateinit var rule: Rule 12 | 13 | @Before 14 | @Throws(Exception::class) 15 | fun setUp() { 16 | } 17 | 18 | @After 19 | @Throws(Exception::class) 20 | fun tearDown() { 21 | } 22 | 23 | @Test 24 | @Throws(Exception::class) 25 | fun errorMessage_CustomErrorMessage() { 26 | val errorMessage = "This is a custom error message" 27 | 28 | rule = object : Rule(errorMessage) { 29 | override fun validate(value: String?): Boolean { 30 | return false 31 | } 32 | } 33 | 34 | assertEquals(errorMessage, rule.errorString) 35 | assertTrue(rule.isErrorAvailable) 36 | assertTrue(rule.isErrorMessageAvailable) 37 | assertFalse(rule.isErrorResAvailable) 38 | } 39 | 40 | @Test 41 | @Throws(Exception::class) 42 | fun errorMessage_CustomErrorRes() { 43 | @StringRes val errorRes = 0 44 | 45 | rule = object : Rule(errorRes) { 46 | override fun validate(value: String?): Boolean { 47 | return false 48 | } 49 | } 50 | 51 | assertEquals(errorRes, rule.errorRes) 52 | assertTrue(rule.isErrorAvailable) 53 | assertTrue(rule.isErrorMessageAvailable) 54 | assertTrue(rule.isErrorResAvailable) 55 | } 56 | } -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 19 | 20 | 21 | 25 | 26 | 30 | 31 | 32 |