Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 8808bbe4

Přidáno uživatelem Ondřej Váně před asi 4 roky(ů)

Implemented changable configuration by UI

- values extracted only for too long sprint anti pattern

Zobrazit rozdíly:

src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/controller/AppController.java
82 82
    public String about() {
83 83
        return "about";
84 84
    }
85

  
86
    @GetMapping("/configuration")
87
    public String configuration(Model model) {
88
        model.addAttribute("antiPatterns", antiPatternService.antiPatternsToModel(antiPatternService.getAllAntiPatterns()));
89
        return "configuration";
90
    }
91

  
92
    @PostMapping("/configuration")
93
    public String configurationPost(Model model,
94
                                    @RequestParam(value = "configValues", required = false) String[] configValues,
95
                                    @RequestParam(value = "configNames", required = false) String[] configNames) {
96

  
97
        if (antiPatternService.saveNewConfiguration(configNames, configValues)) {
98
            model.addAttribute("successMessage", "All threshold values has been successfully saved.");
99
        } else {
100
            model.addAttribute("errorMessage", "One or more configuration values are not in correct format");
101
        }
102

  
103
        model.addAttribute("antiPatterns", antiPatternService.antiPatternsToModel(antiPatternService.getAllAntiPatterns()));
104

  
105
        return "configuration";
106
    }
85 107
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/TooLongSprintDetectorImpl.java
1 1
package cz.zcu.fav.kiv.antipatterndetectionapp.detecting.detectors;
2 2

  
3 3
import cz.zcu.fav.kiv.antipatterndetectionapp.detecting.DatabaseConnection;
4
import cz.zcu.fav.kiv.antipatterndetectionapp.model.AntiPattern;
5
import cz.zcu.fav.kiv.antipatterndetectionapp.model.Project;
6
import cz.zcu.fav.kiv.antipatterndetectionapp.model.QueryResultItem;
7
import cz.zcu.fav.kiv.antipatterndetectionapp.model.ResultDetail;
4
import cz.zcu.fav.kiv.antipatterndetectionapp.model.*;
8 5
import org.slf4j.Logger;
9 6
import org.slf4j.LoggerFactory;
10 7

  
11 8
import java.util.ArrayList;
9
import java.util.HashMap;
12 10
import java.util.List;
13 11
import java.util.Map;
14 12

  
......
23 21
                    "maximum 3 weeks). It could also be detected here if the length " +
24 22
                    "of the iteration does not change often (It can change at the " +
25 23
                    "beginning and at the end of the project, but it should not " +
26
                    "change in the already started project).");
24
                    "change in the already started project).",
25
            new HashMap<>() {{
26
                put("maxIterationLength", new Configuration<Integer>("maxIterationLength",
27
                        "Max Iteration Length",
28
                        "Maximum iteration length in days", 21));
29
                put("maxNumberOfTooLongIterations", new Configuration<Integer>("maxNumberOfTooLongIterations",
30
                        "Max number of foo long iterations",
31
                        "Maximum number of too long iterations in project", 1));
32
            }}
33
    );
27 34

  
28 35
    private final String SQL_FILE_NAME = "too_long_sprint.sql";
29 36
    // sql queries loaded from sql file
30 37
    private List<String> sqlQueries;
31 38

  
32
    /**
33
     * SETTINGS
34
     */
35
    private static final int MAX_NUMBER_OF_TOO_LONG_ITERATIONS = 1;
36
    private static final int MAX_ITERATION_LENGTH = 21;
37

  
38

  
39 39
    @Override
40 40
    public AntiPattern getAntiPatternModel() {
41 41
        return this.antiPattern;
......
51 51
        this.sqlQueries = queries;
52 52
    }
53 53

  
54
    private Integer getMaxIterationLength(){
55
        return (Integer) this.antiPattern.getConfigurations().get("maxIterationLength").getValue();
56
    }
57

  
58
    private Integer getMaxNumberOfTooLongIterations(){
59
        return (Integer) this.antiPattern.getConfigurations().get("maxNumberOfTooLongIterations").getValue();
60
    }
61

  
54 62
    /**
55 63
     * Postup detekce:
56 64
     *      1) najít všechny iterace danného projektu
57
     *      2) odebrat první a poslední iteraci( ty mohou být z důvodu nastartování projektu dlouhé)
65
     *      2) odebrat první a poslední iteraci ( ty mohou být z důvodu nastartování projektu dlouhé)
58 66
     *      3) zjistit jejich délku (rozdíl mezi start date a end date)
59 67
     *      4) pokud iterace přesháne délku 21 dní (3 týdny), tak jsou označeny jako moc dlouhé
60 68
     *      5) pokud je nalezena jedna nebo více iterací jako dlouhé, tak je anti pattern detekován
......
66 74
    @Override
67 75
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection) {
68 76

  
77
        // get configuration
78
        int maxIterationLength = getMaxIterationLength();
79
        int maxNumberOfTooLongIterations = getMaxNumberOfTooLongIterations();
80

  
81
        // auxiliary variables
69 82
        int numberOfLongIterations = 0;
70 83
        int totalCountOfIteration = 0;
71 84

  
......
77 90
            if (!iterationLengths.containsKey("iterationLength") || iterationLengths.get("iterationLength") == null)
78 91
                continue;
79 92
            int iterationLength = (int) iterationLengths.get("iterationLength");
80
            if (iterationLength > MAX_ITERATION_LENGTH) {
93
            if (iterationLength > maxIterationLength) {
81 94
                numberOfLongIterations++;
82 95
            }
83 96
        }
84 97
        List<ResultDetail> resultDetails = new ArrayList<>();
85 98
        resultDetails.add(new ResultDetail("Count of iterations without first and last", String.valueOf(totalCountOfIteration)));
86 99
        resultDetails.add(new ResultDetail("Number of too long iterations", String.valueOf(numberOfLongIterations)));
87
        if (numberOfLongIterations >= MAX_NUMBER_OF_TOO_LONG_ITERATIONS) {
100
        if (numberOfLongIterations >= maxNumberOfTooLongIterations) {
88 101
            resultDetails.add(new ResultDetail("Conclusion", "One or more iteration is too long"));
89 102
        } else {
90 103
            resultDetails.add(new ResultDetail("Conclusion", "All iterations in limit"));
......
93 106
        LOGGER.info(this.antiPattern.getPrintName());
94 107
        LOGGER.info(resultDetails.toString());
95 108

  
96
        return new QueryResultItem(this.antiPattern, numberOfLongIterations >= 1, resultDetails);
109
        return new QueryResultItem(this.antiPattern, numberOfLongIterations >= maxNumberOfTooLongIterations, resultDetails);
97 110
    }
98 111
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/model/AntiPattern.java
1 1
package cz.zcu.fav.kiv.antipatterndetectionapp.model;
2 2

  
3
import java.util.Map;
4

  
3 5
public class AntiPattern {
4 6

  
5 7
    private Long id;
6 8
    private String printName;
7 9
    private String name;
8 10
    private String description;
11
    private Map<String, Configuration> configurations;
9 12

  
10 13
    public AntiPattern(Long id, String printName, String name, String description) {
11 14
        this.id = id;
......
14 17
        this.description = description;
15 18
    }
16 19

  
20
    public AntiPattern(Long id, String printName, String name, String description, Map<String, Configuration> configurations) {
21
        this.id = id;
22
        this.printName = printName;
23
        this.name = name;
24
        this.description = description;
25
        this.configurations = configurations;
26
    }
27

  
17 28
    public Long getId() {
18 29
        return id;
19 30
    }
......
46 57
        this.description = description;
47 58
    }
48 59

  
60
    public Map<String, Configuration> getConfigurations() {
61
        return configurations;
62
    }
63

  
64
    public void setConfigurations(Map<String, Configuration> configurations) {
65
        this.configurations = configurations;
66
    }
67

  
49 68
    @Override
50 69
    public String toString() {
51 70
        return "AntiPattern{" +
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/model/Configuration.java
1
package cz.zcu.fav.kiv.antipatterndetectionapp.model;
2

  
3
public class Configuration<T> {
4
    private String name;
5
    private String printName;
6
    private String description;
7
    private T value;
8

  
9
    public Configuration(String name, String printName, String description, T value) {
10
        this.name = name;
11
        this.printName = printName;
12
        this.description = description;
13
        this.value = value;
14
    }
15

  
16
    public String getName() {
17
        return name;
18
    }
19

  
20
    public void setName(String name) {
21
        this.name = name;
22
    }
23

  
24
    public String getPrintName() {
25
        return printName;
26
    }
27

  
28
    public void setPrintName(String printName) {
29
        this.printName = printName;
30
    }
31

  
32
    public String getDescription() {
33
        return description;
34
    }
35

  
36
    public void setDescription(String description) {
37
        this.description = description;
38
    }
39

  
40
    public T getValue() {
41
        return value;
42
    }
43

  
44
    public void setValue(T value) {
45
        this.value = value;
46
    }
47
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/AntiPatternService.java
17 17

  
18 18
    List<AntiPatternDetector> getAllAntiPatternsForGivenIds(Long[] ids);
19 19

  
20

  
20
    boolean saveNewConfiguration(String[] configNames, String[] configValues);
21 21
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/AntiPatternServiceImpl.java
50 50
        }
51 51
        return antiPatternDetectors;
52 52
    }
53

  
54
    @Override
55
    public boolean saveNewConfiguration(String[] configNames, String[] configValues) {
56
        List<AntiPatternDetector> antiPatternDetectors = antiPatternRepository.getAllAntiPatterns();
57

  
58
        for (AntiPatternDetector antiPatternDetector : antiPatternDetectors) {
59
            // not every anti-pattern should have configuration
60
            if (antiPatternDetector.getAntiPatternModel().getConfigurations() == null) {
61
                continue;
62
            }
63
            for (int i = 0; i < configNames.length; i++) {
64
                if (antiPatternDetector.getAntiPatternModel().getConfigurations().containsKey(configNames[i])) {
65

  
66
                    if (antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).getValue().getClass() == Integer.class) {
67
                        try {
68
                            antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).setValue((Integer.parseInt(configValues[i])));
69
                        } catch (NumberFormatException e) {
70
                            return false;
71
                        }
72

  
73
                    }
74

  
75

  
76
                }
77
            }
78
        }
79
        return true;
80
    }
53 81
}
src/main/webapp/WEB-INF/templates/about.html
21 21
        <br>
22 22
        <strong>Author:</strong> Ondřej Váně
23 23
        <br>
24
        <strong>E-mail:</strong> <a href="mailto:onry.vane@gmail.com">onry.vane@gmail.com</a>
24
        <strong>E-mail:</strong> <a href="mailto:vaneo@students.zcu.cz">vaneo@students.zcu.cz</a>
25 25
    </p>
26 26
    <p>
27 27
        This application is used to detect presence of anti-patterns in project management tools data. Seven selected anti-patterns are implemented in this application.
src/main/webapp/WEB-INF/templates/configuration.html
1
<!DOCTYPE HTML>
2
<html xmlns:th="http://www.thymeleaf.org">
3
<head>
4
    <title>Anti Pattern Detector - Configuration</title>
5
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
6
    <meta name="viewport" content="width=device-width, initial-scale=1">
7
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
8
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
9
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
10
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
11

  
12
    <style>
13
        .analyze-button-container {
14
            margin: 20px 40% 40px;
15
        }
16
    </style>
17

  
18
</head>
19
<body>
20
<!-- Navigation bar imported -->
21
<div th:replace="fragments/navbar :: navBar"></div>
22
<!-- ./Navigation bar imported -->
23

  
24
<!-- Page body -->
25
<div class="container">
26
    <h1>Configuration</h1>
27

  
28
    <!-- Form for configuration values -->
29
    <form action="#" th:action="@{/configuration}" th:object="${antiPatterns}" method="post">
30
        <div th:each="antiPattern : ${antiPatterns}">
31
            <h3 th:text="${antiPattern.printName}"></h3>
32
            <div th:each="config : ${antiPattern.configurations}">
33
                <div class="form-group row">
34
                    <label th:text="${config.value.printName}" th:for="${config.value.name}"
35
                           class="col-sm-5 col-form-label"></label>
36
                    <div class="col-sm-5">
37
                        <input th:value="${config.value.value}" type="number" class="form-control" th:id="${config.value.name}"
38
                               name="configValues">
39
                        <input th:value="${config.value.name}" style="display: none" class="form-control"
40
                               name="configNames">
41
                        <small th:text="${config.value.description}" th:value="${config.value.name}"
42
                               class="form-text text-muted"></small>
43
                    </div>
44
                </div>
45

  
46
            </div>
47
        </div>
48
        <!-- Container for show error message -->
49
        <div class="container">
50
            <div th:if="${errorMessage}" th:text="${errorMessage}" class="alert alert-danger" role="alert">
51
            </div>
52
        </div>
53
        <!-- ./Container for show error message -->
54
        <!-- Container for show success message -->
55
        <div class="container">
56
            <div th:if="${successMessage}" th:text="${successMessage}" class="alert alert-success" role="alert">
57
            </div>
58
        </div>
59
        <!-- ./Container for show success message -->
60
        <div class="analyze-button-container">
61
            <button type="submit" class="btn btn-primary btn-lg btn-block">Save</button>
62
        </div>
63
    </form>
64
    <!-- ./Form for configuration values -->
65
</div>
66
<!-- ./Page body -->
67

  
68
</body>
69
</html>
70

  
src/main/webapp/WEB-INF/templates/fragments/navbar.html
9 9
                <li class="nav-item active">
10 10
                    <a class="nav-link" th:href="@{/}">Home</a>
11 11
                </li>
12
                <li class="nav-item active">
13
                    <a class="nav-link" th:href="@{/configuration}">Configuration</a>
14
                </li>
12 15
                <li class="nav-item active">
13 16
                    <a class="nav-link" th:href="@{/about}">About</a>
14 17
                </li>

Také k dispozici: Unified diff