Skip to content

Commit

Permalink
Provide links to spring academy guides in response if present
Browse files Browse the repository at this point in the history
  • Loading branch information
mbhave committed Jul 21, 2023
1 parent 0c3c141 commit 06c111d
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 17 deletions.
12 changes: 12 additions & 0 deletions src/main/java/io/spring/renderer/RendererProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

package io.spring.renderer;

import java.util.HashMap;
import java.util.Map;

import javax.validation.constraints.Pattern;

import org.springframework.boot.context.properties.ConfigurationProperties;
Expand All @@ -30,10 +33,19 @@ public class RendererProperties {

private final Github github = new Github();

/**
* Mappings from guide names to correspoding spring academy urls.
*/
private final Map<String, String> academy = new HashMap<>();

public Github getGithub() {
return this.github;
}

public Map<String, String> getAcademy() {
return this.academy;
}

public static class Github {

/**
Expand Down
45 changes: 45 additions & 0 deletions src/main/java/io/spring/renderer/guides/GuideMetadata.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2022-2023 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.renderer.guides;

import io.spring.renderer.github.Repository;

/**
* Metadata needed to create a {@link GuideModel}.
*
* @author Madhura Bhave
*/
class GuideMetadata {

private final Repository repository;

private final String academyUrl;

GuideMetadata(Repository repository, String academyUrl) {
this.repository = repository;
this.academyUrl = academyUrl;
}

public Repository getRepository() {
return this.repository;
}

public String getAcademyUrl() {
return this.academyUrl;
}

}
10 changes: 9 additions & 1 deletion src/main/java/io/spring/renderer/guides/GuideModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ class GuideModel extends RepresentationModel<GuideModel> {

private String[] projects;

GuideModel(Repository repository) {
private String academyUrl;

GuideModel(GuideMetadata guideMetadata) {
Repository repository = guideMetadata.getRepository();
this.type = GuideType.fromRepositoryName(repository.getName());
this.name = this.type.stripPrefix(repository.getName());
this.repositoryName = repository.getFullName();
Expand All @@ -72,6 +75,7 @@ class GuideModel extends RepresentationModel<GuideModel> {
else {
this.projects = new String[0];
}
this.academyUrl = guideMetadata.getAcademyUrl();
}

public String getName() {
Expand Down Expand Up @@ -114,4 +118,8 @@ public String[] getProjects() {
return this.projects;
}

public String getAcademyUrl() {
return this.academyUrl;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;

class GuideModelAssembler extends RepresentationModelAssemblerSupport<Repository, GuideModel> {
class GuideModelAssembler extends RepresentationModelAssemblerSupport<GuideMetadata, GuideModel> {

GuideModelAssembler() {
super(GuidesController.class, GuideModel.class);
}

@Override
public GuideModel toModel(Repository repository) {
GuideModel resource = new GuideModel(repository);
public GuideModel toModel(GuideMetadata guideMetadata) {
GuideModel resource = new GuideModel(guideMetadata);
resource.add(
linkTo(methodOn(GuidesController.class).showGuide(resource.getType().getSlug(), resource.getName()))
.withSelfRel());
Expand Down
19 changes: 13 additions & 6 deletions src/main/java/io/spring/renderer/guides/GuidesController.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ public ResponseEntity resourceNotFound() {

@GetMapping("")
public CollectionModel<GuideModel> listGuides() {
List<GuideModel> guideModels = this.guideAssembler
.toCollectionModel(
this.githubClient.fetchOrgRepositories(this.properties.getGithub().getOrganization()))
.getContent().stream().filter(guide -> !guide.getType().equals(GuideType.UNKNOWN))
.collect(Collectors.toList());
List<Repository> repositories = this.githubClient
.fetchOrgRepositories(this.properties.getGithub().getOrganization());
List<GuideMetadata> guideMetadataList = repositories.stream()
.map((repository) -> new GuideMetadata(repository, getAcademyUrl(repository))).toList();
List<GuideModel> guideModels = this.guideAssembler.toCollectionModel(guideMetadataList).getContent().stream()
.filter(guide -> !guide.getType().equals(GuideType.UNKNOWN)).collect(Collectors.toList());
CollectionModel<GuideModel> resources = CollectionModel.of(guideModels);
for (GuideType type : GuideType.values()) {
if (!GuideType.UNKNOWN.equals(type)) {
Expand All @@ -79,6 +80,10 @@ public CollectionModel<GuideModel> listGuides() {
return resources;
}

private String getAcademyUrl(Repository repository) {
return this.properties.getAcademy().get(repository.getName());
}

@GetMapping("/{type}/{guide}")
public ResponseEntity<GuideModel> showGuide(@PathVariable String type, @PathVariable String guide) {
GuideType guideType = GuideType.fromSlug(type);
Expand All @@ -87,7 +92,9 @@ public ResponseEntity<GuideModel> showGuide(@PathVariable String type, @PathVari
}
Repository repository = this.githubClient.fetchOrgRepository(this.properties.getGithub().getOrganization(),
guideType.getPrefix() + guide);
GuideModel guideModel = this.guideAssembler.toModel(repository);
String academyUrl = this.properties.getAcademy().get(repository.getName());
GuideMetadata guideMetadata = new GuideMetadata(repository, academyUrl);
GuideModel guideModel = this.guideAssembler.toModel(guideMetadata);
if (guideModel.getType().equals(GuideType.UNKNOWN)) {
return ResponseEntity.notFound().build();
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ renderer:
action-org: ${renderer-github-webhook-action-org:}
action-repo: ${renderer-github-webhook-action-repo:}
dispatch-token: ${renderer-github-webhook-dispatch-token:}
academy:
gs-accessing-data-jpa: https://spring.academy/guides/accessing-data-jpa
gs-rest-service: https://spring.academy/guides/rest-service
spring:
security:
user:
Expand Down
15 changes: 10 additions & 5 deletions src/test/java/io/spring/renderer/guides/GuideModelTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

import java.util.Arrays;

import org.junit.jupiter.api.Test;
import io.spring.renderer.github.Repository;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

Expand All @@ -35,7 +35,8 @@ public void nullRepositoryDescription() {
"git://example.org/spring-guides/gs-sample-guide.git",
"[email protected]:spring-guides/gs-sample-guide.git",
"https://example.org/spring-guides/gs-sample-guide.git", null);
GuideModel guideModel = new GuideModel(repository);
GuideMetadata guideMetadata = new GuideMetadata(repository, null);
GuideModel guideModel = new GuideModel(guideMetadata);
assertThat(guideModel.getName()).isEqualTo("sample-guide");
assertThat(guideModel.getRepositoryName()).isEqualTo("spring-guides/gs-sample-guide");
assertThat(guideModel.getTitle()).isEmpty();
Expand All @@ -55,13 +56,15 @@ public void noGuideProjects() {
"git://example.org/spring-guides/tut-sample-guide.git",
"[email protected]:spring-guides/tut-sample-guide.git",
"https://example.org/spring-guides/tut-sample-guide.git", null);
GuideModel guideModel = new GuideModel(repository);
GuideMetadata guideMetadata = new GuideMetadata(repository, "http://test.academy");
GuideModel guideModel = new GuideModel(guideMetadata);
assertThat(guideModel.getName()).isEqualTo("sample-guide");
assertThat(guideModel.getRepositoryName()).isEqualTo("spring-guides/tut-sample-guide");
assertThat(guideModel.getTitle()).isEqualTo("Title");
assertThat(guideModel.getDescription()).isEqualTo("Description");
assertThat(guideModel.getType()).isEqualTo(GuideType.TUTORIAL);
assertThat(guideModel.getProjects()).isEmpty();
assertThat(guideModel.getAcademyUrl()).isEqualTo("http://test.academy");
}

@Test
Expand All @@ -72,7 +75,8 @@ public void withGuideProjects() {
"[email protected]:spring-guides/top-sample-guide.git",
"https://example.org/spring-guides/top-sample-guide.git",
Arrays.asList("spring-framework", "spring-boot"));
GuideModel guideModel = new GuideModel(repository);
GuideMetadata guideMetadata = new GuideMetadata(repository, null);
GuideModel guideModel = new GuideModel(guideMetadata);
assertThat(guideModel.getName()).isEqualTo("sample-guide");
assertThat(guideModel.getRepositoryName()).isEqualTo("spring-guides/top-sample-guide");
assertThat(guideModel.getTitle()).isEqualTo("Title");
Expand All @@ -90,7 +94,8 @@ public void deprecatedGuide() {
"[email protected]:spring-guides/deprecated-gs-sample-guide.git",
"https://example.org/spring-guides/deprecated-gs-sample-guide.git",
Arrays.asList("spring-framework", "spring-boot"));
GuideModel guideModel = new GuideModel(repository);
GuideMetadata guideMetadata = new GuideMetadata(repository, null);
GuideModel guideModel = new GuideModel(guideMetadata);
assertThat(guideModel.getName()).isEqualTo("deprecated-gs-sample-guide");
assertThat(guideModel.getTitle()).isEqualTo("Title");
assertThat(guideModel.getDescription()).isEqualTo("Description");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import java.util.Arrays;

import io.spring.renderer.github.GithubClient;
import io.spring.renderer.github.GithubResourceNotFoundException;
import io.spring.renderer.github.Repository;
import org.junit.jupiter.api.Test;
import io.spring.renderer.github.GithubResourceNotFoundException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
Expand All @@ -45,7 +45,7 @@
/**
* Tests for {@link GuidesController}
*/
@WebMvcTest(GuidesController.class)
@WebMvcTest(controllers = GuidesController.class, properties = "renderer.academy.gs-rest-service: http://test.com")
@WithMockUser
public class GuidesControllerTests {

Expand Down Expand Up @@ -77,10 +77,12 @@ public void fetchAllGuides() throws Exception {

this.mvc.perform(get("/guides/")).andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.guides[0].name").value("rest-service"))
.andExpect(jsonPath("$._embedded.guides[0].academyUrl").value("http://test.com"))
.andExpect(jsonPath("$._embedded.guides[0].projects[0]").value("spring-boot"))
.andExpect(hasLink("$._embedded.guides[0]._links", "self",
"http://localhost/guides/getting-started/rest-service"))
.andExpect(jsonPath("$._embedded.guides[1].name").value("securing-web"))
.andExpect(jsonPath("$._embedded.guides[1].academyUrl").isEmpty())
.andExpect(jsonPath("$._embedded.guides[1].projects").isEmpty())
.andExpect(hasLink("$._embedded.guides[1]._links", "self",
"http://localhost/guides/getting-started/securing-web"));
Expand Down Expand Up @@ -122,6 +124,7 @@ public void fetchGuide() throws Exception {
.andExpect(jsonPath("$.gitUrl").value("git://example.org/spring-guides/gs-rest-service.git"))
.andExpect(jsonPath("$.sshUrl").value("[email protected]:spring-guides/gs-rest-service.git"))
.andExpect(jsonPath("$.cloneUrl").value("https://example.org/spring-guides/gs-rest-service.git"))
.andExpect(jsonPath("$.academyUrl").value("http://test.com"))
.andExpect(jsonPath("$.projects[0]").value("spring-boot"))
.andExpect(hasLink("self", "http://localhost/guides/getting-started/rest-service"));
}
Expand Down

0 comments on commit 06c111d

Please sign in to comment.