1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.arch.persistence.room;
18
19import android.content.Context;
20import android.support.annotation.NonNull;
21
22/**
23 * Utility class for Room.
24 */
25@SuppressWarnings("unused")
26public class Room {
27    static final String LOG_TAG = "ROOM";
28    /**
29     * The master table where room keeps its metadata information.
30     */
31    public static final String MASTER_TABLE_NAME = RoomMasterTable.TABLE_NAME;
32    private static final String CURSOR_CONV_SUFFIX = "_CursorConverter";
33
34    /**
35     * Creates a RoomDatabase.Builder for a persistent database. Once a database is built, you
36     * should keep a reference to it and re-use it.
37     *
38     * @param context The context for the database. This is usually the Application context.
39     * @param klass   The abstract class which is annotated with {@link Database} and extends
40     *                {@link RoomDatabase}.
41     * @param name    The name of the database file.
42     * @param <T>     The type of the database class.
43     * @return A {@code RoomDatabaseBuilder<T>} which you can use to create the database.
44     */
45    @SuppressWarnings("WeakerAccess")
46    public static <T extends RoomDatabase> RoomDatabase.Builder<T> databaseBuilder(
47            @NonNull Context context, @NonNull Class<T> klass, @NonNull String name) {
48        //noinspection ConstantConditions
49        if (name == null || name.trim().length() == 0) {
50            throw new IllegalArgumentException("Cannot build a database with null or empty name."
51                    + " If you are trying to create an in memory database, use Room"
52                    + ".inMemoryDatabaseBuilder");
53        }
54        return new RoomDatabase.Builder<>(context, klass, name);
55    }
56
57    /**
58     * Creates a RoomDatabase.Builder for an in memory database. Information stored in an in memory
59     * database disappears when the process is killed.
60     * Once a database is built, you should keep a reference to it and re-use it.
61     *
62     * @param context The context for the database. This is usually the Application context.
63     * @param klass   The abstract class which is annotated with {@link Database} and extends
64     *                {@link RoomDatabase}.
65     * @param <T>     The type of the database class.
66     * @return A {@code RoomDatabaseBuilder<T>} which you can use to create the database.
67     */
68    public static <T extends RoomDatabase> RoomDatabase.Builder<T> inMemoryDatabaseBuilder(
69            @NonNull Context context, @NonNull Class<T> klass) {
70        return new RoomDatabase.Builder<>(context, klass, null);
71    }
72
73    @NonNull
74    static <T, C> T getGeneratedImplementation(Class<C> klass, String suffix) {
75        final String fullPackage = klass.getPackage().getName();
76        String name = klass.getCanonicalName();
77        final String postPackageName = fullPackage.isEmpty()
78                ? name
79                : (name.substring(fullPackage.length() + 1));
80        final String implName = postPackageName.replace('.', '_') + suffix;
81        //noinspection TryWithIdenticalCatches
82        try {
83
84            @SuppressWarnings("unchecked")
85            final Class<T> aClass = (Class<T>) Class.forName(
86                    fullPackage.isEmpty() ? implName : fullPackage + "." + implName);
87            return aClass.newInstance();
88        } catch (ClassNotFoundException e) {
89            throw new RuntimeException("cannot find implementation for "
90                    + klass.getCanonicalName() + ". " + implName + " does not exist");
91        } catch (IllegalAccessException e) {
92            throw new RuntimeException("Cannot access the constructor"
93                    + klass.getCanonicalName());
94        } catch (InstantiationException e) {
95            throw new RuntimeException("Failed to create an instance of "
96                    + klass.getCanonicalName());
97        }
98    }
99}
100