LegacyUserStateController.java

1
package edu.ucsb.cs.scaffold.controller;
2
3
import com.fasterxml.jackson.annotation.JsonProperty;
4
import com.fasterxml.jackson.core.JsonProcessingException;
5
import com.fasterxml.jackson.core.type.TypeReference;
6
import com.fasterxml.jackson.databind.JsonNode;
7
import com.fasterxml.jackson.databind.ObjectMapper;
8
import edu.ucsb.cs.scaffold.model.LegacyUserState;
9
import edu.ucsb.cs.scaffold.repository.LegacyUserStateRepository;
10
import io.swagger.v3.oas.annotations.Operation;
11
import io.swagger.v3.oas.annotations.Parameter;
12
import io.swagger.v3.oas.annotations.tags.Tag;
13
import java.util.List;
14
import lombok.RequiredArgsConstructor;
15
import org.springframework.http.ResponseEntity;
16
import org.springframework.web.bind.annotation.*;
17
18
// Serves only LegacyHomePage.tsx (via legacyClient.ts). State here is per-user with no
19
// course scoping; the course-scoped counterpart is UserStateController at /api/user-state.
20
@Tag(name = "Legacy User State")
21
@RestController
22
@RequiredArgsConstructor
23
public class LegacyUserStateController {
24
25
  private final LegacyUserStateRepository legacyUserStateRepository;
26
  private final ObjectMapper objectMapper;
27
28
  @Operation(summary = "Get saved legacy user state by user ID")
29
  @GetMapping("/api/legacy/user-state/{userid}")
30
  public ResponseEntity<LegacyUserStateResponse> getUserState(
31
      @Parameter(description = "User ID (from users table)") @PathVariable Long userid) {
32 1 1. getUserState : replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::getUserState → KILLED
    return legacyUserStateRepository
33
        .findByUserid(userid)
34
        .map(
35
            state ->
36 1 1. lambda$getUserState$0 : replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::lambda$getUserState$0 → KILLED
                ResponseEntity.ok(
37
                    new LegacyUserStateResponse(
38
                        parseStringList(state.getStarredIds()),
39
                        parseJsonNode(state.getDetailCards()),
40
                        parseStringList(state.getMasteredSubconcepts()))))
41 1 1. lambda$getUserState$1 : replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::lambda$getUserState$1 → KILLED
        .orElseGet(() -> ResponseEntity.notFound().build());
42
  }
43
44
  @Operation(summary = "Upsert saved legacy user state by user ID")
45
  @PostMapping("/api/legacy/user-state")
46
  public ResponseEntity<Void> upsertUserState(@RequestBody LegacyUserStateRequest body) {
47 1 1. upsertUserState : negated conditional → KILLED
    if (body.userid() == null) {
48 1 1. upsertUserState : replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::upsertUserState → KILLED
      return ResponseEntity.badRequest().build();
49
    }
50
51
    LegacyUserState state =
52
        legacyUserStateRepository.findByUserid(body.userid()).orElseGet(LegacyUserState::new);
53 1 1. upsertUserState : removed call to edu/ucsb/cs/scaffold/model/LegacyUserState::setUserid → KILLED
    state.setUserid(body.userid());
54 2 1. upsertUserState : removed call to edu/ucsb/cs/scaffold/model/LegacyUserState::setStarredIds → KILLED
2. upsertUserState : negated conditional → KILLED
    state.setStarredIds(writeJson(body.starredIds() == null ? List.of() : body.starredIds()));
55 1 1. upsertUserState : removed call to edu/ucsb/cs/scaffold/model/LegacyUserState::setDetailCards → KILLED
    state.setDetailCards(
56
        writeJson(
57 1 1. upsertUserState : negated conditional → KILLED
            body.detailCards() == null ? objectMapper.createArrayNode() : body.detailCards()));
58 1 1. upsertUserState : removed call to edu/ucsb/cs/scaffold/model/LegacyUserState::setMasteredSubconcepts → KILLED
    state.setMasteredSubconcepts(
59 1 1. upsertUserState : negated conditional → KILLED
        writeJson(body.masteredSubconcepts() == null ? List.of() : body.masteredSubconcepts()));
60
    legacyUserStateRepository.save(state);
61
62 1 1. upsertUserState : replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::upsertUserState → KILLED
    return ResponseEntity.noContent().build();
63
  }
64
65
  private List<String> parseStringList(String json) {
66
    try {
67 1 1. parseStringList : replaced return value with Collections.emptyList for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::parseStringList → KILLED
      return objectMapper.readValue(json, new TypeReference<>() {});
68
    } catch (JsonProcessingException e) {
69
      throw new IllegalStateException("Unable to parse stored string list JSON", e);
70
    }
71
  }
72
73
  private JsonNode parseJsonNode(String json) {
74
    try {
75 1 1. parseJsonNode : replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::parseJsonNode → KILLED
      return objectMapper.readTree(json);
76
    } catch (JsonProcessingException e) {
77
      throw new IllegalStateException("Unable to parse stored JSON payload", e);
78
    }
79
  }
80
81
  private String writeJson(Object value) {
82
    try {
83 1 1. writeJson : replaced return value with "" for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::writeJson → KILLED
      return objectMapper.writeValueAsString(value);
84
    } catch (JsonProcessingException e) {
85
      throw new IllegalArgumentException("Unable to serialize JSON payload", e);
86
    }
87
  }
88
89
  public record LegacyUserStateRequest(
90
      Long userid,
91
      @JsonProperty("starred_ids") List<String> starredIds,
92
      @JsonProperty("detail_cards") JsonNode detailCards,
93
      @JsonProperty("mastered_subconcepts") List<String> masteredSubconcepts) {}
94
95
  public record LegacyUserStateResponse(
96
      @JsonProperty("starred_ids") List<String> starredIds,
97
      @JsonProperty("detail_cards") JsonNode detailCards,
98
      @JsonProperty("mastered_subconcepts") List<String> masteredSubconcepts) {}
99
}

Mutations

32

1.1
Location : getUserState
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:missingLegacyUserStateReturns404()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::getUserState → KILLED

36

1.1
Location : lambda$getUserState$0
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::lambda$getUserState$0 → KILLED

41

1.1
Location : lambda$getUserState$1
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:missingLegacyUserStateReturns404()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::lambda$getUserState$1 → KILLED

47

1.1
Location : upsertUserState
Killed by : edu.ucsb.cs.scaffold.controller.LegacyUserStateControllerExceptionTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.LegacyUserStateControllerExceptionTests]/[method:writeJsonThrowsIllegalArgumentOnJsonProcessingException()]
negated conditional → KILLED

48

1.1
Location : upsertUserState
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:upsertLegacyUserStateWithNullUseridReturnsBadRequest()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::upsertUserState → KILLED

53

1.1
Location : upsertUserState
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
removed call to edu/ucsb/cs/scaffold/model/LegacyUserState::setUserid → KILLED

54

1.1
Location : upsertUserState
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
removed call to edu/ucsb/cs/scaffold/model/LegacyUserState::setStarredIds → KILLED

2.2
Location : upsertUserState
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
negated conditional → KILLED

55

1.1
Location : upsertUserState
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
removed call to edu/ucsb/cs/scaffold/model/LegacyUserState::setDetailCards → KILLED

57

1.1
Location : upsertUserState
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
negated conditional → KILLED

58

1.1
Location : upsertUserState
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
removed call to edu/ucsb/cs/scaffold/model/LegacyUserState::setMasteredSubconcepts → KILLED

59

1.1
Location : upsertUserState
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
negated conditional → KILLED

62

1.1
Location : upsertUserState
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::upsertUserState → KILLED

67

1.1
Location : parseStringList
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
replaced return value with Collections.emptyList for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::parseStringList → KILLED

75

1.1
Location : parseJsonNode
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::parseJsonNode → KILLED

83

1.1
Location : writeJson
Killed by : edu.ucsb.cs.scaffold.ScaffoldApplicationTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.ScaffoldApplicationTests]/[method:legacyUserStateCanBeUpsertedAndFetchedByUserId()]
replaced return value with "" for edu/ucsb/cs/scaffold/controller/LegacyUserStateController::writeJson → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0