Revize 157c07d1
Přidáno uživatelem Ondřej Váně před téměř 3 roky(ů)
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/Constants.java | ||
---|---|---|
2 | 2 |
|
3 | 3 |
public class Constants { |
4 | 4 |
public static final String ANTI_PATTERN_CATALOGUE_URL = "https://github.com/ReliSA/Software-process-antipatterns-catalogue/blob/master/catalogue/"; |
5 |
public static final String SUBSTRING_DELIMITER = "||"; |
|
5 | 6 |
} |
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/DatabaseConnection.java | ||
---|---|---|
6 | 6 |
import cz.zcu.fav.kiv.antipatterndetectionapp.utils.Utils; |
7 | 7 |
|
8 | 8 |
import java.sql.*; |
9 |
import java.util.*; |
|
9 |
import java.util.ArrayList; |
|
10 |
import java.util.List; |
|
11 |
import java.util.Map; |
|
10 | 12 |
|
13 |
/** |
|
14 |
* A class that takes care of database connections and running queries. |
|
15 |
*/ |
|
11 | 16 |
public class DatabaseConnection { |
12 | 17 |
|
13 | 18 |
private Connection databaseConnection; |
14 | 19 |
|
20 |
/** |
|
21 |
* Constructor that takes application properties from configuration file name application.properties |
|
22 |
* and creating new database connection with given parameters. |
|
23 |
*/ |
|
15 | 24 |
public DatabaseConnection() { |
16 | 25 |
ApplicationProperties applicationProperties = ((ApplicationProperties) SpringApplicationContext.getContext() |
17 | 26 |
.getBean("applicationProperties")); |
... | ... | |
21 | 30 |
this.databaseConnection = createConnection(connectionUrl, dataSourceUsername, dataSourcePassword); |
22 | 31 |
} |
23 | 32 |
|
33 |
/** |
|
34 |
* Method for creating database connection with given parameters. |
|
35 |
* |
|
36 |
* @param connectionUrl database url to connect |
|
37 |
* @param dataSourceUsername database username |
|
38 |
* @param dataSourcePassword database user password |
|
39 |
* @return new database connection |
|
40 |
*/ |
|
24 | 41 |
private Connection createConnection(String connectionUrl, String dataSourceUsername, String dataSourcePassword) { |
25 | 42 |
Connection conn = null; |
26 | 43 |
try { |
... | ... | |
32 | 49 |
return conn; |
33 | 50 |
} |
34 | 51 |
|
35 |
public void closeConnection() { |
|
52 |
/** |
|
53 |
* Method for closing database connection. It is necessary to close the database |
|
54 |
* connection when the database connection is not used due to the accumulation |
|
55 |
* of unused connections. |
|
56 |
*/ |
|
57 |
void closeConnection() { |
|
36 | 58 |
try { |
37 | 59 |
this.databaseConnection.close(); |
38 | 60 |
} catch (SQLException e) { |
... | ... | |
40 | 62 |
} |
41 | 63 |
} |
42 | 64 |
|
65 |
/** |
|
66 |
* Simple getter for getting the database connection. |
|
67 |
* |
|
68 |
* @return database connection |
|
69 |
*/ |
|
43 | 70 |
public Connection getDatabaseConnection() { |
44 | 71 |
return databaseConnection; |
45 | 72 |
} |
46 | 73 |
|
74 |
/** |
|
75 |
* Method for analyzing a given project. These methods are intended |
|
76 |
* for queries that have a single select output (for example Road To Nowhere). |
|
77 |
* |
|
78 |
* @param project analyzed project |
|
79 |
* @param queries list of queries |
|
80 |
* @return result set of results |
|
81 |
*/ |
|
47 | 82 |
public ResultSet executeQueries(Project project, List<String> queries) { |
48 | 83 |
Statement stmt; |
49 | 84 |
ResultSet resultSet = null; |
... | ... | |
51 | 86 |
stmt = this.getDatabaseConnection().createStatement(); |
52 | 87 |
|
53 | 88 |
for (String query : queries) { |
54 |
if(queries.indexOf(query) != queries.size()-1){
|
|
55 |
if(query.contains("?")) |
|
89 |
if (queries.indexOf(query) != queries.size() - 1) {
|
|
90 |
if (query.contains("?"))
|
|
56 | 91 |
query = query.replace("?", project.getId().toString()); |
57 | 92 |
stmt.executeQuery(query); |
58 | 93 |
} else { |
... | ... | |
66 | 101 |
return resultSet; |
67 | 102 |
} |
68 | 103 |
|
69 |
public List<List<Map<String,Object>>> executeQueriesWithMultipleResults(Project project, List<String> queries) { |
|
104 |
public List<List<Map<String, Object>>> executeQueriesWithMultipleResults(Project project, List<String> queries) {
|
|
70 | 105 |
Statement stmt; |
71 |
List<List<Map<String,Object>>> allResults = new ArrayList<>(); |
|
106 |
List<List<Map<String, Object>>> allResults = new ArrayList<>();
|
|
72 | 107 |
ResultSet resultSet = null; |
73 | 108 |
try { |
74 | 109 |
stmt = this.getDatabaseConnection().createStatement(); |
75 | 110 |
|
76 | 111 |
for (String query : queries) { |
77 |
if(queries.indexOf(query) != queries.size()-1){
|
|
78 |
if(query.contains("?")) |
|
112 |
if (queries.indexOf(query) != queries.size() - 1) {
|
|
113 |
if (query.contains("?"))
|
|
79 | 114 |
query = query.replace("?", project.getId().toString()); |
80 | 115 |
resultSet = stmt.executeQuery(query); |
81 | 116 |
} else { |
... | ... | |
83 | 118 |
} |
84 | 119 |
|
85 | 120 |
if (query.toLowerCase().startsWith("select")) { |
86 |
allResults.add(resultSetToArrayList(resultSet)); |
|
121 |
allResults.add(Utils.resultSetToArrayList(resultSet));
|
|
87 | 122 |
} |
88 | 123 |
|
89 | 124 |
} |
... | ... | |
93 | 128 |
|
94 | 129 |
return allResults; |
95 | 130 |
} |
96 |
|
|
97 |
private List<Map<String,Object>> resultSetToArrayList(ResultSet rs) throws SQLException { |
|
98 |
ResultSetMetaData md = rs.getMetaData(); |
|
99 |
int columns = md.getColumnCount(); |
|
100 |
List<Map<String, Object>> list = new ArrayList<>(); |
|
101 |
while (rs.next()) { |
|
102 |
Map<String, Object> row = new HashMap<>(columns); |
|
103 |
for (int i = 1; i <= columns; ++i) { |
|
104 |
row.put(md.getColumnName(i), rs.getObject(i)); |
|
105 |
} |
|
106 |
list.add(row); |
|
107 |
} |
|
108 |
|
|
109 |
return list; |
|
110 |
} |
|
111 | 131 |
} |
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/BusinessAsUsualDetectorImpl.java | ||
---|---|---|
1 | 1 |
package cz.zcu.fav.kiv.antipatterndetectionapp.detecting.detectors; |
2 | 2 |
|
3 |
import cz.zcu.fav.kiv.antipatterndetectionapp.Constants; |
|
3 | 4 |
import cz.zcu.fav.kiv.antipatterndetectionapp.detecting.DatabaseConnection; |
4 | 5 |
import cz.zcu.fav.kiv.antipatterndetectionapp.model.*; |
6 |
import cz.zcu.fav.kiv.antipatterndetectionapp.utils.Utils; |
|
5 | 7 |
import org.slf4j.Logger; |
6 | 8 |
import org.slf4j.LoggerFactory; |
7 | 9 |
|
8 |
import java.util.ArrayList; |
|
9 |
import java.util.HashMap; |
|
10 |
import java.util.List; |
|
11 |
import java.util.Map; |
|
10 |
import java.util.*; |
|
12 | 11 |
|
13 | 12 |
public class BusinessAsUsualDetectorImpl implements AntiPatternDetector { |
14 | 13 |
|
... | ... | |
23 | 22 |
put("divisionOfIterationsWithRetrospective", new Configuration<Float>("divisionOfIterationsWithRetrospective", |
24 | 23 |
"Division of iterations with retrospective", |
25 | 24 |
"Minimum percentage of the total number of iterations with a retrospective (0,1)", 0.66666f)); |
25 |
put("searchSubstringsWithRetrospective", new Configuration<String>("searchSubstringsWithRetrospective", |
|
26 |
"Search substrings with retrospective", |
|
27 |
"Substring that will be search in wikipages and activities", |
|
28 |
"%retr%" + Constants.SUBSTRING_DELIMITER + |
|
29 |
"%revi%" + Constants.SUBSTRING_DELIMITER + |
|
30 |
"%week%scrum%")); |
|
26 | 31 |
}}, |
27 | 32 |
"Business_As_Usual.md"); |
28 | 33 |
|
... | ... | |
35 | 40 |
return (float) antiPattern.getConfigurations().get("divisionOfIterationsWithRetrospective").getValue(); |
36 | 41 |
} |
37 | 42 |
|
43 |
private List<String> getSearchSubstringsWithRetrospective() { |
|
44 |
return Arrays.asList(((String) antiPattern.getConfigurations().get("searchSubstringsWithRetrospective").getValue()).split("\\|\\|")); |
|
45 |
} |
|
46 |
|
|
38 | 47 |
@Override |
39 | 48 |
public AntiPattern getAntiPatternModel() { |
40 | 49 |
return this.antiPattern; |
... | ... | |
75 | 84 |
Map<String, Integer> iterationsResults = new HashMap<>(); |
76 | 85 |
|
77 | 86 |
// projít výsledky dotazů a dát do jedné mapy => v této mapě by měly být všechny iterace |
78 |
List<List<Map<String, Object>>> resultSets = databaseConnection.executeQueriesWithMultipleResults(project, this.sqlQueries); |
|
87 |
List<List<Map<String, Object>>> resultSets = databaseConnection.executeQueriesWithMultipleResults(project, |
|
88 |
Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithRetrospective())); |
|
79 | 89 |
for (int i = 0; i < resultSets.size(); i++) { |
80 | 90 |
List<Map<String, Object>> rs = resultSets.get(i); |
81 | 91 |
|
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/LongOrNonExistentFeedbackLoopsDetectorImpl.java | ||
---|---|---|
1 | 1 |
package cz.zcu.fav.kiv.antipatterndetectionapp.detecting.detectors; |
2 | 2 |
|
3 |
import cz.zcu.fav.kiv.antipatterndetectionapp.Constants; |
|
3 | 4 |
import cz.zcu.fav.kiv.antipatterndetectionapp.detecting.DatabaseConnection; |
4 | 5 |
import cz.zcu.fav.kiv.antipatterndetectionapp.model.*; |
5 | 6 |
import cz.zcu.fav.kiv.antipatterndetectionapp.utils.Utils; |
... | ... | |
8 | 9 |
|
9 | 10 |
import java.math.BigDecimal; |
10 | 11 |
import java.sql.Date; |
11 |
import java.util.ArrayList; |
|
12 |
import java.util.HashMap; |
|
13 |
import java.util.List; |
|
14 |
import java.util.Map; |
|
12 |
import java.util.*; |
|
15 | 13 |
|
16 | 14 |
public class LongOrNonExistentFeedbackLoopsDetectorImpl implements AntiPatternDetector { |
17 | 15 |
|
... | ... | |
33 | 31 |
"Maximum gap between feedback loop rate", |
34 | 32 |
"Value that multiplies average iteration length for given project. Result" + |
35 | 33 |
" is maximum threshold value for gap between feedback loops in days.", 2f)); |
34 |
put("searchSubstringsWithFeedbackLoop", new Configuration<String>("searchSubstringsWithFeedbackLoop", |
|
35 |
"Search substrings with feedback loop", |
|
36 |
"Substring that will be search in wikipages and activities", |
|
37 |
"%schůz%zákazník%" + Constants.SUBSTRING_DELIMITER + |
|
38 |
"%předvedení%zákazník%" + Constants.SUBSTRING_DELIMITER + |
|
39 |
"%zákazn%demo%" + Constants.SUBSTRING_DELIMITER + |
|
40 |
"%schůz%zadavat%" + Constants.SUBSTRING_DELIMITER + |
|
41 |
"%inform%schůz%" + Constants.SUBSTRING_DELIMITER + |
|
42 |
"%zákazn%" + Constants.SUBSTRING_DELIMITER + |
|
43 |
"%zadavatel%")); |
|
36 | 44 |
}} |
37 |
);
|
|
45 |
); |
|
38 | 46 |
|
39 | 47 |
private final String SQL_FILE_NAME = "long_or_non_existent_feedback_loops.sql"; |
40 | 48 |
// sql queries loaded from sql file |
... | ... | |
48 | 56 |
return (float) antiPattern.getConfigurations().get("maxGapBetweenFeedbackLoopRate").getValue(); |
49 | 57 |
} |
50 | 58 |
|
59 |
private List<String> getSearchSubstringsWithFeedbackLoop() { |
|
60 |
return Arrays.asList(((String) antiPattern.getConfigurations().get("searchSubstringsWithFeedbackLoop").getValue()).split("\\|\\|")); |
|
61 |
} |
|
62 |
|
|
51 | 63 |
@Override |
52 | 64 |
public AntiPattern getAntiPatternModel() { |
53 | 65 |
return this.antiPattern; |
... | ... | |
91 | 103 |
Date projectStartDate = null; |
92 | 104 |
Date projectEndDate = null; |
93 | 105 |
|
94 |
List<List<Map<String, Object>>> resultSets = databaseConnection.executeQueriesWithMultipleResults(project, this.sqlQueries); |
|
106 |
List<List<Map<String, Object>>> resultSets = databaseConnection.executeQueriesWithMultipleResults(project, |
|
107 |
Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithFeedbackLoop())); |
|
95 | 108 |
for (int i = 0; i < resultSets.size(); i++) { |
96 | 109 |
List<Map<String, Object>> rs = resultSets.get(i); |
97 | 110 |
|
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/RoadToNowhereDetectorImpl.java | ||
---|---|---|
1 | 1 |
package cz.zcu.fav.kiv.antipatterndetectionapp.detecting.detectors; |
2 | 2 |
|
3 |
import cz.zcu.fav.kiv.antipatterndetectionapp.Constants; |
|
3 | 4 |
import cz.zcu.fav.kiv.antipatterndetectionapp.detecting.DatabaseConnection; |
4 | 5 |
import cz.zcu.fav.kiv.antipatterndetectionapp.model.*; |
6 |
import cz.zcu.fav.kiv.antipatterndetectionapp.utils.Utils; |
|
5 | 7 |
import org.slf4j.Logger; |
6 | 8 |
import org.slf4j.LoggerFactory; |
7 | 9 |
|
8 | 10 |
import java.sql.ResultSet; |
9 | 11 |
import java.sql.SQLException; |
10 |
import java.util.ArrayList; |
|
11 |
import java.util.HashMap; |
|
12 |
import java.util.List; |
|
12 |
import java.util.*; |
|
13 | 13 |
|
14 | 14 |
public class RoadToNowhereDetectorImpl implements AntiPatternDetector { |
15 | 15 |
|
... | ... | |
28 | 28 |
put("minNumberOfActivitiesWithProjectPlan", new Configuration<Integer>("minNumberOfActivitiesWithProjectPlan", |
29 | 29 |
"Minimum number of activities with project plan", |
30 | 30 |
"Number of activities", 1)); |
31 |
put("searchSubstringsWithProjectPlan", new Configuration<String>("searchSubstringsWithProjectPlan", |
|
32 |
"Search substrings with project plan", |
|
33 |
"Substring that will be search in wikipages and activities", |
|
34 |
"%plán projektu%" + Constants.SUBSTRING_DELIMITER + |
|
35 |
"%project plan%" + Constants.SUBSTRING_DELIMITER + |
|
36 |
"%plan project%" + Constants.SUBSTRING_DELIMITER + |
|
37 |
"%projektový plán%")); |
|
31 | 38 |
}}, |
32 | 39 |
"Road_To_Nowhere.md"); |
33 | 40 |
|
... | ... | |
43 | 50 |
return (int) antiPattern.getConfigurations().get("minNumberOfActivitiesWithProjectPlan").getValue(); |
44 | 51 |
} |
45 | 52 |
|
53 |
private List<String> getSearchSubstringsWithProjectPlan() { |
|
54 |
return Arrays.asList(((String) antiPattern.getConfigurations().get("searchSubstringsWithProjectPlan").getValue()).split("\\|\\|")); |
|
55 |
} |
|
56 |
|
|
46 | 57 |
@Override |
47 | 58 |
public AntiPattern getAntiPatternModel() { |
48 | 59 |
return this.antiPattern; |
... | ... | |
60 | 71 |
|
61 | 72 |
/** |
62 | 73 |
* Postup detekce: |
63 |
* 1) u každého projektu zkusit nalézt jestli obsahuje nějaké wiki stránky s projektovým plánem
|
|
64 |
* 2) dále zkusit najít aktivity, které by naznačovali, že vznikl nějaký projektový plán
|
|
65 |
* 3) pokud nebude nalezena žádná aktivita nebo wiki stránka, tak je antivzor detekován
|
|
74 |
* 1) u každého projektu zkusit nalézt jestli obsahuje nějaké wiki stránky s projektovým plánem |
|
75 |
* 2) dále zkusit najít aktivity, které by naznačovali, že vznikl nějaký projektový plán |
|
76 |
* 3) pokud nebude nalezena žádná aktivita nebo wiki stránka, tak je antivzor detekován |
|
66 | 77 |
* |
67 | 78 |
* @param project analyzovaný project |
68 | 79 |
* @param databaseConnection databázové připojení |
... | ... | |
77 | 88 |
int numberOfWikiPagesForProjectPlan = 0; |
78 | 89 |
|
79 | 90 |
try { |
80 |
ResultSet rs = databaseConnection.executeQueries(project, this.sqlQueries); |
|
91 |
ResultSet rs = databaseConnection.executeQueries(project, |
|
92 |
Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithProjectPlan())); |
|
81 | 93 |
if (rs != null) { |
82 | 94 |
while (rs.next()) { |
83 | 95 |
numberOfIssuesForProjectPlan = rs.getInt("numberOfIssuesForProjectPlan"); |
... | ... | |
94 | 106 |
resultDetails.add(new ResultDetail("Number of issues for creating project plan", String.valueOf(numberOfIssuesForProjectPlan))); |
95 | 107 |
resultDetails.add(new ResultDetail("Number of wiki pages for creating project plan", String.valueOf(numberOfWikiPagesForProjectPlan))); |
96 | 108 |
|
97 |
if( numberOfIssuesForProjectPlan >= getMinNumberOfActivitiesWithProjectPlan() || numberOfWikiPagesForProjectPlan >= getMinNumberOfWikiPagesWithProjectPlan()) {
|
|
109 |
if (numberOfIssuesForProjectPlan >= getMinNumberOfActivitiesWithProjectPlan() || numberOfWikiPagesForProjectPlan >= getMinNumberOfWikiPagesWithProjectPlan()) {
|
|
98 | 110 |
resultDetails.add(new ResultDetail("Conclusion", "Found some activities or wiki pages for project plan in first two iterations")); |
99 | 111 |
return new QueryResultItem(this.antiPattern, false, resultDetails); |
100 | 112 |
} else { |
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/SpecifyNothingDetectorImpl.java | ||
---|---|---|
1 | 1 |
package cz.zcu.fav.kiv.antipatterndetectionapp.detecting.detectors; |
2 | 2 |
|
3 |
import cz.zcu.fav.kiv.antipatterndetectionapp.Constants; |
|
3 | 4 |
import cz.zcu.fav.kiv.antipatterndetectionapp.detecting.DatabaseConnection; |
4 | 5 |
import cz.zcu.fav.kiv.antipatterndetectionapp.model.*; |
6 |
import cz.zcu.fav.kiv.antipatterndetectionapp.utils.Utils; |
|
5 | 7 |
import org.slf4j.Logger; |
6 | 8 |
import org.slf4j.LoggerFactory; |
7 | 9 |
|
8 | 10 |
import java.sql.ResultSet; |
9 | 11 |
import java.sql.SQLException; |
10 |
import java.util.ArrayList; |
|
11 |
import java.util.HashMap; |
|
12 |
import java.util.List; |
|
12 |
import java.util.*; |
|
13 | 13 |
|
14 | 14 |
public class SpecifyNothingDetectorImpl implements AntiPatternDetector { |
15 | 15 |
|
... | ... | |
30 | 30 |
put("minAvgLengthOfActivityDescription", new Configuration<Integer>("minAvgLengthOfActivityDescription", |
31 | 31 |
"Minimum average length of activity description", |
32 | 32 |
"Minimum average number of character of activity description", 150)); |
33 |
put("searchSubstringsWithProjectSpecification", new Configuration<String>("searchSubstringsWithProjectSpecification", |
|
34 |
"Search substrings with project specification", |
|
35 |
"Substring that will be search in wikipages and activities", |
|
36 |
"%dsp%" + Constants.SUBSTRING_DELIMITER + |
|
37 |
"%specifikace%" + Constants.SUBSTRING_DELIMITER + |
|
38 |
"%specification%" + Constants.SUBSTRING_DELIMITER + |
|
39 |
"%vize%proj%" + Constants.SUBSTRING_DELIMITER + |
|
40 |
"%vize%produ%")); |
|
33 | 41 |
}}, |
34 | 42 |
"Specify_Nothing.md"); |
35 | 43 |
|
... | ... | |
49 | 57 |
return (int) antiPattern.getConfigurations().get("minAvgLengthOfActivityDescription").getValue(); |
50 | 58 |
} |
51 | 59 |
|
60 |
private List<String> getSearchSubstringsWithProjectSpecification() { |
|
61 |
return Arrays.asList(((String) antiPattern.getConfigurations().get("searchSubstringsWithProjectSpecification").getValue()).split("\\|\\|")); |
|
62 |
} |
|
63 |
|
|
52 | 64 |
@Override |
53 | 65 |
public AntiPattern getAntiPatternModel() { |
54 | 66 |
return this.antiPattern; |
... | ... | |
86 | 98 |
double averageLengthOfIssueDescription = 0; |
87 | 99 |
|
88 | 100 |
try { |
89 |
ResultSet rs = databaseConnection.executeQueries(project, this.sqlQueries); |
|
101 |
ResultSet rs = databaseConnection.executeQueries(project, |
|
102 |
Utils.fillQueryWithSearchSubstrings(this.sqlQueries, getSearchSubstringsWithProjectSpecification())); |
|
90 | 103 |
if (rs != null) { |
91 | 104 |
while (rs.next()) { |
92 | 105 |
numberOfWikiPages = rs.getInt("numberOfWikiPages"); |
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/AntiPatternServiceImpl.java | ||
---|---|---|
90 | 90 |
} catch (NumberFormatException e) { |
91 | 91 |
return false; |
92 | 92 |
} |
93 |
} else if (antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).getValue().getClass() == String.class) { |
|
94 |
antiPatternDetector.getAntiPatternModel().getConfigurations().get(configNames[i]).setValue((configValues[i])); |
|
95 |
setConfigurationChanged(true); |
|
93 | 96 |
} |
94 | 97 |
} |
95 | 98 |
} |
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/utils/Utils.java | ||
---|---|---|
5 | 5 |
import org.slf4j.LoggerFactory; |
6 | 6 |
|
7 | 7 |
import java.sql.Date; |
8 |
import java.sql.ResultSet; |
|
9 |
import java.sql.ResultSetMetaData; |
|
10 |
import java.sql.SQLException; |
|
8 | 11 |
import java.time.LocalDate; |
9 | 12 |
import java.time.temporal.ChronoUnit; |
10 |
import java.util.ArrayList; |
|
11 |
import java.util.Arrays; |
|
12 |
import java.util.List; |
|
13 |
import java.util.*; |
|
13 | 14 |
|
14 | 15 |
public class Utils { |
15 | 16 |
|
... | ... | |
34 | 35 |
public static List<ResultDetail> createResultDetailsList(ResultDetail... resultDetails) { |
35 | 36 |
return new ArrayList<>(Arrays.asList(resultDetails)); |
36 | 37 |
} |
38 |
|
|
39 |
public static List<Map<String, Object>> resultSetToArrayList(ResultSet rs) throws SQLException { |
|
40 |
ResultSetMetaData md = rs.getMetaData(); |
|
41 |
int columns = md.getColumnCount(); |
|
42 |
List<Map<String, Object>> list = new ArrayList<>(); |
|
43 |
while (rs.next()) { |
|
44 |
Map<String, Object> row = new HashMap<>(columns); |
|
45 |
for (int i = 1; i <= columns; ++i) { |
|
46 |
row.put(md.getColumnName(i), rs.getObject(i)); |
|
47 |
} |
|
48 |
list.add(row); |
|
49 |
} |
|
50 |
|
|
51 |
return list; |
|
52 |
} |
|
53 |
|
|
54 |
public static List<String> fillQueryWithSearchSubstrings(List<String> queries, List<String> substrings) { |
|
55 |
List<String> preparedQueries = new ArrayList<>(); |
|
56 |
for (String query : queries) { |
|
57 |
// check if query contains sequence of substrings to fill |
|
58 |
if (query.contains("§0§")) { |
|
59 |
int counter = 0; |
|
60 |
|
|
61 |
//insert all substrings in the query |
|
62 |
for (String substring : substrings) { |
|
63 |
query = query.replaceAll("§" + counter + "§", substring); |
|
64 |
counter++; |
|
65 |
} |
|
66 |
|
|
67 |
// replacement of unused places for substrings |
|
68 |
query = query.replaceAll("§[0-9]§", "^@"); |
|
69 |
|
|
70 |
} |
|
71 |
preparedQueries.add(query); |
|
72 |
} |
|
73 |
|
|
74 |
return preparedQueries; |
|
75 |
} |
|
37 | 76 |
} |
src/main/webapp/queries/business_as_usual.sql | ||
---|---|---|
17 | 17 |
|
18 | 18 |
/* Init project id */ |
19 | 19 |
set @projectId = ?; |
20 |
/* Retrospective substring */ |
|
21 |
set @restrospectiveSubstring = '%retr%'; |
|
22 |
/* Revision substring */ |
|
23 |
set @revisionSubstring = '%revi%'; |
|
24 | 20 |
/* Number of iterations for given project */ |
25 | 21 |
select COUNT(id) as 'numberOfIterations' from iteration where superProjectId = @projectId and name like '%itera%'; |
26 | 22 |
/* Select all iteration with detected retrospective activities */ |
27 |
select iterationName as 'iterationName', count(name) as 'numberOfIssues' from workUnitView where projectId = @projectId and (name like @restrospectiveSubstring or name like @revisionSubstring or name like '%week%scrum%') group by iterationName;
|
|
23 |
select iterationName as 'iterationName', count(name) as 'numberOfIssues' from workUnitView where projectId = @projectId and (lower(name) like lower('%retr%') or lower(name) like lower('%revi%') or lower(name) like lower('%week%scrum%')) group by iterationName;
|
|
28 | 24 |
/* Select all wikipages that were created or updated in iteration and have name with retr or revi*/ |
29 |
select iteration.name as 'iterationName', count(distinct(artifactView.name)) as 'numberOfWikiPages' from artifactView inner join fieldChangeView on artifactView.id = fieldChangeView.itemId inner join iteration on (fieldChangeView.created between iteration.startDate and iteration.endDate) and iteration.superProjectId = @projectId where artifactView.projectId = @projectId and artifactView.artifactClass like 'WIKIPAGE' and (artifactView.name like '%retr%' or artifactView.description like '%retr%') group by iteration.id order by iteration.name; |
|
25 |
select iteration.name as 'iterationName', count(distinct(artifactView.name)) as 'numberOfWikiPages' from artifactView inner join fieldChangeView on artifactView.id = fieldChangeView.itemId inner join iteration on (fieldChangeView.created between iteration.startDate and iteration.endDate) and iteration.superProjectId = @projectId where artifactView.projectId = @projectId and artifactView.artifactClass like 'WIKIPAGE' and (lower(artifactView.name) like lower('%retr%') or lower(artifactView.description) like lower('%retr%') or lower(artifactView.description) like lower('%week%scrum%')) group by iteration.id order by iteration.name; |
src/main/webapp/queries/long_or_non_existent_feedback_loops.sql | ||
---|---|---|
23 | 23 |
/* Average iteration length */ |
24 | 24 |
select avg(abs(dateDiff(iteration.endDate, iteration.startDate))) as 'averageIterationLength' from iteration where superProjectId = @projectId; |
25 | 25 |
/* Select number of iterations which contains at least one feedback activity */ |
26 |
select count(*) over () as 'totalCountOfIterationsWithFeedbackActivity' from workUnitView as wuv where wuv.projectId = @projectId and (wuv.name like "%schůz%zákazník%" OR wuv.name like "%předvedení%zákazník%" OR wuv.name LIKE "%zákazn%demo%" OR wuv.name like "%schůz%zadavat%" OR wuv.name like "%inform%schůz%" OR wuv.name like "%zákazn%" OR wuv.name like "%zadavatel%") group by wuv.iterationName order by wuv.activityEndDate;
|
|
26 |
select count(*) over () as 'totalCountOfIterationsWithFeedbackActivity' from workUnitView as wuv where wuv.projectId = @projectId and (wuv.name like "§0§" or wuv.name like "§1§" or wuv.name like "§2§" or wuv.name like "§3§" or wuv.name like "§4§" or wuv.name like "§5§" or wuv.name like "§6§" or wuv.name like "§7§" or wuv.name like "§8§" or wuv.name like "§9§") group by wuv.iterationName order by wuv.activityEndDate;
|
|
27 | 27 |
/* Select all activities for feedback loop with last modified date as end date */ |
28 |
select wuv.id, wuv.iterationName, wuv.name, cast(max(fieldChangeView.created) as date) as 'endDate' from workUnitView as wuv inner join fieldChangeView on wuv.id = fieldChangeView.itemId where wuv.projectId = @projectId and (wuv.name like "%schůz%zákazník%" OR wuv.name like "%předvedení%zákazník%" OR wuv.name LIKE "%zákazn%demo%" OR wuv.name like "%schůz%zadavat%" OR wuv.name like "%inform%schůz%" OR wuv.name like "%zákazn%" OR wuv.name like "%zadavatel%") GROUP by id order by fieldChangeView.created;
|
|
28 |
select wuv.id, wuv.iterationName, wuv.name, cast(max(fieldChangeView.created) as date) as 'endDate' from workUnitView as wuv inner join fieldChangeView on wuv.id = fieldChangeView.itemId where wuv.projectId = @projectId and (wuv.name like "§0§" or wuv.name like "§1§" or wuv.name like "§2§" or wuv.name like "§3§" or wuv.name like "§4§" or wuv.name like "§5§" or wuv.name like "§6§" or wuv.name like "§7§" or wuv.name like "§8§" or wuv.name like "§9§") GROUP by id order by fieldChangeView.created;
|
|
29 | 29 |
/* Get project start date */ |
30 | 30 |
select startDate as 'projectStartDate' from iteration where superProjectId = @projectId order by startDate limit 1; |
31 | 31 |
/* Get project end date */ |
32 | 32 |
select endDate as 'projectEndDate' from iteration where superProjectId = @projectId order by endDate desc limit 1; |
33 | 33 |
/* Select all iterations that contains wiki pages which were created or updated in iteration and have name or description that mentions some key words for customer demo*/ |
34 |
select iteration.name as 'iterationWithCustomerFeedback', cast(max(fieldChangeView.created) as date) as 'appointmentDate' from artifactView inner join fieldChangeView on artifactView.id = fieldChangeView.itemId inner join iteration on (fieldChangeView.created between iteration.startDate and iteration.endDate) and iteration.superProjectId = @projectId where artifactView.artifactClass like "WIKIPAGE" and artifactView.projectId = @projectId and length(fieldChangeView.newValue) > length(fieldChangeView.oldValue) and artifactView.name like "%zápis%schůz%" or artifactView.name like "%schůz%zákazník%" OR artifactView.name like "%zákazn%demo%" or artifactView.name like "%schůz%zadavat%" or artifactView.name like "%zadavatel%" OR artifactView.name like "%zákazn%" group by iteration.name order by iteration.name; |
|
34 |
select iteration.name as 'iterationWithCustomerFeedback', cast(max(fieldChangeView.created) as date) as 'appointmentDate' from artifactView inner join fieldChangeView on artifactView.id = fieldChangeView.itemId inner join iteration on (fieldChangeView.created between iteration.startDate and iteration.endDate) and iteration.superProjectId = @projectId where artifactView.artifactClass like "WIKIPAGE" and artifactView.projectId = @projectId and length(fieldChangeView.newValue) > length(fieldChangeView.oldValue) and (artifactView.name like "§0§" or artifactView.name like "§1§" or artifactView.name like "§2§" or artifactView.name like "§3§" or artifactView.name like "§4§" or artifactView.name like "§5§" or artifactView.name like "§6§" or artifactView.name like "§7§" or artifactView.name like "§8§" or artifactView.name like "§9§") group by iteration.name order by iteration.name; |
src/main/webapp/queries/road_to_nowhere.sql | ||
---|---|---|
15 | 15 |
set @projectId = ?; |
16 | 16 |
set @firstIterationStartDate = (select startDate from iteration where superProjectId = @projectId ORDER BY startDate LIMIT 1 offset 0); |
17 | 17 |
set @secondIterationStartDate = (select startDate from iteration where superProjectId = @projectId ORDER BY startDate LIMIT 1 offset 1); |
18 |
set @numberOfIssuesForProjectPlan = (SELECT count(*) from workUnitView where projectId = @projectId and (lower(workUnitView.name) like lower('%plán projektu%') or lower(workUnitView.description) like lower('%plán projektu%') or lower(workUnitView.name) like lower('%project plan%') or lower(workUnitView.description) like lower('%project plan%') or lower(workUnitView.name) like lower('%plan project%') or lower(workUnitView.description) like lower('%plan project%') or lower(workUnitView.name) like lower('%projektový plán%') or lower(workUnitView.description) like lower('%projektový plán%')) AND (iterationStartDate = @firstIterationStartDate OR iterationStartDate = @secondIterationStartDate));
|
|
19 |
set @numberOfWikiPagesForProjectPlan = (SELECT count(*) from artifactView where projectId = @projectId AND artifactClass like 'WIKIPAGE' AND (lower(artifactView.name) like lower('%plán projektu%') or lower(artifactView.description) like lower('%plán projektu%') or lower(artifactView.name) like lower('%plán projektu%') or lower(artifactView.description) like lower('%plán projektu%') or lower(artifactView.name) like lower('%project plan%') or lower(artifactView.description) like lower('%project plan%') or lower(artifactView.name) like lower('%plan project%') or lower(artifactView.description) like lower('%plan project%') or lower(artifactView.name) like lower('%projekotvý plán%') or lower(artifactView.description) like lower('%projektový plán%')));
|
|
18 |
set @numberOfIssuesForProjectPlan = (SELECT count(*) from workUnitView where projectId = @projectId and (lower(workUnitView.name) like lower('§0§') or lower(workUnitView.description) like lower('§0§') or lower(workUnitView.name) like lower('§1§') or lower(workUnitView.description) like lower('§1§') or lower(workUnitView.name) like lower('§2§') or lower(workUnitView.description) like lower('§2§') or lower(workUnitView.name) like lower('§3§') or lower(workUnitView.description) like lower('§3§') or lower(workUnitView.name) like lower('§4§') or lower(workUnitView.description) like lower('§4§') or lower(workUnitView.name) like lower('§5§') or lower(workUnitView.description) like lower('§5§') or lower(workUnitView.name) like lower('§6§') or lower(workUnitView.description) like lower('§6§') or lower(workUnitView.name) like lower('§7§') or lower(workUnitView.description) like lower('§7§') or lower(workUnitView.name) like lower('§8§') or lower(workUnitView.description) like lower('§8§') or lower(workUnitView.name) like lower('§9§') or lower(workUnitView.description) like lower('§9§')) AND (iterationStartDate = @firstIterationStartDate OR iterationStartDate = @secondIterationStartDate));
|
|
19 |
set @numberOfWikiPagesForProjectPlan = (SELECT count(*) from artifactView where projectId = @projectId AND artifactClass like 'WIKIPAGE' AND (lower(artifactView.name) like lower('§0§') or lower(artifactView.description) like lower('§0§') or lower(artifactView.name) like lower('§1§') or lower(artifactView.description) like lower('§1§') or lower(artifactView.name) like lower('§2§') or lower(artifactView.description) like lower('§2§') or lower(artifactView.name) like lower('§3§') or lower(artifactView.description) like lower('§3§') or lower(artifactView.name) like lower('§4§') or lower(artifactView.description) like lower('§4§') or lower(artifactView.name) like lower('§5§') or lower(artifactView.description) like lower('§5§') or lower(artifactView.name) like lower('§6§') or lower(artifactView.description) like lower('§6§') or lower(artifactView.name) like lower('§7§') or lower(artifactView.description) like lower('§7§') or lower(artifactView.name) like lower('§8§') or lower(artifactView.description) like lower('§8§') or lower(artifactView.name) like lower('§9§') or lower(artifactView.description) like lower('§9§')));
|
|
20 | 20 |
select @projectId as `projectId`, @numberOfIssuesForProjectPlan as `numberOfIssuesForProjectPlan`, @numberOfWikiPagesForProjectPlan as `numberOfWikiPagesForProjectPlan`; |
src/main/webapp/queries/specify_nothing.sql | ||
---|---|---|
13 | 13 |
/* Init project id */ |
14 | 14 |
set @projectId = ?; |
15 | 15 |
/* Find number of wikipages with some project specification */ |
16 |
set @numberOfWikiPages = (select count(name) from artifactView where projectId = @projectId and artifactClass = 'WIKIPAGE' and (lower(name) like lower('%dsp%') or lower(name) like lower('%specifikace%') or lower(name) like lower('%specification%') or lower(name) like lower('%vize%proj%') or lower(name) like lower('%vize%produ%') or lower(description) like lower('%DSP%') or lower(description) like lower('%specifikace%') or lower(description) like lower('%specification%')));
|
|
16 |
set @numberOfWikiPages = (select count(name) from artifactView where projectId = @projectId and artifactClass = 'WIKIPAGE' and (lower(name) like lower('§0§') or lower(description) like lower('§0§') or lower(name) like lower('§1§') or lower(description) like lower('§1§') or lower(name) like lower('§2§') or lower(description) like lower('§2§') or lower(name) like lower('§3§') or lower(description) like lower('§3§') or lower(name) like lower('§4§') or lower(description) like lower('§4§') or lower(name) like lower('§5§') or lower(description) like lower('§5§') or lower(name) like lower('§6§') or lower(description) like lower('§6§') or lower(name) like lower('§7§') or lower(description) like lower('§7§') or lower(name) like lower('§8§') or lower(description) like lower('§8§') or lower(name) like lower('§9§') or lower(description) like lower('§9§')));
|
|
17 | 17 |
/* Find activities for creating DSP or project specification */ |
18 |
set @numberOfActivitiesForSpecification = (SELECT count(id) from workUnitView where projectId = @projectId and (lower(name) like lower('%DSP%') or lower(name) like lower('%specifikace%') or lower(name) like lower('%specification%') or lower(name) like lower('%vize%proj%')));
|
|
18 |
set @numberOfActivitiesForSpecification = (SELECT count(id) from workUnitView where projectId = @projectId and (lower(name) like lower('§0§') or lower(name) like lower('§1§') or lower(name) like lower('§2§') or lower(name) like lower('§3§') or lower(name) like lower('§4§') or lower(name) like lower('§5§') or lower(name) like lower('§6§') or lower(name) like lower('§7§') or lower(name) like lower('§8§') or lower(name) like lower('§9§')));
|
|
19 | 19 |
/* Count average length of issues description */ |
20 | 20 |
set @averageLengthOfIssueDescription = (select AVG(CHAR_LENGTH(workUnitView.description)) from workUnitView where workUnitView.projectId = @projectId); |
21 | 21 |
/* Show all statistics */ |
Také k dispozici: Unified diff
#6 Allow for String AP parameters
- sql scripts refactor for string parametrization
- added method for inserting substrings into sql queries
- substrings extracted to the AP classes
- allow reparametrization on configuration page