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

dev.forkhandles.values.factories.kt Maven / Gradle / Ivy

The newest version!
package dev.forkhandles.values

import java.io.File
import java.math.BigDecimal
import java.math.BigInteger
import java.net.URI
import java.net.URL
import java.time.Duration
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.OffsetDateTime
import java.time.OffsetTime
import java.time.Period
import java.time.Year
import java.time.YearMonth
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeFormatter.ISO_INSTANT
import java.time.format.DateTimeFormatter.ISO_LOCAL_DATE
import java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME
import java.time.format.DateTimeFormatter.ISO_LOCAL_TIME
import java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME
import java.time.format.DateTimeFormatter.ISO_OFFSET_TIME
import java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME
import java.time.format.DateTimeFormatter.ofPattern
import java.util.Base64
import java.util.UUID


private val rfcBase64Alphabet get() = "^[0-9A-Za-z+/=]+$".toRegex() // https://www.rfc-editor.org/rfc/rfc4648.html#section-4
private val rfcBase32Alphabet get() = "^[2-7A-Z=]+$".toRegex()  // https://www.rfc-editor.org/rfc/rfc4648.html#section-6
private val rfcBase16Alphabet get() = "^[0-9A-F]+$".toRegex() // https://www.rfc-editor.org/rfc/rfc4648.html#section-8
private val base36Alphabet get() = "^[0-9A-Z=]+$".toRegex()

open class StringValueFactory>(
    fn: (String) -> DOMAIN, validation: Validation? = null,
    showFn: (String) -> String = { it }
) : ValueFactory(fn, validation, { it }, showFn)

open class NonEmptyStringValueFactory>(
    fn: (String) -> DOMAIN,
    showFn: (String) -> String = { it }
) : ValueFactory(fn, 1.minLength, { it }, showFn)

open class NonBlankStringValueFactory>(
    fn: (String) -> DOMAIN,
    showFn: (String) -> String = { it }
) : ValueFactory(fn, 1.minLength.let { v -> { v(it.trim()) } }, { it }, showFn)

open class Base64StringValueFactory>(
    fn: (String) -> DOMAIN,
    validation: Validation = { true },
    parseFn: (String) -> String = { it },
    showFn: (String) -> String = { it },
) : ValueFactory(fn, rfcBase64Alphabet::matches.and(validation), parseFn, showFn) {
    private val encoder = Base64.getEncoder()
    fun encode(value: ByteArray) = encoder.encodeToString(value).let(coerceFn)
}

open class Base36StringValueFactory>(
    fn: (String) -> DOMAIN,
    validation: Validation = { true },
    parseFn: (String) -> String = { it },
    showFn: (String) -> String = { it },
) : ValueFactory(fn, base36Alphabet::matches.and(validation), parseFn, showFn)

open class Base32StringValueFactory>(
    fn: (String) -> DOMAIN,
    validation: Validation = { true },
    parseFn: (String) -> String = { it },
    showFn: (String) -> String = { it },
) : ValueFactory(fn, rfcBase32Alphabet::matches.and(validation), parseFn, showFn)

open class Base16StringValueFactory>(
    fn: (String) -> DOMAIN,
    validation: Validation = { true },
    parseFn: (String) -> String = { it },
    showFn: (String) -> String = { it },
) : ValueFactory(fn, rfcBase16Alphabet::matches.and(validation), parseFn, showFn) {
    // Source: https://stackoverflow.com/a/9855338/1253613
    private val base16Chars = "0123456789ABCDEF".toCharArray()
    fun encode(bytes: ByteArray): DOMAIN {
        val hexChars = CharArray(bytes.size * 2)
        for (j in bytes.indices) {
            val v = bytes[j].toInt() and 0xFF
            hexChars[j * 2] = this.base16Chars[v ushr 4]
            hexChars[j * 2 + 1] = this.base16Chars[v and 0x0F]
        }
        return String(hexChars).let(coerceFn)
    }
}

open class CharValueFactory>(
    fn: (Char) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, String::first)

open class IntValueFactory>(
    fn: (Int) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, String::toInt)

open class LongValueFactory>(
    fn: (Long) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, String::toLong)

open class DoubleValueFactory>(
    fn: (Double) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, String::toDouble)

open class FloatValueFactory>(
    fn: (Float) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, String::toFloat)

open class BooleanValueFactory>(
    fn: (Boolean) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, String::toBoolean)

open class BigIntegerValueFactory>(
    fn: (BigInteger) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, String::toBigInteger)

open class BigDecimalValueFactory>(
    fn: (BigDecimal) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, String::toBigDecimal)

open class UUIDValueFactory>(
    fn: (UUID) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, UUID::fromString)

open class URLValueFactory>(
    fn: (URL) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, { URI.create(it).toURL() })

open class DurationValueFactory>(
    fn: (Duration) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, { Duration.parse(it) })

open class InstantValueFactory>(
    fn: (Instant) -> DOMAIN, validation: Validation? = null,
    fmt: DateTimeFormatter = ISO_INSTANT
) : ValueFactory(fn, validation, { fmt.parse(it, Instant::from) }, fmt::format)

open class LocalDateValueFactory>(
    fn: (LocalDate) -> DOMAIN, validation: Validation? = null,
    fmt: DateTimeFormatter = ISO_LOCAL_DATE
) : ValueFactory(fn, validation, { LocalDate.parse(it, fmt) }, fmt::format)

open class LocalTimeValueFactory>(
    fn: (LocalTime) -> DOMAIN,
    validation: Validation? = null,
    fmt: DateTimeFormatter = ISO_LOCAL_TIME
) : ValueFactory(fn, validation, { LocalTime.parse(it, fmt) }, fmt::format)

open class LocalDateTimeValueFactory>(
    fn: (LocalDateTime) -> DOMAIN,
    validation: Validation? = null,
    fmt: DateTimeFormatter = ISO_LOCAL_DATE_TIME
) : ValueFactory(fn, validation, { LocalDateTime.parse(it, fmt) }, fmt::format)

open class OffsetDateTimeValueFactory>(
    fn: (OffsetDateTime) -> DOMAIN,
    validation: Validation? = null,
    fmt: DateTimeFormatter = ISO_OFFSET_DATE_TIME
) : ValueFactory(fn, validation, { OffsetDateTime.parse(it, fmt) }, fmt::format)

open class OffsetTimeValueFactory>(
    fn: (OffsetTime) -> DOMAIN,
    validation: Validation? = null,
    fmt: DateTimeFormatter = ISO_OFFSET_TIME
) : ValueFactory(fn, validation, { OffsetTime.parse(it, fmt) }, fmt::format)

open class PeriodValueFactory>(
    fn: (Period) -> DOMAIN,
    validation: Validation? = null
) : ValueFactory(fn, validation, { Period.parse(it) })

open class YearMonthValueFactory>(
    fn: (YearMonth) -> DOMAIN,
    validation: Validation? = null,
    fmt: DateTimeFormatter = ofPattern("yyyy-MM")
) : ValueFactory(fn, validation, { YearMonth.parse(it, fmt) }, fmt::format)

open class YearValueFactory>(
    fn: (Year) -> DOMAIN,
    validation: Validation? = null,
    fmt: DateTimeFormatter = ofPattern("yyyy")
) : ValueFactory(fn, validation, { Year.parse(it, fmt) }, fmt::format)

open class ZonedDateTimeValueFactory>(
    fn: (ZonedDateTime) -> DOMAIN,
    validation: Validation? = null,
    fmt: DateTimeFormatter = ISO_ZONED_DATE_TIME
) : ValueFactory(fn, validation, { ZonedDateTime.parse(it, fmt) }, fmt::format)

open class FileValueFactory>(
    fn: (File) -> DOMAIN, validation: Validation? = null
) : ValueFactory(fn, validation, { File(it) })





© 2015 - 2024 Weber Informatics LLC | Privacy Policy