Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration of M-Elo #1

Merged
merged 14 commits into from
Aug 1, 2024
1 change: 1 addition & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
uses: gradle/gradle-build-action@v3

with:
arguments: cleanTest test jacocoTestReport sonar

Expand Down
12 changes: 9 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.+'

id 'org.springframework.boot' version '3.2.+'
id 'io.spring.dependency-management' version '1.+'
id "io.github.kobylynskyi.graphql.codegen" version "5.+"
id "org.sonarqube" version "5.+"
Expand All @@ -21,6 +22,7 @@ if (jacocoEnabled.toBoolean()) {
}

sonarqube {

properties {
property("sonar.projectKey", "MEITREX_flashcard_service")
property("sonar.organization", "meitrex")
Expand Down Expand Up @@ -108,7 +110,8 @@ repositories {
}

dependencies {
implementation 'de.unistuttgart.iste.meitrex:meitrex-common:1.0.6'
implementation 'de.unistuttgart.iste.meitrex:meitrex-common:1.2'
implementation 'com.google.code.findbugs:jsr305:3.0.2' // removes a gradle warning about an unknown annotation
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-graphql'
implementation 'org.springframework.boot:spring-boot-starter-validation'
Expand All @@ -124,7 +127,7 @@ dependencies {
runtimeOnly 'org.postgresql:postgresql'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'de.unistuttgart.iste.meitrex:meitrex-common-test:1.0.6'
testImplementation 'de.unistuttgart.iste.meitrex:meitrex-common-test:1.2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework:spring-webflux'
testImplementation 'org.springframework.graphql:spring-graphql-test'
Expand All @@ -137,3 +140,6 @@ dependencies {
tasks.named('test') {
useJUnitPlatform()
}

tasks.withType(Test).configureEach { testLogging.showStandardStreams = true }

1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ sourceControl {
}
gitRepository(uri('https://github.com/MEITREX/common_test')) {
producesModule('de.unistuttgart.iste.meitrex:meitrex-common-test')

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;



/**
* This is the entry point of the application.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package de.unistuttgart.iste.meitrex.flashcard_service.controller;

import de.unistuttgart.iste.meitrex.generated.dto.Flashcard;
import de.unistuttgart.iste.meitrex.generated.dto.FlashcardSet;

import de.unistuttgart.iste.meitrex.common.exception.NoAccessToCourseException;
import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser;
import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser.UserRoleInCourse;
Expand Down Expand Up @@ -28,7 +31,7 @@ public class FlashcardController {
private final FlashcardUserProgressDataService progressDataService;

@QueryMapping
public List<Flashcard> flashcardsByIds(@Argument(name = "ids") final List<UUID> ids,
public List<Flashcard> flashcardsByIds(@Argument(name = "itemIds") final List<UUID> ids,
@ContextValue final LoggedInUser currentUser) {
final List<UUID> courseIds = flashcardService.getCourseIdsForFlashcardIds(ids);

Expand Down Expand Up @@ -67,7 +70,7 @@ public List<Flashcard> dueFlashcardsByCourseId(@Argument final UUID courseId,
@SchemaMapping(typeName = "Flashcard", field = "userProgressData")
public FlashcardProgressData flashcardUserProgressData(final Flashcard flashcard,
@ContextValue final LoggedInUser currentUser) {
return progressDataService.getProgressData(flashcard.getId(), currentUser.getId());
return progressDataService.getProgressData(flashcard.getItemId(), currentUser.getId());
}

@MutationMapping
Expand All @@ -82,11 +85,16 @@ public FlashcardSetMutation mutateFlashcardSet(@Argument final UUID assessmentId
}

@SchemaMapping(typeName = "FlashcardSetMutation")
public Flashcard createFlashcard(@Argument(name = "input") final CreateFlashcardInput input,
final FlashcardSetMutation mutation) {
public Flashcard _internal_noauth_createFlashcard(@Argument(name = "input") final CreateFlashcardInput input,
final FlashcardSetMutation mutation) {
return flashcardService.createFlashcard(mutation.getAssessmentId(), input);
}

@SchemaMapping(typeName = "FlashcardSetMutation")
public Flashcard _internal_noauth_updateFlashcard(@Argument(name = "input") final UpdateFlashcardInput input) {
return flashcardService.updateFlashcard(input);
}

@SchemaMapping(typeName = "FlashcardSetMutation")
public Flashcard updateFlashcard(@Argument(name = "input") final UpdateFlashcardInput input) {
return flashcardService.updateFlashcard(input);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class SubscriptionController {

private final FlashcardService flashcardService;

@Topic(name = "content-changed", pubsubName = "gits")
@Topic(name = "content-changed", pubsubName = "meitrex")
@PostMapping(path = "/flashcard-service/content-changed-pubsub")
public Mono<Void> updateAssociation(@RequestBody CloudEvent<ContentChangeEvent> cloudEvent) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
public class FlashcardEntity {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private UUID itemId;

@OneToMany(mappedBy = "flashcard", cascade = CascadeType.ALL, orphanRemoval = true)
private List<FlashcardSideEntity> sides;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package de.unistuttgart.iste.meitrex.flashcard_service.persistence.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.*;

import java.io.Serializable;
import java.time.OffsetDateTime;
Expand All @@ -14,6 +11,7 @@
@Entity(name = "FlashcardProgressData")
@Data
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class FlashcardProgressDataEntity {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

@Entity(name = "FlashcardProgressDataLog")
@Data
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class FlashcardProgressDataLogEntity {
Expand All @@ -30,4 +33,8 @@ public class FlashcardProgressDataLogEntity {
@EqualsAndHashCode.Exclude
@ToString.Exclude
private FlashcardProgressDataEntity flashcardProgressData;

public boolean getSuccess() {
return success;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package de.unistuttgart.iste.meitrex.flashcard_service.persistence.mapper;

import de.unistuttgart.iste.meitrex.flashcard_service.persistence.entity.FlashcardEntity;
import de.unistuttgart.iste.meitrex.flashcard_service.persistence.entity.FlashcardSetEntity;
import de.unistuttgart.iste.meitrex.flashcard_service.persistence.entity.FlashcardSideEntity;

import de.unistuttgart.iste.meitrex.flashcard_service.persistence.entity.*;

import de.unistuttgart.iste.meitrex.generated.dto.*;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;


Expand All @@ -14,7 +15,8 @@
*/
@Repository
public interface FlashcardRepository extends JpaRepository<FlashcardEntity, UUID>, JpaSpecificationExecutor<FlashcardEntity> {
List<FlashcardEntity> findByIdIn(List<UUID> ids);
List<FlashcardEntity> findByItemIdIn(List<UUID> ids);


Optional<FlashcardEntity> findByItemId(UUID itemId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public interface FlashcardSetRepository extends MeitrexRepository<FlashcardSetEn

/**
* Find all flashcard sets by course id.
*
* @param courseId the course id
* @return the list of flashcard sets
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.stereotype.Repository;

import java.util.UUID;

@Repository
public interface FlashcardSideRepository extends JpaRepository<FlashcardSideEntity, UUID>,
JpaSpecificationExecutor<FlashcardSideEntity> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import de.unistuttgart.iste.meitrex.common.event.ContentChangeEvent;
import de.unistuttgart.iste.meitrex.common.event.CrudOperation;
import de.unistuttgart.iste.meitrex.common.exception.IncompleteEventMessageException;

import de.unistuttgart.iste.meitrex.common.dapr.TopicPublisher;

import de.unistuttgart.iste.meitrex.flashcard_service.persistence.entity.FlashcardEntity;
import de.unistuttgart.iste.meitrex.flashcard_service.persistence.entity.FlashcardSetEntity;
import de.unistuttgart.iste.meitrex.flashcard_service.persistence.mapper.FlashcardMapper;
Expand All @@ -17,6 +20,7 @@
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;

Expand All @@ -31,6 +35,8 @@ public class FlashcardService {
private final FlashcardMapper flashcardMapper;
private final FlashcardValidator flashcardValidator;

private final TopicPublisher topicPublisher;

public Flashcard createFlashcard(final UUID assessmentId, final CreateFlashcardInput flashcardInput) {
flashcardValidator.validateCreateFlashcardInput(flashcardInput);

Expand All @@ -50,8 +56,8 @@ public Flashcard createFlashcard(final UUID assessmentId, final CreateFlashcardI
public Flashcard updateFlashcard(final UpdateFlashcardInput input) {
flashcardValidator.validateUpdateFlashcardInput(input);

final FlashcardEntity oldFlashcard = flashcardRepository.findById(input.getId())
.orElseThrow(() -> new EntityNotFoundException("Flashcard with id %s not found.".formatted(input.getId())));
final FlashcardEntity oldFlashcard = flashcardRepository.findById(input.getItemId())
.orElseThrow(() -> new EntityNotFoundException("Flashcard with id %s not found.".formatted(input.getItemId())));

FlashcardEntity updatedFlashcard = flashcardMapper.dtoToEntity(input);
updatedFlashcard.setParentSet(oldFlashcard.getParentSet());
Expand All @@ -63,10 +69,11 @@ public Flashcard updateFlashcard(final UpdateFlashcardInput input) {

public UUID deleteFlashcard(final UUID assessmentId, final UUID flashcardId) {
final FlashcardSetEntity set = requireFlashcardSetExisting(assessmentId);
if (!set.getFlashcards().removeIf(x -> x.getId().equals(flashcardId))) {
if (!set.getFlashcards().removeIf(x -> x.getItemId().equals(flashcardId))) {
throw new EntityNotFoundException("Flashcard with id %s not found.".formatted(flashcardId));
}
flashcardSetRepository.save(set);
publishItemChangeEvent(flashcardId);
return flashcardId;
}

Expand All @@ -82,6 +89,7 @@ public FlashcardSet createFlashcardSet(final UUID courseId, final UUID assessmen

public UUID deleteFlashcardSet(final UUID uuid) {
requireFlashcardSetExisting(uuid);
publishDeletedFlashcardSet(uuid);
flashcardSetRepository.deleteById(uuid);
return uuid;
}
Expand All @@ -92,10 +100,10 @@ public FlashcardSetEntity requireFlashcardSetExisting(final UUID uuid) {
}

public List<Flashcard> getFlashcardsByIds(final List<UUID> ids) {
final List<FlashcardEntity> entities = flashcardRepository.findByIdIn(ids);
final List<FlashcardEntity> entities = flashcardRepository.findByItemIdIn(ids);

ids.removeAll(entities.stream().map(FlashcardEntity::getId).toList());
if(!ids.isEmpty()) {
ids.removeAll(entities.stream().map(FlashcardEntity::getItemId).toList());
if (!ids.isEmpty()) {
throw new EntityNotFoundException("Flashcards with ids "
+ ids.stream().map(UUID::toString).collect(Collectors.joining(", "))
+ " not found.");
Expand Down Expand Up @@ -148,6 +156,7 @@ public void deleteFlashcardSetIfContentIsDeleted(final ContentChangeEvent dto) t

flashcardSetRepository.deleteAllById(dto.getContentIds());
}

/**
* helper function to make sure received event message is complete
*
Expand All @@ -159,4 +168,28 @@ private void checkCompletenessOfDto(final ContentChangeEvent dto) throws Incompl
throw new IncompleteEventMessageException(IncompleteEventMessageException.ERROR_INCOMPLETE_MESSAGE);
}
}

/***
* helper function, that creates a ItemChange Event and publish it, when a flashcard was deleted
* @param itemId the id of the item
*/
private void publishItemChangeEvent(final UUID itemId) {
topicPublisher.notifyItemChanges(itemId, CrudOperation.DELETE);

}

/**
* for each flashcard of the deleted flashcard set publish a itemchanged event
*
* @param flashcardSetId the id of the flashcardset to delete
*/
private void publishDeletedFlashcardSet(UUID flashcardSetId) {
Optional<FlashcardSetEntity> flashcardSetOptional = flashcardSetRepository.findById(flashcardSetId);
if(flashcardSetOptional.isPresent()){
FlashcardSetEntity flashcardSet=flashcardSetOptional.get();
for (FlashcardEntity flashcard : flashcardSet.getFlashcards()) {
publishItemChangeEvent(flashcard.getItemId());
}
}
}
}
Loading
Loading