Last active
January 22, 2021 19:05
-
-
Save asvid/5fed8dd3c831c2a72744e8ffe8f7dc0f to your computer and use it in GitHub Desktop.
Kotlin DSL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class Address( | |
val streetName: String, | |
val cityName: String, | |
val streetNumber: String, | |
val postalCode: String | |
) | |
fun address(block: AddressBuilder.() -> Unit) = AddressBuilder().apply(block).build() | |
@ShopDsl | |
class AddressBuilder { | |
var streetName = "" | |
var cityName = "" | |
var streetNumber = "" | |
var postalCode = "" | |
fun build(): Address = Address(streetName, cityName, streetNumber, postalCode) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum class Feature { | |
Bakery, Relax, Atm, CardPayment, TaxFreeShopping, EuroAccepted, NewShop | |
} | |
@ShopDsl | |
class FeaturesBuilder(private val features: Array<out Feature>) { | |
fun build(): Set<Feature> { | |
return features.toSet() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class Location( | |
val lat: Double, | |
val lng: Double | |
) | |
fun location(block: LocationBuilder.() -> Unit): Location = LocationBuilder().apply(block).build() | |
@ShopDsl | |
class LocationBuilder { | |
var lat: Double = 0.0 | |
var lng: Double = 0.0 | |
fun build(): Location = Location(lat, lng) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val shop = shop("ID") { | |
address = address { | |
cityName = "Poznań" | |
streetName = "ul. Półwiejska" | |
streetNumber = "123/2" | |
} | |
location = location { | |
lat = 53.12 | |
lng = 23.4 | |
} | |
openHours = openHours { | |
weekDay = "6:00-22:00" | |
saturday = "7:00-23:00" | |
sunday = "closed" | |
} | |
features( | |
Feature.Bakery, | |
Feature.Atm | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class OpenHours( | |
val weekDay: TimeRange?, | |
val saturday: TimeRange?, | |
val sunday: TimeRange? | |
) | |
fun openHours(block: OpenHoursBuilder.() -> Unit): OpenHours = OpenHoursBuilder().apply( | |
block).build() | |
@ShopDsl | |
class OpenHoursBuilder { | |
var weekDay: String? = null | |
var saturday: String? = null | |
var sunday: String? = null | |
fun build(): OpenHours = OpenHours(weekDay?.toOpenHours(), saturday?.toOpenHours(), | |
sunday?.toOpenHours()) | |
} | |
fun String.toOpenHours(): TimeRange? { | |
val splitted = this.split("-".toRegex()) | |
if (splitted.size != 2) { | |
println("Wrong opening hours format: $this") | |
return null | |
} | |
var startDate = splitted[0].toDate("hh:mm") | |
var endDate = splitted[1].toDate("hh:mm") | |
if (startDate == null) { | |
startDate = splitted[0].toDate("hh.mm") | |
} | |
if (endDate == null) { | |
endDate = splitted[1].toDate("hh.mm") | |
} | |
if (startDate == null || endDate == null) { | |
println("couldn't parse start or end dates of: $this") | |
return null | |
} | |
return TimeRange(startDate, endDate) | |
} | |
fun String.toDate(format: String): Date? { | |
return try { | |
val formatter = SimpleDateFormat(format) | |
formatter.parse(this.trim().removePrefix("0")) | |
} catch (e: ParseException) { | |
println("error parsing time: $this") | |
null | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class Shop( | |
val id: String, | |
val address: Address, | |
val name: String?, | |
var distance: Double?, | |
val location: Location, | |
val openHours: OpenHours, | |
val features: Set<Feature> | |
) | |
fun shop(id: String, block: ShopBuilder.() -> Unit): Shop = ShopBuilder(id).apply(block).build() | |
@DslMarker | |
annotation class ShopDsl | |
@ShopDsl | |
class ShopBuilder( | |
var id: String | |
) { | |
var name: String? = null | |
var distance: Double? = null | |
lateinit var address: Address | |
lateinit var openHours: OpenHours | |
lateinit var location: Location | |
var features: Set<Feature> = setOf() | |
fun address(block: AddressBuilder.() -> Unit) = AddressBuilder().apply(block).build() | |
fun openHours(block: OpenHoursBuilder.() -> Unit) = OpenHoursBuilder().apply(block).build() | |
fun location(block: LocationBuilder.() -> Unit) = LocationBuilder().apply(block).build() | |
fun features(vararg features: Feature) = FeaturesBuilder(features).build() | |
fun build(): Shop = Shop(id, address, name, distance, location, openHours, features) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class TimeRange(val start: LocalTime, val end: LocalTime) { | |
constructor(startDate: Date, endDate: Date) : this( | |
LocalTime.of(startDate.hours, startDate.minutes), | |
LocalTime.of(endDate.hours, endDate.minutes)) | |
override fun toString(): String { | |
val formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).withLocale(Locale.getDefault()) | |
return "${start.format(formatter)} - ${end.format(formatter)}" | |
} | |
fun withinRange(inRange: LocalTime?): Boolean { | |
return (this.start.isBefore(inRange) || this.start == inRange) && | |
(this.end.isAfter(inRange) || this.end == inRange) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment