Projekt

Obecné

Profil

« Předchozí | Další » 

Revize cd3f21e5

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

Configuration renamed to Threshold

Zobrazit rozdíly:

src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/controller/AppController.java
219 219
     * Method of storing new configurations for individual AP.
220 220
     *
221 221
     * @param model object for passing data to the UI
222
     * @param configValues changed configuration values
223
     * @param configNames changed configuration names
222
     * @param thresholdValues changed configuration values
223
     * @param thresholdNames changed configuration names
224 224
     * @return html file name for thymeleaf template
225 225
     */
226 226
    @PostMapping("/configuration")
227 227
    public String configurationPost(Model model,
228
                                    @RequestParam(value = "configValues", required = false) String[] configValues,
229
                                    @RequestParam(value = "configNames", required = false) String[] configNames) {
228
                                    @RequestParam(value = "thresholdValues", required = false) String[] thresholdValues,
229
                                    @RequestParam(value = "thresholdNames", required = false) String[] thresholdNames) {
230 230

  
231 231
        List<AntiPattern> antiPatterns = antiPatternService.antiPatternsToModel(antiPatternService.getAllAntiPatterns());
232
        List<String> wrongParameters = antiPatternService.saveNewConfiguration(configNames, configValues);
232
        List<String> wrongParameters = antiPatternService.saveNewConfiguration(thresholdNames, thresholdValues);
233 233

  
234 234
        if (wrongParameters.isEmpty()) {
235 235
            model.addAttribute("successMessage", "All configuration values has been successfully saved.");
......
247 247
     *
248 248
     * @param model object for passing data to the UI
249 249
     * @param id id of AP
250
     * @param configValues new config values
251
     * @param configNames configuration names
250
     * @param thresholdValues new config values
251
     * @param thresholdNames configuration names
252 252
     * @param redirectAttrs attributes for redirection
253 253
     * @return redirected html file name for thymeleaf template
254 254
     */
255 255
    @PostMapping("/anti-patterns/{id}")
256 256
    public String antiPatternsPost(Model model,
257 257
                                   @PathVariable Long id,
258
                                   @RequestParam(value = "configValues", required = false) String[] configValues,
259
                                   @RequestParam(value = "configNames", required = false) String[] configNames,
258
                                   @RequestParam(value = "thresholdValues", required = false) String[] thresholdValues,
259
                                   @RequestParam(value = "thresholdNames", required = false) String[] thresholdNames,
260 260
                                   RedirectAttributes redirectAttrs) {
261 261

  
262 262
        AntiPattern antiPattern = antiPatternService.antiPatternToModel(antiPatternService.getAntiPatternById(id));
263
        List<String> wrongParameters = antiPatternService.saveNewConfiguration(configNames, configValues);
263
        List<String> wrongParameters = antiPatternService.saveNewConfiguration(thresholdNames, thresholdValues);
264 264

  
265 265
        if (wrongParameters.isEmpty()) {
266 266
            redirectAttrs.addFlashAttribute("successMessage", "All threshold values has been successfully saved.");
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/model/AntiPattern.java
18 18
    private String printName;
19 19
    private String name;
20 20
    private String description;
21
    private Map<String, Configuration> configurations;
21
    private Map<String, Threshold> thresholds;
22 22
    private String catalogueFileName;
23 23

  
24 24
    public AntiPattern(Long id, String printName, String name, String description) {
......
28 28
        this.description = description;
29 29
    }
30 30

  
31
    public AntiPattern(Long id, String printName, String name, String description, Map<String, Configuration> configurations) {
31
    public AntiPattern(Long id, String printName, String name, String description, Map<String, Threshold> thresholds) {
32 32
        this.id = id;
33 33
        this.printName = printName;
34 34
        this.name = name;
35 35
        this.description = description;
36
        this.configurations = configurations;
36
        this.thresholds = thresholds;
37 37
    }
38 38

  
39
    public AntiPattern(Long id, String printName, String name, String description, Map<String, Configuration> configurations, String catalogueFileName) {
39
    public AntiPattern(Long id, String printName, String name, String description, Map<String, Threshold> thresholds, String catalogueFileName) {
40 40
        this.id = id;
41 41
        this.printName = printName;
42 42
        this.name = name;
43 43
        this.description = description;
44
        this.configurations = configurations;
44
        this.thresholds = thresholds;
45 45
        this.catalogueFileName = catalogueFileName;
46 46
    }
47 47

  
......
77 77
        this.description = description;
78 78
    }
79 79

  
80
    public Map<String, Configuration> getConfigurations() {
81
        return configurations;
80
    public Map<String, Threshold> getThresholds() {
81
        return thresholds;
82 82
    }
83 83

  
84
    public void setConfigurations(Map<String, Configuration> configurations) {
85
        this.configurations = configurations;
84
    public void setThresholds(Map<String, Threshold> thresholds) {
85
        this.thresholds = thresholds;
86 86
    }
87 87

  
88 88
    public String getUrl() {
......
156 156
                ", printName='" + printName + '\'' +
157 157
                ", name='" + name + '\'' +
158 158
                ", description='" + description + '\'' +
159
                ", configurations=" + configurations +
159
                ", thresholds=" + thresholds +
160 160
                ", catalogueFileName='" + catalogueFileName + '\'' +
161 161
                '}';
162 162
    }
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/model/Configuration.java
1
package cz.zcu.fav.kiv.antipatterndetectionapp.model;
2

  
3
/**
4
 * Model class for configuration.
5
 * @param <T> configuration can have different data types
6
 */
7
public class Configuration<T> {
8
    private String name;
9
    private String printName;
10
    private String description;
11
    private String errorMessage;
12
    private boolean isErrorMessageShown;
13
    private T value;
14

  
15
    public Configuration(String name, String printName, String description, T value) {
16
        this.name = name;
17
        this.printName = printName;
18
        this.description = description;
19
        this.value = value;
20
        this.isErrorMessageShown = false;
21
    }
22

  
23
    public Configuration(String name, String printName, String description, String errorMessage, T value) {
24
        this.name = name;
25
        this.printName = printName;
26
        this.description = description;
27
        this.errorMessage = errorMessage;
28
        this.value = value;
29
        this.isErrorMessageShown = false;
30
    }
31

  
32
    public String getName() {
33
        return name;
34
    }
35

  
36
    public void setName(String name) {
37
        this.name = name;
38
    }
39

  
40
    public String getPrintName() {
41
        return printName;
42
    }
43

  
44
    public void setPrintName(String printName) {
45
        this.printName = printName;
46
    }
47

  
48
    public String getDescription() {
49
        return description;
50
    }
51

  
52
    public void setDescription(String description) {
53
        this.description = description;
54
    }
55

  
56
    public T getValue() {
57
        return value;
58
    }
59

  
60
    public void setValue(T value) {
61
        this.value = value;
62
    }
63

  
64
    public String getErrorMessage() {
65
        return errorMessage;
66
    }
67

  
68
    public void setErrorMessage(String errorMessage) {
69
        this.errorMessage = errorMessage;
70
    }
71

  
72
    public boolean isErrorMessageShown() {
73
        return isErrorMessageShown;
74
    }
75

  
76
    public void setErrorMessageShown(boolean errorMessageShown) {
77
        isErrorMessageShown = errorMessageShown;
78
    }
79
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/model/Threshold.java
1
package cz.zcu.fav.kiv.antipatterndetectionapp.model;
2

  
3
/**
4
 * Model class for threshold.
5
 * @param <T> threshold can have different data types
6
 */
7
public class Threshold<T> {
8
    private String name;
9
    private String printName;
10
    private String description;
11
    private String errorMessage;
12
    private boolean isErrorMessageShown;
13
    private T value;
14

  
15
    public Threshold(String name, String printName, String description, T value) {
16
        this.name = name;
17
        this.printName = printName;
18
        this.description = description;
19
        this.value = value;
20
        this.isErrorMessageShown = false;
21
    }
22

  
23
    public Threshold(String name, String printName, String description, String errorMessage, T value) {
24
        this.name = name;
25
        this.printName = printName;
26
        this.description = description;
27
        this.errorMessage = errorMessage;
28
        this.value = value;
29
        this.isErrorMessageShown = false;
30
    }
31

  
32
    public String getName() {
33
        return name;
34
    }
35

  
36
    public void setName(String name) {
37
        this.name = name;
38
    }
39

  
40
    public String getPrintName() {
41
        return printName;
42
    }
43

  
44
    public void setPrintName(String printName) {
45
        this.printName = printName;
46
    }
47

  
48
    public String getDescription() {
49
        return description;
50
    }
51

  
52
    public void setDescription(String description) {
53
        this.description = description;
54
    }
55

  
56
    public T getValue() {
57
        return value;
58
    }
59

  
60
    public void setValue(T value) {
61
        this.value = value;
62
    }
63

  
64
    public String getErrorMessage() {
65
        return errorMessage;
66
    }
67

  
68
    public void setErrorMessage(String errorMessage) {
69
        this.errorMessage = errorMessage;
70
    }
71

  
72
    public boolean isErrorMessageShown() {
73
        return isErrorMessageShown;
74
    }
75

  
76
    public void setErrorMessageShown(boolean errorMessageShown) {
77
        isErrorMessageShown = errorMessageShown;
78
    }
79
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/AntiPatternServiceImpl.java
4 4
import cz.zcu.fav.kiv.antipatterndetectionapp.detecting.detectors.AntiPatternDetector;
5 5
import cz.zcu.fav.kiv.antipatterndetectionapp.model.AntiPattern;
6 6
import cz.zcu.fav.kiv.antipatterndetectionapp.model.CacheablesValues;
7
import cz.zcu.fav.kiv.antipatterndetectionapp.model.Configuration;
7
import cz.zcu.fav.kiv.antipatterndetectionapp.model.Threshold;
8 8
import cz.zcu.fav.kiv.antipatterndetectionapp.model.QueryResult;
9 9
import cz.zcu.fav.kiv.antipatterndetectionapp.model.types.Percentage;
10 10
import cz.zcu.fav.kiv.antipatterndetectionapp.model.types.PositiveFloat;
......
48 48
            AntiPattern antiPattern = antiPatternDetector.getAntiPatternModel();
49 49

  
50 50
            // set to default value
51
            for (Map.Entry<String, Configuration> config : antiPattern.getConfigurations().entrySet()) {
52
                config.getValue().setErrorMessageShown(false);
51
            for (Map.Entry<String, Threshold> threshold : antiPattern.getThresholds().entrySet()) {
52
                threshold.getValue().setErrorMessageShown(false);
53 53
            }
54 54
            antiPatterns.add(antiPattern);
55 55
        }
......
60 60
    public AntiPattern antiPatternToModel(AntiPatternDetector antiPatternDetector) {
61 61
        AntiPattern antiPattern = antiPatternDetector.getAntiPatternModel();
62 62
        // set to default value
63
        for (Map.Entry<String, Configuration> config : antiPattern.getConfigurations().entrySet()) {
64
            config.getValue().setErrorMessageShown(false);
63
        for (Map.Entry<String, Threshold> threshold : antiPattern.getThresholds().entrySet()) {
64
            threshold.getValue().setErrorMessageShown(false);
65 65
        }
66 66
        return antiPattern;
67 67
    }
......
76 76
        return antiPatternDetectors;
77 77
    }
78 78

  
79
    public List<String> saveNewConfiguration(String[] configNames, String[] configValues) {
79
    public List<String> saveNewConfiguration(String[] thresholdNames, String[] thresholdValues) {
80 80
        List<AntiPatternDetector> antiPatternDetectors = antiPatternRepository.getAllAntiPatterns();
81 81
        List<String> incorrectParameters = new ArrayList<>();
82 82

  
83 83
        for (AntiPatternDetector antiPatternDetector : antiPatternDetectors) {
84
            // not every anti-pattern should have configuration
85
            if (antiPatternDetector.getAntiPatternModel().getConfigurations() == null) {
84
            // not every anti-pattern should have thresholds
85
            if (antiPatternDetector.getAntiPatternModel().getThresholds() == null) {
86 86
                continue;
87 87
            }
88
            for (int i = 0; i < configNames.length; i++) {
89
                if (antiPatternDetector.getAntiPatternModel().getConfigurations().containsKey(configNames[i])) {
88
            for (int i = 0; i < thresholdNames.length; i++) {
89
                if (antiPatternDetector.getAntiPatternModel().getThresholds().containsKey(thresholdNames[i])) {
90 90

  
91
                    if (antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).getValue().getClass() == Integer.class) {
91
                    if (antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).getValue().getClass() == Integer.class) {
92 92
                        try {
93
                            antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).setValue((Integer.parseInt(configValues[i])));
93
                            antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).setValue((Integer.parseInt(thresholdValues[i])));
94 94
                            setConfigurationChanged(true);
95 95
                        } catch (NumberFormatException e) {
96
                            incorrectParameters.add(configNames[i]);
96
                            incorrectParameters.add(thresholdNames[i]);
97 97
                        }
98 98

  
99
                    } else if (antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).getValue().getClass() == Percentage.class) {
99
                    } else if (antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).getValue().getClass() == Percentage.class) {
100 100
                        try {
101
                            antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).setValue((Percentage.parsePercentage(configValues[i])));
101
                            antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).setValue((Percentage.parsePercentage(thresholdValues[i])));
102 102
                            setConfigurationChanged(true);
103 103
                        } catch (NumberFormatException e) {
104
                            incorrectParameters.add(configNames[i]);
104
                            incorrectParameters.add(thresholdNames[i]);
105 105
                        }
106
                    } else if (antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).getValue().getClass() == PositiveInteger.class) {
106
                    } else if (antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).getValue().getClass() == PositiveInteger.class) {
107 107
                        try {
108
                            antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).setValue((PositiveInteger.parsePositiveInteger(configValues[i])));
108
                            antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).setValue((PositiveInteger.parsePositiveInteger(thresholdValues[i])));
109 109
                            setConfigurationChanged(true);
110 110
                        } catch (NumberFormatException e) {
111
                            incorrectParameters.add(configNames[i]);
111
                            incorrectParameters.add(thresholdNames[i]);
112 112
                        }
113
                    } else if (antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).getValue().getClass() == PositiveFloat.class) {
113
                    } else if (antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).getValue().getClass() == PositiveFloat.class) {
114 114
                        try {
115
                            antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).setValue((PositiveFloat.parsePositiveFloat(configValues[i])));
115
                            antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).setValue((PositiveFloat.parsePositiveFloat(thresholdValues[i])));
116 116
                            setConfigurationChanged(true);
117 117
                        } catch (NumberFormatException e) {
118
                            incorrectParameters.add(configNames[i]);
118
                            incorrectParameters.add(thresholdNames[i]);
119 119
                        }
120
                    } else if (antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).getValue().getClass() == Float.class) {
120
                    } else if (antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).getValue().getClass() == Float.class) {
121 121
                        try {
122
                            antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).setValue((Float.parseFloat(configValues[i])));
122
                            antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).setValue((Float.parseFloat(thresholdValues[i])));
123 123
                            setConfigurationChanged(true);
124 124
                        } catch (NumberFormatException e) {
125
                            incorrectParameters.add(configNames[i]);
125
                            incorrectParameters.add(thresholdNames[i]);
126 126
                        }
127
                    } else if (antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).getValue().getClass() == Double.class) {
127
                    } else if (antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).getValue().getClass() == Double.class) {
128 128
                        try {
129
                            antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).setValue((Double.parseDouble(configValues[i])));
129
                            antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).setValue((Double.parseDouble(thresholdValues[i])));
130 130
                            setConfigurationChanged(true);
131 131
                        } catch (NumberFormatException e) {
132
                            incorrectParameters.add(configNames[i]);
132
                            incorrectParameters.add(thresholdNames[i]);
133 133
                        }
134
                    } else if (antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).getValue().getClass() == String.class) {
135
                        if (Utils.checkStringSubstrings(configValues[i])) {
136
                            antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).setValue((configValues[i]));
134
                    } else if (antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).getValue().getClass() == String.class) {
135
                        if (Utils.checkStringSubstrings(thresholdValues[i])) {
136
                            antiPatternDetector.getAntiPatternModel().getThresholds().get(thresholdNames[i]).setValue((thresholdValues[i]));
137 137
                            setConfigurationChanged(true);
138 138

  
139 139
                        } else {
140
                            incorrectParameters.add(configNames[i]);
140
                            incorrectParameters.add(thresholdNames[i]);
141 141
                        }
142 142
                    }
143 143
                }
......
185 185
    @Override
186 186
    public List<AntiPattern> setErrorMessages(List<AntiPattern> antiPatterns, List<String> wrongParameters) {
187 187
        for (AntiPattern antiPattern : antiPatterns) {
188
            for (Map.Entry<String, Configuration> config : antiPattern.getConfigurations().entrySet()) {
189
                if (wrongParameters.contains(config.getKey())) {
190
                    config.getValue().setErrorMessageShown(true);
188
            for (Map.Entry<String, Threshold> threshold : antiPattern.getThresholds().entrySet()) {
189
                if (wrongParameters.contains(threshold.getKey())) {
190
                    threshold.getValue().setErrorMessageShown(true);
191 191
                } else {
192
                    config.getValue().setErrorMessageShown(false);
192
                    threshold.getValue().setErrorMessageShown(false);
193 193
                }
194 194
            }
195 195
        }
......
220 220
        String APDescription = node.get("description").asText();
221 221
        String APCatalogueFileName = node.get("catalogueFileName") != null ? node.get("catalogueFileName").asText() : null;
222 222

  
223
        Map<String, Configuration> APMap = new HashMap<>();
223
        Map<String, Threshold> APMap = new HashMap<>();
224 224

  
225
        JsonNode array = node.get("configurations");
226
        Configuration<?> tmpConfig = null;
225
        JsonNode array = node.get("thresholds");
226
        Threshold<?> tmpThreshold = null;
227 227

  
228 228
        for(int i = 0; i < array.size(); i++){
229 229
            JsonNode tmpNode = array.get(i);
230 230

  
231
            String configName = tmpNode.get("configName").asText();
232
            String configType = tmpNode.get("configType").asText();
231
            String thresholdName = tmpNode.get("thresholdName").asText();
232
            String thresholdType = tmpNode.get("thresholdType").asText();
233 233

  
234
            JsonNode configNode = tmpNode.get("configuration");
234
            JsonNode thresholdNode = tmpNode.get("threshold");
235 235

  
236
            String CConfigName = configNode.get("configName").asText();
237
            String CConfigPrintName = configNode.get("configPrintName").asText();
238
            String CConfigDescription = configNode.get("configDescription").asText();
239
            String CConfigErrorMess = configNode.get("configErrorMess").asText();
240
            String CConfigValue = configNode.get("configValue").asText();
236
            String tThresholdName = thresholdNode.get("thresholdName").asText();
237
            String tThresholdPrintName = thresholdNode.get("thresholdPrintName").asText();
238
            String tThresholdDescription = thresholdNode.get("thresholdDescription").asText();
239
            String tThresholdErrorMess = thresholdNode.get("thresholdErrorMess").asText();
240
            String tThresholdValue = thresholdNode.get("thresholdValue").asText();
241 241

  
242
            tmpConfig = getConfiguration(configType, CConfigName, CConfigPrintName, CConfigDescription, CConfigErrorMess, CConfigValue);
242
            tmpThreshold = getThreshold(thresholdType, tThresholdName, tThresholdPrintName, tThresholdDescription, tThresholdErrorMess, tThresholdValue);
243 243

  
244
            APMap.put(configName, tmpConfig);
244
            APMap.put(thresholdName, tmpThreshold);
245 245
        }
246 246

  
247 247
        AntiPattern newAP = new AntiPattern(APid, APPrintName, APName, APDescription, APMap, APCatalogueFileName);
......
249 249
        return newAP;
250 250
    }
251 251

  
252
    private Configuration<?> getConfiguration(String configType, String name, String printName, String description, String errorMessage, String value){
252
    private Threshold<?> getThreshold(String thresholdType, String name, String printName, String description, String errorMessage, String value){
253 253

  
254
        if(configType.equals("Percentage")){
255
            return new Configuration<>(name, printName, description, errorMessage, new Percentage(Float.parseFloat(value)));
254
        if(thresholdType.equals("Percentage")){
255
            return new Threshold<>(name, printName, description, errorMessage, new Percentage(Float.parseFloat(value)));
256 256
        }
257
        else if(configType.equals("PositiveFloat")){
258
            return new Configuration<>(name, printName, description, errorMessage, new PositiveFloat(Float.parseFloat(value)));
257
        else if(thresholdType.equals("PositiveFloat")){
258
            return new Threshold<>(name, printName, description, errorMessage, new PositiveFloat(Float.parseFloat(value)));
259 259
        }
260
        else if(configType.equals("PositiveInteger")){
261
            return new Configuration<>(name, printName, description, errorMessage, new PositiveInteger(Integer.parseInt(value)));
260
        else if(thresholdType.equals("PositiveInteger")){
261
            return new Threshold<>(name, printName, description, errorMessage, new PositiveInteger(Integer.parseInt(value)));
262 262
        }
263
        else if(configType.equals("String")){
264
            return new Configuration<>(name, printName, description, errorMessage, value);
263
        else if(thresholdType.equals("String")){
264
            return new Threshold<>(name, printName, description, errorMessage, value);
265 265
        }
266 266

  
267 267
        return null;
src/main/webapp/WEB-INF/templates/anti-pattern.html
147 147

  
148 148
        <!-- Form for configuration values -->
149 149
        <form action="#" th:action="@{/anti-patterns/} + ${antiPattern.id}" th:object="${antiPattern}" method="post">
150
            <div th:each="config : ${antiPattern.configurations}" class="form-group">
151
                <label th:text="${config.value.printName} + ':'"
152
                       th:for="${config.value.name}"></label>
153
                <small th:text="${config.value.description}" th:value="${config.value.name}"
150
            <div th:each="threshold : ${antiPattern.thresholds}" class="form-group">
151
                <label th:text="${threshold.value.printName} + ':'"
152
                       th:for="${threshold.value.name}"></label>
153
                <small th:text="${threshold.value.description}" th:value="${threshold.value.name}"
154 154
                       class="form-text text-muted"></small>
155
                <input th:if="${config.value.isErrorMessageShown}" th:value="${config.value.value}" class="form-control is-invalid" th:id="${config.value.name}"
156
                       name="configValues">
157
                <input th:unless="${config.value.isErrorMessageShown}" th:value="${config.value.value}" class="form-control" th:id="${config.value.name}"
158
                       name="configValues">
159
                <input th:value="${config.value.name}" style="display: none" class="form-control"
160
                       name="configNames">
161
                <small th:if="${config.value.isErrorMessageShown}" th:text="${config.value.errorMessage}" th:value="${config.value.errorMessage}"
155
                <input th:if="${threshold.value.isErrorMessageShown}" th:value="${threshold.value.value}" class="form-control is-invalid" th:id="${threshold.value.name}"
156
                       name="thresholdValues">
157
                <input th:unless="${threshold.value.isErrorMessageShown}" th:value="${threshold.value.value}" class="form-control" th:id="${threshold.value.name}"
158
                       name="thresholdValues">
159
                <input th:value="${threshold.value.name}" style="display: none" class="form-control"
160
                       name="thresholdNames">
161
                <small th:if="${threshold.value.isErrorMessageShown}" th:text="${threshold.value.errorMessage}" th:value="${threshold.value.errorMessage}"
162 162
                       class="form-text text-danger"></small>
163 163

  
164 164
            </div>
src/main/webapp/WEB-INF/templates/configuration.html
37 37
        <form action="#" th:action="@{/configuration}" th:object="${antiPatterns}" method="post">
38 38
            <div th:each="antiPattern : ${antiPatterns}">
39 39
                <h3 th:text="${antiPattern.printName}"></h3>
40
                <div th:each="config : ${antiPattern.configurations}">
40
                <div th:each="threshold : ${antiPattern.thresholds}">
41 41
                    <div class="form-group row">
42
                        <label th:text="${config.value.printName} + ':'" th:for="${config.value.name}"
42
                        <label th:text="${threshold.value.printName} + ':'" th:for="${threshold.value.name}"
43 43
                               class="col-sm-5 col-form-label"></label>
44 44
                        <div class="col-sm-5">
45
                            <small th:text="${config.value.description}" th:value="${config.value.name}"
45
                            <small th:text="${threshold.value.description}" th:value="${threshold.value.name}"
46 46
                                   class="form-text text-muted"></small>
47 47
                            <div id="wrapper">
48 48
                                <div id="first">
49
                                    <input th:if="${config.value.isErrorMessageShown}" th:value="${config.value.value}"
50
                                           class="form-control is-invalid" th:id="${config.value.name}"
51
                                           name="configValues">
52
                                    <input th:unless="${config.value.isErrorMessageShown}"
53
                                           th:value="${config.value.value}"
54
                                           class="form-control" th:id="${config.value.name}"
55
                                           name="configValues">
56
                                    <input th:value="${config.value.name}" style="display: none" class="form-control"
57
                                           name="configNames">
49
                                    <input th:if="${threshold.value.isErrorMessageShown}" th:value="${threshold.value.value}"
50
                                           class="form-control is-invalid" th:id="${threshold.value.name}"
51
                                           name="thresholdValues">
52
                                    <input th:unless="${threshold.value.isErrorMessageShown}"
53
                                           th:value="${threshold.value.value}"
54
                                           class="form-control" th:id="${threshold.value.name}"
55
                                           name="thresholdValues">
56
                                    <input th:value="${threshold.value.name}" style="display: none" class="form-control"
57
                                           name="thresholdNames">
58 58
                                </div>
59
                                <div th:if="${#strings.contains(config.value.name,'Substrings')}" id="second"
59
                                <div th:if="${#strings.contains(threshold.value.name,'Substrings')}" id="second"
60 60
                                     style="margin: 10px; padding-left: 10px">
61 61
                                    <svg style="display: inline-block"
62 62
                                         xmlns="http://www.w3.org/2000/svg"
......
74 74
                                </div>
75 75
                            </div>
76 76

  
77
                            <small th:if="${config.value.isErrorMessageShown}" th:text="${config.value.errorMessage}"
78
                                   th:value="${config.value.errorMessage}"
77
                            <small th:if="${threshold.value.isErrorMessageShown}" th:text="${threshold.value.errorMessage}"
78
                                   th:value="${threshold.value.errorMessage}"
79 79
                                   class="form-text text-danger"></small>
80 80

  
81 81
                        </div>
src/main/webapp/antipatterns/BusinessAsUsual.json
3 3
    "printName": "Business As Usual",
4 4
    "name": "BusinessAsUsual",
5 5
    "description": "Absence of a retrospective after individual iterations or after the completion project.",
6
    "configurations": [
6
    "thresholds": [
7 7
        {
8
            "configName": "divisionOfIterationsWithRetrospective",
9
            "configType": "Percentage",
10
            "configuration": {
11
                "configName": "divisionOfIterationsWithRetrospective",
12
                "configPrintName": "Division of iterations with retrospective",
13
                "configDescription": "Minimum percentage of the total number of iterations with a retrospective (0,100)",
14
                "configErrorMess": "Percentage must be float number between 0 and 100",
15
                "configValue": "66.66f"
8
            "thresholdName": "divisionOfIterationsWithRetrospective",
9
            "thresholdType": "Percentage",
10
            "threshold": {
11
                "thresholdName": "divisionOfIterationsWithRetrospective",
12
                "thresholdPrintName": "Division of iterations with retrospective",
13
                "thresholdDescription": "Minimum percentage of the total number of iterations with a retrospective (0,100)",
14
                "thresholdErrorMess": "Percentage must be float number between 0 and 100",
15
                "thresholdValue": "66.66f"
16 16
            }
17 17
        },
18 18
        {
19
            "configName": "searchSubstringsWithRetrospective",
20
            "configType": "String",
21
            "configuration": {
22
                "configName": "searchSubstringsWithRetrospective",
23
                "configPrintName": "Search substrings with retrospective",
24
                "configDescription": "Substring that will be search in wikipages and activities",
25
                "configErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters || ",
26
                "configValue": "%retr%||%revi%||%week%scrum%"
19
            "thresholdName": "searchSubstringsWithRetrospective",
20
            "thresholdType": "String",
21
            "threshold": {
22
                "thresholdName": "searchSubstringsWithRetrospective",
23
                "thresholdPrintName": "Search substrings with retrospective",
24
                "thresholdDescription": "Substring that will be search in wikipages and activities",
25
                "thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters || ",
26
                "thresholdValue": "%retr%||%revi%||%week%scrum%"
27 27
            }
28 28
        }
29 29
    ],
src/main/webapp/antipatterns/LongOrNonExistentFeedbackLoops.json
3 3
    "printName": "Long Or Non Existent Feedback Loops",
4 4
    "name": "LongOrNonExistentFeedbackLoops",
5 5
    "description": "Long spacings between customer feedback or no feedback. The customer enters the project and sees the final result. In the end, the customer may not get what he really wanted. With long intervals of feedback, some misunderstood functionality can be created and we have to spend a lot of effort and time to redo it. ",
6
    "configurations": [
6
    "thresholds": [
7 7
        {
8
            "configName": "divisionOfIterationsWithFeedbackLoop",
9
            "configType": "Percentage",
10
            "configuration": {
11
                "configName": "divisionOfIterationsWithFeedbackLoop",
12
                "configPrintName": "Division of iterations with feedback loop",
13
                "configDescription": "Minimum percentage of the total number of iterations with feedback loop (0,100)",
14
                "configErrorMess": "Percentage must be float number between 0 and 100",
15
                "configValue": "50.00f"
8
            "thresholdName": "divisionOfIterationsWithFeedbackLoop",
9
            "thresholdType": "Percentage",
10
            "threshold": {
11
                "thresholdName": "divisionOfIterationsWithFeedbackLoop",
12
                "thresholdPrintName": "Division of iterations with feedback loop",
13
                "thresholdDescription": "Minimum percentage of the total number of iterations with feedback loop (0,100)",
14
                "thresholdErrorMess": "Percentage must be float number between 0 and 100",
15
                "thresholdValue": "50.00f"
16 16
            }
17 17
        },
18 18
        {
19
            "configName": "maxGapBetweenFeedbackLoopRate",
20
            "configType": "PositiveFloat",
21
            "configuration": {
22
                "configName": "maxGapBetweenFeedbackLoopRate",
23
                "configPrintName": "Maximum gap between feedback loop rate",
24
                "configDescription": "Value that multiplies average iteration length for given project. Result is maximum threshold value for gap between feedback loops in days.",
25
                "configErrorMess": "Maximum gap between feedback loop rate must be positive float number",
26
                "configValue": "2f"
19
            "thresholdName": "maxGapBetweenFeedbackLoopRate",
20
            "thresholdType": "PositiveFloat",
21
            "threshold": {
22
                "thresholdName": "maxGapBetweenFeedbackLoopRate",
23
                "thresholdPrintName": "Maximum gap between feedback loop rate",
24
                "thresholdDescription": "Value that multiplies average iteration length for given project. Result is maximum threshold value for gap between feedback loops in days.",
25
                "thresholdErrorMess": "Maximum gap between feedback loop rate must be positive float number",
26
                "thresholdValue": "2f"
27 27
            }
28 28
        },
29 29
        {
30
            "configName": "searchSubstringsWithFeedbackLoop",
31
            "configType": "String",
32
            "configuration": {
33
                "configName": "searchSubstringsWithFeedbackLoop",
34
                "configPrintName": "Search substrings with feedback loop",
35
                "configDescription": "Substring that will be search in wikipages and activities",
36
                "configErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||",
37
                "configValue": "%schůz%zákazník%||%předvedení%zákazník%||%zákazn%demo%||%schůz%zadavat%||%inform%schůz%||%zákazn%||%zadavatel%"
30
            "thresholdName": "searchSubstringsWithFeedbackLoop",
31
            "thresholdType": "String",
32
            "threshold": {
33
                "thresholdName": "searchSubstringsWithFeedbackLoop",
34
                "thresholdPrintName": "Search substrings with feedback loop",
35
                "thresholdDescription": "Substring that will be search in wikipages and activities",
36
                "thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||",
37
                "thresholdValue": "%schůz%zákazník%||%předvedení%zákazník%||%zákazn%demo%||%schůz%zadavat%||%inform%schůz%||%zákazn%||%zadavatel%"
38 38
            }
39 39
        }
40 40
    ]
src/main/webapp/antipatterns/NinetyNinetyRule.json
3 3
    "printName": "Ninety Ninety Rule",
4 4
    "name": "NinetyNinetyRule",
5 5
    "description": "The first 90 percent of the code represents the first 90 percent of development time. The remaining 10 percent of the code represents another 90 percent of development time. Then decide on a long delay of the project compared to the original estimate. The functionality is almost done, some number is already closed and is only waiting for one activity to close, but it has been open for a long time.",
6
    "configurations": [
6
    "thresholds": [
7 7
        {
8
            "configName": "maxDivisionRange",
9
            "configType": "PositiveFloat",
10
            "configuration": {
11
                "configName": "maxDivisionRange",
12
                "configPrintName": "Maximum ration value",
13
                "configDescription": "Maximum ratio value of spent and estimated time",
14
                "configErrorMess": "Ration values must be positive float number",
15
                "configValue": "1.25f"
8
            "thresholdName": "maxDivisionRange",
9
            "thresholdType": "PositiveFloat",
10
            "threshold": {
11
                "thresholdName": "maxDivisionRange",
12
                "thresholdPrintName": "Maximum ration value",
13
                "thresholdDescription": "Maximum ratio value of spent and estimated time",
14
                "thresholdErrorMess": "Ration values must be positive float number",
15
                "thresholdValue": "1.25f"
16 16
            }
17 17
        },
18 18
        {
19
            "configName": "maxBadDivisionLimit",
20
            "configType": "PositiveInteger",
21
            "configuration": {
22
                "configName": "maxBadDivisionLimit",
23
                "configPrintName": "Maximum iterations thresholds",
24
                "configDescription": "Maximum number of consecutive iterations where the thresholds were exceeded",
25
                "configErrorMess": "Maximum number of consecutive iterations must be positive integer number",
26
                "configValue": "2"
19
            "thresholdName": "maxBadDivisionLimit",
20
            "thresholdType": "PositiveInteger",
21
            "threshold": {
22
                "thresholdName": "maxBadDivisionLimit",
23
                "thresholdPrintName": "Maximum iterations thresholds",
24
                "thresholdDescription": "Maximum number of consecutive iterations where the thresholds were exceeded",
25
                "thresholdErrorMess": "Maximum number of consecutive iterations must be positive integer number",
26
                "thresholdValue": "2"
27 27
            }
28 28
        }
29 29
    ]
src/main/webapp/antipatterns/RoadToNowhere.json
3 3
    "printName": "Road To Nowhere",
4 4
    "name": "RoadToNowhere",
5 5
    "description": "The project is not sufficiently planned and therefore takes place on an ad hoc basis with an uncertain outcome and deadline. There is no project plan in the project.",
6
    "configurations": [
6
    "thresholds": [
7 7
        {
8
            "configName": "minNumberOfWikiPagesWithProjectPlan",
9
            "configType": "PositiveInteger",
10
            "configuration": {
11
                "configName": "minNumberOfWikiPagesWithProjectPlan",
12
                "configPrintName": "Minimum number of wiki pages with project plan",
13
                "configDescription": "Number of wiki pages",
14
                "configErrorMess": "Minimum number of wikipages must be positive integer number",
15
                "configValue": "1"
8
            "thresholdName": "minNumberOfWikiPagesWithProjectPlan",
9
            "thresholdType": "PositiveInteger",
10
            "threshold": {
11
                "thresholdName": "minNumberOfWikiPagesWithProjectPlan",
12
                "thresholdPrintName": "Minimum number of wiki pages with project plan",
13
                "thresholdDescription": "Number of wiki pages",
14
                "thresholdErrorMess": "Minimum number of wikipages must be positive integer number",
15
                "thresholdValue": "1"
16 16
            }
17 17
        },
18 18
        {
19
            "configName": "minNumberOfActivitiesWithProjectPlan",
20
            "configType": "PositiveInteger",
21
            "configuration": {
22
                "configName": "minNumberOfActivitiesWithProjectPlan",
23
                "configPrintName": "Minimum number of activities with project plan",
24
                "configDescription": "Number of activities",
25
                "configErrorMess": "Minimum number of activities must be positive integer number",
26
                "configValue": "1"
19
            "thresholdName": "minNumberOfActivitiesWithProjectPlan",
20
            "thresholdType": "PositiveInteger",
21
            "threshold": {
22
                "thresholdName": "minNumberOfActivitiesWithProjectPlan",
23
                "thresholdPrintName": "Minimum number of activities with project plan",
24
                "thresholdDescription": "Number of activities",
25
                "thresholdErrorMess": "Minimum number of activities must be positive integer number",
26
                "thresholdValue": "1"
27 27
            }
28 28
        },
29 29
        {
30
            "configName": "searchSubstringsWithProjectPlan",
31
            "configType": "String",
32
            "configuration": {
33
                "configName": "searchSubstringsWithProjectPlan",
34
                "configPrintName": "Search substrings with project plan",
35
                "configDescription": "Substring that will be search in wikipages and activities",
36
                "configErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||",
37
                "configValue": "%plán projektu%||%project plan%||%plan project%||%projektový plán%"
30
            "thresholdName": "searchSubstringsWithProjectPlan",
31
            "thresholdType": "String",
32
            "threshold": {
33
                "thresholdName": "searchSubstringsWithProjectPlan",
34
                "thresholdPrintName": "Search substrings with project plan",
35
                "thresholdDescription": "Substring that will be search in wikipages and activities",
36
                "thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||",
37
                "thresholdValue": "%plán projektu%||%project plan%||%plan project%||%projektový plán%"
38 38
            }
39 39
        }
40 40
    ],
src/main/webapp/antipatterns/SpecifyNothing.json
3 3
    "printName": "Specify Nothing",
4 4
    "name": "SpecifyNothing",
5 5
    "description": "The specification is not done intentionally. Programmers are expected to work better without written specifications.",
6
    "configurations": [
6
    "thresholds": [
7 7
        {
8
            "configName": "minNumberOfWikiPagesWithSpecification",
9
            "configType": "PositiveInteger",
10
            "configuration": {
11
                "configName": "minNumberOfWikiPagesWithSpecification",
12
                "configPrintName": "Minimum number of wiki pages with project specification",
13
                "configDescription": "Number of wiki pages",
14
                "configErrorMess": "Minimum number of wikipages must be positive integer number",
15
                "configValue": "1"
8
            "thresholdName": "minNumberOfWikiPagesWithSpecification",
9
            "thresholdType": "PositiveInteger",
10
            "threshold": {
11
                "thresholdName": "minNumberOfWikiPagesWithSpecification",
12
                "thresholdPrintName": "Minimum number of wiki pages with project specification",
13
                "thresholdDescription": "Number of wiki pages",
14
                "thresholdErrorMess": "Minimum number of wikipages must be positive integer number",
15
                "thresholdValue": "1"
16 16
            }
17 17
        },
18 18
        {
19
            "configName": "minNumberOfActivitiesWithSpecification",
20
            "configType": "PositiveInteger",
21
            "configuration": {
22
                "configName": "minNumberOfActivitiesWithSpecification",
23
                "configPrintName": "Minimum number of activities with project specification",
24
                "configDescription": "Number of activities",
25
                "configErrorMess": "Minimum number of activities with project specification must be positive integer number",
26
                "configValue": "1"
19
            "thresholdName": "minNumberOfActivitiesWithSpecification",
20
            "thresholdType": "PositiveInteger",
21
            "threshold": {
22
                "thresholdName": "minNumberOfActivitiesWithSpecification",
23
                "thresholdPrintName": "Minimum number of activities with project specification",
24
                "thresholdDescription": "Number of activities",
25
                "thresholdErrorMess": "Minimum number of activities with project specification must be positive integer number",
26
                "thresholdValue": "1"
27 27
            }
28 28
        },
29 29
        {
30
            "configName": "minAvgLengthOfActivityDescription",
31
            "configType": "PositiveInteger",
32
            "configuration": {
33
                "configName": "minAvgLengthOfActivityDescription",
34
                "configPrintName": "Minimum average length of activity description",
35
                "configDescription": "Minimum average number of character of activity description",
36
                "configErrorMess": "Minimum average length of activity description must be positive integer number",
37
                "configValue": "150"
30
            "thresholdName": "minAvgLengthOfActivityDescription",
31
            "thresholdType": "PositiveInteger",
32
            "threshold": {
33
                "thresholdName": "minAvgLengthOfActivityDescription",
34
                "thresholdPrintName": "Minimum average length of activity description",
35
                "thresholdDescription": "Minimum average number of character of activity description",
36
                "thresholdErrorMess": "Minimum average length of activity description must be positive integer number",
37
                "thresholdValue": "150"
38 38
            }
39 39
        },
40 40
        {
41
            "configName": "searchSubstringsWithProjectSpecification",
42
            "configType": "String",
43
            "configuration": {
44
                "configName": "searchSubstringsWithProjectSpecification",
45
                "configPrintName": "Search substrings with project specification",
46
                "configDescription": "Substring that will be search in wikipages and activities",
47
                "configErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||",
48
                "configValue": "%dsp%||%specifikace%||%specification%||%vize%proj%||%vize%produ%"
41
            "thresholdName": "searchSubstringsWithProjectSpecification",
42
            "thresholdType": "String",
43
            "threshold": {
44
                "thresholdName": "searchSubstringsWithProjectSpecification",
45
                "thresholdPrintName": "Search substrings with project specification",
46
                "thresholdDescription": "Substring that will be search in wikipages and activities",
47
                "thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||",
48
                "thresholdValue": "%dsp%||%specifikace%||%specification%||%vize%proj%||%vize%produ%"
49 49
            }
50 50
        }
51 51
    ],
src/main/webapp/antipatterns/TooLongSprint.json
3 3
    "printName": "Too Long Sprint",
4 4
    "name": "TooLongSprint",
5 5
    "description": "Iterations too long. (ideal iteration length is about 1-2 weeks, maximum 3 weeks). It could also be detected here if the length of the iteration does not change often (It can change at the beginning and at the end of the project, but it should not change in the already started project).",
6
    "configurations": [
6
    "thresholds": [
7 7
        {
8
            "configName": "maxIterationLength",
9
            "configType": "PositiveInteger",
10
            "configuration": {
11
                "configName": "maxIterationLength",
12
                "configPrintName": "Max Iteration Length",
13
                "configDescription": "Maximum iteration length in days",
14
                "configErrorMess": "Max iteration length must be positive integer",
15
                "configValue": "21"
8
            "thresholdName": "maxIterationLength",
9
            "thresholdType": "PositiveInteger",
10
            "threshold": {
11
                "thresholdName": "maxIterationLength",
12
                "thresholdPrintName": "Max Iteration Length",
13
                "thresholdDescription": "Maximum iteration length in days",
14
                "thresholdErrorMess": "Max iteration length must be positive integer",
15
                "thresholdValue": "21"
16 16
            }
17 17
        },
18 18
        {
19
            "configName": "maxNumberOfTooLongIterations",
20
            "configType": "PositiveInteger",
21
            "configuration": {
22
                "configName": "maxNumberOfTooLongIterations",
23
                "configPrintName": "Max number of foo long iterations",
24
                "configDescription": "Maximum number of too long iterations in project",
25
                "configErrorMess": "Max number of too long iterations must be positive integer",
26
                "configValue": "0"
19
            "thresholdName": "maxNumberOfTooLongIterations",
20
            "thresholdType": "PositiveInteger",
21
            "threshold": {
22
                "thresholdName": "maxNumberOfTooLongIterations",
23
                "thresholdPrintName": "Max number of foo long iterations",
24
                "thresholdDescription": "Maximum number of too long iterations in project",
25
                "thresholdErrorMess": "Max number of too long iterations must be positive integer",
26
                "thresholdValue": "0"
27 27
            }
28 28
        }
29 29
    ]
src/main/webapp/antipatterns/VaryingSprintLength.json
3 3
    "printName": "Varying Sprint Length",
4 4
    "name": "VaryingSprintLength",
5 5
    "description": "The length of the sprint changes very often. It is clear that iterations will be different lengths at the beginning and end of the project, but the length of the sprint should not change during the project.",
6
    "configurations": [
6
    "thresholds": [
7 7
        {
8
            "configName": "maxDaysDifference",
9
            "configType": "PositiveInteger",
10
            "configuration": {
11
                "configName": "maxDaysDifference",
12
                "configPrintName": "Max days difference",
13
                "configDescription": "Maximum distance of two consecutive iterations in days",
14
                "configErrorMess": "Maximum distance must be positive integer number",
15
                "configValue": "7"
8
            "thresholdName": "maxDaysDifference",
9
            "thresholdType": "PositiveInteger",
10
            "threshold": {
11
                "thresholdName": "maxDaysDifference",
12
                "thresholdPrintName": "Max days difference",
13
                "thresholdDescription": "Maximum distance of two consecutive iterations in days",
14
                "thresholdErrorMess": "Maximum distance must be positive integer number",
15
                "thresholdValue": "7"
16 16
            }
17 17
        },
18 18
        {
19
            "configName": "maxIterationChanged",
20
            "configType": "PositiveInteger",
21
            "configuration": {
22
                "configName": "maxIterationChanged",
23
                "configPrintName": "Max number of iteration changed",
24
                "configDescription": "Maximum allowed number of significant changes in iteration lengths",
25
                "configErrorMess": "Maximum number of iterations changed must be positive integer number",
26
                "configValue": "1"
19
            "thresholdName": "maxIterationChanged",
20
            "thresholdType": "PositiveInteger",
21
            "threshold": {
22
                "thresholdName": "maxIterationChanged",
23
                "thresholdPrintName": "Max number of iteration changed",
24
                "thresholdDescription": "Maximum allowed number of significant changes in iteration lengths",
25
                "thresholdErrorMess": "Maximum number of iterations changed must be positive integer number",
26
                "thresholdValue": "1"
27 27
            }
28 28
        }
29 29
    ]

Také k dispozici: Unified diff