Android Open Source - Android-Lib-Database Database Open Helper






From Project

Back to project page Android-Lib-Database.

License

The source code is released under:

Apache License

If you think the Android project Android-Lib-Database listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package android.lib.database;
//from   www .  j  a v  a 2 s .com
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.TextUtils;
import android.util.Log;

/**
 * Handles database table creation.
 */
public class DatabaseOpenHelper extends SQLiteOpenHelper {
    private static final String CREATE_TABLE        = "CREATE TABLE IF NOT EXISTS %s (%s)";                     //$NON-NLS-1$
    private static final String CREATE_INDEX        = "CREATE INDEX IF NOT EXISTS idx_%s_%s ON %s (%s)";        //$NON-NLS-1$
    private static final String CREATE_INDEX_UNIQUE = "CREATE UNIQUE INDEX IF NOT EXISTS idx_%s_%s ON %s (%s)"; //$NON-NLS-1$
    private static final String PRIMARY_KEY         = "PRIMARY KEY";                                            //$NON-NLS-1$
    private static final String AUTO_INCREMENT      = "AUTOINCREMENT";                                          //$NON-NLS-1$
    private static final String NOT_NULL            = "NOT NULL";                                               //$NON-NLS-1$
    private static final String UNIQUE              = "UNIQUE";                                                 //$NON-NLS-1$
    private static final String COLUMN_SEPARATOR    = ", ";                                                     //$NON-NLS-1$
    private static final String SPACE               = " ";                                                      //$NON-NLS-1$
    private static final String TYPE_INTEGER        = "INTEGER";                                                //$NON-NLS-1$
    private static final String TYPE_REAL           = "REAL";                                                   //$NON-NLS-1$
    private static final String TYPE_TEXT           = "TEXT";                                                   //$NON-NLS-1$
    private static final String TYPE_BLOB           = "BLOB";                                                   //$NON-NLS-1$

    private static final Comparator<CompositeIndex> COMPOSITE_INDEX_COMPARATOR = new Comparator<CompositeIndex>() {
        @Override
        public int compare(final CompositeIndex lhs, final CompositeIndex rhs) {
            return lhs.order() - rhs.order();
        }
    };

    private static final Comparator<UniqueCompositeIndex> UNIQUE_COMPOSITE_INDEX_COMPARATOR = new Comparator<UniqueCompositeIndex>() {
        @Override
        public int compare(final UniqueCompositeIndex lhs, final UniqueCompositeIndex rhs) {
            return lhs.order() - rhs.order();
        }
    };

    /**
     * The tables of the database to create in {@link #onCreate(SQLiteDatabase)}.
     */
    protected final Class<?>[] tables;

    /**
     * Creates a new instance of {@link DatabaseOpenHelper} by invoking
     * its super-class {@link android.database.sqlite.SQLiteOpenHelper}, and optionally stores
     * the given <code>tables</code> for database table creation when {@link #onCreate(SQLiteDatabase)} is called.
     * @param context the context to use to open or create the database
     * @param name the file name of the database file, or null for an in-memory database
     * @param version the version number of the database (starting at 1); if the database is older,
     * {@link #onUpgrade(SQLiteDatabase, int, int)} will be used to upgrade the database;
     * if the database is newer, {@link #onDowngrade(SQLiteDatabase, int, int)} will be used to downgrade the database
     * @param tables the tables of the database to create in {@link #onCreate(SQLiteDatabase)}.
     * For subsequent call, <code>tables</code> can be <code>null</code>.
     */
    protected DatabaseOpenHelper(final Context context, final String name, final int version, final Class<?>... tables) {
        super(context, name, null, version);

        this.tables = tables;
    }

    /**
     * Creates a new instance of {@link DatabaseOpenHelper} with the given <code>name</code> and <code>version</code>.
     * @param context the context to use to open or create the database
     * @param name the file name of the database file, or null for an in-memory database
     * @param version the version number of the database (starting at 1); if the database is older,
     * {@link #onUpgrade(SQLiteDatabase, int, int)} will be used to upgrade the database;
     * if the database is newer, {@link #onDowngrade(SQLiteDatabase, int, int)} will be used to downgrade the database
     * @param tables the tables of the database to create in {@link #onCreate(SQLiteDatabase)}.
     * For subsequent call, <code>tables</code> can be <code>null</code>.
     */
    public static DatabaseOpenHelper newInstance(final Context context, final String name, final int version, final Class<?>... tables) {
        return new DatabaseOpenHelper(context, name, version, tables);
    }

    /**
     * Creates a new instance of {@link DatabaseOpenHelper} with the given <code>version</code>.
     * <p>The application package name will be used as the name of the database.</p>
     * @param context the context to use to open or create the database
     * @param version the version number of the database (starting at 1); if the database is older,
     * {@link #onUpgrade(SQLiteDatabase, int, int)} will be used to upgrade the database;
     * if the database is newer, {@link #onDowngrade(SQLiteDatabase, int, int)} will be used to downgrade the database
     * @param tables the tables of the database to create in {@link #onCreate(SQLiteDatabase)}.
     * For subsequent call, <code>tables</code> can be <code>null</code>.
     */
    public static DatabaseOpenHelper newInstance(final Context context, final int version, final Class<?>... tables) {
        return new DatabaseOpenHelper(context, context.getPackageName(), version, tables);
    }

    /**
     * Creates a new instance of {@link DatabaseOpenHelper} with the given <code>name</code>.
     * <p>The application version code will be used as the database version.</p>
     * @param context the context to use to open or create the database
     * @param name the file name of the database file, or null for an in-memory database
     * @param tables the tables of the database to create in {@link #onCreate(SQLiteDatabase)}.
     * For subsequent call, <code>tables</code> can be <code>null</code>.
     */
    public static DatabaseOpenHelper newInstance(final Context context, final String name, final Class<?>... tables) {
        try {
            return new DatabaseOpenHelper(
                            context,
                            name,
                            context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode,
                            tables);
        } catch (final NameNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Creates a new instance of {@link DatabaseOpenHelper}.
     * <p>The application package name and version code will be used as the name and version of the database respectively.</p>
     * @param context the context to use to open or create the database
     * @param tables the tables of the database to create in {@link #onCreate(SQLiteDatabase)}.
     * For subsequent call, <code>tables</code> can be <code>null</code>.
     */
    public static DatabaseOpenHelper newInstance(final Context context, final Class<?>... tables) {
        try {
            return new DatabaseOpenHelper(
                            context,
                            context.getPackageName(),
                            context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode,
                            tables);
        } catch (final NameNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void onCreate(final SQLiteDatabase database) {
        if (this.tables != null) {
            database.beginTransaction();

            try {
                for (final Class<?> table : this.tables) {
                    DatabaseOpenHelper.createTable(database, table);
                }

                database.setTransactionSuccessful();
            } catch (final UnsupportedTypeException e) {
                Log.e(this.getClass().getName(), e.getMessage(), e);
            } finally {
                database.endTransaction();
            }
        }
    }

    @Override
    public void onUpgrade(final SQLiteDatabase database, final int oldVersion, final int newVersion) {
    }

    private static void createTable(final SQLiteDatabase database, final Class<?> clazz) throws UnsupportedTypeException {
        final Table table = clazz.getAnnotation(Table.class);

        if (table != null) {
            final String                                            tableName              = TextUtils.isEmpty(table.value()) ? clazz.getSimpleName() : table.value();
            final StringBuilder                                     columnsBuilder         = new StringBuilder();
            final List<String>                                      createIndexStatements  = new ArrayList<String>();
            final Set<Field>                                        fields                 = new HashSet<Field>();
            final Map<Field, String>                                fieldNames             = new HashMap<Field, String>();
            final Map<String, TreeMap<CompositeIndex, Field>>       compositeIndexes       = new TreeMap<String, TreeMap<CompositeIndex, Field>>();
            final Map<String, TreeMap<UniqueCompositeIndex, Field>> uniqueCompositeIndexes = new TreeMap<String, TreeMap<UniqueCompositeIndex, Field>>();

            for (final Field field : clazz.getFields()) {
                fields.add(field);
            }

            for (final Field field : clazz.getDeclaredFields()) {
                fields.add(field);
            }

            for (final Field field : fields) {
                field.setAccessible(true);

                final Column column = field.getAnnotation(Column.class);

                if (column != null) {
                    if (columnsBuilder.length() > 0) {
                        columnsBuilder.append(DatabaseOpenHelper.COLUMN_SEPARATOR);
                    }

                    columnsBuilder.append(DatabaseOpenHelper.getColumnDefinition(field));

                    final String fieldName = TextUtils.isEmpty(column.value()) ? field.getName() : column.value();
                    final Index  index     = field.getAnnotation(Index.class);

                    fieldNames.put(field, fieldName);

                    if (index != null) {
                        createIndexStatements.add(String.format(index.unique() ? DatabaseOpenHelper.CREATE_INDEX_UNIQUE : DatabaseOpenHelper.CREATE_INDEX, tableName, fieldName, tableName, fieldName));
                    }

                    // Searches for composite index annotation
                    final CompositeIndex compositeIndex = field.getAnnotation(CompositeIndex.class);

                    if (compositeIndex != null) {
                        final String[] indexNames = compositeIndex.value() == null ? new String[] { fieldName } : compositeIndex.value();

                        for (final String indexName : indexNames) {
                            final TreeMap<CompositeIndex, Field> indexes = compositeIndexes.containsKey(indexName) ? compositeIndexes.get(indexName) : new TreeMap<CompositeIndex, Field>(DatabaseOpenHelper.COMPOSITE_INDEX_COMPARATOR);

                            indexes.put(compositeIndex, field);
                            compositeIndexes.put(indexName, indexes);
                        }
                    }

                    // Searches for unique composite index annotation
                    final UniqueCompositeIndex uniqueCompositeIndex = field.getAnnotation(UniqueCompositeIndex.class);

                    if (uniqueCompositeIndex != null) {
                        final String[] indexNames = uniqueCompositeIndex.value() == null ? new String[] { fieldName } : uniqueCompositeIndex.value();

                        for (final String indexName : indexNames) {
                            final TreeMap<UniqueCompositeIndex, Field> indexes = uniqueCompositeIndexes.containsKey(indexName) ? uniqueCompositeIndexes.get(indexName) : new TreeMap<UniqueCompositeIndex, Field>(DatabaseOpenHelper.UNIQUE_COMPOSITE_INDEX_COMPARATOR);

                            indexes.put(uniqueCompositeIndex, field);
                            uniqueCompositeIndexes.put(indexName, indexes);
                        }
                    }
                }
            }

            // Creates table
            database.execSQL(String.format(DatabaseOpenHelper.CREATE_TABLE, tableName, columnsBuilder.toString()));

            // Creates indexes
            for (final String createIndexStatement : createIndexStatements) {
                database.execSQL(createIndexStatement);
            }

            // Creates composite indexes
            if (compositeIndexes.size() > 0) {
                for (final Map.Entry<String, TreeMap<CompositeIndex, Field>> entry : compositeIndexes.entrySet()) {
                    final StringBuilder indexBuilder = new StringBuilder();

                    for (final Map.Entry<CompositeIndex, Field> index : entry.getValue().entrySet()) {
                        if (indexBuilder.length() > 0) {
                            indexBuilder.append(DatabaseOpenHelper.COLUMN_SEPARATOR);
                        }

                        indexBuilder.append(fieldNames.get(index.getValue()));
                    }

                    database.execSQL(String.format(DatabaseOpenHelper.CREATE_INDEX, tableName, entry.getKey(), tableName, indexBuilder.toString()));
                }
            }

            // Creates unique composite indexes
            if (uniqueCompositeIndexes.size() > 0) {
                for (final Map.Entry<String, TreeMap<UniqueCompositeIndex, Field>> entry : uniqueCompositeIndexes.entrySet()) {
                    final StringBuilder indexBuilder = new StringBuilder();

                    for (final Map.Entry<UniqueCompositeIndex, Field> index : entry.getValue().entrySet()) {
                        if (indexBuilder.length() > 0) {
                            indexBuilder.append(DatabaseOpenHelper.COLUMN_SEPARATOR);
                        }

                        indexBuilder.append(fieldNames.get(index.getValue()));
                    }

                    database.execSQL(String.format(DatabaseOpenHelper.CREATE_INDEX_UNIQUE, tableName, entry.getKey(), tableName, indexBuilder.toString()));
                }
            }
        }
    }

    private static String getColumnDefinition(final Field field) throws UnsupportedTypeException {
        final Column        column  = field.getAnnotation(Column.class);
        final StringBuilder builder = new StringBuilder();

        builder.append(TextUtils.isEmpty(column.value()) ? field.getName() : column.value());
        builder.append(DatabaseOpenHelper.SPACE);
        builder.append(DatabaseOpenHelper.getColumnType(field));

        if (column.primaryKey()) {
            builder.append(DatabaseOpenHelper.SPACE);
            builder.append(DatabaseOpenHelper.PRIMARY_KEY);

            if (column.autoIncrement()) {
                builder.append(DatabaseOpenHelper.SPACE);
                builder.append(DatabaseOpenHelper.AUTO_INCREMENT);
            }
        } else {
            if (!column.nullable()) {
                builder.append(DatabaseOpenHelper.SPACE);
                builder.append(DatabaseOpenHelper.NOT_NULL);
            }
        }

        final Index index = field.getAnnotation(Index.class);

        if (index != null) {
            if (index.unique()) {
                builder.append(DatabaseOpenHelper.SPACE);
                builder.append(DatabaseOpenHelper.UNIQUE);
            }
        }

        return builder.toString();
    }

    private static String getColumnType(final Field field) throws UnsupportedTypeException {
        final UseConverter converter = field.getAnnotation(UseConverter.class);
        final Class<?>     type      = converter == null ? field.getType() : converter.type();

        if (type.equals(boolean.class) || type.equals(Boolean.class)) {
            return DatabaseOpenHelper.TYPE_INTEGER;
        } else if (type.equals(byte.class) || type.equals(Byte.class)) {
            return DatabaseOpenHelper.TYPE_INTEGER;
        } else if (type.equals(byte[].class) || type.equals(Byte[].class)) {
            return DatabaseOpenHelper.TYPE_BLOB;
        } else if (type.equals(double.class) || type.equals(Double.class)) {
            return DatabaseOpenHelper.TYPE_REAL;
        } else if (type.equals(float.class) || type.equals(Float.class)) {
            return DatabaseOpenHelper.TYPE_REAL;
        } else if (type.equals(int.class) || type.equals(Integer.class)) {
            return DatabaseOpenHelper.TYPE_INTEGER;
        } else if (type.equals(long.class) || type.equals(Long.class)) {
            return DatabaseOpenHelper.TYPE_INTEGER;
        } else if (type.equals(short.class) || type.equals(Short.class)) {
            return DatabaseOpenHelper.TYPE_INTEGER;
        } else if (type.equals(String.class)) {
            return DatabaseOpenHelper.TYPE_TEXT;
        } else {
            throw new UnsupportedTypeException(String.format("%s is not of SQLite-compatible type", field.getName())); //$NON-NLS-1$
        }
    }
}




Java Source Code List

android.lib.database.Column.java
android.lib.database.CompositeIndex.java
android.lib.database.DatabaseOpenHelper.java
android.lib.database.Database.java
android.lib.database.DateConverter.java
android.lib.database.Index.java
android.lib.database.JSONRowMapper.java
android.lib.database.RowMapper.java
android.lib.database.Table.java
android.lib.database.TypeConverter.java
android.lib.database.UniqueCompositeIndex.java
android.lib.database.UnsupportedTypeException.java
android.lib.database.UseConverter.java
android.lib.database.predicate.ManySidedPredicate.java
android.lib.database.predicate.Predicate.java
android.lib.database.predicate.ThreeSidedPredicate.java
android.lib.database.predicate.TwoSidedPredicate.java
android.lib.database.query.Delete.java
android.lib.database.query.Insert.java
android.lib.database.query.QueryBuilder.java
android.lib.database.query.Query.java
android.lib.database.query.Select.java
android.lib.database.query.Update.java