Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 830a7e2e

Přidáno uživatelem Michal Linha před více než 4 roky(ů)

re #8176 nothing; re #8178 added checks for data types; added table name to the generated table

Zobrazit rozdíly:

src/main/java/vldc/aswi/database/DatabaseInterface.java
95 95
     * @return List of results saved as TableColumn.
96 96
     */
97 97
    public Map<String, TableColumn> executeQueryAndReturnTableColumns(String sqlQuery) {
98
        return jdbcTemplate.query(
99
                sqlQuery,
100
                resultSet -> {
101
                    List<TableColumn> tableColumnsList = new ArrayList<>();
102

  
103
                    ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
104
                    int columnCount = resultSetMetaData.getColumnCount();
98
        try {
99
            return jdbcTemplate.query(
100
                    sqlQuery,
101
                    resultSet -> {
102
                        List<TableColumn> tableColumnsList = new ArrayList<>();
105 103

  
106
                    // The column count starts from 1.
107
                    for (int i = 1; i <= columnCount; i++ ) {
108
                        String columnName = resultSetMetaData.getColumnName(i);
109
                        tableColumnsList.add(new TableColumn(columnName));
110
                    }
104
                        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
105
                        int columnCount = resultSetMetaData.getColumnCount();
111 106

  
112
                    // Add values from row to every column.
113
                    while(resultSet.next()) {
107
                        // The column count starts from 1.
114 108
                        for (int i = 1; i <= columnCount; i++) {
115
                            tableColumnsList.get(i - 1).addValue(resultSet.getString(i));
109
                            String columnName = resultSetMetaData.getColumnName(i);
110
                            tableColumnsList.add(new TableColumn(columnName));
116 111
                        }
117
                    }
118 112

  
119
                    Map<String, TableColumn> tableColumnMap = new HashMap<>();
113
                        // Add values from row to every column.
114
                        while (resultSet.next()) {
115
                            for (int i = 1; i <= columnCount; i++) {
116
                                tableColumnsList.get(i - 1).addValue(resultSet.getString(i));
117
                            }
118
                        }
120 119

  
121
                    // Create map, where key is tablecolumn name.
122
                    for (TableColumn column : tableColumnsList) {
123
                        tableColumnMap.put(column.getName(), column);
124
                    }
120
                        Map<String, TableColumn> tableColumnMap = new HashMap<>();
125 121

  
126
                    return tableColumnMap;
127
                }
128
        );
122
                        // Create map, where key is tablecolumn name.
123
                        for (TableColumn column : tableColumnsList) {
124
                            tableColumnMap.put(column.getName(), column);
125
                        }
126

  
127
                        return tableColumnMap;
128
                    }
129
            );
130
        }
131
        catch (DataAccessException e)
132
            {
133
                // If SQL query is not valid, then JdbcTemplate returned DataAccess exception.
134
                return null;
135
            }
129 136
    }
130 137
}
src/main/java/vldc/aswi/service/ExportManagerImpl.java
41 41

  
42 42
        // Get contingency table rows.
43 43
        List<ContingencyTableRow> contingencyTableRows = this.sqlQueryManager.getContingencyTableRow(newConfiguration.getAssembly(),
44
                newConfiguration.getParametersInConfiguration(), isNotRemoveEmpty);
44
                newConfiguration.getParametersInConfiguration(), isNotRemoveEmpty, newConfiguration.getTableName());
45 45

  
46 46
        try {
47 47
            File tmpFile = null;
src/main/java/vldc/aswi/service/SqlQueryManager.java
17 17
     * @param assembly Assembly from which configuration was created.
18 18
     * @param parametersInConfiguration Parameters in configuration with their locations and operators.
19 19
     * @param isNotRemoveEmpty Sets if empty rows and columns should not be removed.
20
     * @param tableName Name of the table.
20 21
     * @return List of contingencyTableRow.
21 22
     */
22 23
    List<ContingencyTableRow> getContingencyTableRow(Assembly assembly,
23 24
                                                     List<ParameterInConfiguration> parametersInConfiguration,
24
                                                     boolean isNotRemoveEmpty);
25
                                                     boolean isNotRemoveEmpty, String tableName);
25 26

  
26 27
    /**
27 28
     * Validate given SQL query.
src/main/java/vldc/aswi/service/SqlQueryManagerImpl.java
5 5
import org.springframework.stereotype.Service;
6 6
import vldc.aswi.database.DatabaseInterface;
7 7
import vldc.aswi.domain.Assembly;
8
import vldc.aswi.domain.Configuration;
9 8
import vldc.aswi.domain.Function;
10 9
import vldc.aswi.domain.parameter.ParameterInConfiguration;
11 10
import vldc.aswi.model.table.NameUserName;
......
35 34
     * @param assembly Assembly from which configuration was created.
36 35
     * @param parametersInConfiguration Parameters in configuration with their locations and operators.
37 36
     * @param isNotRemoveEmpty Sets if empty rows and columns should not be removed.
38
     * @return List of contingencyTableRow.
37
     * @param tableName Name of the table.
38
     * @return List of contingencyTableRow or null, if error in SQL query occurred.
39 39
     */
40 40
    @Override
41 41
    public List<ContingencyTableRow> getContingencyTableRow(Assembly assembly,
42 42
                                                            List<ParameterInConfiguration> parametersInConfiguration,
43
                                                            boolean isNotRemoveEmpty) {
43
                                                            boolean isNotRemoveEmpty, String tableName) {
44 44
        long startTime = System.nanoTime();
45 45

  
46 46
        Map<String, TableColumn> tableColumns = this.databaseInterface.executeQueryAndReturnTableColumns(
47 47
                generateFullSQLQuery(assembly.getSQLQuery(), parametersInConfiguration)
48 48
        );
49 49

  
50
        if (tableColumns == null) {
51
            return null;
52
        }
53

  
54
        if (tableColumns.values().iterator().next().getValues().size() == 0) {
55
            return new ArrayList<>();
56
        }
57

  
50 58
        long stopTime = System.nanoTime();
51 59
        System.out.println("Select:" + TimeUnit.MILLISECONDS.convert((stopTime - startTime), TimeUnit.NANOSECONDS));
52 60
        List<NameUserName> rowNames = new ArrayList<>();
......
61 69

  
62 70
        initializeContingencyTableDataLists(rowNames, columnNames, valueFunctions, copiedParametersInConfiguration);
63 71

  
64
        Converter converter = new Converter(tableColumns, rowNames, columnNames, valueFunctions, isNotRemoveEmpty);
72
        Converter converter = new Converter(tableColumns, rowNames, columnNames, valueFunctions, isNotRemoveEmpty, tableName);
65 73
        return converter.convertTableColumnsToContingencyTableRows();
66 74
    }
67 75

  
......
84 92
        return this.databaseInterface.getNameOfColumnsFromQuery(sqlQuery);
85 93
    }
86 94

  
95
    /**
96
     * Initializes list with values.
97
     * @param rowNames List of selected rows.
98
     * @param columnNames List of selected columns.
99
     * @param valueFunctions List of selected values and functions.
100
     * @param parametersInConfiguration List of parameters in configuration.
101
     */
87 102
    private void initializeContingencyTableDataLists(List<NameUserName> rowNames, List<NameUserName> columnNames,
88 103
                                                     List<ValueFunction> valueFunctions, List<ParameterInConfiguration> parametersInConfiguration) {
89 104
        for (ParameterInConfiguration parameterInConfiguration : parametersInConfiguration) {
......
151 166
    }
152 167

  
153 168
    /**
154
     * Precesses listing (enum) type.
169
     * Processes listing (enum) type.
155 170
     * @param parameterInConfiguration Listing type parameter iin configuration.
156 171
     * @param finalSQLQuery Resulting SQL query.
157 172
     * @param isWhereDefined Variable storing information if WHERE clause was defined in the resulting SQL query.
......
240 255
        StringBuilder SQLQueryPart = new StringBuilder();
241 256
        SQLQueryPart.append("(");
242 257
        for (int i = 0; i < values.length; i++) {
258
            if (type.equals("Datum")) {
259
                SQLQueryPart.append("date ");
260
            }
261

  
243 262
            addQuotes(type, SQLQueryPart);
244 263
            SQLQueryPart.append(values[i]);
245 264
            addQuotes(type, SQLQueryPart);
......
261 280
    private String betweenNotBetween(String[] values, String type) {
262 281
        StringBuilder SQLQueryPart = new StringBuilder();
263 282

  
283
        if (type.equals("Datum")) {
284
            SQLQueryPart.append("date ");
285
        }
286

  
264 287
        addQuotes(type, SQLQueryPart);
265 288
        SQLQueryPart.append(values[0]);
266 289
        addQuotes(type, SQLQueryPart);
267 290

  
268 291
        SQLQueryPart.append(" AND ");
269 292

  
293
        if (type.equals("Datum")) {
294
            SQLQueryPart.append("date ");
295
        }
296

  
270 297
        addQuotes(type, SQLQueryPart);
271 298
        SQLQueryPart.append(values[1]);
272 299
        addQuotes(type, SQLQueryPart);
......
283 310
    private String otherOperators(String[] values, String type) {
284 311
        StringBuilder SQLQueryPart = new StringBuilder();
285 312

  
313
        if (type.equals("Datum")) {
314
            SQLQueryPart.append("date ");
315
        }
316

  
286 317
        addQuotes(type, SQLQueryPart);
287 318
        SQLQueryPart.append(values[0]);
288 319
        addQuotes(type, SQLQueryPart);
src/main/java/vldc/aswi/utils/Converter.java
8 8
import java.util.ArrayList;
9 9
import java.util.List;
10 10
import java.util.Map;
11
import java.util.Stack;
11 12
import java.util.concurrent.TimeUnit;
12 13

  
13 14
/**
......
15 16
 */
16 17
public class Converter {
17 18

  
19
    /**
20
     * Name of the table
21
     */
22
    private final String tableName;
23

  
18 24
    /**
19 25
     * Stores information about whether user set switch to show empty rows and columns to ON.
20 26
     */
......
57 63
     * @param columnNames List of names and user names of selected columns.
58 64
     * @param valueFunctions List of information about selected value and functions.
59 65
     * @param isNotRemoveEmpty Stores information about whether user set switch to show empty rows and columns to ON.
66
     * @param tableName Name of the table.
60 67
     */
61 68
    public Converter(Map<String, TableColumn> tableColumns, List<NameUserName> rowNames, List<NameUserName> columnNames,
62
                     List<ValueFunction> valueFunctions, boolean isNotRemoveEmpty) {
69
                     List<ValueFunction> valueFunctions, boolean isNotRemoveEmpty, String tableName) {
63 70
        this.tableColumns = tableColumns;
64 71
        this.rowNames = rowNames;
65 72
        this.columnNames = columnNames;
66 73
        this.valueFunctions = valueFunctions;
67 74
        this.isNotRemoveEmpty = isNotRemoveEmpty;
75
        this.tableName = tableName;
68 76
    }
69 77

  
70 78
    /**
......
148 156
            ContingencyTableRow headerRow = headerRows.get(i);
149 157

  
150 158
            if (i == 0) {
151
                headerRow.addTableRowCell(new ContingencyTableRowCell("Tabulka", 1));
159
                headerRow.addTableRowCell(new ContingencyTableRowCell(tableName, 1));
152 160
            }
153 161
            else {
154 162
                headerRow.addTableRowCell(new ContingencyTableRowCell("", 1));
155 163
            }
156 164
        }
157 165

  
158

  
159
        List<String> prevValues = new ArrayList<>();
160
        int prevSize = 0;
161
        for (ValueFunction valueFunction : valueFunctions) {
166
        List<String> prevValues = new ArrayList<>(); // values that were visited
167
        int prevSize = 0; // number of previous column node values
168
        for (ValueFunction valueFunction : valueFunctions) { // for each function
169
            // add cell with the function name and value name to the 0th row with span 0
162 170
            headerRows.get(0).addTableRowCell(new ContingencyTableRowCell(valueFunction.getFunction() + " z " + valueFunction.getParameterName(), 0));
163
            for (Node columnNode : columnNodes) {
164
                for (int i = 0; i < columnNode.getValues().size(); i++) {
171
            for (Node columnNode : columnNodes) { // for each column
172
                for (int i = 0; i < columnNode.getValues().size(); i++) { // for each value in column
165 173
                    String value = columnNode.getValues().get(i);
166
                    if (!prevValues.contains(value)) {
174
                    // check if value is not in the visited list, if list size equals i, the value is not visited
175
                    // eg. i = 0 -> no values in the list, if list size is bigger than i, there are more values than i
176
                    // so then check if value at ith position is not equal to the current value (is not visited)
177
                    if (prevValues.size() == i || (prevValues.size() > i && !prevValues.get(i).equals(value))) {
167 178
                        prevValues.add(value);
179
                        // add cell with value with span 0 to the i + 1th row (0th is for function name and value name cells)
168 180
                        headerRows.get(i + 1).addTableRowCell(new ContingencyTableRowCell(columnNames.get(i).getUserName() + " - " + value, 1));
181
                        // add 1 to the span of the last added function and value name cell
169 182
                        headerRows.get(0).getCells().get(headerRows.get(0).getCells().size() - 1).setColSpan(headerRows.get(0).getCells().get(headerRows.get(0).getCells().size() - 1).getColSpan() + 1);
170 183
                    } else if (columnNode.getValues().size() >= prevSize) {
184
                        // add 1 to the span of the last added cell of the row of i + 1th value
171 185
                        headerRows.get(i + 1).getCells().get(headerRows.get(i + 1).getCells().size() - 1).setColSpan(headerRows.get(i + 1).getCells().get(headerRows.get(i + 1).getCells().size() - 1).getColSpan() + 1);
172 186
                    }
173 187
                }
174 188

  
175
                if (columnNode.getValues().size() < prevSize) {
189
                if (columnNode.getValues().size() < prevSize) { // if there are less values than in previous column node
176 190
                    for (int s = prevSize; s < headerRows.size(); s++) {
191
                        // add blank cell to the rows bellow
177 192
                        headerRows.get(s).addTableRowCell(new ContingencyTableRowCell("", 1));
178 193
                    }
179 194
                    for (int s = 1; s < columnNode.getValues().size(); s++) {
195
                        // add 1 to colspan to the cells above
180 196
                        headerRows.get(s).getCells().get(headerRows.get(s).getCells().size() - 1).setColSpan(headerRows.get(s).getCells().get(headerRows.get(s).getCells().size() - 1).getColSpan() + 1);
181 197
                    }
198
                    // create cell for total values (not for lists of the tree)
182 199
                    headerRows.get(columnNode.getValues().size()).addTableRowCell(new ContingencyTableRowCell(columnNode.getValues().get(columnNode.getValues().size() - 1) + " Celkem", 1));
183 200
                }
184 201

  
185 202
                prevSize = columnNode.getValues().size();
186 203

  
187 204
                if (!prevValues.isEmpty()) {
188
                    prevValues.remove(prevValues.size() - 1);
205
                    prevValues.remove(prevValues.size() - 1); // remove last value
189 206
                }
190 207
            }
191 208
        }
......
203 220

  
204 221
    /**
205 222
     * Gets original values of a given list.
206
     * @param list list from which original values should be taken
207
     * @return list of original values
223
     * @param list List from which original values should be taken.
224
     * @return List of original values.
208 225
     */
209 226
    private List<String> getOriginalValuesFromList(List<String> list) {
210 227
        List<String> origList = new ArrayList<>();
......
220 237

  
221 238
    /**
222 239
     * Creates data rows.
223
     * @return list of contingency table rows
240
     * @return List of contingency table rows.
224 241
     */
225 242
    private List<ContingencyTableRow> createDataRows() {
226 243
        List<ContingencyTableRow> dataRows = new ArrayList<>();
......
237 254
        long stopTime = System.nanoTime();
238 255
        System.out.println("Rows List:" + TimeUnit.MILLISECONDS.convert((stopTime - startTime), TimeUnit.NANOSECONDS));
239 256

  
257
        // loop through all generated rows and store unusable rows to the list rowsToBeRemoved
240 258
        List<ContingencyTableRow> rowsToBeRemoved = new ArrayList<>();
241 259
        for (int i = 0; i < dataRows.size(); i++) {
242 260
            if (!fillRowWithData(dataRows.get(i), rowNodes.get(i))) {
......
244 262
            }
245 263
        }
246 264

  
265
        // remove unusable rows
247 266
        dataRows.removeAll(rowsToBeRemoved);
248 267

  
268
        // create final row (row with total values of each column)
249 269
        if (valueFunctions.get(0).getFunction() != null && (!valueFunctions.get(0).getFunction().equals("NIC") ||
250 270
                (valueFunctions.get(0).getFunction().equals("NIC") && columnNames.size() > 0))) {
251 271
            dataRows.add(createFinalRow());
......
256 276

  
257 277
    /**
258 278
     * Recursively generates all possible row combinations, sorted as in contingency table.
259
     * @param rows list of sorted contingency table rows
260
     * @param index index in the values list
261
     * @param values list of lists of values of each query row
262
     * @param rowNodes list of row nodes
263
     * @param prevNode parent node of the nodes
279
     * @param rows List of sorted contingency table rows.
280
     * @param index Index in the values list.
281
     * @param values List of lists of values of each query row.
282
     * @param rowNodes List of row nodes.
283
     * @param prevNode Parent node of the nodes.
264 284
     */
265 285
    private void generateRows(List<ContingencyTableRow> rows, int index, List<List<String>> values, List<Node> rowNodes,
266 286
                              Node prevNode) {
......
268 288
            List<String> list = values.get(index);
269 289
            for (String s : list) {
270 290
                StringBuilder levelString = new StringBuilder();
291
                // add indent if row value has index higher than 0
271 292
                for (int i = 0; i < index; i++) {
272 293
                    levelString.append("      ");
273 294
                }
......
276 297
                row.addTableRowCell(new ContingencyTableRowCell(levelString.toString(), 1));
277 298
                rows.add(row);
278 299
                Node node = new Node(prevNode);
300
                // save a value from a chosen row
279 301
                node.getValues().add(s);
302
                // visit (save) root
280 303
                rowNodes.add(node);
281 304
                int newIndex = index + 1;
305
                // visit sub tree
282 306
                generateRows(rows, newIndex, values, rowNodes, node);
283 307
            }
284 308
        }
......
286 310

  
287 311
    /**
288 312
     * Recursively generates all possible column combinations, sorted as in contingency table.
289
     * @param index index in the values list
290
     * @param values list of lists of values of each query row
291
     * @param columnNodes list of column nodes
292
     * @param prevNode parent node of the nodes
313
     * @param index Index in the values list.
314
     * @param values List of lists of values of each query row.
315
     * @param columnNodes List of column nodes.
316
     * @param prevNode Parent node of the nodes.
293 317
     */
294 318
    private void generateColumns(int index, List<List<String>> values, List<Node> columnNodes, Node prevNode) {
295 319
        if (index < values.size()) {
296 320
            List<String> list = values.get(index);
297 321
            for (String s : list) {
298 322
                Node node = new Node(prevNode);
323
                // save a value from a chosen column
299 324
                node.getValues().add(s);
300 325
                if (isNotRemoveEmpty) {
301 326
                    int newIndex = index + 1;
327
                    // first visit all subtrees
302 328
                    generateColumns(newIndex, values, columnNodes, node);
329
                    // visit (save) root
303 330
                    columnNodes.add(node);
304 331
                }
305 332
                else if (checkIfColumnIsUsable(node.getValues())) {
306 333
                    int newIndex = index + 1;
334
                    // first visit all subtrees
307 335
                    generateColumns(newIndex, values, columnNodes, node);
336
                    // visit (save) root
308 337
                    columnNodes.add(node);
309 338
                }
310 339
            }
......
313 342

  
314 343
    /**
315 344
     * Fills each data row with data.
316
     * @param row row to ne filled with data
317
     * @param node node of the row
345
     * @param row Row to be filled with data.
346
     * @param rowNode Node of the row.
318 347
     */
319
    private boolean fillRowWithData(ContingencyTableRow row, Node node) {
348
    private boolean fillRowWithData(ContingencyTableRow row, Node rowNode) {
320 349
        if (valueFunctions.size() == 0) {
321 350
            return true;
322 351
        }
323 352

  
324 353
        boolean isSingleValueRow = false;
325 354

  
326
        if (node.getValues().size() <= 1) {
355
        // check if row is a root (single) value
356
        if (rowNode.getValues().size() <= 1) {
327 357
            isSingleValueRow = true;
328 358
        }
329 359

  
360
        // stores if row is usable
330 361
        boolean isRowUsable = false;
362

  
363
        // if user selected an option to show all rows and columns, set that row is always usable
331 364
        if (isNotRemoveEmpty) {
332 365
            isRowUsable = true;
333 366
        }
334 367

  
368
        // if no columns or functions were selected
335 369
        if (columnNodes.size() == 0) {
336 370
            columnNodes.add(new Node());
337 371
        }
338 372

  
339
        List<Integer> usableIDs = getUsableIDs(node);
373
        // load the list of usable original row IDs
374
        List<Integer> usableIDs = getUsableIDs(rowNode.getValues());
340 375

  
341 376
        if (valueFunctions.get(0).getFunction() != null && valueFunctions.get(0).getFunction().equals("NIC") &&
342
                !usableIDs.isEmpty()) {
377
                !usableIDs.isEmpty()) { // return that row is usable because it is used for list generation
343 378
            return true;
344 379
        }
345 380
        else if (valueFunctions.get(0).getFunction() != null && valueFunctions.get(0).getFunction().equals("NIC") &&
346
                usableIDs.isEmpty()) {
381
                usableIDs.isEmpty()) { // no function selected and no usable rows in original return if row is usable
347 382
            return isRowUsable;
348 383
        }
349 384

  
385
        // array of total values for functions
350 386
        DoubleWrapper[] totals = new DoubleWrapper[valueFunctions.size()];
351 387
        initializeDoubleWrapperField(totals);
352 388

  
389
        // array of total sum values for functions if functions are AVG
353 390
        DoubleWrapper[] totalsAvgSum = new DoubleWrapper[valueFunctions.size()];
354 391
        initializeDoubleWrapperField(totalsAvgSum);
355 392

  
393
        // array that stores if total value cell will be filled or left blank for current row and each function
356 394
        boolean[] isFilledValueCells = new boolean[valueFunctions.size()];
357
        //hodnota
395
        // for each function
358 396
        for (int v = 0; v < valueFunctions.size(); v++) {
397
            // if function has not been selected
359 398
            if (valueFunctions.get(v).getFunction() != null && (valueFunctions.get(v).getFunction().equals("") ||
360 399
                    valueFunctions.get(v).getFunction().equals("NIC"))) {
361 400
                isRowUsable = true;
362 401
                break;
363 402
            }
403

  
404
            // stores if first MIN or MAX total value was saved for current function
364 405
            BooleanWrapper isFirstMinMaxTotal = new BooleanWrapper(true);
406

  
365 407
            ValueFunction valueFunction = valueFunctions.get(v);
366
            //sloupec v kont. tabulce
408
            // for each contingency table column
367 409
            for (Node columnNode : columnNodes) {
410
                // result that will be stored in a cell given by row and column rowNode
368 411
                DoubleWrapper result = new DoubleWrapper(0);
412
                // sum result used to calculate AVG result in a cell given by row and column rowNode
369 413
                DoubleWrapper resultAvgSum = new DoubleWrapper(0);
414
                // stores if first MIN or MAX value was saved for current cell
370 415
                BooleanWrapper isFirstMinMax = new BooleanWrapper(true);
416
                // stores if a cell will be filled or left blank
371 417
                boolean isFilledCell = false;
372
                // radek v orig. tabulce
418
                // for each usable row
373 419
                for (Integer usableID : usableIDs) {
374 420
                    boolean isUsable = true;
421
                    // index of selected row
375 422
                    int j;
376
                    // zvoleny sloupec ze sloupcu, ziska hodnoty z pouzitelne radky danych sloupcu originalni tabulky a
377
                    // pokud se vsechny rovnaji hodnotam, ktere jsou ulozeny v hodnotach uzlu na pozici vybraneho
378
                    // sloupce, je kommbinace pouzitelna k vypoctum
423
                    // check if values of the contingency table column rowNode are present in the row (at usableID position
424
                    // of original table) for columns that belong to column rowNode
379 425
                    for (j = 0; j < columnNode.getValues().size(); j++) {
380 426
                        if (!tableColumns.get(columnNames.get(j).getName()).getValues().get(usableID).equals(columnNode.getValues().get(j))) {
381 427
                            isUsable = false;
......
383 429
                        }
384 430
                    }
385 431

  
386
                    // zvoleny sloupec z hodnot
432
                    // selected column from value
387 433
                    if (tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID) == null) {
388 434
                        isUsable = false;
389 435
                    }
390 436

  
391
                    if (isUsable) { // pokud lze hodnotu pouzit, prunik vsech hodnot sedi (ma nejakou hodnotu)
437
                    // if value is usable, "intersect" of values from contingency table row and column, and value is true
438
                    if (isUsable) {
392 439
                        columnNode.setUsable(true);
393 440
                        isRowUsable = true;
394 441
                        isFilledCell = true;
395 442
                        computeValues(valueFunction, result, resultAvgSum, columnNode, isFirstMinMax,
396 443
                                usableID, false, isSingleValueRow);
444
                        // row is a root (single) value, save the result to the total function value cell
397 445
                        if (j <= 1) {
398 446
                            isFilledValueCells[v] = true;
399 447
                            computeValues(valueFunction, totals[v], totalsAvgSum[v], null, isFirstMinMaxTotal,
......
401 449
                        }
402 450
                    }
403 451
                }
452
                // if cell should be blank, add empty value
404 453
                if (!isFilledCell) {
405 454
                    row.addTableRowCell(new ContingencyTableRowCell("", 0));
406 455
                }
407
                else {
456
                else { // generate a cell with a value
408 457
                    columnNode.setFilledTotalValue(true);
409 458
                    row.addTableRowCell(generateFilledCell(valueFunction.getFunction(), result.getValue(), result.getValue(), result.getValue(),
410 459
                            result.getValue(), resultAvgSum.getValue(), result.getValue()));
411 460
                }
412 461
            }
413 462
        }
463
        // generate cell for total function values
414 464
        for (int i = 0; i < valueFunctions.size(); i++) {
415 465
            if (valueFunctions.get(i).getFunction() != null && valueFunctions.get(i).getFunction().equals("NIC")) {
416 466
                break;
417 467
            }
468
            // if cell should be blank, add empty value
418 469
            if (!isFilledValueCells[i]) {
419 470
                row.addTableRowCell(new ContingencyTableRowCell("", 0));
420 471
            }
421
            else {
472
            else { // generate a cell with a value
422 473
                valueFunctions.get(i).setFilledTotalValue(true);
423 474
                row.addTableRowCell(generateFilledCell(valueFunctions.get(i).getFunction(), totals[i].getValue(), totals[i].getValue(),
424 475
                        totals[i].getValue(), totals[i].getValue(), totalsAvgSum[i].getValue(), totals[i].getValue()));
425 476
            }
426 477
        }
427 478

  
479
        // returns if row should be visible in the contingency table
428 480
        return isRowUsable;
429 481
    }
430 482

  
431 483
    /**
432 484
     * Gets a list of IDs of the query rows that fit the contingency table row settings.
433
     * @param node node of the row
434
     * @return list of usable IDs
485
     * @param rowNodeValues Values of a row node.
486
     * @return List of usable row IDs.
435 487
     */
436
    private List<Integer> getUsableIDs(Node node) {
488
    private List<Integer> getUsableIDs(List<String> rowNodeValues) {
437 489
        List<Integer> ids = new ArrayList<>();
438 490

  
491
        // for each row in original table
439 492
        for (int i = 0; i < tableColumns.get(rowNames.get(0).getName()).getValues().size(); i++) {
440 493
            boolean isUsable = true;
441
            for (int j = 0; j < node.getValues().size(); j++) {
442
                if (!tableColumns.get(rowNames.get(j).getName()).getValues().get(i).equals(node.getValues().get(j))) {
494
            // check if a row has values that are stored in the row node (for each chosen row)
495
            for (int j = 0; j < rowNodeValues.size(); j++) {
496
                if (!tableColumns.get(rowNames.get(j).getName()).getValues().get(i).equals(rowNodeValues.get(j))) {
443 497
                    isUsable = false;
444 498
                    break;
445 499
                }
......
458 512
     * @return True if all values of a node are present in the original table columns.
459 513
     */
460 514
    private boolean checkIfColumnIsUsable(List<String> columnNodeValues) {
515
        // for each row in original table
461 516
        for (int i = 0; i < tableColumns.get(columnNames.get(0).getName()).getValues().size(); i++) {
462 517
            boolean isUsable = true;
518
            // check if a row has values that are stored in the column node (for each chosen column)
463 519
            for (int j = 0; j < columnNodeValues.size(); j++) {
464 520
                if (!tableColumns.get(columnNames.get(j).getName()).getValues().get(i).equals(columnNodeValues.get(j))) {
465 521
                    isUsable = false;
......
477 533

  
478 534
    /**
479 535
     * Computes value of the cell in regards to function.
480
     * @param valueFunction Function that should be computed for a cell.
536
     * @param valueFunction Column from which value should be taken and a function used and other info.
481 537
     * @param result Variable to which result is saved.
482 538
     * @param resultAvgSum Variable to which sum is saved of a function is AVG.
483 539
     * @param columnNode Column node of a cell.
......
559 615

  
560 616
    /**
561 617
     * Calculates COUNT function.
562
     * @param valueFunction Function that should be computed for a cell.
618
     * @param valueFunction Column from which value should be taken and other info.
563 619
     * @param result Variable to which result is saved.
564 620
     * @param columnNode Column node of a cell.
565 621
     * @param isValueTotal Tells if a value is total value for the given function.
......
578 634

  
579 635
    /**
580 636
     * Calculates SUM function.
581
     * @param valueFunction Function that should be computed for a cell.
637
     * @param valueFunction Column from which value should be taken and other info.
582 638
     * @param result Variable to which result is saved.
583 639
     * @param columnNode Column node of a cell.
584 640
     * @param usableID ID of the row in the original table.
......
588 644
    private void sum(ValueFunction valueFunction, DoubleWrapper result, Node columnNode, int usableID, boolean isValueTotal,
589 645
                     boolean isSingleValueRow) {
590 646
        if (valueFunction.getType().equals("Číslo")) {
591
            result.setValue(result.getValue() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
647
            double res = getDoubleValueFromTableCell(valueFunction, usableID);
648
            result.setValue(result.getValue() + res);
592 649
            if (columnNode != null && isSingleValueRow) {
593
                columnNode.setTotalResultSum(columnNode.getTotalResultSum() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
650
                columnNode.setTotalResultSum(columnNode.getTotalResultSum() + res);
594 651
            }
595 652
            if (isValueTotal && isSingleValueRow) {
596
                valueFunction.setTotalResultSum(valueFunction.getTotalResultSum() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
653
                valueFunction.setTotalResultSum(valueFunction.getTotalResultSum() + res);
597 654
            }
598 655
        }
599 656
    }
600 657

  
601 658
    /**
602 659
     * Calculates MIN function.
603
     * @param valueFunction Function that should be computed for a cell.
660
     * @param valueFunction Column from which value should be taken and other info.
604 661
     * @param result Variable to which result is saved.
605 662
     * @param columnNode Column node of a cell.
606 663
     * @param isFirstMinMax Tells if the counted value is the first value of the MIN or MAX function.
......
611 668
    private void min(ValueFunction valueFunction, DoubleWrapper result, Node columnNode, BooleanWrapper isFirstMinMax,
612 669
                     int usableID, boolean isValueTotal, boolean isSingleValueRow) {
613 670
        if (valueFunction.getType().equals("Číslo")) {
671
            double res = getDoubleValueFromTableCell(valueFunction, usableID);
672
            // if min value of the cell has not been stored yet
614 673
            if (isFirstMinMax.isValue()) {
615 674
                isFirstMinMax.setValue(false);
616
                result.setValue(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
675
                result.setValue(res);
617 676
            }
618 677
            else {
619
                result.setValue(Math.min(result.getValue(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
678
                result.setValue(Math.min(result.getValue(), res));
620 679
            }
621 680
            if (columnNode != null && isSingleValueRow) {
681
                // if min value of the entire column has not been stored yet
622 682
                if (columnNode.isFirstMin()) {
623 683
                    columnNode.setFirstMin(false);
624
                    columnNode.setTotalMin(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
684
                    columnNode.setTotalMin(res);
625 685
                } else {
626
                    columnNode.setTotalMin(Math.min(columnNode.getTotalMin(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
686
                    columnNode.setTotalMin(Math.min(columnNode.getTotalMin(), res));
627 687
                }
628 688
            }
629 689
            if (isValueTotal && isSingleValueRow) {
690
                // if min value of the entire value column has not been stored yet
630 691
                if (valueFunction.isFirstMin()) {
631 692
                    valueFunction.setFirstMin(false);
632
                    valueFunction.setTotalMin(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
693
                    valueFunction.setTotalMin(res);
633 694
                } else {
634
                    valueFunction.setTotalMin(Math.min(valueFunction.getTotalMin(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
695
                    valueFunction.setTotalMin(Math.min(valueFunction.getTotalMin(), res));
635 696
                }
636 697
            }
637 698
        }
......
639 700

  
640 701
    /**
641 702
     * Calculates MAX function.
642
     * @param valueFunction Function that should be computed for a cell.
703
     * @param valueFunction Column from which value should be taken and other info.
643 704
     * @param result Variable to which result is saved.
644 705
     * @param columnNode Column node of a cell.
645 706
     * @param isFirstMinMax Tells if the counted value is the first value of the MIN or MAX function.
......
650 711
    private void max(ValueFunction valueFunction, DoubleWrapper result, Node columnNode, BooleanWrapper isFirstMinMax,
651 712
                     int usableID, boolean isValueTotal, boolean isSingleValueRow) {
652 713
        if (valueFunction.getType().equals("Číslo")) {
714
            double res = getDoubleValueFromTableCell(valueFunction, usableID);
653 715
            if (isFirstMinMax.isValue()) {
716
                // if max value of the cell has not been stored yet
654 717
                isFirstMinMax.setValue(false);
655
                result.setValue(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
718
                result.setValue(res);
656 719
            }
657 720
            else {
658
                result.setValue(Math.max(result.getValue(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
721
                result.setValue(Math.max(result.getValue(), res));
659 722
            }
660 723
            if (columnNode != null && isSingleValueRow) {
724
                // if max value of the entire column has not been stored yet
661 725
                if (columnNode.isFirstMax()) {
662 726
                    columnNode.setFirstMax(false);
663
                    columnNode.setTotalMax(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
727
                    columnNode.setTotalMax(res);
664 728
                } else {
665
                    columnNode.setTotalMax(Math.max(columnNode.getTotalMax(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
729
                    columnNode.setTotalMax(Math.max(columnNode.getTotalMax(), res));
666 730
                }
667 731
            }
668 732
            if (isValueTotal && isSingleValueRow) {
733
                // if max value of the entire value column has not been stored yet
669 734
                if (valueFunction.isFirstMax()) {
670 735
                    valueFunction.setFirstMax(false);
671
                    valueFunction.setTotalMax(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
736
                    valueFunction.setTotalMax(res);
672 737
                } else {
673
                    valueFunction.setTotalMax(Math.max(valueFunction.getTotalMax(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
738
                    valueFunction.setTotalMax(Math.max(valueFunction.getTotalMax(), res));
674 739
                }
675 740
            }
676 741
        }
......
678 743

  
679 744
    /**
680 745
     * Calculates AVG function.
681
     * @param valueFunction Function that should be computed for a cell.
746
     * @param valueFunction Column from which value should be taken and other info.
682 747
     * @param result Variable to which count result is saved.
683 748
     * @param resultAvgSum Variable to which sum result is saved.
684 749
     * @param columnNode Column node of a cell.
......
689 754
    private void average(ValueFunction valueFunction, DoubleWrapper result, DoubleWrapper resultAvgSum, Node columnNode,
690 755
                         int usableID, boolean isValueTotal, boolean isSingleValueRow) {
691 756
        if (valueFunction.getType().equals("Číslo")) {
757
            double res = getDoubleValueFromTableCell(valueFunction, usableID);
692 758
            result.setValue(result.getValue() + 1);
693
            resultAvgSum.setValue(resultAvgSum.getValue() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
759
            resultAvgSum.setValue(resultAvgSum.getValue() + res);
694 760
            if (columnNode != null && isSingleValueRow) {
695 761
                columnNode.setTotalResultAvg(columnNode.getTotalResultAvg() + 1);
696
                columnNode.setTotalResultAvgSum(columnNode.getTotalResultAvgSum() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
762
                columnNode.setTotalResultAvgSum(columnNode.getTotalResultAvgSum() + res);
697 763
            }
698 764
            if (isValueTotal && isSingleValueRow) {
699 765
                valueFunction.setTotalResultAvg(valueFunction.getTotalResultAvg() + 1);
700
                valueFunction.setTotalResultAvgSum(valueFunction.getTotalResultAvgSum() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
766
                valueFunction.setTotalResultAvgSum(valueFunction.getTotalResultAvgSum() + res);
701 767
            }
702 768
        }
703 769
    }
704 770

  
771
    /**
772
     * Gets double value from a cell in a value column and usableID row in an original table
773
     * @param valueFunction Column from which value should be taken and other info.
774
     * @param usableID ID of the row in the original table.
775
     * @return Parsed double value.
776
     */
777
    private double getDoubleValueFromTableCell(ValueFunction valueFunction, int usableID) {
778
        double res;
779
        try {
780
            res = Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID));
781
        }
782
        catch (Exception e) {
783
            res = Double.NaN;
784
        }
785

  
786
        return res;
787
    }
788

  
705 789
    /**
706 790
     * Generates a final row, with total values of columns.
707 791
     * @return Final row filled with data.
......
715 799
        }
716 800

  
717 801
        List<ContingencyTableRowCell> valueCells = new ArrayList<>();
802
        // for each selected function
718 803
        for (ValueFunction valueFunction : valueFunctions) {
804
            //for each column
719 805
            for (Node columnNode : columnNodes) {
720 806
                if (columnNode.isFilledTotalValue()) {
721 807
                    finalRow.addTableRowCell(generateFilledCell(valueFunction.getFunction(), columnNode.getTotalResult(), columnNode.getTotalResultSum(),
......
736 822
            }
737 823
        }
738 824

  
825
        // append value cells to the end
739 826
        finalRow.addTableRowCells(valueCells);
740 827

  
741 828
        return finalRow;
src/main/java/vldc/aswi/validators/ConfigurationValidator.java
69 69
     * @param operator Operator of the parameter in configuration.
70 70
     */
71 71
    private void validateBETWEEN(ParameterInConfiguration parameterInConfiguration, Errors errors, int i, String operator) {
72
        if (!parameterInConfiguration.getOperatorValue().matches("\\w+;\\w+")) {
72
        if (!parameterInConfiguration.getOperatorValue().matches(".+;.+")) {
73 73
            errors.rejectValue("parametersInConfiguration[" + i + "].operatorValue", "Nesprávně oddělené hodnoty" +
74 74
                    " filtru " + operator +"! Použijte ';' pro oddělení hodnot!");
75 75
        }
......
105 105
     * @param operator Operator of the parameter in configuration.
106 106
     */
107 107
    private void validateIN(ParameterInConfiguration parameterInConfiguration, Errors errors, int i, String operator) {
108
        if (!parameterInConfiguration.getOperatorValue().matches("\\w+(;\\w+)*$")) {
108
        if (!parameterInConfiguration.getOperatorValue().matches(".+(;.+)*$")) {
109 109
            errors.rejectValue("parametersInConfiguration[" + i + "].operatorValue", "Špatně zadaná hodnota" +
110 110
                    " filtru " + operator + "!  Použijte ';' pro oddělení hodnot!");
111 111
        }
src/main/java/vldc/aswi/web/controller/AssemblyController.java
157 157
     * Post method for form, where configuration is created from assembly.
158 158
     * @param newConfiguration - Configuration values.
159 159
     * @param bindingResult - Error results from assembly validators.
160
     * @param atts Attributes.
161
     * @param isNotRemoveEmptyString String that stores if switch to not remove empty rows and columns was set.
162
     * @param id ID of the assembly.
163
     * @param generateTable String used to check if generate table button was clicked.
164
     * @param exportPdf String used to check if export to PDF button was clicked.
165
     * @param exportXlsx String used to check if export to XLSX button was clicked.
166
     * @param redirectAttributes Attributes.
167
     * @param saveConfiguration String used to check if save configuration button was clicked.
168
     * @param response HTTP servlet response.
160 169
     * @return ModelAndView for assembly.
161 170
     */
162 171
    @PostMapping("/assembly")
......
207 216
            }
208 217
            else {
209 218
                List<ContingencyTableRow> rows = this.sqlQueryManager.getContingencyTableRow(newConfiguration.getAssembly(),
210
                        newConfiguration.getParametersInConfiguration(), isNotRemoveEmpty);
211

  
212
                modelMap.addAttribute("configurationID", id);
213
                modelMap.addAttribute("contingencyTableRows", rows);
214
                modelMap.addAttribute("isNotRemoveEmpty", isNotRemoveEmpty);
215
                addConfigurationDataIntoModelAndView(newConfiguration, modelAndView, modelMap);
219
                        newConfiguration.getParametersInConfiguration(), isNotRemoveEmpty, newConfiguration.getTableName());
220

  
221
                if (rows != null) {
222
                    if (rows.isEmpty()) {
223
                        modelMap.addAttribute(assemblyErrorName, "Výsledná tabulka neobsahuje žádné hodnoty (" +
224
                                "SQL dotaz nevrátil žádné řádky)!");
225
                        modelMap.addAttribute(assemblyTitleName, generateTableTitleText + " " + newConfiguration.getName());
226
                    }
227
                    else {
228
                        modelMap.addAttribute("configurationID", id);
229
                        modelMap.addAttribute("contingencyTableRows", rows);
230
                        modelMap.addAttribute("isNotRemoveEmpty", isNotRemoveEmpty);
231
                        addConfigurationDataIntoModelAndView(newConfiguration, modelAndView, modelMap);
232
                    }
233
                }
234
                else {
235
                    modelMap.addAttribute(assemblyErrorName,  "Vyskytla se chyba v SQL dotazu! Prosím " +
236
                            "zkontrolujte zadané hodnoty filtrů nebo kontaktujte administrátora!");
237
                    modelMap.addAttribute(assemblyTitleName, generateTableTitleText + " " + newConfiguration.getName());
238
                }
216 239
            }
217 240
        }
218 241
        else if (exportXlsx != null)
src/main/java/vldc/aswi/web/controller/ConfigurationController.java
72 72
    /**
73 73
     * Opens an configuration page after configuration name was clicked
74 74
     * @param id ID of configuration
75
     * @param errorMsg Error message text.
76
     * @param successMsg Success message text.
75 77
     * @return modelAndView of page to be shown
76 78
     */
77 79
    @GetMapping("/configuration")
......
113 115
    /**
114 116
     * Saves or edits configuration and redirects to the page with configuration
115 117
     * @param newConfiguration contained with configuration data
116
     * @param id ID of configuration, if empty new configuration is created
117
     * @param bindingResult binding result
118
     * @return modelAndView with redirection
118
     * @param bindingResult - Error results from assembly validators.
119
     * @param isNotRemoveEmptyString String that stores if switch to not remove empty rows and columns was set.
120
     * @param id ID of the assembly.
121
     * @param generateTable String used to check if generate table button was clicked.
122
     * @param exportPdf String used to check if export to PDF button was clicked.
123
     * @param exportXlsx String used to check if export to XLSX button was clicked.
124
     * @param redirectAttributes Attributes.
125
     * @param saveConfiguration String used to check if save configuration button was clicked.
126
     * @param response HTTP servlet response.
127
     * @param request HTTP servlet request.
128
     * @return ModelAndView for assembly.
119 129
     */
120 130
    @PostMapping("/configuration")
121 131
    public ModelAndView configurationPost(@Valid Configuration newConfiguration,
......
155 165
            }
156 166
            else {
157 167
                List<ContingencyTableRow> rows = this.sqlQueryManager.getContingencyTableRow(newConfiguration.getAssembly(),
158
                        newConfiguration.getParametersInConfiguration(), isNotRemoveEmpty);
159

  
160
                modelMap.addAttribute("configurationID", id);
161
                modelMap.addAttribute("contingencyTableRows", rows);
162
                addConfigurationDataIntoModelAndView(newConfiguration, modelAndView, modelMap);
168
                        newConfiguration.getParametersInConfiguration(), isNotRemoveEmpty, newConfiguration.getTableName());
169

  
170
                if (rows != null) {
171
                    if (rows.isEmpty()) {
172
                        modelMap.addAttribute(assemblyErrorName, "Výsledná tabulka neobsahuje žádné hodnoty (" +
173
                                "SQL dotaz nevrátil žádné řádky)!");
174
                        modelMap.addAttribute(assemblyTitleName, generateTableTitleText + " " + newConfiguration.getName());
175
                    }
176
                    else {
177
                        modelMap.addAttribute("configurationID", id);
178
                        modelMap.addAttribute("contingencyTableRows", rows);
179
                        modelMap.addAttribute("isNotRemoveEmpty", isNotRemoveEmpty);
180
                        addConfigurationDataIntoModelAndView(newConfiguration, modelAndView, modelMap);
181
                    }
182
                }
183
                else {
184
                    modelMap.addAttribute(assemblyErrorName, "Vyskytla se chyba v SQL dotazu! Prosím " +
185
                            "zkontrolujte zadané hodnoty filtrů nebo kontaktujte administrátora!");
186
                    modelMap.addAttribute(assemblyTitleName, generateTableTitleText + " " + newConfiguration.getName());
187
                }
163 188
            }
164 189
        }
165 190
        else if (exportXlsx != null)
......
195 220
    /**
196 221
     * Get method for configuration delete.
197 222
     * @param id - ID of configuration.
223
     * @param redirectAttributes Attributes.
198 224
     * @return ModelAndView for index.
199 225
     */
200 226
    @GetMapping("/configuration_delete")

Také k dispozici: Unified diff