CommonsFeaturesController.java

1
package edu.ucsb.cs156.happiercows.controllers;
2
3
import edu.ucsb.cs156.happiercows.entities.Commons;
4
import edu.ucsb.cs156.happiercows.entities.CommonsFeature;
5
import edu.ucsb.cs156.happiercows.enums.CommonsFeatures;
6
import edu.ucsb.cs156.happiercows.errors.EntityNotFoundException;
7
import edu.ucsb.cs156.happiercows.repositories.CommonsFeatureRepository;
8
import edu.ucsb.cs156.happiercows.repositories.CommonsRepository;
9
import io.swagger.v3.oas.annotations.tags.Tag;
10
import io.swagger.v3.oas.annotations.Operation;
11
import lombok.extern.slf4j.Slf4j;
12
import org.springframework.beans.factory.annotation.Autowired;
13
import org.springframework.http.ResponseEntity;
14
import org.springframework.security.access.prepost.PreAuthorize;
15
import org.springframework.web.bind.annotation.GetMapping;
16
import org.springframework.web.bind.annotation.PostMapping;
17
import org.springframework.web.bind.annotation.RequestBody;
18
import org.springframework.web.bind.annotation.RequestMapping;
19
import org.springframework.web.bind.annotation.RestController;
20
21
import java.util.Arrays;
22
import java.util.HashMap;
23
import java.util.List;
24
import java.util.Map;
25
import java.util.Optional;
26
import java.util.stream.Collectors;
27
28
@Slf4j
29
@Tag(name = "Commons Features")
30
@RequestMapping("/api/commonsfeatures")
31
@RestController
32
public class CommonsFeaturesController extends ApiController {
33
34
    @Autowired
35
    private CommonsRepository commonsRepository;
36
37
    @Autowired
38
    private CommonsFeatureRepository commonsFeatureRepository;
39
40
    @Operation(summary = "List all commons features")
41
    @GetMapping("")
42
    public ResponseEntity<List<String>> getCommonsFeatures() {
43 1 1. getCommonsFeatures : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsFeatures → KILLED
        return ResponseEntity.ok(
44
            Arrays.stream(CommonsFeatures.values())
45
                .map(Enum::name)
46
                .collect(Collectors.toList())
47
        );
48
    }
49
50
    @Operation(summary = "Save commons feature settings")
51
    @PreAuthorize("hasRole('ROLE_ADMIN')")
52
    @PostMapping("")
53
    public ResponseEntity<Object> saveCommonsFeatures(@RequestBody Map<String, Object> requestBody) {
54
        Long commonsId = getCommonsId(requestBody);
55 1 1. saveCommonsFeatures : negated conditional → KILLED
        if (commonsId == null) {
56 1 1. saveCommonsFeatures : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::saveCommonsFeatures → KILLED
            return ResponseEntity.badRequest().body(genericMessage("commonsId is required"));
57
        }
58
59 1 1. saveCommonsFeatures : negated conditional → KILLED
        if (!commonsRepository.existsById(commonsId)) {
60
            throw new EntityNotFoundException(Commons.class, commonsId);
61
        }
62
63
        Map<String, Boolean> featureValues = new HashMap<>();
64
        for (Map.Entry<String, Object> entry : requestBody.entrySet()) {
65
            String key = entry.getKey();
66 1 1. saveCommonsFeatures : negated conditional → KILLED
            if ("commonsId".equals(key)) {
67
                continue;
68
            }
69
70 1 1. saveCommonsFeatures : negated conditional → KILLED
            if (!CommonsFeatures.isValidFeature(key)) {
71 1 1. saveCommonsFeatures : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::saveCommonsFeatures → KILLED
                return ResponseEntity.badRequest().body(genericMessage("Unknown commons feature: " + key));
72
            }
73
74
            featureValues.put(key, parseBoolean(entry.getValue()));
75
        }
76
77 1 1. saveCommonsFeatures : negated conditional → KILLED
        if (featureValues.isEmpty()) {
78 1 1. saveCommonsFeatures : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::saveCommonsFeatures → KILLED
            return ResponseEntity.badRequest().body(genericMessage("At least one commons feature must be provided"));
79
        }
80
81
        for (Map.Entry<String, Boolean> entry : featureValues.entrySet()) {
82
            String featureName = entry.getKey();
83
            boolean enabled = entry.getValue();
84
85
            CommonsFeature commonsFeature = commonsFeatureRepository
86
                    .findByCommonsIdAndFeature(commonsId, featureName)
87 1 1. lambda$saveCommonsFeatures$0 : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::lambda$saveCommonsFeatures$0 → KILLED
                    .orElseGet(() -> CommonsFeature.builder()
88
                            .commonsId(commonsId)
89
                            .feature(featureName)
90
                            .build());
91
92 1 1. saveCommonsFeatures : removed call to edu/ucsb/cs156/happiercows/entities/CommonsFeature::setEnabled → KILLED
            commonsFeature.setEnabled(enabled);
93
            commonsFeatureRepository.save(commonsFeature);
94
        }
95
96 1 1. saveCommonsFeatures : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::saveCommonsFeatures → KILLED
        return ResponseEntity.ok(genericMessage("Commons features updated successfully"));
97
    }
98
99
    private Long getCommonsId(Map<String, Object> requestBody) {
100
        Object value = requestBody.get("commonsId");
101 1 1. getCommonsId : negated conditional → KILLED
        if (value == null) {
102 1 1. getCommonsId : replaced Long return value with 0L for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsId → KILLED
            return null;
103
        }
104
105 1 1. getCommonsId : negated conditional → KILLED
        if (value instanceof Number) {
106 1 1. getCommonsId : replaced Long return value with 0L for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsId → KILLED
            return ((Number) value).longValue();
107
        }
108
109 1 1. getCommonsId : negated conditional → KILLED
        if (value instanceof String) {
110
            try {
111 1 1. getCommonsId : replaced Long return value with 0L for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsId → KILLED
                return Long.valueOf((String) value);
112
            } catch (NumberFormatException e) {
113 1 1. getCommonsId : replaced Long return value with 0L for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsId → KILLED
                return null;
114
            }
115
        }
116
117 1 1. getCommonsId : replaced Long return value with 0L for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsId → KILLED
        return null;
118
    }
119
120
    private boolean parseBoolean(Object value) {
121 1 1. parseBoolean : negated conditional → KILLED
        if (value instanceof Boolean) {
122 2 1. parseBoolean : replaced boolean return with false for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::parseBoolean → KILLED
2. parseBoolean : replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::parseBoolean → KILLED
            return (Boolean) value;
123
        }
124
125 1 1. parseBoolean : negated conditional → KILLED
        if (value instanceof Number) {
126 2 1. parseBoolean : negated conditional → KILLED
2. parseBoolean : replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::parseBoolean → KILLED
            return ((Number) value).intValue() != 0;
127
        }
128
129 1 1. parseBoolean : negated conditional → KILLED
        if (value instanceof String) {
130 2 1. parseBoolean : replaced boolean return with false for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::parseBoolean → KILLED
2. parseBoolean : replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::parseBoolean → KILLED
            return Boolean.parseBoolean((String) value);
131
        }
132
133
        throw new IllegalArgumentException("Invalid boolean value for commons feature");
134
    }
135
}

Mutations

43

1.1
Location : getCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:getCommonsFeatures_returns_list_of_features_for_admin()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsFeatures → KILLED

55

1.1
Location : saveCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_when_commonsId_missing()]
negated conditional → KILLED

56

1.1
Location : saveCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_when_commonsId_missing()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::saveCommonsFeatures → KILLED

59

1.1
Location : saveCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_for_unknown_feature_key()]
negated conditional → KILLED

66

1.1
Location : saveCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_for_unknown_feature_key()]
negated conditional → KILLED

70

1.1
Location : saveCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_for_unknown_feature_key()]
negated conditional → KILLED

71

1.1
Location : saveCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_for_unknown_feature_key()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::saveCommonsFeatures → KILLED

77

1.1
Location : saveCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_when_no_features_are_provided()]
negated conditional → KILLED

78

1.1
Location : saveCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_when_no_features_are_provided()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::saveCommonsFeatures → KILLED

87

1.1
Location : lambda$saveCommonsFeatures$0
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_parses_boolean_feature_value_true()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::lambda$saveCommonsFeatures$0 → KILLED

92

1.1
Location : saveCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_parses_boolean_feature_value_true()]
removed call to edu/ucsb/cs156/happiercows/entities/CommonsFeature::setEnabled → KILLED

96

1.1
Location : saveCommonsFeatures
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_parses_boolean_feature_value_true()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::saveCommonsFeatures → KILLED

101

1.1
Location : getCommonsId
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_for_unknown_feature_key()]
negated conditional → KILLED

102

1.1
Location : getCommonsId
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_when_commonsId_missing()]
replaced Long return value with 0L for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsId → KILLED

105

1.1
Location : getCommonsId
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_when_commonsId_malformed()]
negated conditional → KILLED

106

1.1
Location : getCommonsId
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_for_unknown_feature_key()]
replaced Long return value with 0L for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsId → KILLED

109

1.1
Location : getCommonsId
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_when_commonsId_has_unrecognized_type()]
negated conditional → KILLED

111

1.1
Location : getCommonsId
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_parses_string_commonsId()]
replaced Long return value with 0L for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsId → KILLED

113

1.1
Location : getCommonsId
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_when_commonsId_malformed()]
replaced Long return value with 0L for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsId → KILLED

117

1.1
Location : getCommonsId
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_returns_bad_request_when_commonsId_has_unrecognized_type()]
replaced Long return value with 0L for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::getCommonsId → KILLED

121

1.1
Location : parseBoolean
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_throws_for_invalid_feature_value_type()]
negated conditional → KILLED

122

1.1
Location : parseBoolean
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_parses_boolean_feature_value_true()]
replaced boolean return with false for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::parseBoolean → KILLED

2.2
Location : parseBoolean
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_saves_features()]
replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::parseBoolean → KILLED

125

1.1
Location : parseBoolean
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_throws_for_invalid_feature_value_type()]
negated conditional → KILLED

126

1.1
Location : parseBoolean
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_parses_numeric_feature_value()]
negated conditional → KILLED

2.2
Location : parseBoolean
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_parses_numeric_feature_value_false()]
replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::parseBoolean → KILLED

129

1.1
Location : parseBoolean
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_throws_for_invalid_feature_value_type()]
negated conditional → KILLED

130

1.1
Location : parseBoolean
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_parses_string_feature_value_true()]
replaced boolean return with false for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::parseBoolean → KILLED

2.2
Location : parseBoolean
Killed by : edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.CommonsFeaturesControllerTests]/[method:postCommonsFeatures_parses_string_feature_value()]
replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/CommonsFeaturesController::parseBoolean → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0