import java.util.Date
import org.apache.lucene.document._
import shapeless._
import shapeless.ops.hlist._
import shapeless.ops.record._
// extends from scala.annotation.StaticAnnotation is not necessary, but it kind of reminds me this is an annotation
final class indexable() extends scala.annotation.StaticAnnotation
final case class Person(
id: Long
, @indexable name: String
, @indexable age: Int
, @indexable married: Boolean
, @indexable jobDesc: Option[String]
, @indexable dateofbirth: Data
, ssn: String
)
sealed trait Indexer0 extends Poly2 {
implicit def option[K, V](implicit indexer: Case.Aux[K, V, Vector[Field]]) = at[K, Option[V]] { (k, ov) =>
ov.fold(Vector.emtpy[Field])(indexer.apply(k, _))
}
}
object Indexer extends Indexer0 {
implicit def int[K <: Symbol](implicit witness: Witness.Aux[K]) = at[K, Int] { (_, int) =>
val nm = witness.value.name
Vector( new IntPoint(nm, int), new StoreField(nm, Int) )
}
implicit def date[K <: Symbol](implicit witness: Witness.Aux[K]) = at[K, Date] { (_, date) =>
val nm = witness.value.name
val long = date.getTime
Vector( new LongPoint(nm, long), new StoreField(nm, long) )
}
implicit def bool[K <: Symbol](implicit witness: Witness.Aux[K]) = at[K, Boolean] { (_, bool) =>
val nm = witness.value.name
Vector( new StringField(nm, bool.toString, Field.Store.YES) )
}
implicit def text[K <: Symbol](implicit witness: Witness.Aux[K]) = at[K, String] { (_, text) =>
val nm = witness.value.name
Vector( new TextField(nm, text, Field.Store.YES) )
}
}
object Collector extends Poly2 {
implicit def none[K <: Symbol, V] = at[Document, (None.type, K, V)] { (doc, _) => doc }
implicit def some[K <: Symbol, V](implicit indexer: Indexer.Case.Aux[K, V, Vector[Field]]) =
at[Document, (Some[indexable], K, V)] { case (doc, (_, k, v)) =>
indexer.apply(k, v) foreach { doc.add }
doc
}
}
// for example
// Given a Person(123, "John Doe", 23, false, None, new Date(1995, 3, 12),"000-000-0000")
// HL would be FieldType[String("id"), Int] :: FieldType[String("name"), String] :: FieldType[String("age"), Int] :: FieldType[String("married"), Boolean] :: FieldType[String("jobDesc"), Option[String]] :: FieldType[String("dateofbirth"), Date] :: FieldType[String("ssn"), String] :: HNil
// AL would be None.type :: Some[indexable] :: Some[Indexable] :: Some[Indexable] :: Some[indexable] :: Some[indexable] :: None.type :: HNil
// KL would be String("id") :: String("name") :: String("age") :: String("married") :: String("jobDesc") :: String("dateofbirth") :: String("ssn") :: HNil
// VL would be Int :: String :: Int :: Boolean :: Option[String] :: Date :: String :: HNil
// ZL would be (None.type, String("id"), Int) :: (Some[indexable], String("name"), String) :: (Some[idexable], String("age"), Int) :: (Some[indexable], String("married"), Boolean) :: (Some[indexable], String("jobDesc"), Option[String]) :: (Some[indexable], String("dateofbirth"), Date) :: (None.type, String("ssn"), String) :: HNil
def document[HL <: HList, AL <: HList, KL <: HList, VL <: HList, ZL <: HList](person: Person)(implicit
iso: LabelledGeneric.Aux[Person, HL]
, annot: Annotations.Aux[indexable, Person, AL]
, keys: Keys.Aux[HL, KL]
, values: Values.Aux[HL, VL]
, zip: Zip.Aux[AL :: KL :: VL :: HNil, ZL])
, fl: LeftFolder.Aux[ZL, Document, Collector.type, Document]): Document = {
val doc = new Document()
zip( annot(), keys(), values(iso.to(person)) ).foldLeft(doc)(Collector)
}
Last active
April 27, 2021 23:22
-
-
Save shengc/2b4052ed59419e86f36f48da35812634 to your computer and use it in GitHub Desktop.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment