Repository: incubator-s2graph
Updated Branches:
  refs/heads/master f3cdd0724 -> 0c5df5eff


[S2GRAPH-32]: Support variable such as now, day, hour on query.

  add TemplateHelper to deal with custom variable on query.

JIRA:
  [S2GRAPH-32] https://issues.apache.org/jira/browse/S2GRAPH-32

Pull Request:
  Closes #27


Project: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/commit/0c5df5ef
Tree: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/tree/0c5df5ef
Diff: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/diff/0c5df5ef

Branch: refs/heads/master
Commit: 0c5df5eff47c71bb3e985caeea9c342c2e426a34
Parents: f3cdd07
Author: DO YUNG YOON <[email protected]>
Authored: Tue Feb 23 20:07:20 2016 +0900
Committer: DO YUNG YOON <[email protected]>
Committed: Tue Feb 23 20:07:20 2016 +0900

----------------------------------------------------------------------
 CHANGES                                         |  2 +
 .../kakao/s2graph/core/rest/RequestParser.scala | 60 ++++++++++++++++++--
 2 files changed, 56 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/0c5df5ef/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 1f2e277..602eb0d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -10,6 +10,8 @@ Release 0.12.1 - unreleased
 
     S2GRAPH-36: Provide Blocking API for Edge/Vertex operations (Committed by 
DOYUNG YOON).
 
+    S2GRAPH-32: Support variable such as now, day, hour on query (Committed by 
DOYUNG YOON).
+
   IMPROVEMENT
 
     S2GRAPH-14: Abstract HBase specific methods in Management and Label 
(Committed by DOYUNG YOON).

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/0c5df5ef/s2core/src/main/scala/com/kakao/s2graph/core/rest/RequestParser.scala
----------------------------------------------------------------------
diff --git 
a/s2core/src/main/scala/com/kakao/s2graph/core/rest/RequestParser.scala 
b/s2core/src/main/scala/com/kakao/s2graph/core/rest/RequestParser.scala
index f0360c2..c7cde59 100644
--- a/s2core/src/main/scala/com/kakao/s2graph/core/rest/RequestParser.scala
+++ b/s2core/src/main/scala/com/kakao/s2graph/core/rest/RequestParser.scala
@@ -8,12 +8,51 @@ import com.kakao.s2graph.core._
 import com.kakao.s2graph.core.mysqls._
 import com.kakao.s2graph.core.parsers.{Where, WhereParser}
 import com.kakao.s2graph.core.types._
-import com.kakao.s2graph.core.utils.logger
 import com.typesafe.config.Config
 import play.api.libs.json._
-
 import scala.util.{Failure, Success, Try}
 
+object TemplateHelper {
+  val findVar = """\"?\$\{(.*?)\}\"?""".r
+  val num = 
"""(next_day|next_hour|next_week|now)?\s*(-?\s*[0-9]+)?\s*(hour|day|week)?""".r
+
+  val hour = 60 * 60 * 1000L
+  val day = hour * 24L
+  val week = day * 7L
+
+  def calculate(now: Long, n: Int, unit: String): Long = {
+    val duration = unit match {
+      case "hour" | "HOUR" => n * hour
+      case "day" | "DAY" => n * day
+      case "week" | "WEEK" => n * week
+      case _ => n * day
+    }
+
+    duration + now
+  }
+
+  def replaceVariable(now: Long, body: String): String = {
+    findVar.replaceAllIn(body, m => {
+      val matched = m group 1
+
+      num.replaceSomeIn(matched, m => {
+        val (_pivot, n, unit) = (m.group(1), m.group(2), m.group(3))
+        val ts = _pivot match {
+          case null => now
+          case "now" | "NOW" => now
+          case "next_week" | "NEXT_WEEK" => now / week * week + week
+          case "next_day" | "NEXT_DAY" => now / day * day + day
+          case "next_hour" | "NEXT_HOUR" => now / hour * hour + hour
+        }
+
+        if (_pivot == null && n == null && unit == null) None
+        else if (n == null || unit == null) Option(ts.toString)
+        else Option(calculate(ts, n.replaceAll(" ", "").toInt, unit).toString)
+      })
+    })
+  }
+}
+
 class RequestParser(config: Config) extends JSONParser {
 
   import Management.JsonModel._
@@ -32,6 +71,7 @@ class RequestParser(config: Config) extends JSONParser {
     .initialCapacity(1000)
     .build[String, Try[Where]]
 
+
   private def extractScoring(labelId: Int, value: JsValue) = {
     val ret = for {
       js <- parse[Option[JsObject]](value, "scoring")
@@ -50,7 +90,10 @@ class RequestParser(config: Config) extends JSONParser {
     ret
   }
 
-  def extractInterval(label: Label, jsValue: JsValue) = {
+  def extractInterval(label: Label, _jsValue: JsValue) = {
+    val replaced = TemplateHelper.replaceVariable(System.currentTimeMillis(), 
_jsValue.toString())
+    val jsValue = Json.parse(replaced)
+
     def extractKv(js: JsValue) = js match {
       case JsObject(obj) => obj
       case JsArray(arr) => arr.flatMap {
@@ -73,7 +116,10 @@ class RequestParser(config: Config) extends JSONParser {
     ret
   }
 
-  def extractDuration(label: Label, jsValue: JsValue) = {
+  def extractDuration(label: Label, _jsValue: JsValue) = {
+    val replaced = TemplateHelper.replaceVariable(System.currentTimeMillis(), 
_jsValue.toString())
+    val jsValue = Json.parse(replaced)
+
     for {
       js <- parse[Option[JsObject]](jsValue, "duration")
     } yield {
@@ -98,11 +144,13 @@ class RequestParser(config: Config) extends JSONParser {
     }
     ret.map(_.toMap).getOrElse(Map.empty[Byte, InnerValLike])
   }
+  
 
   def extractWhere(label: Label, whereClauseOpt: Option[String]): Try[Where] = 
{
     whereClauseOpt match {
       case None => Success(WhereParser.success)
-      case Some(where) =>
+      case Some(_where) =>
+        val where = TemplateHelper.replaceVariable(System.currentTimeMillis(), 
_where)
         val whereParserKey = s"${label.label}_${where}"
         parserCache.get(whereParserKey, new Callable[Try[Where]] {
           override def call(): Try[Where] = {
@@ -329,7 +377,7 @@ class RequestParser(config: Config) extends JSONParser {
         .duration(duration)
         .has(hasFilter)
         .labelOrderSeq(indexSeq)
-        .interval(interval) // Interval param should set after labelOrderSeq 
param
+        .interval(interval)
         .where(where)
         .duplicatePolicy(duplicate)
         .includeDegree(includeDegree)

Reply via email to