Proper single parameter handling.

This commit is contained in:
Oliver Rümpelein 2020-05-01 15:44:45 +02:00
parent b3711f965b
commit 1d2c7e1877
33 changed files with 350 additions and 295 deletions

View file

@ -24,10 +24,19 @@ application {
dependencies { dependencies {
implementation(kotlin("stdlib-jdk8")) implementation(kotlin("stdlib-jdk8"))
testImplementation(kotlin("test-junit")) // testImplementation(kotlin("test-junit"))
testImplementation("io.kotest:kotest-runner-junit5-jvm:4.0.5")
testImplementation("io.kotest:kotest-assertions-core-jvm:4.0.5")
} }
val compileKotlin: KotlinCompile by tasks tasks {
compileKotlin.kotlinOptions { withType<KotlinCompile>().configureEach {
freeCompilerArgs = listOf("-XXLanguage:+InlineClasses") kotlinOptions {
freeCompilerArgs = listOf("-XXLanguage:+InlineClasses")
}
}
test {
useJUnitPlatform()
}
} }

View file

@ -1,6 +1,12 @@
package de.pheerai.rcdbquery package de.pheerai.rcdbquery
import de.pheerai.rcdbquery.dataMappings.* import de.pheerai.rcdbquery.dataMappings.order.sortBy
import de.pheerai.rcdbquery.dataMappings.page.page
import de.pheerai.rcdbquery.dataMappings.searchTerm.searchTerm
import de.pheerai.rcdbquery.dataMappings.searchType.SearchType
import de.pheerai.rcdbquery.dataMappings.searchType.searchType
import de.pheerai.rcdbquery.dataMappings.vendor.Vendor
import de.pheerai.rcdbquery.dataMappings.vendor.vendors
import de.pheerai.rcdbquery.dsl.* import de.pheerai.rcdbquery.dsl.*
fun main() { fun main() {

View file

@ -1,27 +0,0 @@
package de.pheerai.rcdbquery.dataMappings
import de.pheerai.rcdbquery.dsl.ParamsBuilder
enum class Classification(
override val prettyName: String,
override val fullName: String,
override val paramValue: Int
) : RcdbParamOption<Int> {
ROLLERCOASTER("Roller Coaster", 277),
POWERED_COASTER("Powered Coaster", 278),
MOUNTAIN_COASTER("Mountain Coaster", 279)
;
constructor(name: String, paramValue: Int): this(name, name, paramValue)
companion object {
const val staticParamName = "cs";
}
}
fun ParamsBuilder.classification(body: ClassificationBuilder.() -> ClassificationBuilder): ParamsBuilder {
val builder = ClassificationBuilder()
builder.body()
this[Classification.staticParamName] = builder.build()
return this
}

View file

@ -1,104 +0,0 @@
package de.pheerai.rcdbquery.dataMappings
// TODO: Find way to only have one generic parameter
sealed class MultiParamBuilder<out U : Any, T : RcdbParamOption<U>> {
private val paramList: MutableList<T> = mutableListOf()
open fun add(param: T): MultiParamBuilder<U, T> {
paramList.add(param)
return this
}
protected open fun addAll(items: Array<T>): MultiParamBuilder<U, T> {
paramList.addAll(items)
return this
}
protected open fun addAll(items: Collection<T>): MultiParamBuilder<U, T> {
paramList.addAll(items)
return this
}
fun build() = paramList.toList()
}
class VendorBuilder : MultiParamBuilder<Int, Vendor>() {
override fun add(param: Vendor): VendorBuilder {
super.add(param)
return this
}
fun of(vendor: Vendor) = this.add(vendor)
fun vekoma() = this.add(Vendor.VEKOMA)
fun intamin() = this.add(Vendor.INTAMIN)
fun mack() = this.add(Vendor.MACK)
fun bandm() = this.add(Vendor.B_AND_M)
fun gerstlauer() = this.add(Vendor.GERSTLAUER)
}
class OrderBuilder : MultiParamBuilder<Int, Order>() {
override fun add(param: Order): OrderBuilder {
super.add(param)
return this
}
override fun addAll(items: Array<Order>): OrderBuilder {
super.addAll(items)
return this
}
override fun addAll(items: Collection<Order>): OrderBuilder {
super.addAll(items)
return this
}
fun of(order: Order) = this.add(order)
fun manufacturer() = this.add(Order.MANUFACTURER)
fun inversions() = this.add(Order.INVERSIONS)
fun name() = this.add(Order.NAME)
fun location() = this.add(Order.LOCATION)
fun park() = this.add(Order.PARK)
fun opened() = this.add(Order.OPENED)
fun closed() = this.add(Order.CLOSED)
fun entered() = this.add(Order.ENTERED)
fun type() = this.add(Order.TYPE)
fun design() = this.add(Order.DESIGN)
fun classification() = this.add(Order.CLASSIFICATION)
fun layout() = this.add(Order.LAYOUT)
fun model() = this.add(Order.MODEL)
fun modelLine() = this.add(Order.MODEL_LINE)
fun speed() = this.add(Order.SPEED)
fun height() = this.add(Order.HEIGHT)
fun drop() = this.add(Order.DROP)
fun length() = this.add(Order.LENGTH)
fun angle() = this.add(Order.ANGLE)
fun serialNo() = this.add(Order.SERIAL_NO)
fun scale() = this.add(Order.SCALE)
fun rideTime() = this.add(Order.RIDE_TIME)
fun state() = this.add(Order.STATUS)
fun closing() = this.add(Order.CLOSING)
fun allRelevant() = this.addAll(Order.values().filter { it.relevantForAll })
}
class StatusBuilder : MultiParamBuilder<Int, Status>() {
override fun add(param: Status): StatusBuilder {
super.add(param)
return this
}
fun sbno() = this.add(Status.SBNO)
fun operating() = this.add(Status.OPERATING)
fun underConstruction() = this.add(Status.UNDER_CONSTRUCTION)
fun stored() = this.add(Status.STORED)
}
class ClassificationBuilder : MultiParamBuilder<Int, Classification>() {
override fun add(param: Classification): ClassificationBuilder {
super.add(param)
return this
}
fun rollerCoaster() = this.add(Classification.ROLLERCOASTER)
fun poweredCoaster() = this.add(Classification.POWERED_COASTER)
fun mountainCoaster() = this.add(Classification.MOUNTAIN_COASTER)
}

View file

@ -1,23 +0,0 @@
package de.pheerai.rcdbquery.dataMappings
import de.pheerai.rcdbquery.dsl.ParamsBuilder
class Page(override val paramValue: Int) : RcdbParamOption<Int> {
override val fullName = "The page to show"
override val prettyName = "Page"
companion object {
const val staticParamName = "page"
}
}
fun ParamsBuilder.page(page: Int) = if (Page.staticParamName !in this.keys()) {
also { this[Page.staticParamName] = listOf(Page(page)) }
} else {
error(
"""Only one page must be given!
| Old page: ${this.getMulti(Page.staticParamName)!![0].paramValue}
| New page: $page
""".trimMargin()
)
}

View file

@ -1,23 +0,0 @@
package de.pheerai.rcdbquery.dataMappings
import de.pheerai.rcdbquery.dsl.ParamsBuilder
class SearchTerm(override val paramValue: String) : RcdbParamOption<String> {
override val prettyName = "Search Term"
override val fullName = "Search for elements whose name contain this term"
companion object {
const val staticParamName = "nc"
}
}
fun ParamsBuilder.searchTerm(term: String) =
if (SearchTerm.staticParamName !in this.keys()) {
also { this[SearchTerm.staticParamName] = listOf(SearchTerm(term)) }
} else {
error(
"""Only one search term must ever be set
| Old term: ${this.getMulti(SearchTerm.staticParamName)!![0].paramValue}
| New term: $term""".trimMargin()
)
}

View file

@ -1,24 +0,0 @@
@file:Suppress("unused")
package de.pheerai.rcdbquery.dataMappings
import de.pheerai.rcdbquery.dsl.ParamsBuilder
class StartsWith(override val paramValue: String) : RcdbParamOption<String> {
override val prettyName = "Starts with"
override val fullName = "Name starting with term"
companion object {
const val staticParamName = "nl"
}
}
fun ParamsBuilder.startsWith(term: String) = if (StartsWith.staticParamName !in this.keys()) {
also { this[StartsWith.staticParamName] = listOf(StartsWith(term)) }
} else {
error(
"""Only one starts with term must ever be set
| Old term: ${this.getMulti(StartsWith.staticParamName)!![0].paramValue}
| New term: $term""".trimMargin()
)
}

View file

@ -0,0 +1,20 @@
package de.pheerai.rcdbquery.dataMappings.classification
import de.pheerai.rcdbquery.dataMappings.internal.RcdbParamOption
enum class Classification(
override val prettyName: String,
override val fullName: String,
override val paramValue: Int
) : RcdbParamOption<Int> {
ROLLER_COASTER("Roller Coaster", 277),
POWERED_COASTER("Powered Coaster", 278),
MOUNTAIN_COASTER("Mountain Coaster", 279)
;
constructor(name: String, paramValue: Int) : this(name, name, paramValue)
companion object {
const val staticParamName = "cs"
}
}

View file

@ -0,0 +1,14 @@
package de.pheerai.rcdbquery.dataMappings.classification
import de.pheerai.rcdbquery.dataMappings.internal.MultiParamBuilder
class ClassificationBuilder : MultiParamBuilder<Int, Classification>() {
override fun add(param: Classification): ClassificationBuilder {
super.add(param)
return this
}
fun rollerCoaster() = this.add(Classification.ROLLER_COASTER)
fun poweredCoaster() = this.add(Classification.POWERED_COASTER)
fun mountainCoaster() = this.add(Classification.MOUNTAIN_COASTER)
}

View file

@ -0,0 +1,10 @@
package de.pheerai.rcdbquery.dataMappings.classification
import de.pheerai.rcdbquery.dsl.ParamsCollector
fun ParamsCollector.classification(body: ClassificationBuilder.() -> ClassificationBuilder): ParamsCollector {
val builder = ClassificationBuilder()
builder.body()
this[Classification.staticParamName] = builder.build()
return this
}

View file

@ -0,0 +1,23 @@
package de.pheerai.rcdbquery.dataMappings.internal
open class MultiParamBuilder<out U : Any, T : RcdbParamOption<U>> {
private val paramList: MutableList<T> = mutableListOf()
open fun add(param: T): MultiParamBuilder<U, T> {
paramList.add(param)
return this
}
protected open fun addAll(items: Array<T>): MultiParamBuilder<U, T> {
paramList.addAll(items)
return this
}
protected open fun addAll(items: Collection<T>): MultiParamBuilder<U, T> {
paramList.addAll(items)
return this
}
fun build() = paramList.toList()
}

View file

@ -1,4 +1,4 @@
package de.pheerai.rcdbquery.dataMappings package de.pheerai.rcdbquery.dataMappings.internal
interface RcdbParamOption<out T> { interface RcdbParamOption<out T> {
val prettyName: String val prettyName: String

View file

@ -1,4 +1,4 @@
package de.pheerai.rcdbquery.dataMappings package de.pheerai.rcdbquery.dataMappings.internal
interface RelevantForAll { interface RelevantForAll {
val relevantForAll: Boolean val relevantForAll: Boolean

View file

@ -1,6 +1,7 @@
package de.pheerai.rcdbquery.dataMappings package de.pheerai.rcdbquery.dataMappings.order
import de.pheerai.rcdbquery.dsl.ParamsBuilder import de.pheerai.rcdbquery.dataMappings.internal.RcdbParamOption
import de.pheerai.rcdbquery.dataMappings.internal.RelevantForAll
@Suppress("unused") @Suppress("unused")
enum class Order( enum class Order(
@ -8,7 +9,8 @@ enum class Order(
override val fullName: String, override val fullName: String,
override val paramValue: Int, override val paramValue: Int,
override val relevantForAll: Boolean = true override val relevantForAll: Boolean = true
) : RcdbParamOption<Int>, RelevantForAll { ) : RcdbParamOption<Int>,
RelevantForAll {
IMAGES("Images", "Amount of Images", 0), IMAGES("Images", "Amount of Images", 0),
NAME("Name", "Name of the Coaster", 1), NAME("Name", "Name of the Coaster", 1),
AKA("AKA", "Is/was also known as", 2, relevantForAll = false), AKA("AKA", "Is/was also known as", 2, relevantForAll = false),
@ -44,16 +46,9 @@ enum class Order(
CLOSING("Closing", "(Future) closign date for temporary installations", 31) CLOSING("Closing", "(Future) closign date for temporary installations", 31)
; ;
constructor(name: String, paramId: Int, deprecated: Boolean = false) : this(name, name, paramId) constructor(name: String, paramId: Int) : this(name, name, paramId)
companion object { companion object {
const val staticParamName = "order" const val staticParamName = "order"
} }
} }
fun ParamsBuilder.sortBy(body: OrderBuilder.() -> OrderBuilder): ParamsBuilder {
val builder = OrderBuilder()
builder.body()
this[Order.staticParamName] = builder.build()
return this
}

View file

@ -0,0 +1,47 @@
package de.pheerai.rcdbquery.dataMappings.order
import de.pheerai.rcdbquery.dataMappings.internal.MultiParamBuilder
class OrderBuilder : MultiParamBuilder<Int, Order>() {
override fun add(param: Order): OrderBuilder {
super.add(param)
return this
}
override fun addAll(items: Array<Order>): OrderBuilder {
super.addAll(items)
return this
}
override fun addAll(items: Collection<Order>): OrderBuilder {
super.addAll(items)
return this
}
fun of(order: Order) = this.add(order)
fun manufacturer() = this.add(Order.MANUFACTURER)
fun inversions() = this.add(Order.INVERSIONS)
fun name() = this.add(Order.NAME)
fun location() = this.add(Order.LOCATION)
fun park() = this.add(Order.PARK)
fun opened() = this.add(Order.OPENED)
fun closed() = this.add(Order.CLOSED)
fun entered() = this.add(Order.ENTERED)
fun type() = this.add(Order.TYPE)
fun design() = this.add(Order.DESIGN)
fun classification() = this.add(Order.CLASSIFICATION)
fun layout() = this.add(Order.LAYOUT)
fun model() = this.add(Order.MODEL)
fun modelLine() = this.add(Order.MODEL_LINE)
fun speed() = this.add(Order.SPEED)
fun height() = this.add(Order.HEIGHT)
fun drop() = this.add(Order.DROP)
fun length() = this.add(Order.LENGTH)
fun angle() = this.add(Order.ANGLE)
fun serialNo() = this.add(Order.SERIAL_NO)
fun scale() = this.add(Order.SCALE)
fun rideTime() = this.add(Order.RIDE_TIME)
fun state() = this.add(Order.STATUS)
fun closing() = this.add(Order.CLOSING)
fun allRelevant() = this.addAll(Order.values().filter { it.relevantForAll })
}

View file

@ -0,0 +1,10 @@
package de.pheerai.rcdbquery.dataMappings.order
import de.pheerai.rcdbquery.dsl.ParamsCollector
fun ParamsCollector.sortBy(body: OrderBuilder.() -> OrderBuilder): ParamsCollector {
val builder = OrderBuilder()
builder.body()
this[Order.staticParamName] = builder.build()
return this
}

View file

@ -0,0 +1,13 @@
package de.pheerai.rcdbquery.dataMappings.page
import de.pheerai.rcdbquery.dataMappings.internal.RcdbParamOption
class Page(override val paramValue: Int) :
RcdbParamOption<Int> {
override val fullName = "The page to show"
override val prettyName = "Page"
companion object {
const val staticParamName = "page"
}
}

View file

@ -0,0 +1,7 @@
package de.pheerai.rcdbquery.dataMappings.page
import de.pheerai.rcdbquery.dsl.ParamsCollector
fun ParamsCollector.page(page: Int) = also { this[Page.staticParamName] =
Page(page)
}

View file

@ -0,0 +1,13 @@
package de.pheerai.rcdbquery.dataMappings.searchTerm
import de.pheerai.rcdbquery.dataMappings.internal.RcdbParamOption
class SearchTerm(override val paramValue: String) :
RcdbParamOption<String> {
override val prettyName = "Search Term"
override val fullName = "Search for elements whose name contain this term"
companion object {
const val staticParamName = "nc"
}
}

View file

@ -0,0 +1,9 @@
package de.pheerai.rcdbquery.dataMappings.searchTerm
import de.pheerai.rcdbquery.dsl.ParamsCollector
fun ParamsCollector.searchTerm(term: String) = also {
it[SearchTerm.staticParamName] = listOf(
SearchTerm(term)
)
}

View file

@ -1,6 +1,6 @@
package de.pheerai.rcdbquery.dataMappings package de.pheerai.rcdbquery.dataMappings.searchType
import de.pheerai.rcdbquery.dsl.ParamsBuilder import de.pheerai.rcdbquery.dataMappings.internal.RcdbParamOption
@Suppress("unused") @Suppress("unused")
enum class SearchType( enum class SearchType(
@ -18,14 +18,3 @@ enum class SearchType(
const val staticParamName = "ot" const val staticParamName = "ot"
} }
} }
fun ParamsBuilder.searchType(searchType: SearchType) =
if (SearchType.staticParamName !in this.keys()) {
also { this[SearchType.staticParamName] = listOf(searchType) }
} else {
error(
"""Only one search type must ever be set
| Old type: ${this.getMulti(SearchType.staticParamName)!![0].prettyName}
| New type: ${searchType.prettyName}""".trimMargin()
)
}

View file

@ -0,0 +1,7 @@
package de.pheerai.rcdbquery.dataMappings.searchType
import de.pheerai.rcdbquery.dsl.ParamsCollector
fun ParamsCollector.searchType(searchType: SearchType) = also {
it[SearchType.staticParamName] = searchType
}

View file

@ -0,0 +1,16 @@
@file:Suppress("unused")
package de.pheerai.rcdbquery.dataMappings.startsWith
import de.pheerai.rcdbquery.dataMappings.internal.RcdbParamOption
class StartsWith(override val paramValue: String) :
RcdbParamOption<String> {
override val prettyName = "Starts with"
override val fullName = "Name starting with term"
companion object {
const val staticParamName = "nl"
}
}

View file

@ -0,0 +1,8 @@
package de.pheerai.rcdbquery.dataMappings.startsWith
import de.pheerai.rcdbquery.dsl.ParamsCollector
fun ParamsCollector.startsWith(term: String) = also {
this[StartsWith.staticParamName] =
StartsWith(term)
}

View file

@ -1,6 +1,6 @@
package de.pheerai.rcdbquery.dataMappings package de.pheerai.rcdbquery.dataMappings.status
import de.pheerai.rcdbquery.dsl.ParamsBuilder import de.pheerai.rcdbquery.dataMappings.internal.RcdbParamOption
@Suppress("unused") @Suppress("unused")
enum class Status( enum class Status(
@ -29,9 +29,3 @@ enum class Status(
} }
} }
fun ParamsBuilder.status(body: StatusBuilder.() -> StatusBuilder): ParamsBuilder {
val builder = StatusBuilder()
builder.body()
this[Status.staticParamName] = builder.build()
return this
}

View file

@ -0,0 +1,15 @@
package de.pheerai.rcdbquery.dataMappings.status
import de.pheerai.rcdbquery.dataMappings.internal.MultiParamBuilder
class StatusBuilder : MultiParamBuilder<Int, Status>() {
override fun add(param: Status): StatusBuilder {
super.add(param)
return this
}
fun sbno() = this.add(Status.SBNO)
fun operating() = this.add(Status.OPERATING)
fun underConstruction() = this.add(Status.UNDER_CONSTRUCTION)
fun stored() = this.add(Status.STORED)
}

View file

@ -0,0 +1,10 @@
package de.pheerai.rcdbquery.dataMappings.status
import de.pheerai.rcdbquery.dsl.ParamsCollector
fun ParamsCollector.status(body: StatusBuilder.() -> StatusBuilder): ParamsCollector {
val builder = StatusBuilder()
builder.body()
this[Status.staticParamName] = builder.build()
return this
}

View file

@ -1,13 +1,14 @@
package de.pheerai.rcdbquery.dataMappings package de.pheerai.rcdbquery.dataMappings
import de.pheerai.rcdbquery.dsl.ParamsBuilder import de.pheerai.rcdbquery.dataMappings.order.Order
import de.pheerai.rcdbquery.dsl.ParamsCollector
@Suppress("unused") @Suppress("unused")
@Deprecated( @Deprecated(
"The parameter for extra columns has not yet been discovered (if it even exists). Use multiple values in the `sortBy` param instead (first values take sorting precedence)", "The parameter for extra columns has not yet been discovered (if it even exists). Use multiple values in the `sortBy` param instead (first values take sorting precedence)",
ReplaceWith("sortBy"), DeprecationLevel.ERROR ReplaceWith("sortBy"), DeprecationLevel.ERROR
) )
fun ParamsBuilder.extraColumns(orders: List<Order>): Nothing = fun ParamsCollector.extraColumns(orders: List<Order>): Nothing =
error("The parameter for extra columns has not yet been discovered (if it even exists). Use multiple values in the `sortBy` param instead (first values take sorting precedence)") error("The parameter for extra columns has not yet been discovered (if it even exists). Use multiple values in the `sortBy` param instead (first values take sorting precedence)")
@Suppress("unused") @Suppress("unused")
@ -15,5 +16,5 @@ fun ParamsBuilder.extraColumns(orders: List<Order>): Nothing =
"The parameter for extra columns has not yet been discovered (if it even exists). Use multiple values in the `sortBy` param instead (first values take sorting precedence)", "The parameter for extra columns has not yet been discovered (if it even exists). Use multiple values in the `sortBy` param instead (first values take sorting precedence)",
ReplaceWith("sortBy"), DeprecationLevel.ERROR ReplaceWith("sortBy"), DeprecationLevel.ERROR
) )
fun ParamsBuilder.extraColumns(vararg orders: Order): Nothing = fun ParamsCollector.extraColumns(vararg orders: Order): Nothing =
error("The parameter for extra columns has not yet been discovered (if it even exists). Use multiple values in the `sortBy` param instead (first values take sorting precedence)") error("The parameter for extra columns has not yet been discovered (if it even exists). Use multiple values in the `sortBy` param instead (first values take sorting precedence)")

View file

@ -1,6 +1,6 @@
package de.pheerai.rcdbquery.dataMappings package de.pheerai.rcdbquery.dataMappings.vendor
import de.pheerai.rcdbquery.dsl.ParamsBuilder import de.pheerai.rcdbquery.dataMappings.internal.RcdbParamOption
@Suppress("unused") @Suppress("unused")
enum class Vendor( enum class Vendor(
@ -28,19 +28,19 @@ enum class Vendor(
MOLINA_AND_SONS("Molina & Son's", 6871), MOLINA_AND_SONS("Molina & Son's", 6871),
ALLAN_HERSCHELL("Allan Herschell Company", 6872), ALLAN_HERSCHELL("Allan Herschell Company", 6872),
SDC("S.D.C.", 6873), SDC("S.D.C.", 6873),
HENSEL_PHELPS("Hensel Phelps","Hensel Phelps Construction Co.", 6879), HENSEL_PHELPS("Hensel Phelps", "Hensel Phelps Construction Co.", 6879),
HOPKINS("Hopkins", 6881), HOPKINS("Hopkins", 6881),
CHANCE("Chance", "Chance Rides", 6887), CHANCE("Chance", "Chance Rides", 6887),
BRADLEY_AND_KAYE("Bradley and Kaye", 6894), BRADLEY_AND_KAYE("Bradley and Kaye", 6894),
SARTORI("Sartori", "Sartori Rides", 6895), SARTORI("Sartori", "Sartori Rides", 6895),
MICHAEL_BLACK("Michael Black Assoc.","Michael Black and Associates", 6898), MICHAEL_BLACK("Michael Black Assoc.", "Michael Black and Associates", 6898),
REVERCHON("Reverchon", 6902), REVERCHON("Reverchon", 6902),
TOP_FUN("Top Fun", 6903), TOP_FUN("Top Fun", 6903),
WISDOM("WISDOM", "Wisdom Rides", 6904), WISDOM("WISDOM", "Wisdom Rides", 6904),
L_AND_T("L&T", "L&T Systems", 6906), L_AND_T("L&T", "L&T Systems", 6906),
COASTER_WORKS("Coaster Works", "Coaster Works, Inc.", 6907), COASTER_WORKS("Coaster Works", "Coaster Works, Inc.", 6907),
GIOVANOLA("Giovanola", 6908), GIOVANOLA("Giovanola", 6908),
B_A_SCHIFF("B. A. Schiff Assoc.","B. A. Schiff & Associates", 6914), B_A_SCHIFF("B. A. Schiff Assoc.", "B. A. Schiff & Associates", 6914),
RCCA("RCCA", "Roller Coaster Corporation of America", 6918), RCCA("RCCA", "Roller Coaster Corporation of America", 6918),
CARIPRO("Caripro", 6919), CARIPRO("Caripro", 6919),
SETPOINT("Setpoint", 6920), SETPOINT("Setpoint", 6920),
@ -55,12 +55,12 @@ enum class Vendor(
BHS("BHS", "Bayerische Berg-, Hütten- und Salzwerke AG", 6951), BHS("BHS", "Bayerische Berg-, Hütten- und Salzwerke AG", 6951),
FABBRI("Fabbri", 6953), FABBRI("Fabbri", 6953),
MEISHO("Meisho", "Meisho Amusement Machines", 6954), MEISHO("Meisho", "Meisho Amusement Machines", 6954),
SENYO_KOGYO("Senyo","Senyo Kogyo Co., Ltd.", 6957), SENYO_KOGYO("Senyo", "Senyo Kogyo Co., Ltd.", 6957),
NIPPON("Nippon", 6958), NIPPON("Nippon", 6958),
OKAMOTO("Okamoto", "Okamoto Co., Ltd.", 6970), OKAMOTO("Okamoto", "Okamoto Co., Ltd.", 6970),
PAX("Pax", "Pax Company", 6971), PAX("Pax", "Pax Company", 6971),
HOEI_SANGYO("Hoei Sangyo", "Hoei Sangyo Co., Ltd.", 6973), HOEI_SANGYO("Hoei Sangyo", "Hoei Sangyo Co., Ltd.", 6973),
THOMPSON("Thompson","L.A. Thompson Scenic Railway Company", 6975), THOMPSON("Thompson", "L.A. Thompson Scenic Railway Company", 6975),
WGH_TRANSPORTATION("WGH Transportation", 6979), WGH_TRANSPORTATION("WGH Transportation", 6979),
HARTON("TM Harton", "TM Harton Company", 7000), HARTON("TM Harton", "TM Harton Company", 7000),
APPLE("Apple", 7030), APPLE("Apple", 7030),
@ -111,7 +111,7 @@ enum class Vendor(
CAM_BABY_KART("CAM Baby Kart", 7400), CAM_BABY_KART("CAM Baby Kart", 7400),
EOS("EOS", 7418), EOS("EOS", 7418),
ACA("ACA", 7446), ACA("ACA", 7446),
IKEDA("Ikeda","Ikeda Works", 7447), IKEDA("Ikeda", "Ikeda Works", 7447),
BUTLIN("Butlin", 7452), BUTLIN("Butlin", 7452),
TAKAHASHI_KIKAI_SANGYO("Takahashi Kikai Sangyo", 7472), TAKAHASHI_KIKAI_SANGYO("Takahashi Kikai Sangyo", 7472),
DYNAMIC("Dynamic Attractions", 7489), DYNAMIC("Dynamic Attractions", 7489),
@ -125,7 +125,7 @@ enum class Vendor(
DEBRINQUEDO("DeBrinquedo", 7567), DEBRINQUEDO("DeBrinquedo", 7567),
ZHEJIANG_JUMA_AMUSEMENT_EQUIPMENT("Zhejiang Juma Amusement Equipment Co., Ltd.", 7573), ZHEJIANG_JUMA_AMUSEMENT_EQUIPMENT("Zhejiang Juma Amusement Equipment Co., Ltd.", 7573),
SAEKI("Saeki", 7582), SAEKI("Saeki", 7582),
KUMBAK("KumbaK","""KumbaK "The Amusement Engineers"""", 7608), KUMBAK("KumbaK", """KumbaK "The Amusement Engineers"""", 7608),
PINTO_BROTHERS("Pinto Brothers", 7657), PINTO_BROTHERS("Pinto Brothers", 7657),
CEDEAL("Cedeal Rides", 7688), CEDEAL("Cedeal Rides", 7688),
DOPPELMAYR("Doppelmayr", 7700), DOPPELMAYR("Doppelmayr", 7700),
@ -138,7 +138,10 @@ enum class Vendor(
VAFAEI("Vafaei Rides", 7953), VAFAEI("Vafaei Rides", 7953),
VOSTOK("Vostok", 7959), VOSTOK("Vostok", 7959),
PARKASH_AMUSEMENTS("Parkash Amusements", 7963), PARKASH_AMUSEMENTS("Parkash Amusements", 7963),
HEBEI_ZHONGYE_METALLURGICAL_EQUIPMENT_MANUFACTURING("Hebei Zhongye Metallurgical Equipment Manufacturing Co., Ltd", 7980), HEBEI_ZHONGYE_METALLURGICAL_EQUIPMENT_MANUFACTURING(
"Hebei Zhongye Metallurgical Equipment Manufacturing Co., Ltd",
7980
),
R_AND_R("R&R", 8006), R_AND_R("R&R", 8006),
ABC("abc", "abc rides", 8026), // Not a test object ABC("abc", "abc rides", 8026), // Not a test object
TECHNICAL_PARK("Technical Park", 8046), TECHNICAL_PARK("Technical Park", 8046),
@ -253,10 +256,3 @@ enum class Vendor(
} }
} }
} }
fun ParamsBuilder.vendors(body: VendorBuilder.() -> VendorBuilder): ParamsBuilder {
val builder = VendorBuilder()
builder.body()
this[Vendor.staticParamName] = builder.build()
return this
}

View file

@ -0,0 +1,17 @@
package de.pheerai.rcdbquery.dataMappings.vendor
import de.pheerai.rcdbquery.dataMappings.internal.MultiParamBuilder
class VendorBuilder : MultiParamBuilder<Int, Vendor>() {
override fun add(param: Vendor): VendorBuilder {
super.add(param)
return this
}
fun of(vendor: Vendor) = this.add(vendor)
fun vekoma() = this.add(Vendor.VEKOMA)
fun intamin() = this.add(Vendor.INTAMIN)
fun mack() = this.add(Vendor.MACK)
fun bandm() = this.add(Vendor.B_AND_M)
fun gerstlauer() = this.add(Vendor.GERSTLAUER)
}

View file

@ -0,0 +1,10 @@
package de.pheerai.rcdbquery.dataMappings.vendor
import de.pheerai.rcdbquery.dsl.ParamsCollector
fun ParamsCollector.vendors(body: VendorBuilder.() -> VendorBuilder): ParamsCollector {
val builder = VendorBuilder()
builder.body()
this[Vendor.staticParamName] = builder.build()
return this
}

View file

@ -1,7 +1,9 @@
package de.pheerai.rcdbquery.dsl package de.pheerai.rcdbquery.dsl
import de.pheerai.rcdbquery.dataMappings.RcdbParamOption import de.pheerai.rcdbquery.dataMappings.internal.RcdbParamOption
import de.pheerai.rcdbquery.dataMappings.SearchType import de.pheerai.rcdbquery.dataMappings.searchType.SearchType
// TODO: Restructure
data class RcdbParams( data class RcdbParams(
val multiParams: MultiParams, val multiParams: MultiParams,
@ -12,7 +14,7 @@ data class RcdbParams(
.params .params
.asSequence() .asSequence()
.map { e -> e.key to e.value.joinToString(separator = ",") } .map { e -> e.key to e.value.joinToString(separator = ",") }
val singleParamSequence: Sequence<Pair<String,String>> = this.singleParams val singleParamSequence: Sequence<Pair<String, String>> = this.singleParams
.params .params
.asSequence() .asSequence()
.map { it.toPair() } .map { it.toPair() }
@ -22,15 +24,16 @@ data class RcdbParams(
} }
} }
// In preparation for new handler
sealed class Params<T> { sealed class Params<T> {
abstract val params: Map<String, T> abstract val params: Map<String, T>
} }
class ParamAlreadySetException(message: String) : IllegalArgumentException(message)
class MultiParams(override val params: Map<String, List<String>>) : Params<List<String>>() class MultiParams(override val params: Map<String, List<String>>) : Params<List<String>>()
class SingleParams(override val params: Map<String, String>) : Params<String>() class SingleParams(override val params: Map<String, String>) : Params<String>()
class ParamsBuilder { class ParamsCollector {
private val multiParams: MutableMap<String, List<RcdbParamOption<Any>>> = mutableMapOf() private val multiParams: MutableMap<String, List<RcdbParamOption<Any>>> = mutableMapOf()
private val singleParams: MutableMap<String, RcdbParamOption<Any>> = mutableMapOf() private val singleParams: MutableMap<String, RcdbParamOption<Any>> = mutableMapOf()
@ -41,16 +44,16 @@ class ParamsBuilder {
* If no Search type has been set, this will default to "Coaster" * If no Search type has been set, this will default to "Coaster"
*/ */
private fun buildMulti() = multiParams.apply { private fun buildMulti() = multiParams.apply {
putIfAbsent(SearchType.staticParamName, listOf(SearchType.COASTER)) // Defaults go here, if any
} }
.filter { it.value.isNotEmpty() } .filter { it.value.isNotEmpty() }
.mapValues { e -> e.value.map { o -> o.paramValue.toString() } } .mapValues { e -> e.value.map { o -> o.paramValue.toString() } }
.let { MultiParams(it) } .let { MultiParams(it) }
private fun buildSingle() = singleParams.apply { private fun buildSingle() = singleParams.apply {
// Defaults go here putIfAbsent(SearchType.staticParamName, SearchType.COASTER)
} }
.mapValues { it.toString() } .mapValues { e -> e.value.paramValue.toString() }
.let { SingleParams(it) } .let { SingleParams(it) }
operator fun set(paramName: String, options: List<RcdbParamOption<Any>>) { operator fun set(paramName: String, options: List<RcdbParamOption<Any>>) {
@ -58,7 +61,11 @@ class ParamsBuilder {
} }
operator fun set(paramName: String, option: RcdbParamOption<Any>) { operator fun set(paramName: String, option: RcdbParamOption<Any>) {
this.singleParams[paramName] = option if (paramName !in singleParams && paramName !in multiParams) {
this.singleParams[paramName] = option
} else {
throw ParamAlreadySetException("Parameter $paramName already set.")
}
} }
fun getSingle(paramName: String) = this.multiParams[paramName] ?: this.singleParams[paramName] fun getSingle(paramName: String) = this.multiParams[paramName] ?: this.singleParams[paramName]
@ -69,7 +76,7 @@ class ParamsBuilder {
private fun singleKeys() = this.singleParams.keys.toSet() private fun singleKeys() = this.singleParams.keys.toSet()
} }
fun rcdbQuery(body: ParamsBuilder.() -> ParamsBuilder) = fun rcdbQuery(body: ParamsCollector.() -> ParamsCollector) =
RcdbUrlQuery("https://www.rcdb.com/r.htm?", rcdbQueryParams(body)).toString() RcdbUrlQuery("https://www.rcdb.com/r.htm?", rcdbQueryParams(body)).toString()
data class RcdbUrlQuery(val baseUrl: String, val params: RcdbParams) { data class RcdbUrlQuery(val baseUrl: String, val params: RcdbParams) {
@ -82,9 +89,8 @@ data class RcdbUrlQuery(val baseUrl: String, val params: RcdbParams) {
/** /**
* Builder for the parameters only (mainly because it might be possilbe in the future to have an API with a POST search object? * Builder for the parameters only (mainly because it might be possilbe in the future to have an API with a POST search object?
*/ */
fun rcdbQueryParams(body: ParamsBuilder.() -> ParamsBuilder): RcdbParams { fun rcdbQueryParams(body: ParamsCollector.() -> ParamsCollector): RcdbParams {
val builder = ParamsBuilder() val builder = ParamsCollector()
builder.body() builder.body()
return builder.build() return builder.build()
} }

View file

@ -1,27 +1,38 @@
package de.pheerai.rcdbquery.dsl package de.pheerai.rcdbquery.dsl
import de.pheerai.rcdbquery.dataMappings.Vendor import de.pheerai.rcdbquery.dataMappings.vendor.Vendor
import de.pheerai.rcdbquery.dataMappings.sortBy import de.pheerai.rcdbquery.dataMappings.order.sortBy
import de.pheerai.rcdbquery.dataMappings.vendors import de.pheerai.rcdbquery.dataMappings.vendor.vendors
import kotlin.test.Test import io.kotest.core.spec.style.StringSpec
import kotlin.test.assertEquals import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
class RcdbQueryDslTest { class RcdbQueryDslTest : StringSpec({
@Test
fun testQueryParamBuilder() { "should generate a proper URL" {
assertEquals( val actual = rcdbQuery {
"https://www.rcdb.com/r.htm?mk=6836,6856,6905&order=24,30&ot=2", vendors {
rcdbQuery { vekoma()
vendors { mack()
vekoma() of(Vendor.MAURER)
mack()
of(Vendor.MAURER)
}
sortBy {
inversions()
manufacturer()
}
} }
) sortBy {
inversions()
manufacturer()
}
}
actual.length shouldBe 61
actual.shouldContain("https://www.rcdb.com/r.htm?")
actual.shouldContain("mk=")
actual.shouldContain("6836")
actual.shouldContain("6856")
actual.shouldContain("6905")
actual.shouldContain("order=")
actual.shouldContain("24")
actual.shouldContain("30")
actual.shouldContain("ot=2")
actual.filter { it == '&' }.length shouldBe 2
} }
} })