diff --git a/backend/demo-group7/src/main/java/com/group7/demo/controllers/PostController.java b/backend/demo-group7/src/main/java/com/group7/demo/controllers/PostController.java index 1b3aa20..70efd45 100644 --- a/backend/demo-group7/src/main/java/com/group7/demo/controllers/PostController.java +++ b/backend/demo-group7/src/main/java/com/group7/demo/controllers/PostController.java @@ -2,10 +2,14 @@ import com.group7.demo.dtos.PostRequest; import com.group7.demo.dtos.PostResponse; +import com.group7.demo.dtos.jsonld.PostJsonLd; +import com.group7.demo.dtos.mapper.Mapper; +import com.group7.demo.models.Post; import com.group7.demo.services.PostService; import jakarta.servlet.http.HttpServletRequest; import lombok.AllArgsConstructor; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -17,6 +21,7 @@ @RequestMapping("/api/posts") @AllArgsConstructor public class PostController { + private final Mapper mapper; private PostService postService; @PostMapping @@ -125,5 +130,14 @@ public ResponseEntity> fetchPostsWithPagination( return ResponseEntity.ok(response); } + @GetMapping(value = "/{postId}", produces = "application/ld+json") + public ResponseEntity getPostJsonLd(@PathVariable Long postId) { + Post post = postService.getPostById(postId); + PostJsonLd jsonLd = mapper.mapToPostJsonLd(post); + return ResponseEntity.ok() + .contentType(MediaType.valueOf("application/ld+json")) + .body(jsonLd); + } + } diff --git a/backend/demo-group7/src/main/java/com/group7/demo/dtos/jsonld/PostJsonLd.java b/backend/demo-group7/src/main/java/com/group7/demo/dtos/jsonld/PostJsonLd.java new file mode 100644 index 0000000..c5595dc --- /dev/null +++ b/backend/demo-group7/src/main/java/com/group7/demo/dtos/jsonld/PostJsonLd.java @@ -0,0 +1,34 @@ +package com.group7.demo.dtos.jsonld; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; +import lombok.Data; + +import java.util.Map; + +@Data +@Builder +public class PostJsonLd { + @JsonProperty("@context") + private String context; + + @JsonProperty("@type") + private String type; + + private String identifier; + private String text; + private String datePublished; + + @JsonProperty("author") + private Map author; + + private String image; + + @JsonProperty("interactionStatistic") + private Map[] interactionStatistics; + + private String[] keywords; + + @JsonProperty("associatedProgram") + private Map trainingProgram; +} diff --git a/backend/demo-group7/src/main/java/com/group7/demo/dtos/mapper/Mapper.java b/backend/demo-group7/src/main/java/com/group7/demo/dtos/mapper/Mapper.java index 5c517e3..5d484cd 100644 --- a/backend/demo-group7/src/main/java/com/group7/demo/dtos/mapper/Mapper.java +++ b/backend/demo-group7/src/main/java/com/group7/demo/dtos/mapper/Mapper.java @@ -1,6 +1,7 @@ package com.group7.demo.dtos.mapper; import com.group7.demo.dtos.*; +import com.group7.demo.dtos.jsonld.PostJsonLd; import com.group7.demo.models.*; import com.group7.demo.models.enums.TrainingProgramWithTrackingStatus; import com.group7.demo.services.AuthenticationService; @@ -10,6 +11,7 @@ import java.time.LocalDate; import java.util.Comparator; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -222,6 +224,50 @@ public FeedbackResponse mapToFeedbackResponse(Feedback feedback) { .build(); } + public PostJsonLd mapToPostJsonLd(Post post) { + // Create array of interaction statistics for both likes and bookmarks + Map[] interactionStats = new Map[2]; + + // Like statistics + interactionStats[0] = Map.of( + "@type", "InteractionCounter", + "interactionType", "https://schema.org/LikeAction", + "userInteractionCount", post.getLikedByUsers() != null ? post.getLikedByUsers().size() : 0 + ); + + // Bookmark statistics + interactionStats[1] = Map.of( + "@type", "InteractionCounter", + "interactionType", "https://schema.org/BookmarkAction", + "userInteractionCount", post.getBookmarkedByUsers() != null ? post.getBookmarkedByUsers().size() : 0 + ); + return PostJsonLd.builder() + .context("https://schema.org") + .type("SocialMediaPosting") + .identifier(post.getId().toString()) + .text(post.getContent()) + .datePublished(post.getCreatedAt().toString()) + .author(Map.of( + "@type", "Person", + "identifier", post.getUser().getId().toString(), + "name", post.getUser().getUsername() + )) + .image(post.getImageUrl() != null ? post.getImageUrl() : "") + .interactionStatistics(interactionStats) + .keywords(post.getTags() != null ? + post.getTags().stream() + .map(Tag::getName) + .toArray(String[]::new) + : new String[0]) + .trainingProgram(post.getTrainingProgram() != null ? Map.of( + "@type", "ExercisePlan", + "identifier", post.getTrainingProgram().getId().toString(), + "name", post.getTrainingProgram().getTitle(), + "description", post.getTrainingProgram().getDescription(), + "instructor", post.getTrainingProgram().getTrainer().getUsername() + ) : null) + .build(); + } } diff --git a/backend/demo-group7/src/main/java/com/group7/demo/services/PostService.java b/backend/demo-group7/src/main/java/com/group7/demo/services/PostService.java index c49a7df..b17f2c1 100644 --- a/backend/demo-group7/src/main/java/com/group7/demo/services/PostService.java +++ b/backend/demo-group7/src/main/java/com/group7/demo/services/PostService.java @@ -270,4 +270,9 @@ public Map getPostsByTagsWithPagination(Set tagNames, in return response; } + public Post getPostById(Long postId) { + return postRepository.findById(postId) + .orElseThrow(() -> new EntityNotFoundException("Post not found with id: " + postId)); + } + }