diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/SpringProjectsClient.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/SpringProjectsClient.java index 0c2361723..69df1028e 100644 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/SpringProjectsClient.java +++ b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/SpringProjectsClient.java @@ -20,6 +20,9 @@ public class SpringProjectsClient { private static final TypeReferences.CollectionModelType releaseCollection = new TypeReferences.CollectionModelType() {}; + private static final TypeReferences.CollectionModelType projectCollection = + new TypeReferences.CollectionModelType() {}; + private final Traverson traverson; public SpringProjectsClient(RestTemplateBuilder builder) { @@ -39,7 +42,11 @@ public List fetchProjectReleases(String projectSlug) { CollectionModel releases = this.traverson.follow("projects") .follow(Hop.rel("project").withParameter("id", projectSlug)).follow(Hop.rel("releases")) .toObject(releaseCollection); - return new ArrayList(releases.getContent()); + return new ArrayList<>(releases.getContent()); } + public List fetchAllProjects() { + CollectionModel projects = this.traverson.follow("projects").toObject(projectCollection); + return new ArrayList<>(projects.getContent()); + } } diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/search/SearchController.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/search/SearchController.java new file mode 100644 index 000000000..e31cbec9d --- /dev/null +++ b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/search/SearchController.java @@ -0,0 +1,55 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed 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 + * + * https://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 io.spring.sample.graphql.search; + +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import org.springframework.graphql.data.method.annotation.Argument; +import org.springframework.graphql.data.method.annotation.QueryMapping; +import org.springframework.stereotype.Controller; + +import io.spring.sample.graphql.project.Project; +import io.spring.sample.graphql.project.SpringProjectsClient; +import io.spring.sample.graphql.repository.ArtifactRepositories; +import io.spring.sample.graphql.repository.ArtifactRepository; + +@Controller +public class SearchController { + + private final SpringProjectsClient client; + private final ArtifactRepositories repositories; + + public SearchController(SpringProjectsClient client, ArtifactRepositories repositories) { + this.client = client; + this.repositories = repositories; + } + + @QueryMapping + public Stream search(@Argument String text, @Argument SearchType type) { + Stream repos = + (type == null || type == SearchType.ARTIFACTREPOSITORY) ? + StreamSupport.stream(repositories.findAll().spliterator(), false) + .filter(r -> r.getName().toLowerCase().contains(text.toLowerCase())) : + Stream.empty(); + Stream projects = + (type == null || type == SearchType.PROJECT) ? + client.fetchAllProjects().stream() + .filter(p -> p.getName().toLowerCase().contains(text.toLowerCase())) : + Stream.empty(); + return Stream.concat(repos, projects); + } +} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/search/SearchType.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/search/SearchType.java new file mode 100644 index 000000000..c480acef9 --- /dev/null +++ b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/search/SearchType.java @@ -0,0 +1,21 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed 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 + * + * https://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 io.spring.sample.graphql.search; + +public enum SearchType { + ARTIFACTREPOSITORY, + PROJECT +} diff --git a/samples/webmvc-http/src/main/resources/graphql/schema.graphqls b/samples/webmvc-http/src/main/resources/graphql/schema.graphqls index 9d4d995e0..3da916462 100644 --- a/samples/webmvc-http/src/main/resources/graphql/schema.graphqls +++ b/samples/webmvc-http/src/main/resources/graphql/schema.graphqls @@ -3,6 +3,7 @@ type Query { artifactRepositories : [ArtifactRepository] artifactRepository(id : ID!) : ArtifactRepository project(slug: ID!): Project + search(text: String!, type: SearchType): [SearchResult] } type ArtifactRepository { @@ -26,6 +27,13 @@ type Release { current: Boolean } +union SearchResult = ArtifactRepository | Project + +enum SearchType { + ARTIFACTREPOSITORY + PROJECT +} + enum ProjectStatus { ACTIVE COMMUNITY diff --git a/samples/webmvc-http/src/main/resources/graphql/search.graphql b/samples/webmvc-http/src/main/resources/graphql/search.graphql new file mode 100644 index 000000000..f22076947 --- /dev/null +++ b/samples/webmvc-http/src/main/resources/graphql/search.graphql @@ -0,0 +1,10 @@ +query search($text: String!, $type: SearchType) { + search(text: $text, type: $type) { + ... on ArtifactRepository { + name + } + ... on Project { + name + } + } +} diff --git a/samples/webmvc-http/src/test/java/io/spring/sample/graphql/search/SearchControllerTests.java b/samples/webmvc-http/src/test/java/io/spring/sample/graphql/search/SearchControllerTests.java new file mode 100644 index 000000000..88f3f15a9 --- /dev/null +++ b/samples/webmvc-http/src/test/java/io/spring/sample/graphql/search/SearchControllerTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed 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 + * + * https://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 io.spring.sample.graphql.search; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.graphql.boot.test.tester.AutoConfigureWebGraphQlTester; +import org.springframework.graphql.test.tester.WebGraphQlTester; + +import org.junit.jupiter.api.Test; + +@SpringBootTest +@AutoConfigureWebGraphQlTester +class SearchControllerTests { + + @Autowired + private WebGraphQlTester graphQlTester; + + @Test + void fullResults() { + this.graphQlTester.queryName("search") + .variable("text", "spring") + .execute() + .path("search[*].name") + .entityList(String.class).hasSizeGreaterThan(3); + } + + @Test + void artifactRepositoriesResults() { + this.graphQlTester.queryName("search") + .variable("text", "spring") + .variable("type", SearchType.ARTIFACTREPOSITORY) + .execute() + .path("search[*].name") + .entityList(String.class).hasSize(3); + } + + @Test + void projectsResults() { + this.graphQlTester.queryName("search") + .variable("text", "spring") + .variable("type", SearchType.PROJECT) + .execute() + .path("search[*].name") + .entityList(String.class).hasSizeGreaterThan(3); + } +}