Revize c3914f4b
Přidáno uživatelem stepanekp před asi 3 roky(ů)
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/repository/AntiPatternRepository.java | ||
---|---|---|
16 | 16 |
import java.io.IOException; |
17 | 17 |
import java.io.InputStreamReader; |
18 | 18 |
import java.lang.reflect.InvocationTargetException; |
19 |
import java.net.MalformedURLException; |
|
20 | 19 |
import java.net.URL; |
21 | 20 |
import java.util.*; |
22 | 21 |
|
... | ... | |
70 | 69 |
AntiPatternDetector antiPatternDetector = subType.getDeclaredConstructor().newInstance(); |
71 | 70 |
|
72 | 71 |
// loading anti-pattern from json file and linking it to the detector file |
73 |
antiPatternDetector.setAntiPattern(getAntiPatternFromJsonFile(antiPatternDetector.getJsonFileName())); |
|
72 |
AntiPattern antiPattern = getAntiPatternFromJsonFile(antiPatternDetector.getJsonFileName()); |
|
73 |
|
|
74 |
// anti-pattern was not read from file properly |
|
75 |
if(antiPattern == null) { |
|
76 |
LOGGER.error("Anti-pattern from " + antiPatternDetector.getJsonFileName() + " was not read correctly"); |
|
77 |
continue; |
|
78 |
} |
|
79 |
antiPatternDetector.setAntiPattern(antiPattern); |
|
74 | 80 |
|
75 | 81 |
antiPatterns.putIfAbsent(antiPatternDetector.getAntiPatternModel().getId(), antiPatternDetector); |
76 | 82 |
LOGGER.info("Creating detector " + antiPatternDetector.getAntiPatternModel().getPrintName()); |
... | ... | |
133 | 139 |
return queries; |
134 | 140 |
} |
135 | 141 |
|
142 |
|
|
136 | 143 |
/** |
137 |
* Method for reading anti-pattern information from json files
|
|
144 |
* Method for reading anti-pattern parameters from json file
|
|
138 | 145 |
* |
139 | 146 |
* @param jsonFileName Name of the file |
140 | 147 |
* @return AntiPattern object |
141 | 148 |
*/ |
142 |
public AntiPattern getAntiPatternFromJsonFile(String jsonFileName){ |
|
143 |
String json = ""; // json configuration file |
|
144 |
JsonNode node = null; |
|
149 |
private AntiPattern getAntiPatternFromJsonFile(String jsonFileName){ |
|
150 |
String json = ""; // json configuration file content as string |
|
145 | 151 |
|
146 | 152 |
LOGGER.info("Reading anti-pattern from json file " + jsonFileName); |
147 | 153 |
|
148 | 154 |
try { |
149 | 155 |
URL url = servletContext.getResource(AP_DIR + jsonFileName); |
156 |
|
|
150 | 157 |
BufferedReader read = new BufferedReader( |
151 | 158 |
new InputStreamReader(url.openStream())); |
152 | 159 |
|
... | ... | |
154 | 161 |
while ((line = read.readLine()) != null) { |
155 | 162 |
json += line; |
156 | 163 |
} |
157 |
node = JsonParser.parse(json); |
|
158 |
} catch (IOException e) { |
|
164 |
} catch (Exception e) { |
|
159 | 165 |
LOGGER.warn("Cannot read anti-pattern from json file " + jsonFileName); |
160 | 166 |
return null; |
161 | 167 |
} |
162 | 168 |
|
163 |
Long APid = Long.parseLong(node.get("id").asText()); |
|
164 |
String APPrintName = node.get("printName").asText(); |
|
165 |
String APName = node.get("name").asText(); |
|
166 |
String APDescription = node.get("description").asText(); |
|
167 |
String APCatalogueFileName = node.get("catalogueFileName") != null ? node.get("catalogueFileName").asText() : null; |
|
169 |
return parseAntiPatternFromJson(json); |
|
170 |
} |
|
171 |
|
|
172 |
/** |
|
173 |
* Method for parsing json file content and making AntiPattern object |
|
174 |
* @param jsonString Json file content |
|
175 |
* @return AntiPattern object made from json file |
|
176 |
*/ |
|
177 |
private AntiPattern parseAntiPatternFromJson(String jsonString){ |
|
178 |
Long APid; |
|
179 |
JsonNode node = null; |
|
180 |
String APPrintName, APName, APDescription, APCatalogueFileName; |
|
181 |
|
|
182 |
// reading of anti-pattern basic information |
|
183 |
try { |
|
184 |
node = JsonParser.parse(jsonString); |
|
168 | 185 |
|
169 |
Map<String, Threshold> APMap = new HashMap<>(); |
|
186 |
APid = Long.parseLong(node.get("id").asText()); |
|
187 |
APPrintName = node.get("printName").asText(); |
|
188 |
APName = node.get("name").asText(); |
|
189 |
APDescription = node.get("description").asText(); |
|
190 |
APCatalogueFileName = node.get("catalogueFileName") != null ? node.get("catalogueFileName").asText() : null; // optional field |
|
191 |
} |
|
192 |
catch(Exception e){ |
|
193 |
return null; |
|
194 |
} |
|
170 | 195 |
|
196 |
// reading of thresholds |
|
197 |
Map<String, Threshold> thresholdMap = new HashMap<>(); |
|
171 | 198 |
JsonNode array = node.get("thresholds"); |
172 | 199 |
Threshold tmpThreshold = null; |
173 | 200 |
|
201 |
String thresholdName, thresholdType, thresholdPrintName, thresholdDescription, thresholdErrorMess; |
|
202 |
|
|
174 | 203 |
for(int i = 0; i < array.size(); i++){ |
175 | 204 |
JsonNode tmpNode = array.get(i); |
205 |
try { |
|
206 |
thresholdName = tmpNode.get("thresholdName").asText(); |
|
207 |
thresholdType = tmpNode.get("thresholdType").asText(); |
|
208 |
thresholdPrintName = tmpNode.get("thresholdPrintName").asText(); |
|
209 |
thresholdDescription = tmpNode.get("thresholdDescription").asText(); |
|
210 |
thresholdErrorMess = tmpNode.get("thresholdErrorMess").asText(); |
|
211 |
} |
|
212 |
catch(Exception e){ |
|
213 |
return null; |
|
214 |
} |
|
176 | 215 |
|
177 |
String thresholdName = tmpNode.get("thresholdName").asText(); |
|
178 |
String thresholdType = tmpNode.get("thresholdType").asText(); |
|
179 |
|
|
180 |
JsonNode thresholdNode = tmpNode.get("threshold"); |
|
181 |
|
|
182 |
String tThresholdName = thresholdNode.get("thresholdName").asText(); |
|
183 |
String tThresholdPrintName = thresholdNode.get("thresholdPrintName").asText(); |
|
184 |
String tThresholdDescription = thresholdNode.get("thresholdDescription").asText(); |
|
185 |
String tThresholdErrorMess = thresholdNode.get("thresholdErrorMess").asText(); |
|
186 |
|
|
187 |
tmpThreshold = getThreshold(thresholdType, tThresholdName, tThresholdPrintName, tThresholdDescription, tThresholdErrorMess); |
|
188 |
|
|
189 |
APMap.put(thresholdName, tmpThreshold); |
|
216 |
// creating of Threshold object and storing it in map |
|
217 |
tmpThreshold = getThreshold(thresholdType, thresholdName, thresholdPrintName, thresholdDescription, thresholdErrorMess); |
|
218 |
thresholdMap.put(thresholdName, tmpThreshold); |
|
190 | 219 |
} |
191 | 220 |
|
192 |
AntiPattern newAP = new AntiPattern(APid, APPrintName, APName, APDescription, APMap, APCatalogueFileName); |
|
221 |
// creating of the AntiPattern object |
|
222 |
AntiPattern result = new AntiPattern(APid, APPrintName, APName, APDescription, thresholdMap, APCatalogueFileName); |
|
193 | 223 |
|
194 |
return newAP;
|
|
224 |
return result;
|
|
195 | 225 |
} |
196 | 226 |
|
197 | 227 |
/** |
src/main/webapp/antipatterns/BusinessAsUsual.json | ||
---|---|---|
7 | 7 |
{ |
8 | 8 |
"thresholdName": "divisionOfIterationsWithRetrospective", |
9 | 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 |
} |
|
10 |
"thresholdPrintName": "Division of iterations with retrospective", |
|
11 |
"thresholdDescription": "Minimum percentage of the total number of iterations with a retrospective (0,100)", |
|
12 |
"thresholdErrorMess": "Percentage must be float number between 0 and 100" |
|
16 | 13 |
}, |
17 | 14 |
{ |
18 | 15 |
"thresholdName": "searchSubstringsWithRetrospective", |
19 | 16 |
"thresholdType": "String", |
20 |
"threshold": { |
|
21 |
"thresholdName": "searchSubstringsWithRetrospective", |
|
22 |
"thresholdPrintName": "Search substrings with retrospective", |
|
23 |
"thresholdDescription": "Substring that will be search in wikipages and activities", |
|
24 |
"thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters || " |
|
25 |
} |
|
17 |
"thresholdPrintName": "Search substrings with retrospective", |
|
18 |
"thresholdDescription": "Substring that will be search in wikipages and activities", |
|
19 |
"thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters || " |
|
26 | 20 |
} |
27 | 21 |
], |
28 | 22 |
"catalogueFileName": "Business_As_Usual.md" |
src/main/webapp/antipatterns/LongOrNonExistentFeedbackLoops.json | ||
---|---|---|
7 | 7 |
{ |
8 | 8 |
"thresholdName": "divisionOfIterationsWithFeedbackLoop", |
9 | 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 |
} |
|
10 |
"thresholdPrintName": "Division of iterations with feedback loop", |
|
11 |
"thresholdDescription": "Minimum percentage of the total number of iterations with feedback loop (0,100)", |
|
12 |
"thresholdErrorMess": "Percentage must be float number between 0 and 100" |
|
16 | 13 |
}, |
17 | 14 |
{ |
18 | 15 |
"thresholdName": "maxGapBetweenFeedbackLoopRate", |
19 | 16 |
"thresholdType": "PositiveFloat", |
20 |
"threshold": { |
|
21 |
"thresholdName": "maxGapBetweenFeedbackLoopRate", |
|
22 |
"thresholdPrintName": "Maximum gap between feedback loop rate", |
|
23 |
"thresholdDescription": "Value that multiplies average iteration length for given project. Result is maximum threshold value for gap between feedback loops in days.", |
|
24 |
"thresholdErrorMess": "Maximum gap between feedback loop rate must be positive float number" |
|
25 |
} |
|
17 |
"thresholdPrintName": "Maximum gap between feedback loop rate", |
|
18 |
"thresholdDescription": "Value that multiplies average iteration length for given project. Result is maximum threshold value for gap between feedback loops in days.", |
|
19 |
"thresholdErrorMess": "Maximum gap between feedback loop rate must be positive float number" |
|
26 | 20 |
}, |
27 | 21 |
{ |
28 | 22 |
"thresholdName": "searchSubstringsWithFeedbackLoop", |
29 | 23 |
"thresholdType": "String", |
30 |
"threshold": { |
|
31 |
"thresholdName": "searchSubstringsWithFeedbackLoop", |
|
32 |
"thresholdPrintName": "Search substrings with feedback loop", |
|
33 |
"thresholdDescription": "Substring that will be search in wikipages and activities", |
|
34 |
"thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||" |
|
35 |
} |
|
24 |
"thresholdPrintName": "Search substrings with feedback loop", |
|
25 |
"thresholdDescription": "Substring that will be search in wikipages and activities", |
|
26 |
"thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||" |
|
36 | 27 |
} |
37 | 28 |
] |
38 | 29 |
} |
src/main/webapp/antipatterns/NinetyNinetyRule.json | ||
---|---|---|
7 | 7 |
{ |
8 | 8 |
"thresholdName": "maxDivisionRange", |
9 | 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 |
} |
|
10 |
"thresholdPrintName": "Maximum ration value", |
|
11 |
"thresholdDescription": "Maximum ratio value of spent and estimated time", |
|
12 |
"thresholdErrorMess": "Ration values must be positive float number" |
|
16 | 13 |
}, |
17 | 14 |
{ |
18 | 15 |
"thresholdName": "maxBadDivisionLimit", |
19 | 16 |
"thresholdType": "PositiveInteger", |
20 |
"threshold": { |
|
21 |
"thresholdName": "maxBadDivisionLimit", |
|
22 |
"thresholdPrintName": "Maximum iterations thresholds", |
|
23 |
"thresholdDescription": "Maximum number of consecutive iterations where the thresholds were exceeded", |
|
24 |
"thresholdErrorMess": "Maximum number of consecutive iterations must be positive integer number" |
|
25 |
} |
|
17 |
"thresholdPrintName": "Maximum iterations thresholds", |
|
18 |
"thresholdDescription": "Maximum number of consecutive iterations where the thresholds were exceeded", |
|
19 |
"thresholdErrorMess": "Maximum number of consecutive iterations must be positive integer number" |
|
26 | 20 |
} |
27 | 21 |
] |
28 | 22 |
} |
src/main/webapp/antipatterns/RoadToNowhere.json | ||
---|---|---|
7 | 7 |
{ |
8 | 8 |
"thresholdName": "minNumberOfWikiPagesWithProjectPlan", |
9 | 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 |
} |
|
10 |
"thresholdPrintName": "Minimum number of wiki pages with project plan", |
|
11 |
"thresholdDescription": "Number of wiki pages", |
|
12 |
"thresholdErrorMess": "Minimum number of wikipages must be positive integer number" |
|
16 | 13 |
}, |
17 | 14 |
{ |
18 | 15 |
"thresholdName": "minNumberOfActivitiesWithProjectPlan", |
19 | 16 |
"thresholdType": "PositiveInteger", |
20 |
"threshold": { |
|
21 |
"thresholdName": "minNumberOfActivitiesWithProjectPlan", |
|
22 |
"thresholdPrintName": "Minimum number of activities with project plan", |
|
23 |
"thresholdDescription": "Number of activities", |
|
24 |
"thresholdErrorMess": "Minimum number of activities must be positive integer number" |
|
25 |
} |
|
17 |
"thresholdPrintName": "Minimum number of activities with project plan", |
|
18 |
"thresholdDescription": "Number of activities", |
|
19 |
"thresholdErrorMess": "Minimum number of activities must be positive integer number" |
|
26 | 20 |
}, |
27 | 21 |
{ |
28 | 22 |
"thresholdName": "searchSubstringsWithProjectPlan", |
29 | 23 |
"thresholdType": "String", |
30 |
"threshold": { |
|
31 |
"thresholdName": "searchSubstringsWithProjectPlan", |
|
32 |
"thresholdPrintName": "Search substrings with project plan", |
|
33 |
"thresholdDescription": "Substring that will be search in wikipages and activities", |
|
34 |
"thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||" |
|
35 |
} |
|
24 |
"thresholdPrintName": "Search substrings with project plan", |
|
25 |
"thresholdDescription": "Substring that will be search in wikipages and activities", |
|
26 |
"thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||" |
|
36 | 27 |
} |
37 | 28 |
], |
38 | 29 |
"catalogueFileName": "Road_To_Nowhere.md" |
src/main/webapp/antipatterns/SpecifyNothing.json | ||
---|---|---|
7 | 7 |
{ |
8 | 8 |
"thresholdName": "minNumberOfWikiPagesWithSpecification", |
9 | 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 |
} |
|
10 |
"thresholdPrintName": "Minimum number of wiki pages with project specification", |
|
11 |
"thresholdDescription": "Number of wiki pages", |
|
12 |
"thresholdErrorMess": "Minimum number of wikipages must be positive integer number" |
|
16 | 13 |
}, |
17 | 14 |
{ |
18 | 15 |
"thresholdName": "minNumberOfActivitiesWithSpecification", |
19 | 16 |
"thresholdType": "PositiveInteger", |
20 |
"threshold": { |
|
21 |
"thresholdName": "minNumberOfActivitiesWithSpecification", |
|
22 |
"thresholdPrintName": "Minimum number of activities with project specification", |
|
23 |
"thresholdDescription": "Number of activities", |
|
24 |
"thresholdErrorMess": "Minimum number of activities with project specification must be positive integer number" |
|
25 |
} |
|
17 |
"thresholdPrintName": "Minimum number of activities with project specification", |
|
18 |
"thresholdDescription": "Number of activities", |
|
19 |
"thresholdErrorMess": "Minimum number of activities with project specification must be positive integer number" |
|
26 | 20 |
}, |
27 | 21 |
{ |
28 | 22 |
"thresholdName": "minAvgLengthOfActivityDescription", |
29 | 23 |
"thresholdType": "PositiveInteger", |
30 |
"threshold": { |
|
31 |
"thresholdName": "minAvgLengthOfActivityDescription", |
|
32 |
"thresholdPrintName": "Minimum average length of activity description", |
|
33 |
"thresholdDescription": "Minimum average number of character of activity description", |
|
34 |
"thresholdErrorMess": "Minimum average length of activity description must be positive integer number" |
|
35 |
} |
|
24 |
"thresholdPrintName": "Minimum average length of activity description", |
|
25 |
"thresholdDescription": "Minimum average number of character of activity description", |
|
26 |
"thresholdErrorMess": "Minimum average length of activity description must be positive integer number" |
|
36 | 27 |
}, |
37 | 28 |
{ |
38 | 29 |
"thresholdName": "searchSubstringsWithProjectSpecification", |
39 | 30 |
"thresholdType": "String", |
40 |
"threshold": { |
|
41 |
"thresholdName": "searchSubstringsWithProjectSpecification", |
|
42 |
"thresholdPrintName": "Search substrings with project specification", |
|
43 |
"thresholdDescription": "Substring that will be search in wikipages and activities", |
|
44 |
"thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||" |
|
45 |
} |
|
31 |
"thresholdPrintName": "Search substrings with project specification", |
|
32 |
"thresholdDescription": "Substring that will be search in wikipages and activities", |
|
33 |
"thresholdErrorMess": "Maximum number of substrings is ten and must not starts and ends with characters ||" |
|
46 | 34 |
} |
47 | 35 |
], |
48 | 36 |
"catalogueFileName": "Specify_Nothing.md" |
src/main/webapp/antipatterns/TooLongSprint.json | ||
---|---|---|
7 | 7 |
{ |
8 | 8 |
"thresholdName": "maxIterationLength", |
9 | 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 |
} |
|
10 |
"thresholdPrintName": "Max Iteration Length", |
|
11 |
"thresholdDescription": "Maximum iteration length in days", |
|
12 |
"thresholdErrorMess": "Max iteration length must be positive integer" |
|
16 | 13 |
}, |
17 | 14 |
{ |
18 | 15 |
"thresholdName": "maxNumberOfTooLongIterations", |
19 | 16 |
"thresholdType": "PositiveInteger", |
20 |
"threshold": { |
|
21 |
"thresholdName": "maxNumberOfTooLongIterations", |
|
22 |
"thresholdPrintName": "Max number of foo long iterations", |
|
23 |
"thresholdDescription": "Maximum number of too long iterations in project", |
|
24 |
"thresholdErrorMess": "Max number of too long iterations must be positive integer" |
|
25 |
} |
|
17 |
"thresholdPrintName": "Max number of foo long iterations", |
|
18 |
"thresholdDescription": "Maximum number of too long iterations in project", |
|
19 |
"thresholdErrorMess": "Max number of too long iterations must be positive integer" |
|
20 |
|
|
26 | 21 |
} |
27 | 22 |
] |
28 | 23 |
} |
src/main/webapp/antipatterns/VaryingSprintLength.json | ||
---|---|---|
7 | 7 |
{ |
8 | 8 |
"thresholdName": "maxDaysDifference", |
9 | 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 |
} |
|
10 |
"thresholdPrintName": "Max days difference", |
|
11 |
"thresholdDescription": "Maximum distance of two consecutive iterations in days", |
|
12 |
"thresholdErrorMess": "Maximum distance must be positive integer number" |
|
16 | 13 |
}, |
17 | 14 |
{ |
18 | 15 |
"thresholdName": "maxIterationChanged", |
19 | 16 |
"thresholdType": "PositiveInteger", |
20 |
"threshold": { |
|
21 |
"thresholdName": "maxIterationChanged", |
|
22 |
"thresholdPrintName": "Max number of iteration changed", |
|
23 |
"thresholdDescription": "Maximum allowed number of significant changes in iteration lengths", |
|
24 |
"thresholdErrorMess": "Maximum number of iterations changed must be positive integer number" |
|
25 |
} |
|
17 |
"thresholdPrintName": "Max number of iteration changed", |
|
18 |
"thresholdDescription": "Maximum allowed number of significant changes in iteration lengths", |
|
19 |
"thresholdErrorMess": "Maximum number of iterations changed must be positive integer number" |
|
26 | 20 |
} |
27 | 21 |
] |
28 | 22 |
} |
Také k dispozici: Unified diff
Reading anti-patterns from json files modified