Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 38cde13c

Přidáno uživatelem stepanekp před asi 3 roky(ů)

#14 Adding possibilty to use configurations from external files in analyzing

Zobrazit rozdíly:

src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/controller/AppController.java
118 118
    @PostMapping("/analyze")
119 119
    public String analyze(Model model,
120 120
                          @RequestParam(value = "selectedProjects", required = false) String[] selectedProjects,
121
                          @RequestParam(value = "selectedAntiPatterns", required = false) String[] selectedAntiPatterns
121
                          @RequestParam(value = "selectedAntiPatterns", required = false) String[] selectedAntiPatterns,
122
                          HttpSession session
122 123
    ) {
123 124

  
124 125
        if (selectedProjects == null) {
......
135 136
            return "index";
136 137
        }
137 138

  
138
        List<QueryResult> results = antiPatternManager.analyze(selectedProjects, selectedAntiPatterns);
139
        String currentConfigurationName = configurationGetFromSession(session);
140
        Map<String, Map<String, String>> currentConfiguration = configurationService.getConfigurationByName(currentConfigurationName);
141

  
142
        List<QueryResult> results = antiPatternManager.analyze(selectedProjects, selectedAntiPatterns, currentConfiguration);
139 143
        antiPatternService.saveAnalyzedProjects(selectedProjects, selectedAntiPatterns);
140 144
        antiPatternService.saveResults(results);
141 145
        antiPatternService.setConfigurationChanged(false);
......
186 190
    public String resultRecalculate(Model model) {
187 191

  
188 192
        List<QueryResult> results = antiPatternManager.analyze(antiPatternService.getAnalyzedProjects(),
189
                antiPatternService.getAnalyzedAntiPatterns());
193
                antiPatternService.getAnalyzedAntiPatterns(), null);
190 194

  
191 195
        antiPatternService.saveResults(results);
192 196
        antiPatternService.setConfigurationChanged(false);
......
426 430
        if(session.getAttribute("configuration") != null)
427 431
            return session.getAttribute("configuration").toString(); // return configuration stored in session
428 432
        else{
429
            List<String> configurationList = configurationService.getAllConfigurationNames();
433
            List<String> configurationList = configurationService.getDefaultConfigurationNames();
430 434
            if(configurationList.size() == 0)
431 435
                return null;
432 436

  
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/AntiPatternManager.java
4 4
import cz.zcu.fav.kiv.antipatterndetectionapp.model.QueryResult;
5 5

  
6 6
import java.util.List;
7
import java.util.Map;
7 8

  
8 9
public interface AntiPatternManager {
9 10

  
10
    List<QueryResult> analyze(String[] selectedProjects, String[] selectedAntiPatterns);
11
    List<QueryResult> analyze(String[] selectedProjects, String[] selectedAntiPatterns, Map<String, Map<String, String>> configuration);
11 12
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/AntiPatternManagerImpl.java
13 13

  
14 14
import java.util.ArrayList;
15 15
import java.util.List;
16
import java.util.Map;
16 17

  
17 18
@Service
18 19
public class AntiPatternManagerImpl implements AntiPatternManager {
......
24 25
    private AntiPatternService antiPatternService;
25 26

  
26 27
    @Override
27
    public List<QueryResult> analyze(String[] selectedProjects, String[] selectedAntiPatterns) {
28
    public List<QueryResult> analyze(String[] selectedProjects, String[] selectedAntiPatterns, Map<String, Map<String, String>> configuration) {
28 29

  
29 30
        return this.analyze(projectService.getAllProjectsForGivenIds(Utils.arrayOfStringsToArrayOfLongs(selectedProjects)),
30
                antiPatternService.getAllAntiPatternsForGivenIds(Utils.arrayOfStringsToArrayOfLongs(selectedAntiPatterns)));
31
                antiPatternService.getAllAntiPatternsForGivenIds(Utils.arrayOfStringsToArrayOfLongs(selectedAntiPatterns)), configuration);
31 32
    }
32 33

  
33 34
    /**
......
36 37
     * @param antiPatternDetectors Ap detectoros
37 38
     * @return List of results
38 39
     */
39
    private List<QueryResult> analyze(List<Project> projects, List<AntiPatternDetector> antiPatternDetectors) {
40
    private List<QueryResult> analyze(List<Project> projects, List<AntiPatternDetector> antiPatternDetectors, Map<String, Map<String, String>> configuration) {
40 41
        DatabaseConnection databaseConnection = new DatabaseConnection();
41 42

  
42 43
        List<QueryResult> queryResults = new ArrayList<>();
......
46 47
            QueryResult queryResult = new QueryResult();
47 48
            queryResult.setProject(project);
48 49
            List<QueryResultItem> queryResultItems = new ArrayList<>();
50

  
49 51
            for (AntiPatternDetector antiPattern : antiPatternDetectors) {
50
                queryResultItems.add(antiPattern.analyze(project, databaseConnection));
52
                String antiPatternName = antiPattern.getAntiPatternModel().getName();
53

  
54
                Map<String, String> thresholds = null;
55

  
56
                if(configuration != null)
57
                    thresholds = configuration.get(antiPatternName);
58

  
59
                queryResultItems.add(antiPattern.analyze(project, databaseConnection, thresholds));
51 60
            }
52 61
            queryResult.setQueryResultItems(queryResultItems);
53 62
            queryResults.add(queryResult);
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/AntiPatternDetector.java
4 4
import cz.zcu.fav.kiv.antipatterndetectionapp.model.AntiPattern;
5 5
import cz.zcu.fav.kiv.antipatterndetectionapp.model.Project;
6 6
import cz.zcu.fav.kiv.antipatterndetectionapp.model.QueryResultItem;
7
import cz.zcu.fav.kiv.antipatterndetectionapp.utils.Utils;
8 7

  
9 8
import java.util.List;
9
import java.util.Map;
10 10

  
11 11
/**
12 12
 * This is base interface for all AP detector. In case you need to implement new AP detector
......
57 57
     * @param databaseConnection database connection
58 58
     * @return model class for results
59 59
     */
60
    QueryResultItem analyze(Project project, DatabaseConnection databaseConnection);
60
    QueryResultItem analyze(Project project, DatabaseConnection databaseConnection, Map<String, String> thresholds);
61 61
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/BusinessAsUsualDetectorImpl.java
28 28
    // sql queries loaded from sql file
29 29
    private List<String> sqlQueries;
30 30

  
31
    private float getDivisionOfIterationsWithRetrospective() {
31
    private float getDivisionOfIterationsWithRetrospective(Map<String, String> thresholds) {
32
        if(thresholds != null)
33
            return new Percentage(Float.parseFloat(thresholds.get("divisionOfIterationsWithRetrospective"))).getValue();
34

  
32 35
        return ((Percentage) antiPattern.getThresholds().get("divisionOfIterationsWithRetrospective").getValue()).getValue();
33 36
    }
34 37

  
35
    private List<String> getSearchSubstringsWithRetrospective() {
38
    private List<String> getSearchSubstringsWithRetrospective(Map<String, String> thresholds) {
39
        if(thresholds != null)
40
            return Arrays.asList(thresholds.get("searchSubstringsWithRetrospective").split("\\|\\|"));
41

  
36 42
        return Arrays.asList(((String) antiPattern.getThresholds().get("searchSubstringsWithRetrospective").getValue()).split("\\|\\|"));
37 43
    }
38 44

  
......
78 84
     * @return results of detection
79 85
     */
80 86
    @Override
81
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection) {
87
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection, Map<String, String> thresholds) {
82 88

  
83 89
        // init values
84 90
        List<ResultDetail> resultDetails = new ArrayList<>();
......
87 93

  
88 94
        // go through the results of the queries and put in one map => in this map should be all iterations
89 95
        List<List<Map<String, Object>>> resultSets = databaseConnection.executeQueriesWithMultipleResults(project,
90
                Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithRetrospective()));
96
                Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithRetrospective(thresholds)));
91 97
        for (int i = 0; i < resultSets.size(); i++) {
92 98
            List<Map<String, Object>> rs = resultSets.get(i);
93 99

  
......
113 119

  
114 120
        }
115 121

  
116
        int minRetrospectiveLimit = Math.round(totalNumberIterations * getDivisionOfIterationsWithRetrospective());
122
        int minRetrospectiveLimit = Math.round(totalNumberIterations * getDivisionOfIterationsWithRetrospective(thresholds));
117 123

  
118 124
        resultDetails.add(new ResultDetail("Min retrospective limit", String.valueOf(minRetrospectiveLimit)));
119 125
        resultDetails.add(new ResultDetail("Found retrospectives", String.valueOf(iterationsResults.size())));
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/LongOrNonExistentFeedbackLoopsDetectorImpl.java
35 35
    // sql queries loaded from sql file
36 36
    private List<String> sqlQueries;
37 37

  
38
    private float getDivisionOfIterationsWithFeedbackLoop() {
38
    private float getDivisionOfIterationsWithFeedbackLoop(Map<String, String> thresholds) {
39
        if(thresholds != null)
40
            return new Percentage(Float.parseFloat(thresholds.get("divisionOfIterationsWithFeedbackLoop"))).getValue();
41

  
39 42
        return ((Percentage) antiPattern.getThresholds().get("divisionOfIterationsWithFeedbackLoop").getValue()).getValue();
40 43
    }
41 44

  
42
    private float getMaxGapBetweenFeedbackLoopRate() {
45
    private float getMaxGapBetweenFeedbackLoopRate(Map<String, String> thresholds) {
46
        if(thresholds != null)
47
            return new PositiveFloat(Float.parseFloat(thresholds.get("maxGapBetweenFeedbackLoopRate"))).floatValue();
48

  
43 49
        return ((PositiveFloat) antiPattern.getThresholds().get("maxGapBetweenFeedbackLoopRate").getValue()).floatValue();
44 50
    }
45 51

  
46
    private List<String> getSearchSubstringsWithFeedbackLoop() {
52
    private List<String> getSearchSubstringsWithFeedbackLoop(Map<String, String> thresholds) {
53
        if(thresholds != null)
54
            return Arrays.asList(thresholds.get("searchSubstringsWithFeedbackLoop").split("\\|\\|"));
55

  
47 56
        return Arrays.asList(((String) antiPattern.getThresholds().get("searchSubstringsWithFeedbackLoop").getValue()).split("\\|\\|"));
48 57
    }
49 58

  
......
92 101
     * @return detection result
93 102
     */
94 103
    @Override
95
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection) {
104
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection, Map<String, String> thresholds) {
96 105

  
97 106
        // init values
98 107
        long totalNumberIterations = 0;
......
105 114
        Date projectEndDate = null;
106 115

  
107 116
        List<List<Map<String, Object>>> resultSets = databaseConnection.executeQueriesWithMultipleResults(project,
108
                Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithFeedbackLoop()));
117
                Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithFeedbackLoop(thresholds)));
109 118
        for (int i = 0; i < resultSets.size(); i++) {
110 119
            List<Map<String, Object>> rs = resultSets.get(i);
111 120

  
......
147 156
            }
148 157
        }
149 158

  
150
        double halfNumberOfIterations = totalNumberIterations * getDivisionOfIterationsWithFeedbackLoop();
159
        double halfNumberOfIterations = totalNumberIterations * getDivisionOfIterationsWithFeedbackLoop(thresholds);
151 160

  
152 161
        // if the number of iterations that contain at least one feedback activity is the ideal case
153 162
        if (totalNumberIterations <= numberOfIterationsWhichContainsAtLeastOneActivityForFeedback) {
......
170 179
                long daysBetween = Utils.daysBetween(firstDate, secondDate);
171 180
                firstDate = secondDate;
172 181

  
173
                if (daysBetween >= getMaxGapBetweenFeedbackLoopRate() * averageIterationLength) {
182
                if (daysBetween >= getMaxGapBetweenFeedbackLoopRate(thresholds) * averageIterationLength) {
174 183
                    List<ResultDetail> resultDetails = Utils.createResultDetailsList(
175 184
                            new ResultDetail("Days between", Long.toString(daysBetween)),
176 185
                            new ResultDetail("Average iteration length", Integer.toString(averageIterationLength)),
......
211 220
                long daysBetween = Utils.daysBetween(firstDate, secondDate);
212 221
                firstDate = secondDate;
213 222

  
214
                if (daysBetween >= getMaxGapBetweenFeedbackLoopRate() * averageIterationLength) {
223
                if (daysBetween >= getMaxGapBetweenFeedbackLoopRate(thresholds) * averageIterationLength) {
215 224
                    List<ResultDetail> resultDetails = Utils.createResultDetailsList(
216 225
                            new ResultDetail("Days between", Long.toString(daysBetween)),
217 226
                            new ResultDetail("Average iteration length", Integer.toString(averageIterationLength)),
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/NinetyNinetyRuleDetectorImpl.java
2 2

  
3 3
import cz.zcu.fav.kiv.antipatterndetectionapp.detecting.DatabaseConnection;
4 4
import cz.zcu.fav.kiv.antipatterndetectionapp.model.*;
5
import cz.zcu.fav.kiv.antipatterndetectionapp.model.types.Percentage;
5 6
import cz.zcu.fav.kiv.antipatterndetectionapp.model.types.PositiveFloat;
6 7
import cz.zcu.fav.kiv.antipatterndetectionapp.model.types.PositiveInteger;
7 8
import cz.zcu.fav.kiv.antipatterndetectionapp.service.AntiPatternService;
......
26 27
    // sql queries loaded from sql file
27 28
    private List<String> sqlQueries;
28 29

  
29
    private double getMaxDivisionRange() {
30
    private double getMaxDivisionRange(Map<String, String> thresholds) {
31
        if(thresholds != null)
32
            return new PositiveFloat(Float.parseFloat(thresholds.get("maxDivisionRange"))).floatValue();
33

  
30 34
        return ((PositiveFloat) antiPattern.getThresholds().get("maxDivisionRange").getValue()).doubleValue();
31 35
    }
32 36

  
33
    private int getMaxBadDivisionLimit() {
37
    private int getMaxBadDivisionLimit(Map<String, String> thresholds) {
38
        if(thresholds != null)
39
            return new PositiveInteger(Integer.parseInt(thresholds.get("maxBadDivisionLimit"))).intValue();
40

  
34 41
        return ((PositiveInteger) antiPattern.getThresholds().get("maxBadDivisionLimit").getValue()).intValue();
35 42
    }
36 43

  
......
72 79
     * @return detection result
73 80
     */
74 81
    @Override
75
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection) {
82
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection, Map<String, String> thresholds) {
76 83

  
77 84
        List<ResultDetail> resultDetails = new ArrayList<>();
78 85
        List<Double> divisionsResults = new ArrayList<>();
......
88 95
                }
89 96
                divisionsResults.add(resultDivision);
90 97
                // if is one division is out of range set boolean to false
91
                if (resultDivision > getMaxDivisionRange()) {
98
                if (resultDivision > getMaxDivisionRange(thresholds)) {
92 99
                    isAllInRange = false;
93 100
                }
94 101
            }
......
102 109

  
103 110
        int counterOverEstimated = 0;
104 111
        for (Double divisionResult : divisionsResults) {
105
            if (divisionResult > getMaxDivisionRange()) {
112
            if (divisionResult > getMaxDivisionRange(thresholds)) {
106 113
                counterOverEstimated++;
107 114
            } else {
108 115
                counterOverEstimated = 0;
109 116
            }
110 117

  
111
            if (counterOverEstimated > getMaxBadDivisionLimit()) {
118
            if (counterOverEstimated > getMaxBadDivisionLimit(thresholds)) {
112 119
                resultDetails.add(new ResultDetail("Conclusion",
113
                        getMaxBadDivisionLimit() + " or more consecutive iterations has a bad trend in estimates"));
120
                        getMaxBadDivisionLimit(thresholds) + " or more consecutive iterations has a bad trend in estimates"));
114 121
                return new QueryResultItem(this.antiPattern, true, resultDetails);
115 122
            }
116 123

  
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/RoadToNowhereDetectorImpl.java
2 2

  
3 3
import cz.zcu.fav.kiv.antipatterndetectionapp.detecting.DatabaseConnection;
4 4
import cz.zcu.fav.kiv.antipatterndetectionapp.model.*;
5
import cz.zcu.fav.kiv.antipatterndetectionapp.model.types.Percentage;
6
import cz.zcu.fav.kiv.antipatterndetectionapp.model.types.PositiveFloat;
5 7
import cz.zcu.fav.kiv.antipatterndetectionapp.model.types.PositiveInteger;
6 8
import cz.zcu.fav.kiv.antipatterndetectionapp.service.AntiPatternService;
7 9
import cz.zcu.fav.kiv.antipatterndetectionapp.service.AntiPatternServiceImpl;
......
14 16
import java.util.ArrayList;
15 17
import java.util.Arrays;
16 18
import java.util.List;
19
import java.util.Map;
17 20

  
18 21
public class RoadToNowhereDetectorImpl implements AntiPatternDetector {
19 22

  
......
34 37
    // sql queries loaded from sql file
35 38
    private List<String> sqlQueries;
36 39

  
37
    private int getMinNumberOfWikiPagesWithProjectPlan() {
40
    private int getMinNumberOfWikiPagesWithProjectPlan(Map<String, String> thresholds) {
41
        if(thresholds != null)
42
            return new PositiveInteger(Integer.parseInt(thresholds.get("minNumberOfWikiPagesWithProjectPlan"))).intValue();
43

  
38 44
        return ((PositiveInteger) antiPattern.getThresholds().get("minNumberOfWikiPagesWithProjectPlan").getValue()).intValue();
39 45
    }
40 46

  
41
    private int getMinNumberOfActivitiesWithProjectPlan() {
47
    private int getMinNumberOfActivitiesWithProjectPlan(Map<String, String> thresholds) {
48
        if(thresholds != null)
49
            return new PositiveInteger(Integer.parseInt(thresholds.get("minNumberOfActivitiesWithProjectPlan"))).intValue();
50

  
42 51
        return ((PositiveInteger) antiPattern.getThresholds().get("minNumberOfActivitiesWithProjectPlan").getValue()).intValue();
43 52
    }
44 53

  
45
    private List<String> getSearchSubstringsWithProjectPlan() {
54
    private List<String> getSearchSubstringsWithProjectPlan(Map<String, String> thresholds) {
55
        if(thresholds != null)
56
            return Arrays.asList(thresholds.get("searchSubstringsWithProjectPlan").split("\\|\\|"));
57

  
46 58
        return Arrays.asList(((String) antiPattern.getThresholds().get("searchSubstringsWithProjectPlan").getValue()).split("\\|\\|"));
47 59
    }
48 60

  
......
82 94
     * @return detection result
83 95
     */
84 96
    @Override
85
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection) {
97
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection, Map<String, String> thresholds) {
86 98

  
87 99
        /* Init values */
88 100
        List<ResultDetail> resultDetails = new ArrayList<>();
......
91 103

  
92 104
        try {
93 105
            ResultSet rs = databaseConnection.executeQueries(project,
94
                    Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithProjectPlan()));
106
                    Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithProjectPlan(thresholds)));
95 107
            if (rs != null) {
96 108
                while (rs.next()) {
97 109
                    numberOfIssuesForProjectPlan = rs.getInt("numberOfActivitiesWithSubstrings");
......
108 120
        resultDetails.add(new ResultDetail("Number of issues for creating project plan", String.valueOf(numberOfIssuesForProjectPlan)));
109 121
        resultDetails.add(new ResultDetail("Number of wiki pages for creating project plan", String.valueOf(numberOfWikiPagesForProjectPlan)));
110 122

  
111
        if (numberOfIssuesForProjectPlan >= getMinNumberOfActivitiesWithProjectPlan() || numberOfWikiPagesForProjectPlan >= getMinNumberOfWikiPagesWithProjectPlan()) {
123
        if (numberOfIssuesForProjectPlan >= getMinNumberOfActivitiesWithProjectPlan(thresholds) || numberOfWikiPagesForProjectPlan >= getMinNumberOfWikiPagesWithProjectPlan(thresholds)) {
112 124
            resultDetails.add(new ResultDetail("Conclusion", "Found some activities or wiki pages for project plan in first two iterations"));
113 125
            return new QueryResultItem(this.antiPattern, false, resultDetails);
114 126
        } else {
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/SpecifyNothingDetectorImpl.java
14 14
import java.util.ArrayList;
15 15
import java.util.Arrays;
16 16
import java.util.List;
17
import java.util.Map;
17 18

  
18 19
public class SpecifyNothingDetectorImpl implements AntiPatternDetector {
19 20

  
......
33 34
    // sql queries loaded from sql file
34 35
    private List<String> sqlQueries;
35 36

  
36
    private int getMinNumberOfWikiPagesWithSpecification() {
37
    private int getMinNumberOfWikiPagesWithSpecification(Map<String, String> thresholds) {
38
        if(thresholds != null)
39
            return new PositiveInteger(Integer.parseInt(thresholds.get("minNumberOfWikiPagesWithSpecification"))).intValue();
40

  
37 41
        return ((PositiveInteger) antiPattern.getThresholds().get("minNumberOfWikiPagesWithSpecification").getValue()).intValue();
38 42
    }
39 43

  
40
    private int getMinNumberOfActivitiesWithSpecification() {
44
    private int getMinNumberOfActivitiesWithSpecification(Map<String, String> thresholds) {
45
        if(thresholds != null)
46
            return new PositiveInteger(Integer.parseInt(thresholds.get("minNumberOfActivitiesWithSpecification"))).intValue();
47

  
41 48
        return ((PositiveInteger) antiPattern.getThresholds().get("minNumberOfActivitiesWithSpecification").getValue()).intValue();
42 49
    }
43 50

  
44
    private int getMinAvgLengthOfActivityDescription() {
51
    private int getMinAvgLengthOfActivityDescription(Map<String, String> thresholds) {
52
        if(thresholds != null)
53
            return new PositiveInteger(Integer.parseInt(thresholds.get("minAvgLengthOfActivityDescription"))).intValue();
54

  
45 55
        return ((PositiveInteger) antiPattern.getThresholds().get("minAvgLengthOfActivityDescription").getValue()).intValue();
46 56
    }
47 57

  
48
    private List<String> getSearchSubstringsWithProjectSpecification() {
58
    private List<String> getSearchSubstringsWithProjectSpecification(Map<String, String> thresholds) {
59
        if(thresholds != null)
60
            return Arrays.asList(thresholds.get("searchSubstringsWithProjectSpecification").split("\\|\\|"));
61

  
49 62
        return Arrays.asList(((String) antiPattern.getThresholds().get("searchSubstringsWithProjectSpecification").getValue()).split("\\|\\|"));
50 63
    }
51 64

  
......
87 100
     * @return detection result
88 101
     */
89 102
    @Override
90
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection) {
103
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection, Map<String, String> thresholds) {
91 104

  
92 105
        /* Init values */
93 106
        List<ResultDetail> resultDetails = new ArrayList<>();
......
97 110

  
98 111
        try {
99 112
            ResultSet rs = databaseConnection.executeQueries(project,
100
                    Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithProjectSpecification()));
113
                    Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithProjectSpecification(thresholds)));
101 114
            if (rs != null) {
102 115
                while (rs.next()) {
103 116
                    numberOfWikiPages = rs.getInt("numberOfWikiPagesWithSubstrings");
......
115 128
        resultDetails.add(new ResultDetail("Number of activities for specification", String.valueOf(numberOfActivitiesForSpecification)));
116 129
        resultDetails.add(new ResultDetail("Number of wiki pages for specification", String.valueOf(numberOfWikiPages)));
117 130

  
118
        if (numberOfActivitiesForSpecification >= getMinNumberOfActivitiesWithSpecification() ||
119
                numberOfWikiPages >= getMinNumberOfWikiPagesWithSpecification()) {
131
        if (numberOfActivitiesForSpecification >= getMinNumberOfActivitiesWithSpecification(thresholds) ||
132
                numberOfWikiPages >= getMinNumberOfWikiPagesWithSpecification(thresholds)) {
120 133
            resultDetails.add(new ResultDetail("Conclusion", "Found activities or wiki pages that represents creation of specification"));
121 134
            return new QueryResultItem(this.antiPattern, false, resultDetails);
122 135
        } else {
123
            if (averageLengthOfIssueDescription > getMinAvgLengthOfActivityDescription()) {
136
            if (averageLengthOfIssueDescription > getMinAvgLengthOfActivityDescription(thresholds)) {
124 137
                resultDetails.add(new ResultDetail("Conclusion", "Average length of activity description is grater then minimum"));
125 138
                return new QueryResultItem(this.antiPattern, false, resultDetails);
126 139
            } else {
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/TooLongSprintDetectorImpl.java
53 53
        this.sqlQueries = queries;
54 54
    }
55 55

  
56
    private Integer getMaxIterationLength() {
56
    private Integer getMaxIterationLength(Map<String, String> thresholds) {
57
        if(thresholds != null)
58
            return new PositiveInteger(Integer.parseInt(thresholds.get("maxIterationLength"))).intValue();
59

  
57 60
        return ((PositiveInteger) this.antiPattern.getThresholds().get("maxIterationLength").getValue()).intValue();
58 61
    }
59 62

  
60
    private Integer getMaxNumberOfTooLongIterations() {
63
    private Integer getMaxNumberOfTooLongIterations(Map<String, String> thresholds) {
64
        if(thresholds != null)
65
            return new PositiveInteger(Integer.parseInt(thresholds.get("maxNumberOfTooLongIterations"))).intValue();
66

  
61 67
        return ((PositiveInteger) this.antiPattern.getThresholds().get("maxNumberOfTooLongIterations").getValue()).intValue();
62 68
    }
63 69

  
......
74 80
     * @return detection result
75 81
     */
76 82
    @Override
77
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection) {
83
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection, Map<String, String> thresholds) {
78 84

  
79 85
        // get configuration
80
        int maxIterationLength = getMaxIterationLength();
81
        int maxNumberOfTooLongIterations = getMaxNumberOfTooLongIterations();
86
        int maxIterationLength = getMaxIterationLength(thresholds);
87
        int maxNumberOfTooLongIterations = getMaxNumberOfTooLongIterations(thresholds);
82 88

  
83 89
        // auxiliary variables
84 90
        int numberOfLongIterations = 0;
......
106 112
            resultDetails.add(new ResultDetail("Conclusion", "All iterations in limit"));
107 113
        }
108 114

  
109
        LOGGER.info(this.antiPattern.getPrintName());
110
        LOGGER.info(resultDetails.toString());
111

  
112 115
        return new QueryResultItem(this.antiPattern, numberOfLongIterations > maxNumberOfTooLongIterations, resultDetails);
113 116
    }
114 117
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/VaryingSprintLengthDetectorImpl.java
13 13
import java.util.ArrayList;
14 14
import java.util.Arrays;
15 15
import java.util.List;
16
import java.util.Map;
16 17

  
17 18
public class VaryingSprintLengthDetectorImpl implements AntiPatternDetector {
18 19

  
......
31 32
    // sql queries loaded from sql file
32 33
    private List<String> sqlQueries;
33 34

  
34
    private Integer getMaxDaysDifference() {
35
    private Integer getMaxDaysDifference(Map<String, String> thresholds) {
36
        if(thresholds != null)
37
            return new PositiveInteger(Integer.parseInt(thresholds.get("maxDaysDifference"))).intValue();
38

  
35 39
        return ((PositiveInteger) this.antiPattern.getThresholds().get("maxDaysDifference").getValue()).intValue();
36 40
    }
37 41

  
38
    private Integer getMaxIterationChanged() {
42
    private Integer getMaxIterationChanged(Map<String, String> thresholds) {
43
        if(thresholds != null)
44
            return new PositiveInteger(Integer.parseInt(thresholds.get("maxIterationChanged"))).intValue();
45

  
39 46
        return ((PositiveInteger) this.antiPattern.getThresholds().get("maxIterationChanged").getValue()).intValue();
40 47
    }
41 48

  
......
78 85
     * @return detection result
79 86
     */
80 87
    @Override
81
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection) {
88
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection, Map<String, String> thresholds) {
82 89

  
83 90
        // init values
84 91
        List<ResultDetail> resultDetails = new ArrayList<>();
......
100 107
                        secondIterationLength = iterationLength;
101 108
                    }
102 109

  
103
                    if (Math.abs(firstIterationLength - secondIterationLength) >= getMaxDaysDifference()) {
110
                    if (Math.abs(firstIterationLength - secondIterationLength) >= getMaxDaysDifference(thresholds)) {
104 111
                        iterationLengthChanged = iterationLengthChanged + 1;
105 112
                    }
106 113
                    firstIterationLength = secondIterationLength;
......
113 120
            return new QueryResultItem(this.antiPattern, true, resultDetails);
114 121
        }
115 122

  
116
        resultDetails.add(new ResultDetail("Maximum iteration length change", String.valueOf(getMaxIterationChanged())));
123
        resultDetails.add(new ResultDetail("Maximum iteration length change", String.valueOf(getMaxIterationChanged(thresholds))));
117 124
        resultDetails.add(new ResultDetail("Count of iterations", String.valueOf(numberOfIterations)));
118 125
        resultDetails.add(new ResultDetail("Iteration length changed", String.valueOf(iterationLengthChanged)));
119 126

  
120 127

  
121
        if (iterationLengthChanged > getMaxIterationChanged()) {
128
        if (iterationLengthChanged > getMaxIterationChanged(thresholds)) {
122 129
            resultDetails.add(new ResultDetail("Conclusion", "Iteration length changed significantly too often"));
123 130
        } else {
124 131
            resultDetails.add(new ResultDetail("Conclusion", "Varying iteration length is all right"));
125 132
        }
126 133

  
127
        LOGGER.info(this.antiPattern.getPrintName());
128
        LOGGER.info(resultDetails.toString());
129

  
130
        return new QueryResultItem(this.antiPattern, (iterationLengthChanged > getMaxIterationChanged()), resultDetails);
134
        return new QueryResultItem(this.antiPattern, (iterationLengthChanged > getMaxIterationChanged(thresholds)), resultDetails);
131 135
    }
132 136
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/ConfigurationService.java
1 1
package cz.zcu.fav.kiv.antipatterndetectionapp.service;
2 2

  
3
import java.util.HashMap;
3 4
import java.util.List;
5
import java.util.Map;
4 6

  
5 7
public interface ConfigurationService {
6 8

  
......
8 10

  
9 11
    List<String> getDefaultConfigurationNames();
10 12

  
11

  
13
    Map<String, Map<String, String>> getConfigurationByName(String configurationName);
12 14
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/ConfigurationServiceImpl.java
6 6

  
7 7
import java.util.ArrayList;
8 8
import java.util.List;
9
import java.util.Map;
9 10

  
10 11
@Service
11 12
public class ConfigurationServiceImpl implements ConfigurationService {
......
17 18
    public List<String> getAllConfigurationNames() {
18 19
        List<String> configList = new ArrayList<String>();
19 20

  
20
        // get all configurations
21
        // insert default configuration
22
        configList.add("Default");
23

  
24
        // get all external configurations
21 25
        for (String key : configurationRepository.allConfigurations.keySet() ) {
22 26
            configList.add(key);
23 27
        }
......
35 39
        return configList;
36 40
    }
37 41

  
42
    @Override
43
    public Map<String, Map<String, String>> getConfigurationByName(String configurationName) {
44
        return configurationRepository.allConfigurations.get(configurationName);
45
    }
38 46
}
src/main/webapp/configurations/Default.json
1
{
2
    "configuration": [
3
        {
4
            "antiPattern": "TooLongSprint",
5
            "thresholds": [
6
                {
7
                    "thresholdName": "maxIterationLength",
8
                    "value": "21"
9
                },
10
                {
11
                    "thresholdName": "maxNumberOfTooLongIterations",
12
                    "value": "0"
13
                }
14
            ]
15
        },
16
        {
17
            "antiPattern": "VaryingSprintLength",
18
            "thresholds": [
19
                {
20
                    "thresholdName": "maxDaysDifference",
21
                    "value": "7"
22
                },
23
                {
24
                    "thresholdName": "maxIterationChanged",
25
                    "value": "1"
26
                }
27
            ]
28
        },
29
        {
30
            "antiPattern": "BusinessAsUsual",
31
            "thresholds": [
32
                {
33
                    "thresholdName": "divisionOfIterationsWithRetrospective",
34
                    "value": "66.66f"
35
                },
36
                {
37
                    "thresholdName": "searchSubstringsWithRetrospective",
38
                    "value": "%retr%||%revi%||%week%scrum%"
39
                }
40
            ]
41
        },
42
        {
43
            "antiPattern": "SpecifyNothing",
44
            "thresholds": [
45
                {
46
                    "thresholdName": "minNumberOfWikiPagesWithSpecification",
47
                    "value": "1"
48
                },
49
                {
50
                    "thresholdName": "minNumberOfActivitiesWithSpecification",
51
                    "value": "1"
52
                },
53
                {
54
                    "thresholdName": "minAvgLengthOfActivityDescription",
55
                    "value": "150"
56
                },
57
                {
58
                    "thresholdName": "searchSubstringsWithProjectSpecification",
59
                    "value": "%dsp%||%specifikace%||%specification%||%vize%proj%||%vize%produ%"
60
                }
61
            ]
62
        },
63
        {
64
            "antiPattern": "RoadToNowhere",
65
            "thresholds": [
66
                {
67
                    "thresholdName": "minNumberOfWikiPagesWithProjectPlan",
68
                    "value": "1"
69
                },
70
                {
71
                    "thresholdName": "minNumberOfActivitiesWithProjectPlan",
72
                    "value": "1"
73
                },
74
                {
75
                    "thresholdName": "searchSubstringsWithProjectPlan",
76
                    "value": "%plán projektu%||%project plan%||%plan project%||%projektový plán%"
77
                }
78
            ]
79
        },
80
        {
81
            "antiPattern": "LongOrNonExistentFeedbackLoops",
82
            "thresholds": [
83
                {
84
                    "thresholdName": "divisionOfIterationsWithFeedbackLoop",
85
                    "value": "50.00f"
86
                },
87
                {
88
                    "thresholdName": "maxGapBetweenFeedbackLoopRate",
89
                    "value": "2f"
90
                },
91
                {
92
                    "thresholdName": "searchSubstringsWithFeedbackLoop",
93
                    "value": "%schůz%zákazník%||%předvedení%zákazník%||%zákazn%demo%||%schůz%zadavat%||%inform%schůz%||%zákazn%||%zadavatel%"
94
                }
95
            ]
96
        },
97
        {
98
            "antiPattern": "NinetyNinetyRule",
99
            "thresholds": [
100
                {
101
                    "thresholdName": "maxDivisionRange",
102
                    "value": "1.25f"
103
                },
104
                {
105
                    "thresholdName": "maxBadDivisionLimit",
106
                    "value": "2"
107
                }
108
            ]
109
        }
110
    ]
111
}
src/main/webapp/configurations/MyConfig.json
1
{
2
    "configuration": [
3
        {
4
            "antiPattern": "TooLongSprint",
5
            "thresholds": [
6
                {
7
                    "thresholdName": "maxIterationLength",
8
                    "value": "21"
9
                },
10
                {
11
                    "thresholdName": "maxNumberOfTooLongIterations",
12
                    "value": "0"
13
                }
14
            ]
15
        },
16
        {
17
            "antiPattern": "VaryingSprintLength",
18
            "thresholds": [
19
                {
20
                    "thresholdName": "maxDaysDifference",
21
                    "value": "7"
22
                },
23
                {
24
                    "thresholdName": "maxIterationChanged",
25
                    "value": "1"
26
                }
27
            ]
28
        },
29
        {
30
            "antiPattern": "BusinessAsUsual",
31
            "thresholds": [
32
                {
33
                    "thresholdName": "divisionOfIterationsWithRetrospective",
34
                    "value": "66.66f"
35
                },
36
                {
37
                    "thresholdName": "searchSubstringsWithRetrospective",
38
                    "value": "%retr%||%revi%||%week%scrum%"
39
                }
40
            ]
41
        },
42
        {
43
            "antiPattern": "SpecifyNothing",
44
            "thresholds": [
45
                {
46
                    "thresholdName": "minNumberOfWikiPagesWithSpecification",
47
                    "value": "1"
48
                },
49
                {
50
                    "thresholdName": "minNumberOfActivitiesWithSpecification",
51
                    "value": "1"
52
                },
53
                {
54
                    "thresholdName": "minAvgLengthOfActivityDescription",
55
                    "value": "150"
56
                },
57
                {
58
                    "thresholdName": "searchSubstringsWithProjectSpecification",
59
                    "value": "%dsp%||%specifikace%||%specification%||%vize%proj%||%vize%produ%"
60
                }
61
            ]
62
        },
63
        {
64
            "antiPattern": "RoadToNowhere",
65
            "thresholds": [
66
                {
67
                    "thresholdName": "minNumberOfWikiPagesWithProjectPlan",
68
                    "value": "1"
69
                },
70
                {
71
                    "thresholdName": "minNumberOfActivitiesWithProjectPlan",
72
                    "value": "1"
73
                },
74
                {
75
                    "thresholdName": "searchSubstringsWithProjectPlan",
76
                    "value": "%plán projektu%||%project plan%||%plan project%||%projektový plán%"
77
                }
78
            ]
79
        },
80
        {
81
            "antiPattern": "LongOrNonExistentFeedbackLoops",
82
            "thresholds": [
83
                {
84
                    "thresholdName": "divisionOfIterationsWithFeedbackLoop",
85
                    "value": "50.00f"
86
                },
87
                {
88
                    "thresholdName": "maxGapBetweenFeedbackLoopRate",
89
                    "value": "2f"
90
                },
91
                {
92
                    "thresholdName": "searchSubstringsWithFeedbackLoop",
93
                    "value": "%schůz%zákazník%||%předvedení%zákazník%||%zákazn%demo%||%schůz%zadavat%||%inform%schůz%||%zákazn%||%zadavatel%"
94
                }
95
            ]
96
        },
97
        {
98
            "antiPattern": "NinetyNinetyRule",
99
            "thresholds": [
100
                {
101
                    "thresholdName": "maxDivisionRange",
102
                    "value": "1.25f"
103
                },
104
                {
105
                    "thresholdName": "maxBadDivisionLimit",
106
                    "value": "2"
107
                }
108
            ]
109
        }
110
    ]
111
}

Také k dispozici: Unified diff