Improve XML parsing to handle attributes as well.
[cfb.git] / prod / net / jaekl / cfb / db / Schema.java
1 package net.jaekl.cfb.db;
2
3 // Copyright (C) 2015 Christian Jaekl
4
5 import java.sql.Connection;
6 import java.sql.DatabaseMetaData;
7 import java.sql.ResultSet;
8 import java.sql.SQLException;
9 import java.util.ArrayList;
10 import java.util.HashSet;
11 import java.util.Locale;
12
13 import net.jaekl.cfb.db.driver.DbDriver;
14
15 public class Schema {
16         String m_name;
17         DbDriver m_driver;
18         ArrayList<Table> m_tables;
19         
20         public Schema(String name, DbDriver driver) {
21                 m_name = name;
22                 m_driver = driver;
23                 m_tables = new ArrayList<Table>();
24         }
25         
26         public boolean ensureDbInitialized(Connection con) throws SQLException {
27                 assert(null != con);
28                 
29                 if (allTablesPresent(con)) {
30                         return true;
31                 }
32                 
33                 if (!createAllTables(con)) {
34                         return false;
35                 }
36                 
37                 return true;
38         }
39         
40         boolean allTablesPresent(Connection con) throws SQLException 
41         {
42                 assert(null != con);
43                 
44                 DatabaseMetaData dbmd = con.getMetaData();
45                 HashSet<String> extantTables = new HashSet<String>();
46                 
47                 try (ResultSet rs = dbmd.getTables(null, null, null, new String[]{"TABLE"})) {
48                         while (rs.next()) {
49                                 extantTables.add(rs.getString(3).toUpperCase(Locale.CANADA));
50                         }
51                 }
52                 
53                 for (Table table : m_tables) {
54                         String name = table.getName().toUpperCase(Locale.CANADA);
55                         if ( ! extantTables.contains(name) ) {
56                                 // One or more tables missing
57                                 return false;
58                         }
59                 }
60                 
61                 // We could be more thorough here, and check that the expected columns are in place.
62                 // Also, eventually, some sort of DB schema versioning will be needed.
63                 
64                 return true;            
65         }
66         
67         boolean createAllTables(Connection con) throws SQLException {
68                 for (Table table : m_tables) {
69                         if (!m_driver.createTable(con, table)) {
70                                 return false;
71                         }
72                 }
73                 return true;
74         }
75         
76         void addTable(Table table) {
77                 m_tables.add(table);
78         }
79         
80         // Add a list of tables.
81         // Define each table in the list as follows:
82         // {
83         //   { table_name },
84         //   { column_name, type, width (-1 for default), null/not_null }
85         // }
86         void addTables(Object[][][] tables) 
87         {
88                 for (Object[][] table : tables) {
89                         addTable(Table.construct(table));
90                 }
91         }       
92 }