dev.forkhandles.values.factories.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of values4k Show documentation
Show all versions of values4k Show documentation
ForkHandles Value-types library
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) })