All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jetbrains.exodus.entitystore.constraints.PropertyConstraints.kt Maven / Gradle / Ivy

/**
 * Copyright 2006 - 2017 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jetbrains.exodus.entitystore.constraints

import com.jetbrains.teamsys.dnq.database.PropertyConstraint
import java.net.MalformedURLException
import java.net.URL
import java.util.regex.Pattern

open class alpha(var message: String = "should contain only letters") : PropertyConstraint() {
    override fun isValid(value: String?) = value == null || value.all { it.isLetter() }

    override fun getExceptionMessage(propertyName: String, propertyValue: String?): String {
        return "$propertyName should contain only alpha characters but was $propertyValue"
    }

    override fun getDisplayMessage(propertyName: String, propertyValue: String?) = message
}

open class numeric(var message: String = "should contain only digits") : PropertyConstraint() {
    override fun isValid(value: String?) = value == null || value.all { it.isDigit() }

    override fun getExceptionMessage(propertyName: String, propertyValue: String?): String {
        return "$propertyName should contain only numeric characters but was $propertyValue"
    }

    override fun getDisplayMessage(propertyName: String, propertyValue: String?) = message
}


open class alphaNumeric(var message: String = "should contain only letters and digits") : PropertyConstraint() {
    override fun isValid(value: String?) = value == null || value.all { it.isLetterOrDigit() }

    override fun getExceptionMessage(propertyName: String, propertyValue: String?): String {
        return "$propertyName should contain only alpha and numeric characters but was $propertyValue"
    }

    override fun getDisplayMessage(propertyName: String, propertyValue: String?) = message
}

open class containsNone(var chars: String = "", var message: String = "shouldn't contain characters %s") : PropertyConstraint() {
    override fun isValid(value: String?) = containsNone(value, *chars.toCharArray())

    override fun getExceptionMessage(propertyName: String, propertyValue: String?): String {
        return "$propertyName shouldn't contain chars ${toCommaSeparatedList()} but was $propertyValue"
    }

    override fun getDisplayMessage(propertyName: String, propertyValue: String?): String {
        return String.format(message, toCommaSeparatedList())
    }

    private fun toCommaSeparatedList(): String {
        return chars.asSequence().joinToString { "'$it'" }
    }
}

class notBlank(var message: String = "shouldn't be blank") : PropertyConstraint() {
    override fun isValid(value: String?): Boolean = !value.isNullOrBlank()

    override fun getExceptionMessage(propertyName: String, propertyValue: String?): String {
        return "$propertyName shouldn't be blank"
    }

    override fun getDisplayMessage(propertyName: String, propertyValue: String?) = message
}

open class url(var message: String = "is not a valid URL") : PropertyConstraint() {
    override fun isValid(propertyValue: String?): Boolean {
        if (propertyValue == null) {
            return true
        }
        return try {
            URL(propertyValue)
            true
        } catch (e: MalformedURLException) {
            false
        }

    }

    override fun getExceptionMessage(propertyName: String, propertyValue: String?): String {
        return "$propertyName should be valid url but was $propertyValue"
    }

    override fun getDisplayMessage(propertyName: String, propertyValue: String?) = message
}

open class regexp(var pattern: Pattern, var message: String = "wrong value format") : PropertyConstraint() {
    override fun isValid(value: String?) = value == null || pattern.matcher(value).matches()

    override fun getExceptionMessage(propertyName: String, propertyValue: String?): String {
        return "$propertyName should match pattern $pattern but was $propertyValue"
    }

    override fun getDisplayMessage(propertyName: String, propertyValue: String?): String = message
}

internal val EMAIL_PATTERN = Pattern.compile("[\\w\\-]+(?:[\\+\\.][\\w\\-]+)*@(?:[\\w\\-]+\\.)+[a-z]{2,}", 2)

open class email(message: String = "is not a valid email") : regexp(EMAIL_PATTERN, message) {

    override fun getExceptionMessage(propertyName: String, propertyValue: String?): String {
        return "$propertyName should be valid email but was $propertyValue"
    }
}

open class length(
        var min: Int = 0,
        var max: Int = Int.MAX_VALUE,
        var minMessage: String = "should be at least %d characters long",
        var maxMessage: String = "should be at most %d characters long",
        var rangeMessage: String = "should be from %d to %d characters long"
) : PropertyConstraint() {

    override fun isValid(value: String?) = (value?.length ?: 0) in min..max

    override fun getExceptionMessage(propertyName: String, propertyValue: String?): String {
        return "Length of $propertyName should be in range [$min, $max] but was [${propertyValue?.length ?: 0}]"
    }

    override fun getDisplayMessage(propertyName: String, propertyValue: String?): String {
        return if (min > 0 && max < Int.MAX_VALUE) {
            String.format(rangeMessage, min, max)
        } else if (min > 0) {
            String.format(minMessage, min)
        } else {
            String.format(maxMessage, max)
        }
    }
}

open class inRange(
        var min: Long = 0,
        var max: Long = Long.MAX_VALUE,
        var minMessage: String = "should be at least %d",
        var maxMessage: String = "should be at most %d",
        var rangeMessage: String = "should be in range from %d to %d"

) : PropertyConstraint() {

    override fun isValid(value: T) = value == null || value.toLong() in min..max

    override fun getExceptionMessage(propertyName: String, propertyValue: T): String {
        return "$propertyName should be in range [$min, $max] but was $propertyValue"
    }

    override fun getDisplayMessage(propertyName: String, propertyValue: T): String {
        return if (min > 0 && max < Long.MAX_VALUE) {
            String.format(rangeMessage, min, max)
        } else if (min > 0) {
            String.format(minMessage, min)
        } else {
            String.format(maxMessage, max)
        }
    }
}

internal fun containsNone(value: String?, vararg searchChars: Char): Boolean {
    if (value == null) {
        return true
    }

    val length = value.length
    val lastIndex = length - 1
    val searchRange = 0 until searchChars.size
    val lastSearchIndex = searchChars.size - 1

    (0 until length).forEach { i ->
        val ch = value[i]
        searchRange.forEach { j ->
            if (searchChars[j] == ch) {
                if (Character.isHighSurrogate(ch)) {
                    if (j == lastSearchIndex) {
                        return false
                    }
                    if (i < lastIndex && searchChars[j + 1] == value[i + 1]) {
                        return false
                    }
                } else {
                    return false
                }
            }
        }
    }

    return true
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy