Skip to content

Instantly share code, notes, and snippets.

@feoktant
Created March 3, 2021 12:38
Show Gist options
  • Save feoktant/0701fe9136f97d93a80e0d68fcad82bb to your computer and use it in GitHub Desktop.
Save feoktant/0701fe9136f97d93a80e0d68fcad82bb to your computer and use it in GitHub Desktop.
Trying to achieve the same bson path as in KMongo
package io.feoktant.path
package domain
import scala.annotation.tailrec
object App extends App {
println(Sample.UserFields.emailAddress.id)
println(Sample.UserFields.emails(3).value)
}
case class EmailAddress(
id: String,
value: String,
)
case class User(
id: String,
name: String,
age: Int,
emailAddress: EmailAddress,
apples: List[String],
emails: List[EmailAddress],
)
object Sample {
trait Fields[T] {
def field(name: String): Field = new Field(name, None)
def field(name: String, parent: Field): Field = new Field(name, Some(parent))
}
class Field(
private val name: String,
private val parent: Option[Field],
) {
lazy val dotNotation: String = {
@tailrec
def loop(p: Option[Field], acc: List[String]): String = p match {
case Some(par) => loop(par.parent, par.name :: acc)
case None => acc.mkString(".")
}
loop(parent, name :: Nil)
}
override def toString: String = dotNotation
}
object UserFields extends Fields[User] {
val id: Field = field("id")
val name: Field = field("name")
val age: Field = field("age")
val emailAddress: EmailEmbeddedDoc = new EmailEmbeddedDoc("emailAddress", None)
val apples: ArrayField = new ArrayField("apples")
val emails: EmailsArrayField = new EmailsArrayField("emails")
// if field only - field
class ArrayField(
private val name: String,
private val parent: Option[Field] = None,
) extends Field(name, parent) { self =>
def apply(i: Int): Field = field(i.toString, self)
}
// if embedded document - ed
class EmailEmbeddedDoc(
private val name: String,
private val parent: Option[Field],
) extends Field(name, parent) { self =>
val id: Field = field("id", self)
val value: Field = field("value", self)
}
class EmailsArrayField(
private val name: String,
private val parent: Option[Field] = None,
) extends EmailEmbeddedDoc(name, parent) { self =>
def apply(i: Int): EmailEmbeddedDoc = new EmailEmbeddedDoc(i.toString, Some(self))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment