I am trying to make a query builder for GraphQL syntax, by using a builder pattern. I already did it for the filtering part:
Example where I would get the title for all the events from "somewhere" with a price lower than 100.:
val query = Query.Builder()
.filter(PLACE,"Somewhere")
.filter(PRICELT, 100)
.build()
So for that part ^ it was easy, because it was not nested. and I just used a MutableMap<ENUM, Any>
in kotlin so that I can pass strings and ints and longs and so on, and then I have a method that collects everything to a string.
{events(place:"Somewhere", priceLT:100){title}}
But now I want to programatically make a way to say what data I want to get back from the query. (NOTE: before the title
part of the query was hardcoded into the QueryBuilder.
So for that I made another class called Entity which has a list of itself as an attribute.
class Entity(
private val entity: EntityType,
private val entities: MutableList<Entity> = mutableListOf()
) {
override fun toString(): String {
return if (this.entities.isEmpty()) {
entity.str
} else {
this.entity.str + "{" + this.entities.onEach {
it.toString()
}.joinToString(" ") + "}"
}
}
}
And I got it to work. But to build the structure. then I have to append to the list and "visit" the list of the entity to visit the entities in that list.
For example if I want to build this query:
{
events{
title
location {
coordinates {
longitude
latiitude
}
}
}
}
Then I need to go 2 levels down in the layers of the Entity, And the way I am doing it now, then my code is getting very wide.
fun main() {
val e1 = Entity(
EntityType.EVENTS,
mutableListOf(
Entity(EntityType.TITLE),
Entity(EntityType.LOCATION,
mutableListOf(
Entity(EntityType.COORDINATES,
mutableListOf(
Entity(EntityType.LONGITUDE),
Entity(EntityType.LATITUDE)
)
)
)
),
)
)
}
So I was thinking to use builder pattern. Or something else which will be smarter.
Thank you in advance for your help, and have a nice day.
BTW: I am using following enums:
enum class EntityType(val str: String) {
EVENTS("events"),
TITLE("title"),
GENRE("genre"),
IMAGE("image"),
LINK("link"),
OTHER("other"),
PRICE("price"),
TEXT("text"),
TICKETS("tickets"),
TIME("time"),
LOCATION("location"),
AREA("area"),
PLACE("place"),
ADDRESS("address"),
CITY("city"),
STREET("street"),
NO("no"),
STATE("state"),
ZIP("zip"),
COORDINATES("coordinates"),
LONGITUDE("longitude"),
LATITUDE("latitude"),
}
enum class Filter(val str: String) {
PLACE("place"),
PRICELT("priceLT"),
PRICEGT("priceGT"),
TIMELT("timestampLT"),
TIMEGT("timestampGT"),
AREA("area"),
TITLE("title"),
GENRE("genre")
}
And the rest of my code looks like this:
I share it for transparency, even though its not that relevant to my question. Later I will implement the Entities in the code where i have written the comments.
class Query private constructor(val query: String) {
class Builder {
private var query = ""
private var filters = mutableMapOf<Filter, Any>()
private var entities = Entity(EntityType.EVENTS) // I started merging the entities into the query
fun filter(key: Filter, value: Any) = apply {
this.filters[key] = value
}
fun build(): Query {
this.query = "{events{" // Here the first part of the event string should come.
if (filters.isNotEmpty()) {
this.query += "("
filters.forEach {
this.query += if (it.value is Int || it.value is Long) it.key.str + ":" + it.value + "," else {
it.key.str + ":\"" + it.value + "\","
}
}
this.query = this.query.dropLast(1) + ")"
}
this.query += "title}}" // Here the Entities.toString will be called
return Query(this.query)
}
}
}
Aucun commentaire:
Enregistrer un commentaire