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)
