1package com.xtremelabs.robolectric.util;
2
3import java.lang.annotation.ElementType;
4import java.lang.annotation.Inherited;
5import java.lang.annotation.Retention;
6import java.lang.annotation.RetentionPolicy;
7import java.lang.annotation.Target;
8import java.sql.Connection;
9import java.sql.DriverManager;
10import java.sql.SQLException;
11
12
13public class DatabaseConfig {
14    private static DatabaseMap dbMap = null;
15    private static boolean isLoaded = false;
16
17    public static void setDatabaseMap(DatabaseMap map) {
18        dbMap = map;
19        isLoaded = false; //make sure to reset isLoaded or mixing databases in a test suite will fail.
20    }
21
22    public static DatabaseMap getDatabaseMap() {
23        return dbMap;
24    }
25
26    /**
27     * check if the map has been loaded
28     *
29     * @return
30     */
31    public static boolean isMapLoaded() {
32        return isLoaded;
33    }
34
35    /**
36     * Check if the map has been set at all.
37     *
38     * @return
39     */
40    public static boolean isMapNull() {
41        return dbMap == null;
42    }
43
44    /**
45     * Sets what database will be used and loads the database driver, based on what DBmap is provided.
46     */
47    private static void LoadSQLiteDriver() {
48        if (isMapNull()) throw new NullDatabaseMapException("Error in DatabaseConfig: DatabaseMap has not been set.");
49        try {
50            Class.forName(dbMap.getDriverClassName()).newInstance();
51        } catch (InstantiationException e) {
52            throw new CannotLoadDatabaseMapDriverException("Error in DatabaseConfig: SQLite driver could not be instantiated;", e);
53        } catch (IllegalAccessException e) {
54            throw new CannotLoadDatabaseMapDriverException("Error in DatabaseConfig: SQLite driver could not be accessed;", e);
55        } catch (ClassNotFoundException e) {
56            throw new CannotLoadDatabaseMapDriverException("Error in DatabaseConfig: SQLite driver class could not be found;", e);
57        }
58        isLoaded = true;
59    }
60
61    /**
62     * Gets an in memory DB connection.  Will load DB Driver if not already loaded.
63     *
64     * @return Connection to In Memory Database.
65     */
66    public static Connection getMemoryConnection() {
67        if (!isMapLoaded()) LoadSQLiteDriver();
68        try {
69            return DriverManager.getConnection(dbMap.getConnectionString());
70        } catch (SQLException e) {
71            throw new CannotLoadDatabaseMapDriverException("Error in DatabaseConfig, could not retrieve connection to in memory database.", e);
72        }
73    }
74
75    /**
76     * Makes any edits necessary in the SQL string for it to be compatible with the database in use.
77     *
78     * @return
79     * @throws SQLException
80     */
81    public static String getScrubSQL(String sql) throws SQLException {
82        if (isMapNull()) throw new NullDatabaseMapException("No database map set!");
83        return dbMap.getScrubSQL(sql);
84    }
85
86    public static String getSelectLastInsertIdentity() {
87        if (isMapNull()) throw new NullDatabaseMapException("No database map set!");
88        return dbMap.getSelectLastInsertIdentity();
89    }
90
91    public static int getResultSetType() {
92        if (isMapNull()) throw new NullDatabaseMapException("No database map set!");
93        return dbMap.getResultSetType();
94    }
95
96    public interface DatabaseMap {
97        String getDriverClassName();
98
99        String getConnectionString();
100
101        String getScrubSQL(String sql) throws SQLException;
102
103        String getSelectLastInsertIdentity();
104
105        int getResultSetType();
106    }
107
108    public static class NullDatabaseMapException extends RuntimeException {
109        private static final long serialVersionUID = -4580960157495617424L;
110
111        public NullDatabaseMapException(String message) {
112            super(message);
113        }
114    }
115
116    public static class CannotLoadDatabaseMapDriverException extends RuntimeException {
117        private static final long serialVersionUID = 2614876121296128364L;
118
119        public CannotLoadDatabaseMapDriverException(String message, Throwable cause) {
120            super(message, cause);
121        }
122    }
123
124    @Retention(RetentionPolicy.RUNTIME)
125    @Target(ElementType.TYPE)
126    @Inherited
127    public @interface UsingDatabaseMap {
128        /**
129         * @return the classes to be run
130         */
131        public Class<? extends DatabaseMap> value();
132    }
133}
134