You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2020/04/17 14:24:33 UTC

[sling-whiteboard] branch master updated: Decorate schemas with data fetcher definitions, work in progress

This is an automated email from the ASF dual-hosted git repository.

bdelacretaz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 25cbb95  Decorate schemas with data fetcher definitions, work in progress
25cbb95 is described below

commit 25cbb95d97477e268891f216d96cc453a9c6bdfa
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Fri Apr 17 16:24:15 2020 +0200

    Decorate schemas with data fetcher definitions, work in progress
---
 .../scripting/gql/engine/GraphQLResourceQuery.java |  8 +--
 .../gql/engine/GraphQLScriptEngineFactory.java     |  1 +
 .../scripting/gql/schema/FetcherDefinition.java    | 70 +++++++++++++++++++
 .../{engine => schema}/GraphQLSchemaProvider.java  |  4 +-
 .../scripting/gql/servlet/GraphQLServlet.java      |  2 +-
 .../gql/engine/GraphQLResourceQueryTest.java       |  1 +
 .../scripting/gql/engine/MockSchemaProvider.java   |  1 +
 .../gql/schema/FetcherDefinitionTest.java          | 81 ++++++++++++++++++++++
 .../apps/graphql/test/one/GQLschema.jsp            |  7 +-
 9 files changed, 165 insertions(+), 10 deletions(-)

diff --git a/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLResourceQuery.java b/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLResourceQuery.java
index c90a30a..94975cf 100644
--- a/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLResourceQuery.java
+++ b/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLResourceQuery.java
@@ -23,6 +23,7 @@ package org.apache.sling.scripting.gql.engine;
 import javax.script.ScriptException;
 
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.scripting.gql.schema.GraphQLSchemaProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -95,9 +96,8 @@ public class GraphQLResourceQuery {
     }
 
     private RuntimeWiring buildWiring(Resource r) {
-        return RuntimeWiring.newRuntimeWiring()
-            .type(TypeRuntimeWiring.newTypeWiring("Query").dataFetcher("currentResource", new EchoDataFetcher(r)).build())
-            .build()
-        ;
+        final RuntimeWiring.Builder b = RuntimeWiring.newRuntimeWiring();
+        b.type(TypeRuntimeWiring.newTypeWiring("Query").dataFetcher("currentResource", new EchoDataFetcher(r)).build());
+        return b.build();
     }
 }
diff --git a/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLScriptEngineFactory.java b/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLScriptEngineFactory.java
index f0f6ecb..7f231db 100644
--- a/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLScriptEngineFactory.java
+++ b/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLScriptEngineFactory.java
@@ -23,6 +23,7 @@ import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
 
 import org.apache.sling.scripting.api.AbstractScriptEngineFactory;
+import org.apache.sling.scripting.gql.schema.GraphQLSchemaProvider;
 import org.osgi.framework.Constants;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
diff --git a/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/schema/FetcherDefinition.java b/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/schema/FetcherDefinition.java
new file mode 100644
index 0000000..5d3a7ee
--- /dev/null
+++ b/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/schema/FetcherDefinition.java
@@ -0,0 +1,70 @@
+
+/*
+ * 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.sling.scripting.gql.schema;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class FetcherDefinition {
+    public final String typeName;
+    public final String fieldName;
+    public final String fetcherNamespace;
+    public final String fetcherName;
+    public final String fetcherOptions;
+    public final String fetcherSourceExpression;
+
+    /** Definitions are formatted like 
+     *  fetch:test/digest:sha512/$.path
+     */
+    private static final Pattern REGEXP = Pattern.compile("fetch\\:(\\w+)/(\\w+)(/(\\S+))?( +(.*))?");
+
+    /** Creates a definition from a formatted String like
+     *  
+      */
+    public FetcherDefinition(String typeName, String fieldName, String fetcherDef) {
+        if(typeName == null || fieldName == null || fetcherDef == null) {
+            throw new IllegalArgumentException("Invalid input: " + typeName + "," + fieldName + "," + fetcherDef);
+        }
+        final Matcher m = REGEXP.matcher(fetcherDef);
+        if(!m.matches()) {
+            throw new IllegalArgumentException("Input does not match " + REGEXP + ": " + fetcherDef);
+        }
+        this.typeName = typeName;
+        this.fieldName = fieldName;
+        fetcherNamespace = m.group(1);
+        fetcherName = m.group(2);
+        fetcherOptions = optional(m.group(4));
+        fetcherSourceExpression = optional(m.group(6));
+    }
+
+    private static final String optional(String input) {
+        return input == null ? "" : input.trim();
+    }
+
+    @Override
+    public String toString() {
+        return String.format(
+            "%s#%s#%s#%s#%s#%s#%s", 
+            getClass().getSimpleName(), typeName, fieldName, 
+            fetcherNamespace, fetcherName, 
+            fetcherOptions, fetcherSourceExpression);
+    }
+}
diff --git a/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLSchemaProvider.java b/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/schema/GraphQLSchemaProvider.java
similarity index 97%
rename from graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLSchemaProvider.java
rename to graphql-scripting/src/main/java/org/apache/sling/scripting/gql/schema/GraphQLSchemaProvider.java
index ad10e0a..dd3b0d2 100644
--- a/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/engine/GraphQLSchemaProvider.java
+++ b/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/schema/GraphQLSchemaProvider.java
@@ -18,12 +18,10 @@
  * under the License.
  */
 
-package org.apache.sling.scripting.gql.engine;
+package org.apache.sling.scripting.gql.schema;
 
 import java.io.IOException;
 
-import javax.servlet.ServletException;
-
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.engine.SlingRequestProcessor;
diff --git a/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/servlet/GraphQLServlet.java b/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/servlet/GraphQLServlet.java
index f9489d9..b4f19a1 100644
--- a/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/servlet/GraphQLServlet.java
+++ b/graphql-scripting/src/main/java/org/apache/sling/scripting/gql/servlet/GraphQLServlet.java
@@ -31,7 +31,7 @@ import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
 import org.apache.sling.scripting.gql.engine.GraphQLResourceQuery;
-import org.apache.sling.scripting.gql.engine.GraphQLSchemaProvider;
+import org.apache.sling.scripting.gql.schema.GraphQLSchemaProvider;
 import org.apache.sling.scripting.gql.engine.GraphQLScriptEngine;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
diff --git a/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/engine/GraphQLResourceQueryTest.java b/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/engine/GraphQLResourceQueryTest.java
index e29d543..4e89cd3 100644
--- a/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/engine/GraphQLResourceQueryTest.java
+++ b/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/engine/GraphQLResourceQueryTest.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.fail;
 import java.util.UUID;
 
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.scripting.gql.schema.GraphQLSchemaProvider;
 import org.junit.Test;
 import org.mockito.Mockito;
 
diff --git a/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/engine/MockSchemaProvider.java b/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/engine/MockSchemaProvider.java
index f1fbf43..699376e 100644
--- a/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/engine/MockSchemaProvider.java
+++ b/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/engine/MockSchemaProvider.java
@@ -19,6 +19,7 @@
 package org.apache.sling.scripting.gql.engine;
 
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.scripting.gql.schema.GraphQLSchemaProvider;
 
 class MockSchemaProvider extends GraphQLSchemaProvider {
 
diff --git a/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/schema/FetcherDefinitionTest.java b/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/schema/FetcherDefinitionTest.java
new file mode 100644
index 0000000..947ee49
--- /dev/null
+++ b/graphql-scripting/src/test/java/org/apache/sling/scripting/gql/schema/FetcherDefinitionTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.sling.scripting.gql.schema;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class FetcherDefinitionTest {
+
+    private final String input;
+    private final String expected;
+    private final Class<?> failureClass;
+
+    @Parameters(name="{0}")
+    public static Collection<Object[]> data() {
+        final List<Object []> result = new ArrayList<>();
+        
+        result.add(new Object[] { "fetch:test/withOptions/sha512,armored(UTF-8) $.path", "test#withOptions#sha512,armored(UTF-8)#$.path" });
+        result.add(new Object[] { "fetch:namespace2/FetcherOption/upperCase", "namespace2#FetcherOption#upperCase#" });
+        result.add(new Object[] { "fetch:namespace2/FetcherExpression \t  sqrt(42)/3.4", "namespace2#FetcherExpression##sqrt(42)/3.4" });
+        result.add(new Object[] { "fetch:namespace2/noOptions", "namespace2#noOptions##" });
+        result.add(new Object[] { "wrongPrefix:namespace2/noOptions", IllegalArgumentException.class });
+        result.add(new Object[] { "nimportequoi", IllegalArgumentException.class });
+        result.add(new Object[] { "", IllegalArgumentException.class });
+        result.add(new Object[] { null, IllegalArgumentException.class });
+        
+        return result;
+    }
+
+    public FetcherDefinitionTest(String input, Object expected) {
+        this.input = input;
+        if(expected instanceof String) {
+            this.expected = (String)expected;
+            this.failureClass = null;
+        } else {
+            this.expected = null;
+            this.failureClass = (Class<?>)expected;
+        }
+    }
+
+    @Test
+    public void testMatch() throws Exception {
+        if(failureClass == null) {
+            final FetcherDefinition d = new FetcherDefinition("TYPE", "FIELD", input);
+            assertEquals("FetcherDefinition#TYPE#FIELD#" + expected, d.toString());
+        } else {
+            try {
+                new FetcherDefinition("TYPE", "FIELD", input);
+                fail("Expecting a " + failureClass.getName());
+            } catch(Throwable t) {
+                assertEquals("Expecting a " + failureClass.getName(), failureClass, t.getClass());
+            }
+        } 
+    }
+}
diff --git a/graphql-scripting/src/test/resources/initial-content/apps/graphql/test/one/GQLschema.jsp b/graphql-scripting/src/test/resources/initial-content/apps/graphql/test/one/GQLschema.jsp
index e8c8c5b..ef695fe 100644
--- a/graphql-scripting/src/test/resources/initial-content/apps/graphql/test/one/GQLschema.jsp
+++ b/graphql-scripting/src/test/resources/initial-content/apps/graphql/test/one/GQLschema.jsp
@@ -25,9 +25,12 @@ additional DataFetcher information that we need.
 --%>
 
 type Query { 
-  currentResource : SlingResource 
+  currentResource : SlingResource ## fetch:test/pipe $
 }
 
 type SlingResource { 
-  path: String resourceType: String 
+  path: String
+  resourceType: String
+  # pathMD5: String ## fetch:test/digest/md5 $.path
+  # pathSHA512: String ## fetch:test/digest/sha512,armored(UTF-8) $.path
 }
\ No newline at end of file