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-org-apache-sling-graphql-core.git


The following commit(s) were added to refs/heads/master by this push:
     new d148df6  Add support for multiple SchemaProvider services
d148df6 is described below

commit d148df64acb4927c9bb6f65aece3a875e44d4fb2
Author: Bertrand Delacretaz <[email protected]>
AuthorDate: Wed May 13 19:10:15 2020 +0200

    Add support for multiple SchemaProvider services
---
 pom.xml                                            |   6 ++
 .../graphql/core/engine/GraphQLResourceQuery.java  |   8 +-
 .../graphql/core/schema/DefaultSchemaProvider.java |   2 +
 .../graphql/core/schema/RankedSchemaProviders.java |  83 ++++++++++++++++
 .../core/scripting/GraphQLScriptEngine.java        |   4 +-
 .../core/scripting/GraphQLScriptEngineFactory.java |   7 +-
 .../sling/graphql/core/servlet/GraphQLServlet.java |   5 +-
 .../core/engine/GraphQLResourceQueryTest.java      |   5 +-
 .../sling/graphql/core/it/GraphQLServletIT.java    |  19 ++++
 ...{BasicContentIT.java => ServerSideQueryIT.java} |  32 ++++--
 .../core/mocks/ReplacingSchemaProvider.java        |  63 ++++++++++++
 .../core/schema/RankedSchemaProvidersTest.java     | 108 +++++++++++++++++++++
 .../apps/graphql/test/one/GQLschema.jsp            |   2 +-
 .../test/one/{json.gql => REPLACED.json.gql}       |   3 +-
 .../initial-content/apps/graphql/test/one/json.gql |   3 +-
 15 files changed, 327 insertions(+), 23 deletions(-)

diff --git a/pom.xml b/pom.xml
index 9c68420..5bd3c7a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -168,6 +168,12 @@
     </dependency>
     <dependency>
       <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.commons.osgi</artifactId>
+      <version>2.4.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
       <artifactId>org.apache.sling.testing.paxexam</artifactId>
       <version>3.1.0</version>
       <scope>test</scope>
diff --git 
a/src/main/java/org/apache/sling/graphql/core/engine/GraphQLResourceQuery.java 
b/src/main/java/org/apache/sling/graphql/core/engine/GraphQLResourceQuery.java
index 81daff4..edc9a3f 100644
--- 
a/src/main/java/org/apache/sling/graphql/core/engine/GraphQLResourceQuery.java
+++ 
b/src/main/java/org/apache/sling/graphql/core/engine/GraphQLResourceQuery.java
@@ -51,11 +51,6 @@ public class GraphQLResourceQuery {
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
-    public ExecutionResult executeQuery(SchemaProvider schemaProvider, 
DataFetcherSelector fetchers,
-                                        Resource r, String [] 
requestSelectors, String query) throws ScriptException {
-        return executeQuery(schemaProvider, fetchers, r, requestSelectors, 
query, Collections.emptyMap());
-    }
-
     public ExecutionResult executeQuery(SchemaProvider schemaProvider, 
DataFetcherSelector fetchersSelector,
                                         Resource r,
                                         String [] requestSelectors,
@@ -72,6 +67,9 @@ public class GraphQLResourceQuery {
         if(fetchersSelector == null) {
             throw new ScriptException("DataFetcherSelector is null");
         }
+        if(variables == null) {
+            variables = Collections.emptyMap();
+        }
 
         String schemaDef = null;
         try {
diff --git 
a/src/main/java/org/apache/sling/graphql/core/schema/DefaultSchemaProvider.java 
b/src/main/java/org/apache/sling/graphql/core/schema/DefaultSchemaProvider.java
index 05017d2..3395805 100644
--- 
a/src/main/java/org/apache/sling/graphql/core/schema/DefaultSchemaProvider.java
+++ 
b/src/main/java/org/apache/sling/graphql/core/schema/DefaultSchemaProvider.java
@@ -34,10 +34,12 @@ import org.osgi.service.component.annotations.Reference;
 
 /** Provides a Resource-specific GraphQL Schema, as text */
 @Component(service = SchemaProvider.class, immediate = true, property = {
+        Constants.SERVICE_RANKING + ":Integer=" + 
DefaultSchemaProvider.SERVICE_RANKING,
         Constants.SERVICE_DESCRIPTION + "=Apache Sling Scripting GraphQL 
SchemaProvider",
         Constants.SERVICE_VENDOR + "=The Apache Software Foundation" })
 public class DefaultSchemaProvider implements SchemaProvider {
 
+    public static final int SERVICE_RANKING = Integer.MAX_VALUE - 100;
     public static final String SCHEMA_EXTENSION = ".GQLschema";
 
     public static class SchemaProviderException extends IOException {
diff --git 
a/src/main/java/org/apache/sling/graphql/core/schema/RankedSchemaProviders.java 
b/src/main/java/org/apache/sling/graphql/core/schema/RankedSchemaProviders.java
new file mode 100644
index 0000000..63e47c1
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/graphql/core/schema/RankedSchemaProviders.java
@@ -0,0 +1,83 @@
+
+/*
+ * 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.graphql.core.schema;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.commons.osgi.Order;
+import org.apache.sling.commons.osgi.RankedServices;
+import org.apache.sling.graphql.api.SchemaProvider;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+/**
+ * Uses multiple registered SchemaProvider services to get a schema, using the
+ * first one that returns non-null.
+ */
+@Component(service = RankedSchemaProviders.class)
+public class RankedSchemaProviders implements SchemaProvider {
+
+    final RankedServices<SchemaProvider> providers = new 
RankedServices<>(Order.ASCENDING);
+
+    @Override
+    public @Nullable String getSchema(@NotNull final Resource r, @Nullable 
final String[] selectors) throws IOException {
+        String result = null;
+
+        for(SchemaProvider p : providers) {
+            result = p.getSchema(r, selectors);
+            if(result != null) {
+                break;
+            }
+        }
+
+        if(result == null) {
+            throw new IOException(
+                "No schema found for " + r.getPath() + " / " + 
Arrays.asList(selectors)
+                + ", SchemaProviders=" + providers);
+        }
+
+        return result;
+    }
+
+    @Reference(
+        service = SchemaProvider.class,
+        cardinality = ReferenceCardinality.AT_LEAST_ONE,
+        policy = ReferencePolicy.DYNAMIC,
+        policyOption = ReferencePolicyOption.GREEDY)
+    protected void bindSchemaProvider(SchemaProvider service, Map<String, 
Object> props) {
+        providers.bind(service, props);
+    }
+
+    protected void unbindSchemaProvider(SchemaProvider service, Map<String, 
Object> props) {
+        providers.unbind(service, props);
+    }
+}
diff --git 
a/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngine.java
 
b/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngine.java
index 60a2126..f3f2af1 100644
--- 
a/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngine.java
+++ 
b/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngine.java
@@ -60,8 +60,8 @@ public class GraphQLScriptEngine extends AbstractScriptEngine 
{
 
             final Resource resource = (Resource) 
context.getBindings(ScriptContext.ENGINE_SCOPE)
                     .get(SlingBindings.RESOURCE);
-            final ExecutionResult result = 
q.executeQuery(factory.getSchemaProvider(), factory.getdataFetcherSelector(),
-                    resource, null, IOUtils.toString(reader));
+            final ExecutionResult result = 
q.executeQuery(factory.getSchemaProviders(), factory.getdataFetcherSelector(),
+                    resource, null, IOUtils.toString(reader), null);
             final PrintWriter out = (PrintWriter) 
context.getBindings(ScriptContext.ENGINE_SCOPE).get(SlingBindings.OUT);
             jsonSerializer.sendJSON(out, result);
         } catch(Exception e) {
diff --git 
a/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngineFactory.java
 
b/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngineFactory.java
index 1e15851..445062a 100644
--- 
a/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngineFactory.java
+++ 
b/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngineFactory.java
@@ -25,6 +25,7 @@ import javax.script.ScriptEngineFactory;
 import org.apache.sling.scripting.api.AbstractScriptEngineFactory;
 import org.apache.sling.graphql.api.SchemaProvider;
 import org.apache.sling.graphql.core.schema.DataFetcherSelector;
+import org.apache.sling.graphql.core.schema.RankedSchemaProviders;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.service.component.annotations.Activate;
@@ -51,7 +52,7 @@ public class GraphQLScriptEngineFactory extends 
AbstractScriptEngineFactory {
     public static final String LANGUAGE_VERSION = "Sling:GraphQL:0.1";
 
     @Reference
-    private SchemaProvider schemaProvider;
+    private RankedSchemaProviders schemaProviders;
 
     private DataFetcherSelector dataFetcherSelector;
 
@@ -78,8 +79,8 @@ public class GraphQLScriptEngineFactory extends 
AbstractScriptEngineFactory {
         return new GraphQLScriptEngine(this);
     }
 
-    SchemaProvider getSchemaProvider() {
-        return schemaProvider;
+    RankedSchemaProviders getSchemaProviders() {
+        return schemaProviders;
     }
 
     DataFetcherSelector getdataFetcherSelector() {
diff --git 
a/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java 
b/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
index 8a8499e..e062622 100644
--- a/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
+++ b/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
@@ -33,6 +33,7 @@ import org.apache.sling.graphql.api.SchemaProvider;
 import org.apache.sling.graphql.core.engine.GraphQLResourceQuery;
 import org.apache.sling.graphql.core.json.JsonSerializer;
 import org.apache.sling.graphql.core.schema.DataFetcherSelector;
+import org.apache.sling.graphql.core.schema.RankedSchemaProviders;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
@@ -95,7 +96,7 @@ public class GraphQLServlet extends SlingAllMethodsServlet {
     }
 
     @Reference
-    private SchemaProvider schemaProvider;
+    private RankedSchemaProviders schemaProviders;
 
     private DataFetcherSelector dataFetcherSelector;
     private final JsonSerializer jsonSerializer = new JsonSerializer();
@@ -128,7 +129,7 @@ public class GraphQLServlet extends SlingAllMethodsServlet {
 
         try {
             final GraphQLResourceQuery q = new GraphQLResourceQuery();
-            final ExecutionResult result = q.executeQuery(schemaProvider, 
dataFetcherSelector,
+            final ExecutionResult result = q.executeQuery(schemaProviders, 
dataFetcherSelector,
                 resource, request.getRequestPathInfo().getSelectors(), query, 
parser.getVariables());
             jsonSerializer.sendJSON(response.getWriter(), result);
         } catch(Exception ex) {
diff --git 
a/src/test/java/org/apache/sling/graphql/core/engine/GraphQLResourceQueryTest.java
 
b/src/test/java/org/apache/sling/graphql/core/engine/GraphQLResourceQueryTest.java
index 3c5a0dd..8e69c04 100644
--- 
a/src/test/java/org/apache/sling/graphql/core/engine/GraphQLResourceQueryTest.java
+++ 
b/src/test/java/org/apache/sling/graphql/core/engine/GraphQLResourceQueryTest.java
@@ -91,7 +91,8 @@ public class GraphQLResourceQueryTest {
     }
 
     private String queryJSON(String stmt, String [] selectors) throws 
Exception {
-        final ExecutionResult result = new 
GraphQLResourceQuery().executeQuery(schemaProvider, dataFetchersSelector, 
resource, selectors, stmt);
+        final ExecutionResult result = new 
GraphQLResourceQuery().executeQuery(schemaProvider,
+            dataFetchersSelector, resource, selectors, stmt, null);
         assertTrue("Expecting no errors: " + result.getErrors(), 
result.getErrors().isEmpty());
         return new JsonSerializer().toJSON(result);
     }
@@ -137,7 +138,7 @@ public class GraphQLResourceQueryTest {
     public void dataFetcherFailureTest() throws Exception {
         try {
             final String stmt = "{ currentResource { failure } }";
-            new GraphQLResourceQuery().executeQuery(schemaProvider, 
dataFetchersSelector, resource, null, stmt);
+            new GraphQLResourceQuery().executeQuery(schemaProvider, 
dataFetchersSelector, resource, null, stmt, null);
         } catch(RuntimeException rex) {
             assertThat(rex.getMessage(), equalTo("FailureDataFetcher"));
         }
diff --git 
a/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java 
b/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
index d325c9c..793cd92 100644
--- a/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
+++ b/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
@@ -23,6 +23,8 @@ import javax.inject.Inject;
 import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
 import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath;
 
+import org.apache.sling.graphql.api.SchemaProvider;
+import org.apache.sling.graphql.core.mocks.ReplacingSchemaProvider;
 import org.apache.sling.resource.presence.ResourcePresence;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -32,6 +34,7 @@ import org.ops4j.pax.exam.junit.PaxExam;
 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
 import org.ops4j.pax.exam.spi.reactors.PerClass;
 import org.ops4j.pax.exam.util.Filter;
+import org.osgi.framework.BundleContext;
 
 import static org.junit.Assert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
@@ -45,6 +48,12 @@ public class GraphQLServletIT extends 
GraphQLScriptingTestSupport {
     @Filter(value = "(path=/content/graphql/two)")
     private ResourcePresence resourcePresence;
 
+    @Inject
+    private BundleContext bundleContext;
+
+    @Inject
+    private SchemaProvider defaultSchemaProvider;
+
     private static final String GRAPHQL_SERVLET_CONFIG_PID = 
"org.apache.sling.graphql.core.GraphQLServlet";
 
     @Configuration
@@ -112,4 +121,14 @@ public class GraphQLServletIT extends 
GraphQLScriptingTestSupport {
         assertThat(json, hasJsonPath("$.title", equalTo("GraphQL two")));
         assertThat(json, hasJsonPath("$.jcr:primaryType", 
equalTo("nt:unstructured")));
     }
+
+    @Test
+    public void testMultipleSchemaProviders() throws Exception {
+        new ReplacingSchemaProvider("currentResource", 
"REPLACED").register(bundleContext, defaultSchemaProvider, 1);
+        new ReplacingSchemaProvider("currentResource", 
"NOT_THIS_ONE").register(bundleContext, defaultSchemaProvider, 
Integer.MAX_VALUE);
+        final String json = getContent("/graphql/two.gql", "query", "{ 
REPLACED { resourceType name } }");
+        assertThat(json, hasJsonPath("$.data.REPLACED.resourceType", 
equalTo("graphql/test/two")));
+        assertThat(json, hasJsonPath("$.data.REPLACED.name", equalTo("two")));
+        assertThat(json, hasNoJsonPath("$.data.REPLACED.path"));
+    }
 }
diff --git a/src/test/java/org/apache/sling/graphql/core/it/BasicContentIT.java 
b/src/test/java/org/apache/sling/graphql/core/it/ServerSideQueryIT.java
similarity index 64%
rename from src/test/java/org/apache/sling/graphql/core/it/BasicContentIT.java
rename to src/test/java/org/apache/sling/graphql/core/it/ServerSideQueryIT.java
index cef98fd..a9a9fbd 100644
--- a/src/test/java/org/apache/sling/graphql/core/it/BasicContentIT.java
+++ b/src/test/java/org/apache/sling/graphql/core/it/ServerSideQueryIT.java
@@ -23,6 +23,8 @@ import javax.script.ScriptEngineFactory;
 
 import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
 
+import org.apache.sling.graphql.api.SchemaProvider;
+import org.apache.sling.graphql.core.mocks.ReplacingSchemaProvider;
 import org.apache.sling.resource.presence.ResourcePresence;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -32,6 +34,7 @@ import org.ops4j.pax.exam.junit.PaxExam;
 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
 import org.ops4j.pax.exam.spi.reactors.PerClass;
 import org.ops4j.pax.exam.util.Filter;
+import org.osgi.framework.BundleContext;
 
 import static org.junit.Assert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
@@ -39,7 +42,7 @@ import static 
org.ops4j.pax.exam.cm.ConfigurationAdminOptions.factoryConfigurati
 
 @RunWith(PaxExam.class)
 @ExamReactorStrategy(PerClass.class)
-public class BasicContentIT extends GraphQLScriptingTestSupport {
+public class ServerSideQueryIT extends GraphQLScriptingTestSupport {
 
     @Inject
     @Filter(value = "(names=graphql)")
@@ -49,6 +52,12 @@ public class BasicContentIT extends 
GraphQLScriptingTestSupport {
     @Filter(value = "(path=/apps/graphql/test/one/json.gql)")
     private ResourcePresence resourcePresence;
 
+    @Inject
+    private BundleContext bundleContext;
+
+    @Inject
+    private SchemaProvider defaultSchemaProvider;
+
     @Configuration
     public Option[] configuration() {
         return new Option[]{
@@ -60,12 +69,23 @@ public class BasicContentIT extends 
GraphQLScriptingTestSupport {
         };
     }
 
+    private void assertDefaultContent(String selector, String fieldName) 
throws Exception {
+        final String path = "/graphql/one";
+        final String json = getContent(path + selector + ".json");
+        assertThat(json, hasJsonPath("$.data." + fieldName));
+        assertThat(json, hasJsonPath("$.data." + fieldName + ".path", 
equalTo("/content/graphql/one")));
+        assertThat(json, hasJsonPath("$.data." + fieldName + ".resourceType", 
equalTo("graphql/test/one")));
+    }
+
     @Test
     public void testJsonContent() throws Exception {
-        final String path = "/graphql/one";
-        final String json = getContent(path + ".json");
-        assertThat(json, hasJsonPath("$.data.currentResource"));
-        assertThat(json, hasJsonPath("$.data.currentResource.path", 
equalTo("/content/graphql/one")));
-        assertThat(json, hasJsonPath("$.data.currentResource.resourceType", 
equalTo("graphql/test/one")));
+        assertDefaultContent("", "scriptedSchemaResource");
+    }
+
+    @Test
+    public void testMultipleSchemaProviders() throws Exception {
+        new ReplacingSchemaProvider("scriptedSchemaResource", 
"REPLACED").register(bundleContext, defaultSchemaProvider, 1);
+        new ReplacingSchemaProvider("scriptedSchemaResource", 
"NOT_THIS_ONE").register(bundleContext, defaultSchemaProvider, 
Integer.MAX_VALUE);
+        assertDefaultContent(".REPLACED", "REPLACED");
     }
 }
diff --git 
a/src/test/java/org/apache/sling/graphql/core/mocks/ReplacingSchemaProvider.java
 
b/src/test/java/org/apache/sling/graphql/core/mocks/ReplacingSchemaProvider.java
new file mode 100644
index 0000000..217c9c1
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/graphql/core/mocks/ReplacingSchemaProvider.java
@@ -0,0 +1,63 @@
+/*
+ * 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.graphql.core.mocks;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.graphql.api.SchemaProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * SchemaProvider that replaces a regexp in the schema, or always returns a 
null
+ * schema. provided by the DefaultSchemaProvider. Used for testing the
+ * RankedSchemaProvider.
+ */
+public class ReplacingSchemaProvider implements SchemaProvider {
+
+    private final String pattern;
+    private final String replacement;
+    private SchemaProvider defaultSchemaProvider;
+
+    public ReplacingSchemaProvider(String pattern, String replacement) {
+        this.pattern = pattern;
+        this.replacement = replacement;
+    }
+
+    @Override
+    public String getSchema(Resource r, String[] selectors) throws IOException 
{
+        final String original = defaultSchemaProvider.getSchema(r, selectors);
+        return original.replaceAll(pattern, replacement);
+    }
+
+    public ServiceRegistration<?> register(BundleContext ctx, SchemaProvider 
defaultSchemaProvider, int serviceRanking) throws InvalidSyntaxException {
+        this.defaultSchemaProvider = defaultSchemaProvider;
+
+        final Dictionary<String, Object> props = new Hashtable<>();
+        props.put(Constants.SERVICE_RANKING, serviceRanking);
+        return ctx.registerService(SchemaProvider.class, this, props);
+    }
+
+}
diff --git 
a/src/test/java/org/apache/sling/graphql/core/schema/RankedSchemaProvidersTest.java
 
b/src/test/java/org/apache/sling/graphql/core/schema/RankedSchemaProvidersTest.java
new file mode 100644
index 0000000..e7279f7
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/graphql/core/schema/RankedSchemaProvidersTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.graphql.core.schema;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.engine.SlingRequestProcessor;
+import org.apache.sling.graphql.api.SchemaProvider;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+
+public class RankedSchemaProvidersTest {
+    private final String DEFAULT_SCHEMA_PROVIDER_OUTPUT = "";
+    private final int DEFAULT_SERVICE_RANKING = 
DefaultSchemaProvider.SERVICE_RANKING;
+
+    @Rule
+    public final OsgiContext context = new OsgiContext();
+
+    @Before
+    public void setup() {
+        final SlingRequestProcessor rp = 
Mockito.mock(SlingRequestProcessor.class);
+        context.bundleContext().registerService(SlingRequestProcessor.class, 
rp, null);
+        context.registerInjectActivateService(new DefaultSchemaProvider(), 
Constants.SERVICE_RANKING,
+                DefaultSchemaProvider.SERVICE_RANKING);
+        context.registerInjectActivateService(new RankedSchemaProviders());
+    }
+
+    private void assertProvider(String info, String expected) throws 
IOException {
+        final RankedSchemaProviders sp = 
context.getService(RankedSchemaProviders.class);
+        final Resource r = Mockito.mock(Resource.class);
+        assertEquals(info, expected, sp.getSchema(r, null));
+    }
+
+    private ServiceRegistration<?> registerProvider(String name, int 
serviceRanking) throws IOException {
+        final SchemaProvider sp = Mockito.mock(SchemaProvider.class);
+        Mockito.when(sp.toString()).thenReturn(name);
+        Mockito.when(sp.getSchema(Mockito.any(), 
Mockito.any())).thenReturn(name);
+        final Dictionary<String, Object> props = new Hashtable<>();
+        props.put(Constants.SERVICE_RANKING, serviceRanking);
+        return context.bundleContext().registerService(SchemaProvider.class, 
sp, props);
+    }
+
+    @Test
+    public void defaultProviderActive() throws IOException {
+        assertProvider("Default", DEFAULT_SCHEMA_PROVIDER_OUTPUT);
+    }
+
+    @Test
+    public void providerPriorities() throws IOException {
+        assertProvider("Beginning", DEFAULT_SCHEMA_PROVIDER_OUTPUT);
+
+        registerProvider("Y", DEFAULT_SERVICE_RANKING + 1);
+        assertProvider("After Y", DEFAULT_SCHEMA_PROVIDER_OUTPUT);
+
+        final ServiceRegistration<?> z = registerProvider("Z", 
DEFAULT_SERVICE_RANKING - 1);
+        assertProvider("After Z", "Z");
+
+        final ServiceRegistration<?> a = registerProvider("A", 1);
+        assertProvider("After A", "A");
+
+        final ServiceRegistration<?> b = registerProvider("B", 2);
+        assertProvider("After B", "A");
+
+        a.unregister();
+        assertProvider("After removing A", "B");
+
+        b.unregister();
+        assertProvider("After removing B", "Z");
+
+        z.unregister();
+        assertProvider("After removing Z", DEFAULT_SCHEMA_PROVIDER_OUTPUT);
+    }
+
+    @Test
+    public void nullProviderResultIgnored() throws IOException {
+        assertProvider("Beginning", DEFAULT_SCHEMA_PROVIDER_OUTPUT);
+        registerProvider(null, 1);
+        assertProvider("After null", DEFAULT_SCHEMA_PROVIDER_OUTPUT);
+        registerProvider("A", 1);
+        assertProvider("After A", "A");
+    }
+}
\ No newline at end of file
diff --git 
a/src/test/resources/initial-content/apps/graphql/test/one/GQLschema.jsp 
b/src/test/resources/initial-content/apps/graphql/test/one/GQLschema.jsp
index 3a41c05..ad09f7e 100644
--- a/src/test/resources/initial-content/apps/graphql/test/one/GQLschema.jsp
+++ b/src/test/resources/initial-content/apps/graphql/test/one/GQLschema.jsp
@@ -26,7 +26,7 @@ additional DataFetcher information that we need.
 
 type Query {
   ## fetch:test/pipe $
-  currentResource : SlingResource
+  scriptedSchemaResource : SlingResource
 }
 
 type SlingResource { 
diff --git a/src/test/resources/initial-content/apps/graphql/test/one/json.gql 
b/src/test/resources/initial-content/apps/graphql/test/one/REPLACED.json.gql
similarity index 89%
copy from src/test/resources/initial-content/apps/graphql/test/one/json.gql
copy to 
src/test/resources/initial-content/apps/graphql/test/one/REPLACED.json.gql
index 1dde25b..ae60533 100644
--- a/src/test/resources/initial-content/apps/graphql/test/one/json.gql
+++ b/src/test/resources/initial-content/apps/graphql/test/one/REPLACED.json.gql
@@ -15,4 +15,5 @@
 # * specific language governing permissions and limitations
 # * under the License.
 
-{ currentResource { path resourceType } }
\ No newline at end of file
+# Define the query for this resource type, selector and extension
+{ REPLACED { path resourceType } }
\ No newline at end of file
diff --git a/src/test/resources/initial-content/apps/graphql/test/one/json.gql 
b/src/test/resources/initial-content/apps/graphql/test/one/json.gql
index 1dde25b..cc25dd7 100644
--- a/src/test/resources/initial-content/apps/graphql/test/one/json.gql
+++ b/src/test/resources/initial-content/apps/graphql/test/one/json.gql
@@ -15,4 +15,5 @@
 # * specific language governing permissions and limitations
 # * under the License.
 
-{ currentResource { path resourceType } }
\ No newline at end of file
+# Define the query for this resource type, selector and extension
+{ scriptedSchemaResource { path resourceType } }
\ No newline at end of file

Reply via email to