· 9 years ago · Nov 29, 2016, 03:14 AM
1package controller;
2
3import java.io.File;
4import java.util.ArrayList;
5import java.util.HashSet;
6import java.util.List;
7import java.util.Set;
8import javax.script.ScriptException;
9import model.ClassFactory;
10import model.Database;
11import model.DatabaseFilterGenerator;
12import model.DatabaseHelper;
13import model.ObjectFactory;
14import model.Observer;
15import model.Record;
16import model.SelectionTable;
17import model.Table;
18import model.statements.Create;
19import model.statements.Delete;
20import model.statements.Drop;
21import model.statements.Insert;
22import model.statements.Query;
23import model.statements.Select;
24import model.statements.Update;
25import model.statements.Use;
26import util.App;
27import util.BooleanEvaluator;
28import util.ErrorCode;
29
30public class DatabaseController implements DBMS, Observer {
31 private DBMSController dbmsController;
32 private DatabaseHelper dbHelper;
33 private DatabaseFilterGenerator databaseFilter;
34 private ClassFactory classFactory;
35 private ObjectFactory objectFactory;
36
37 public DatabaseController(DBMSController dbmsController) {
38 databaseFilter = new DatabaseFilterGenerator();
39 classFactory = new ClassFactory();
40 objectFactory = new ObjectFactory();
41 this.dbmsController = dbmsController;
42 this.dbHelper = new DatabaseHelper(this);
43 }
44
45 public DatabaseHelper getHelper() {
46 return dbHelper;
47 }
48
49 @Override
50 public void update() {
51 Query currentQuery = this.dbmsController.getSQLParserController().getSqlParserHelper()
52 .getCurrentQuery();
53 if (currentQuery instanceof Create) {
54 this.handleCreate((Create) currentQuery);
55 } else if (currentQuery instanceof Delete) {
56 this.handleDelete((Delete) currentQuery);
57 } else if (currentQuery instanceof Drop) {
58 this.handleDrop((Drop) currentQuery);
59 } else if (currentQuery instanceof Insert) {
60 this.handleInsert((Insert) currentQuery);
61 } else if (currentQuery instanceof Select) {
62 this.handleSelect((Select) currentQuery);
63 } else if (currentQuery instanceof Update) {
64 this.handleUpdate((Update) currentQuery);
65 } else if (currentQuery instanceof Use) {
66 this.handleUse((Use) currentQuery);
67 } else {
68 this.dbmsController.getSQLParserController().callForFailure(ErrorCode.SYNTAX_ERROR);
69 }
70 }
71
72 private void handleCreate(Create create) {
73 if (create.isDatabase()) {
74 this.dbmsController.getCLIController()
75 .status(this.createDatabase(create.getDatabaseIdentifier()));
76 } else {
77 this.dbmsController.getCLIController().status(this.createTable(
78 create.getTableIdentifier(), create.getColumns(), create.getTypes()));
79 }
80 }
81
82 private void handleDelete(Delete delete) {
83 this.dbmsController.getCLIController().status(this
84 .deleteFromTable(delete.getTableIdentifier(), delete.getWhere().getExpression()));
85 }
86
87 private void handleDrop(Drop drop) {
88 if (drop.isDatabase())
89 this.dbmsController.getCLIController()
90 .status(this.dropDatabase(drop.getDatabaseIdentifier()));
91 else
92 this.dbmsController.getCLIController()
93 .status(this.dropTable(drop.getTableIdentifier()));
94 }
95
96 private void handleInsert(Insert insert) {
97 if (insert.isDefaultSelection()) {
98 // this.insertIntoTable(insert.getTableIdentifier(), insert.getValues());
99 }
100 }
101
102 private void handleSelect(Select select) {
103 this.dbmsController.getCLIController()
104 .status(this.selectFromTable(select.getTableIdentifier(), select.getColumns(),
105 select.getWhere().getExpression()));
106 }
107
108 private void handleUpdate(Update update) {
109 // this.updateTable(u, colNames, values, condition)
110 }
111
112 private void handleUse(Use use) {
113 this.dbmsController.getCLIController()
114 .status(this.useDatabase(use.getDatabaseIdentifier()));
115 }
116
117 @Override
118 public boolean useDatabase(String databaseName) {
119 File usedDatabaseDir = getDatabase(databaseName);
120 if (!App.checkForExistence(usedDatabaseDir)) {
121 throw new RuntimeException("Database doesnot exist");
122 // return false;
123 }
124 dbHelper.setDatabase(usedDatabaseDir);
125 reLoadTables(dbHelper.getCurrentDatabase());
126 return true;
127 }
128
129 @Override
130 public boolean createDatabase(String databaseName) {
131 if (databaseExists(databaseName)) {
132 this.dbmsController.getCLIController().callForFailure(ErrorCode.DATABASE_DUPLICATION);
133 return false;
134 }
135 new Database(this.dbHelper.getWorkspaceDir().getAbsolutePath(), databaseName);
136 return true;
137 }
138
139 @Override
140 public boolean createTable(String tableName, List<String> colNames, List<Class<?>> types) {
141 if (!App.checkForExistence(dbHelper.getCurrentDatabase())) {
142 throw new RuntimeException("No database selected");
143 // return false;
144 }
145 if (colNames.size() != types.size() || containsDublicates(colNames)) {
146 throw new RuntimeException("Wrong data entered");
147 }
148 if (this.tableExists(tableName)) {
149 throw new RuntimeException("Table already exists");
150 }
151 File tableFile = new File(
152 dbHelper.getCurrentDatabase().getPath() + File.separator + tableName);
153 Table table = new Table(tableFile);
154 dbHelper.getCurrentDatabase().registerTable(table);
155 File xmlFile = dbmsController.getXMLController().initializeXML(table.getTablePath(),
156 tableName, colNames, types);
157 File dtdFile = dbmsController.getXMLController().initializeDTD(table.getTablePath(),
158 tableName, colNames, types);
159 table.registerFiles(xmlFile, dtdFile);
160 return true;
161 }
162
163 @Override
164 public boolean dropTable(String tableName) {
165 if (!App.checkForExistence(dbHelper.getCurrentDatabase())) {
166 throw new RuntimeException("No database selected.");
167 // return false;
168 }
169 int index = 0;
170 for (Table table : dbHelper.getCurrentDatabase().getTables()) {
171 if (equalStrings(table.getTableName(), tableName)) {
172 deleteDir(table.getTableDir());
173 dbHelper.getCurrentDatabase().getTables().remove(index);
174 return true;
175 }
176 }
177 return false;
178 }
179
180 @Override
181 public boolean dropDatabase(String databaseName) {
182 File database = getDatabase(databaseName);
183 if (!App.checkForExistence(database)) {
184 return false;
185 }
186 deleteDir(database);
187 return true;
188 }
189
190 @Override
191 public boolean insertIntoTable(String tableName, List<String> colNames,
192 List<String> valuesAsString) {
193 if (!App.checkForExistence(dbHelper.getCurrentDatabase())) {
194 throw new RuntimeException("No database selected.");
195 // return false;
196 }
197 if (containsDublicates(colNames) || colNames.size() != valuesAsString.size()) {
198 return false;
199 }
200 Table table = getTable(tableName);
201 if (!App.checkForExistence(table)) {
202 throw new RuntimeException("Cannot find table");
203 }
204 List<String> typesAsStrings = dbmsController.getXMLController().getTypes(table);
205 List<String> tableColNames = dbmsController.getXMLController().getColumnsNames(table);
206 List<Class<?>> types = getTypesFromStrings(typesAsStrings);
207 List<Object> values = getObjectsFromStrings(types, valuesAsString);
208 for (String colName : colNames) {
209 if (!tableColNames.contains(colName)) {
210 throw new RuntimeException("Data doesnot match table.");
211 }
212 }
213 if (!isMatched(tableColNames, colNames, types, values)) {
214 throw new RuntimeException("Data doesnot match table.");
215 }
216 List<Object> generateValues = new ArrayList<>();
217 for (int i = 0; i < tableColNames.size(); i++) {
218 boolean found = false;
219 for (int j = 0; j < colNames.size(); j++) {
220 if (equalStrings(tableColNames.get(i), colNames.get(j))) {
221 generateValues.add(values.get(j));
222 found = true;
223 break;
224 }
225 }
226 if (!found) {
227 generateValues.add(null);
228 }
229 }
230 Record record = new Record(generateValues);
231 return dbmsController.getXMLController().insertIntoTable(table, record);
232 }
233
234 @Override
235 public boolean insertIntoTable(String tableName, List<String> valuesAsString) {
236 if (!App.checkForExistence(dbHelper.getCurrentDatabase())) {
237 throw new RuntimeException("No database selected.");
238 // return false;
239 }
240 Table table = getTable(tableName);
241 if (!App.checkForExistence(table)) {
242 throw new RuntimeException("Cannot find table");
243 }
244 List<String> typesAsStrings = dbmsController.getXMLController().getTypes(table);
245 List<Class<?>> types = getTypesFromStrings(typesAsStrings);
246 List<Object> values = getObjectsFromStrings(types, valuesAsString);
247 if (values.size() != types.size()) {
248 throw new RuntimeException("Wrong data");
249 }
250 for (int i = 0; i < types.size(); i++) {
251 if (!types.get(i).isInstance(values.get(i))) {
252 throw new RuntimeException("Wrong data");
253 }
254 }
255 Record record = new Record(values);
256 return dbmsController.getXMLController().insertIntoTable(table, record);
257 }
258
259 @Override
260 public boolean selectFromTable(String tableName, List<String> colNames, String condition) {
261 if (!App.checkForExistence(dbHelper.getCurrentDatabase())) {
262 throw new RuntimeException("No database selected.");
263 // return false;
264 }
265 Table table = getTable(tableName);
266 if (!App.checkForExistence(table)) {
267 throw new RuntimeException("Cannot find table");
268 }
269 if (containsDublicates(colNames)) {
270 throw new RuntimeException("Data contains dublicates");
271 }
272 List<String> tableColNames = dbmsController.getXMLController().getColumnsNames(table);
273 if (!containsAllStrings(tableColNames, colNames)) {
274 throw new RuntimeException("Wrong column names");
275 // return false;
276 }
277 try {
278 if (condition.equals("*")) {
279 condition = "true";
280 }
281 SelectionTable selectedTable = dbmsController.getXMLController().selectFromTable(table,
282 colNames, condition);
283 selectedTable = reformTable(selectedTable, colNames);
284 dbHelper.setSelectedTable(selectedTable);
285 } catch (Exception e) {
286 throw new RuntimeException("Cannot read Table");
287 // return false;
288 }
289 return true;
290 }
291
292 @Override
293 public boolean updateTable(String tableName, List<String> colNames, List<String> valuesAsString,
294 String condition) {
295 if (!App.checkForExistence(dbHelper.getCurrentDatabase())) {
296 throw new RuntimeException("No database selected.");
297 // return false;
298 }
299 Table table = getTable(tableName);
300 if (!App.checkForExistence(table)) {
301 throw new RuntimeException("Cannot find table");
302 }
303 List<String> tableColNames = dbmsController.getXMLController().getColumnsNames(table);
304 List<String> typesAsStrings = dbmsController.getXMLController().getTypes(table);
305 List<Class<?>> types = getTypesFromStrings(typesAsStrings);
306 List<Object> values = getObjectsFromStrings(types, valuesAsString);
307 if (colNames.size() != values.size() || containsDublicates(colNames)
308 || !isMatched(tableColNames, colNames, types, values)) {
309 throw new RuntimeException("Wrong data inserted");
310 // return false;
311 }
312 try {
313 if (condition.equals("*")) {
314 condition = "true";
315 }
316 dbmsController.getXMLController().updateTable(table, colNames, values, condition);
317 } catch (Exception e) {
318 throw new RuntimeException("Something went wrong Cannot update table.");
319 // return false;
320 }
321 return true;
322 }
323
324 @Override
325 public boolean deleteFromTable(String tableName, String condition) {
326 if (!App.checkForExistence(dbHelper.getCurrentDatabase())) {
327 throw new RuntimeException("No database selected.");
328 // return false;
329 }
330 Table table = getTable(tableName);
331 if (!App.checkForExistence(table)) {
332 throw new RuntimeException("Cannot find table");
333 }
334 try {
335 if (condition.equals("*")) {
336 condition = "true";
337 }
338 dbmsController.getXMLController().removeFromTable(table, condition);
339 } catch (Exception e) {
340 throw new RuntimeException("Something went wrong Cannot remove from table.");
341 // return false;
342 }
343 return true;
344 }
345
346 public boolean evaluate(String expression, Record record) throws ScriptException {
347 String exp = getFilledExpression(expression, record);
348 exp = exp.toLowerCase();
349 exp = App.replace(exp, "and", " && ");
350 exp = App.replace(exp, "or", " || ");
351 exp = App.replace(exp, "not", " ! ");
352 return BooleanEvaluator.evaluate(exp);
353 }
354
355 private Table getTable(String tableName) {
356 if (!App.checkForExistence(dbHelper.getCurrentDatabase())) {
357 throw new RuntimeException("No database selected.");
358 // return false;
359 }
360 for (Table table : dbHelper.getCurrentDatabase().getTables()) {
361 if (equalStrings(table.getTableName(), tableName)) {
362 return table;
363 }
364 }
365 return null;
366 }
367
368 private List<Class<?>> getTypesFromStrings(List<String> typesAsStrings) {
369 List<Class<?>> types = new ArrayList<>();
370 for (int i = 0; i < typesAsStrings.size(); i++) {
371 types.add(classFactory.getClass(typesAsStrings.get(i)));
372 }
373 return types;
374 }
375
376 private <T> boolean containsDublicates(List<T> list) {
377 Set<T> temp = new HashSet<>(list);
378 if (temp.size() != list.size()) {
379 return true;
380 }
381 return false;
382 }
383
384 private boolean databaseExists(String databaseName) {
385 File database = getDatabase(databaseName);
386 if (!App.checkForExistence(database)) {
387 return false;
388 }
389 return true;
390 }
391
392 private boolean tableExists(String tableName) {
393 if (!App.checkForExistence(dbHelper.getCurrentDatabase())) {
394 throw new RuntimeException("No database selected.");
395 // return false;
396 }
397 for (Table table : dbHelper.getCurrentDatabase().getTables()) {
398 if (equalStrings(table.getTableName(), tableName)) {
399 return true;
400 }
401 }
402 return false;
403 }
404
405 private void deleteDir(File file) {
406 File[] contents = file.listFiles();
407 if (App.checkForExistence(contents)) {
408 for (File f : contents) {
409 deleteDir(f);
410 }
411 }
412 file.delete();
413 }
414
415 private File getDatabase(String databaseName) {
416 File[] databases = dbHelper.getDatabaseDir().listFiles(databaseFilter);
417 for (File databaseFile : databases) {
418 if (equalStrings(databaseFile.getName(), databaseName)) {
419 return databaseFile;
420 }
421 }
422 return null;
423 }
424
425 private void reLoadTables(Database database) {
426 database.clearTableList();
427 File[] tables = database.getDatabaseDir().listFiles(databaseFilter);
428 for (File tableDir : tables) {
429 Table table = new Table(tableDir);
430 File xmlFile = new File(
431 table.getTablePath() + File.separator + table.getTableName() + ".xml");
432 File dtdFile = new File(
433 table.getTablePath() + File.separator + table.getTableName() + ".dtd");
434 if (!(xmlFile.exists() && dtdFile.exists())) {
435 throw new RuntimeException("Missing table files");
436 }
437 table.registerFiles(xmlFile, dtdFile);
438 database.getTables().add(table);
439 }
440 }
441
442 private String getFilledExpression(String expression, Record record) {
443 String exp = expression.toLowerCase();
444 for (int i = 0; i < record.getColumns().size(); i++) {
445 if (record.getValues().get(i) instanceof String) {
446 exp = App.replace(exp, record.getColumns().get(i).toLowerCase(),
447 "\"" + record.getValues().get(i).toString() + "\"");
448 } else {
449 exp = App.replace(exp, record.getColumns().get(i).toLowerCase(),
450 record.getValues().get(i).toString());
451 }
452 }
453 return exp;
454 }
455
456 private boolean isMatched(List<String> tableColNames, List<String> colNames,
457 List<Class<?>> types, List<Object> values) {
458 for (int i = 0; i < colNames.size(); i++) {
459 for (int j = 0; j < tableColNames.size(); j++) {
460 if (equalStrings(colNames.get(i), tableColNames.get(j))) {
461 if (!types.get(j).isInstance(values.get(i))) {
462 return false;
463 }
464 }
465 }
466 }
467 return true;
468 }
469
470 private boolean equalStrings(String str1, String str2) {
471 return str1.toLowerCase().equals(str2.toLowerCase());
472 }
473
474 private SelectionTable reformTable(SelectionTable selectedTable, List<String> colNames) {
475 SelectionTable ret = new SelectionTable(colNames);
476 List<Object> values;
477 for (int i = 0; i < selectedTable.getRecordList().size(); i++) {
478 values = new ArrayList<>();
479 for (String str : colNames) {
480 for (int j = 0; j < selectedTable.getHeader().size(); j++) {
481 if (equalStrings(str, selectedTable.getHeader().get(j))) {
482 values.add(selectedTable.getRecordList().get(i).getValues().get(j));
483 }
484 }
485 }
486 ret.addRecord(new Record(values));
487 }
488 return ret;
489 }
490
491 private boolean containsAllStrings(List<String> list1, List<String> list2) {
492 for (String str2 : list2) {
493 boolean found = false;
494 for (String str1 : list1) {
495 if (equalStrings(str1, str2)) {
496 found = true;
497 break;
498 }
499 }
500 if (!found) {
501 return false;
502 }
503 }
504 return true;
505 }
506
507 private List<Object> getObjectsFromStrings(List<Class<?>> types, List<String> values) {
508 List<Object> ret = new ArrayList<>();
509 for (int i = 0; i < values.size(); i++) {
510 ret.add(objectFactory.parseToObject(types.get(i), values.get(i)));
511 }
512 return ret;
513 }
514}