Repository: incubator-s2graph Updated Branches: refs/heads/master 32eb344a7 -> 5706bbf1d
implement @trasform directive Project: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/commit/2d37cf65 Tree: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/tree/2d37cf65 Diff: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/diff/2d37cf65 Branch: refs/heads/master Commit: 2d37cf658f1860e39ab32d8c8d33c3a57933e829 Parents: 33e3d26 Author: daewon <[email protected]> Authored: Wed May 30 16:21:04 2018 +0900 Committer: daewon <[email protected]> Committed: Wed May 30 16:21:04 2018 +0900 ---------------------------------------------------------------------- build.sbt | 4 +- s2core/build.sbt | 2 +- s2graphql/build.sbt | 4 +- .../apache/s2graph/graphql/GraphQLServer.scala | 5 +- .../s2graph/graphql/middleware/Transform.scala | 51 ++++++++++++++++++++ .../s2graph/graphql/types/FieldResolver.scala | 2 +- .../s2graph/graphql/types/S2Directive.scala | 49 +++++++++++++++++++ .../s2graph/graphql/types/SchemaDef.scala | 12 +++-- 8 files changed, 120 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/2d37cf65/build.sbt ---------------------------------------------------------------------- diff --git a/build.sbt b/build.sbt index 84d17d5..de7c02f 100755 --- a/build.sbt +++ b/build.sbt @@ -25,9 +25,9 @@ name := "s2graph" lazy val commonSettings = Seq( organization := "org.apache.s2graph", - scalaVersion := "2.11.7", + scalaVersion := "2.11.8", isSnapshot := version.value.endsWith("-SNAPSHOT"), - scalacOptions := Seq("-language:postfixOps", "-unchecked", "-deprecation", "-feature", "-Xlint", "-Xlint:-missing-interpolator"), + scalacOptions := Seq("-language:postfixOps", "-unchecked", "-deprecation", "-feature", "-Xlint", "-Xlint:-missing-interpolator", "-target:jvm-1.8"), javaOptions ++= collection.JavaConversions.propertiesAsScalaMap(System.getProperties).map { case (key, value) => "-D" + key + "=" + value }.toSeq, testOptions in Test += Tests.Argument("-oDF"), concurrentRestrictions in Global += Tags.limit(Tags.Test, 1), http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/2d37cf65/s2core/build.sbt ---------------------------------------------------------------------- diff --git a/s2core/build.sbt b/s2core/build.sbt index cfc32d6..229bf41 100644 --- a/s2core/build.sbt +++ b/s2core/build.sbt @@ -47,7 +47,7 @@ libraryDependencies ++= Seq( "org.apache.tinkerpop" % "gremlin-test" % tinkerpopVersion % "test", "org.scalatest" %% "scalatest" % "2.2.4" % "test", "org.specs2" %% "specs2-core" % specs2Version % "test", - "org.apache.hadoop" % "hadoop-hdfs" % hadoopVersion , + "org.apache.hadoop" % "hadoop-hdfs" % hadoopVersion, "org.apache.lucene" % "lucene-core" % "6.6.0", "org.apache.lucene" % "lucene-queryparser" % "6.6.0", "org.rocksdb" % "rocksdbjni" % rocksVersion, http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/2d37cf65/s2graphql/build.sbt ---------------------------------------------------------------------- diff --git a/s2graphql/build.sbt b/s2graphql/build.sbt index a3fbec0..bc71f98 100644 --- a/s2graphql/build.sbt +++ b/s2graphql/build.sbt @@ -26,13 +26,15 @@ description := "GraphQL server with akka-http and sangria and s2graph" scalacOptions ++= Seq("-deprecation", "-feature") libraryDependencies ++= Seq( + "org.scala-lang" % "scala-compiler" % scalaVersion.value, + "org.scala-lang" % "scala-reflect" % scalaVersion.value, + "org.sangria-graphql" %% "sangria" % "1.4.0", "org.sangria-graphql" %% "sangria-spray-json" % "1.0.0", "org.sangria-graphql" %% "sangria-play-json" % "1.0.1" % Test, "com.typesafe.akka" %% "akka-http" % "10.0.10", "com.typesafe.akka" %% "akka-http-spray-json" % "10.0.10", - "com.typesafe.akka" %% "akka-slf4j" % "2.4.6", "org.scalatest" %% "scalatest" % "3.0.4" % Test http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/2d37cf65/s2graphql/src/main/scala/org/apache/s2graph/graphql/GraphQLServer.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/main/scala/org/apache/s2graph/graphql/GraphQLServer.scala b/s2graphql/src/main/scala/org/apache/s2graph/graphql/GraphQLServer.scala index eee7c93..8ea4c89 100644 --- a/s2graphql/src/main/scala/org/apache/s2graph/graphql/GraphQLServer.scala +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/GraphQLServer.scala @@ -115,6 +115,8 @@ object GraphQLServer { newSchema } + val transformMiddleWare = new org.apache.s2graph.graphql.middleware.Transform() + private def executeGraphQLQuery(query: Document, op: Option[String], vars: JsObject)(implicit e: ExecutionContext) = { val cacheKey = className + "s2Schema" val s2schema = schemaCache.withCache(cacheKey, broadcast = false)(createNewSchema()) @@ -127,7 +129,8 @@ object GraphQLServer { s2Repository, variables = vars, operationName = op, - deferredResolver = resolver + deferredResolver = resolver, + middleware = List(transformMiddleWare) ) .map((res: spray.json.JsValue) => OK -> res) .recover { http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/2d37cf65/s2graphql/src/main/scala/org/apache/s2graph/graphql/middleware/Transform.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/main/scala/org/apache/s2graph/graphql/middleware/Transform.scala b/s2graphql/src/main/scala/org/apache/s2graph/graphql/middleware/Transform.scala new file mode 100644 index 0000000..9aa86fb --- /dev/null +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/middleware/Transform.scala @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.s2graph.graphql.middleware + +import org.apache.s2graph.graphql.types.S2Directive +import sangria.ast.StringValue +import sangria.execution.{Middleware, MiddlewareAfterField, MiddlewareQueryContext} +import sangria.schema.Context + +case class Transform() extends Middleware[Any] with MiddlewareAfterField[Any] { + type QueryVal = Unit + type FieldVal = Unit + + def beforeQuery(context: MiddlewareQueryContext[Any, _, _]) = () + + def afterQuery(queryVal: QueryVal, context: MiddlewareQueryContext[Any, _, _]) = () + + def beforeField(cache: QueryVal, mctx: MiddlewareQueryContext[Any, _, _], ctx: Context[Any, _]) = continue + + def afterField(cache: QueryVal, fromCache: FieldVal, value: Any, mctx: MiddlewareQueryContext[Any, _, _], ctx: Context[Any, _]) = { + + value match { + case s: String => { + val transformFuncOpt = ctx.astFields.headOption.flatMap(_.directives.find(_.name == S2Directive.Transform.name)).map { directive => + directive.arguments.head.value.asInstanceOf[StringValue].value + } + + transformFuncOpt.map(funcString => S2Directive.resolveTransform(funcString, s)).orElse(Option(s)) + } + + case _ â None + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/2d37cf65/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/FieldResolver.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/FieldResolver.scala b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/FieldResolver.scala index 478517f..a2b80da 100644 --- a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/FieldResolver.scala +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/FieldResolver.scala @@ -28,7 +28,6 @@ import org.apache.s2graph.graphql.types.S2Type.EdgeQueryParam import sangria.schema._ object FieldResolver { - def graphElement[A](name: String, cType: String, c: Context[GraphRepository, Any]): A = { c.value match { case v: S2VertexLike => name match { @@ -36,6 +35,7 @@ object FieldResolver { case _ => val innerVal = v.propertyValue(name).get JSONParser.innerValToAny(innerVal, cType).asInstanceOf[A] + } case e: S2EdgeLike => name match { case "timestamp" => e.ts.asInstanceOf[A] http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/2d37cf65/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2Directive.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2Directive.scala b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2Directive.scala new file mode 100644 index 0000000..2eb5768 --- /dev/null +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2Directive.scala @@ -0,0 +1,49 @@ +package org.apache.s2graph.graphql.types + +import sangria.schema.{Argument, Directive, DirectiveLocation, StringType} + +object S2Directive { + + object Eval { + + import scala.collection._ + + val codeMap = mutable.Map.empty[String, () => Any] + + def compileCode(code: String): () => Any = { + import scala.tools.reflect.ToolBox + val toolbox = reflect.runtime.currentMirror.mkToolBox() + + toolbox.compile(toolbox.parse(code)) + } + + def getCompiledCode[T](code: String): T = { + val compiledCode = Eval.codeMap.getOrElseUpdate(code, Eval.compileCode(code)) + + compiledCode + .asInstanceOf[() => Any] + .apply() + .asInstanceOf[T] + } + } + + type TransformFunc = String => String + + val funcArg = Argument("func", StringType) + + val Transform = + Directive("transform", + arguments = List(funcArg), + locations = Set(DirectiveLocation.Field), + shouldInclude = _ => true) + + def resolveTransform(code: String, input: String): String = { + try { + val fn = Eval.getCompiledCode[TransformFunc](code) + + fn.apply(input) + } catch { + case e: Exception => e.toString + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/2d37cf65/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/SchemaDef.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/SchemaDef.scala b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/SchemaDef.scala index 27b0c50..7451023 100644 --- a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/SchemaDef.scala +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/SchemaDef.scala @@ -20,8 +20,6 @@ package org.apache.s2graph.graphql.types import org.apache.s2graph.graphql.repository.GraphRepository -import org.apache.s2graph.graphql.types._ - /** * S2Graph GraphQL schema. @@ -47,5 +45,13 @@ class SchemaDef(g: GraphRepository) { fields(s2Type.mutationFields ++ mutateManagementFields: _*) ) - val S2GraphSchema = Schema(S2QueryType, Option(S2MutationType)) + val directives = S2Directive.Transform :: BuiltinDirectives + + private val s2Schema = Schema( + S2QueryType, + Option(S2MutationType), + directives = directives + ) + + val S2GraphSchema = s2Schema }
