Created
July 15, 2015 12:14
-
-
Save amazari/d8d99510e44c9feeaf7c to your computer and use it in GitHub Desktop.
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
import com.github.nscala_time.time.StaticInterval | |
import com.twitter.algebird.Monoid | |
import shapeless._, record._, syntax.singleton._ | |
import shapeless.ops.record.SelectAll | |
/** Represents a path component generator, basically a function keysTemplate.type -> Set[Seq[String]] | |
* | |
*/ | |
trait PathPattern { | |
val keysTemplate: HList | |
val w: Witness | |
def apply[L <: HList](keys: keysTemplate.type) | |
(implicit sel: ops.record.Selector[keysTemplate.type , w.T]): Set[Seq[String]] | |
} | |
/** A path component generator taking a Joda Time Interval and generating a list of path components, | |
* one for each hour contained in the interval | |
*/ | |
case object HourlyIntervalPathPattern extends PathPattern { | |
override val keysTemplate: HList = ("interval" ->> StaticInterval.lastHour) :: HNil | |
override val w = Witness("interval") | |
override def apply(keys: keysTemplate.type) | |
(implicit sel: ops.record.Selector[keysTemplate.type , w.T]): Set[Seq[String]] = | |
_("interval").by[Set](1.hour).map(date => | |
Seq(date.toString("YYYY-MM-dd"), date.toString("HH"))) | |
} | |
case class ConstantStringPathPattern(constant: String) extends PathPattern { | |
override val keysTemplate: HList = (constant ->> "") :: HNil | |
override def apply(keys: keysTemplate.type) | |
(implicit sel: ops.record.Selector[keysTemplate.type , w.T]): Set[Seq[String]] = | |
Set(Seq(keys(constant))) | |
} | |
/** Make the path generators composable | |
* The resulting generator takes a Shapeless records containing the keys of each sub-generators | |
*/ | |
implicit object PathPatternMonoid extends Monoid[PathPattern] { | |
override def zero: PathPattern = new PathPattern { | |
override val keysTemplate = HNil | |
override def apply(keys: keysTemplate.type) | |
(implicit sel: ops.record.Selector[keysTemplate.type , w.T])= Set(Seq("")) | |
} | |
override def plus(l: PathPattern, r: PathPattern): PathPattern = new PathPattern { | |
override val keysTemplate = l.keysTemplate :: r.keysTemplate | |
override def genPath (pKeys: keysTemplate.type) | |
(implicit sel: ops.record.Selector[keysTemplate.type , w.T])= for { | |
p1 <- l(SelectAll[keysTemplate.type, l.keysTemplate.type](pKeys)) | |
p2 <- r(SelectAll[keysTemplate.type, r.keysTemplate.type](pKeys)) | |
} yield (p1 ++ p2) | |
} | |
} | |
/** "Nice" syntax | |
* | |
* @param pathPattern | |
*/ | |
implicit class SlashablePathPattern(pathPattern: PathPattern) { | |
def /(child: PathPattern)(implicit mon: Monoid[PathPattern]) = mon.plus(pathPattern, child) | |
} | |
val RegionHourlyPathPattern = ConstantStringPathPattern("region") / HourlyIntervalPathPattern | |
val paths = RegionHourlyPathPattern(("region" ->> "US") :: ("interval" ->> StaticInterval.lastHour) :: HNil) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment