com.activeandroid.sebbia.Cache.java Source code

Java tutorial

Introduction

Here is the source code for com.activeandroid.sebbia.Cache.java

Source

package com.activeandroid.sebbia;

/*
 * Copyright (C) 2010 Michael Pardo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.v4.util.LruCache;

import com.activeandroid.sebbia.annotation.DoNotGenerate;
import com.activeandroid.sebbia.internal.EmptyModelFiller;
import com.activeandroid.sebbia.internal.ModelFiller;
import com.activeandroid.sebbia.serializer.TypeSerializer;
import com.activeandroid.sebbia.util.Log;
import com.activeandroid.sebbia.util.ReflectionUtils;

public final class Cache {
    //////////////////////////////////////////////////////////////////////////////////////
    // PUBLIC CONSTANTS
    //////////////////////////////////////////////////////////////////////////////////////

    public static final int DEFAULT_CACHE_SIZE = 1024;

    //////////////////////////////////////////////////////////////////////////////////////
    // PRIVATE MEMBERS
    //////////////////////////////////////////////////////////////////////////////////////

    private static Context sContext;

    private static ModelInfo sModelInfo;
    private static DatabaseHelper sDatabaseHelper;

    private static LruCache<String, Model> sEntities;

    private static boolean sIsInitialized = false;

    private static Map<Class<? extends Model>, ModelFiller> sFillers;

    //////////////////////////////////////////////////////////////////////////////////////
    // CONSTRUCTORS
    //////////////////////////////////////////////////////////////////////////////////////

    private Cache() {
    }

    //////////////////////////////////////////////////////////////////////////////////////
    // PUBLIC METHODS
    //////////////////////////////////////////////////////////////////////////////////////

    public static synchronized void initialize(Configuration configuration) {
        if (sIsInitialized) {
            Log.v("ActiveAndroid already initialized.");
            return;
        }

        sContext = configuration.getContext();
        sModelInfo = new ModelInfo(configuration);
        sDatabaseHelper = new DatabaseHelper(configuration);

        // TODO: It would be nice to override sizeOf here and calculate the memory
        // actually used, however at this point it seems like the reflection
        // required would be too costly to be of any benefit. We'll just set a max
        // object size instead.
        sEntities = new LruCache<String, Model>(configuration.getCacheSize());

        initializeModelFillers();

        openDatabase();

        sIsInitialized = true;

        Log.v("ActiveAndroid initialized successfully.");
    }

    public static synchronized void clear() {
        sEntities.evictAll();
        Log.v("Cache cleared.");
    }

    public static synchronized void dispose() {
        closeDatabase();

        sEntities = null;
        sModelInfo = null;
        sDatabaseHelper = null;

        sIsInitialized = false;

        Log.v("ActiveAndroid disposed. Call initialize to use library.");
    }

    // Database access

    public static boolean isInitialized() {
        return sIsInitialized;
    }

    public static synchronized SQLiteDatabase openDatabase() {
        return sDatabaseHelper.getWritableDatabase();
    }

    public static synchronized void closeDatabase() {
        if (sDatabaseHelper != null) {
            sDatabaseHelper.close();
        }
    }

    // Context access

    public static Context getContext() {
        return sContext;
    }

    // Entity cache

    public static String getIdentifier(Class<? extends Model> type, Long id) {
        return getTableName(type) + "@" + id;
    }

    public static String getIdentifier(Model entity) {
        return getIdentifier(entity.getClass(), entity.getId());
    }

    public static synchronized void addEntity(Model entity) {
        sEntities.put(getIdentifier(entity), entity);
    }

    public static synchronized Model getEntity(Class<? extends Model> type, long id) {
        return sEntities.get(getIdentifier(type, id));
    }

    public static synchronized void removeEntity(Model entity) {
        sEntities.remove(getIdentifier(entity));
    }

    // Model cache

    public static synchronized Collection<TableInfo> getTableInfos() {
        return sModelInfo.getTableInfos();
    }

    public static synchronized TableInfo getTableInfo(Class<? extends Model> type) {
        return sModelInfo.getTableInfo(type);
    }

    public static synchronized TypeSerializer getParserForType(Class<?> type) {
        return sModelInfo.getTypeSerializer(type);
    }

    public static synchronized String getTableName(Class<? extends Model> type) {
        return sModelInfo.getTableInfo(type).getTableName();
    }

    static ModelFiller getFiller(Class<? extends Model> type) {
        return sFillers.get(type);
    }

    private static void initializeModelFillers() {
        sFillers = new HashMap<Class<? extends Model>, ModelFiller>();
        for (TableInfo tableInfo : sModelInfo.getTableInfos()) {
            try {
                Class<? extends Model> type = tableInfo.getType();
                if (!isDoNotGenerate(type))
                    sFillers.put(type, instantiateFiller(type));
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            }
        }

    }

    private static boolean isDoNotGenerate(Class<?> clazz) {
        if (clazz.isAnnotationPresent(DoNotGenerate.class))
            return true;
        if (clazz.getSuperclass() != null)
            return isDoNotGenerate(clazz.getSuperclass());
        return false;
    }

    @SuppressWarnings("unchecked")
    private static ModelFiller instantiateFiller(Class<? extends Model> type)
            throws IllegalAccessException, InstantiationException {
        ModelFiller modelFiller = sFillers.get(type);
        if (modelFiller == null) {
            String fillerClassName = type.getName() + ModelFiller.SUFFIX;
            try {
                Class<? extends ModelFiller> fillerType = (Class<? extends ModelFiller>) Class
                        .forName(fillerClassName);
                modelFiller = fillerType.newInstance();
            } catch (ClassNotFoundException e) {
                modelFiller = new EmptyModelFiller();
            }
            if (type.getSuperclass() != null && ReflectionUtils.isModel(type.getSuperclass())) {
                modelFiller.superModelFiller = instantiateFiller((Class<? extends Model>) type.getSuperclass());
            }
        }
        return modelFiller;
    }
}