Link to home
Start Free TrialLog in
Avatar of Rohit Bajaj
Rohit BajajFlag for India

asked on

using annotations

Hi,
I have the following piece of code which uses its own custom made annotation :

package co.riva.vader.medusa.store;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.IntDef;

import com.google.gson.Gson;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import co.riva.vader.medusa.event.AllApps;
import co.riva.vader.medusa.event.AppInstall;
import co.riva.vader.medusa.event.AppUninstall;
import co.riva.vader.medusa.event.MedusaEvent;
import co.riva.vader.medusa.event.SearchCountEvent;
import co.riva.vader.medusa.event.SearchKeyword;
import to.talk.logging.Logger;
import to.talk.logging.LoggerFactory;

public class MedusaEventStore {
    private static final String TABLE_NAME = "medusa";
    private static final Logger _logger = LoggerFactory
            .getTrimmer(MedusaEventStore.class, "EventStore");
    private static final int EVENT_NONE = -1;
    private static final int EVENT_ALL_APPS = 0;
    private static final int EVENT_APP_INSTALL = 1;
    private static final int EVENT_APP_UNINSTALL = 2;
    private static final int EVENT_SEARCH_KEYWORD = 3;
    private static final int EVENT_SEARCH_COUNT = 4;
    private final SQLiteDatabase _database;
    private final List<MedusaEvent> _eventList;
    private final Gson _gson = new Gson();
    private final ReadWriteLock _lock = new ReentrantReadWriteLock();

    public MedusaEventStore(SQLiteDatabase database) {
        _database = database;
        _eventList = loadFromDb();
    }

    public static List<String> getCreateQuery() {
        String tableCreate = String.format("CREATE TABLE %s ( %s TEXT NOT NULL, " +
                        "%s INTEGER NOT NULL, %s INTEGER NOT NULL)",
                TABLE_NAME,
                Columns.EVENT,
                Columns.TYPE,
                Columns.TIMESTAMP);
        return Collections.singletonList(tableCreate);
    }

    public static String getDeleteQuery() {
        return "DROP TABLE IF EXISTS " + TABLE_NAME;
    }

    public void add(MedusaEvent event) {
        _lock.writeLock().lock();
        try {
            ContentValues cv = new ContentValues();
            if (!(getEventType(event) == EVENT_NONE)) {
                String json = toJson(event);
                cv.put(Columns.EVENT.toString(), json);
                cv.put(Columns.TIMESTAMP.toString(), event.getEventTime());
                cv.put(Columns.TYPE.toString(), getEventType(event));
                _eventList.add(event);
                _database.replace(TABLE_NAME, null, cv);
            } else {
                _logger.info("MedusaEvent of type none encountered : {}",event);
            }
        } finally {
            _lock.writeLock().unlock();
        }
    }

    public void addAll(List<MedusaEvent> events) {
        _lock.writeLock().lock();
        try {
            for (MedusaEvent event : events) {
                add(event);
            }
        } finally {
            _lock.writeLock().unlock();
        }
    }

    public void clear() {
        _lock.writeLock().lock();
        try {
            _eventList.clear();
            _database.delete(TABLE_NAME, null, null);
        } finally {
            _lock.writeLock().unlock();
        }
    }

    public List<MedusaEvent> getAll() {
        _lock.readLock().lock();
        try {
            return new ArrayList<>(_eventList);
        } finally {
            _lock.readLock().unlock();
        }
    }

    public void removeAllBefore(long timeMillis) {
        _lock.writeLock().lock();
        try {
            Iterator<MedusaEvent> iterator = _eventList.iterator();
            while (iterator.hasNext()) {
                long timestamp = iterator.next().getEventTime();
                if (timestamp <= timeMillis) {
                    iterator.remove();
                }
            }
            String where = Columns.TIMESTAMP + "<= ?";
            String[] whereArgs = new String[]{String.valueOf(timeMillis)};
            _database.delete(TABLE_NAME, where, whereArgs);
        } finally {
            _lock.writeLock().unlock();
        }
    }

    private List<MedusaEvent> loadFromDb() {
        _lock.writeLock().lock();
        String[] column = new String[]{Columns.EVENT.toString(), Columns.TYPE.toString()};
        Cursor cursor = _database.query(TABLE_NAME, column, null, null, null, null, null, null);
        List<MedusaEvent> events = new ArrayList<>();
        try {
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    String event = cursor.getString(cursor.getColumnIndexOrThrow(Columns.EVENT.toString()));
                    @EventType int type = cursor.getInt(cursor.getColumnIndexOrThrow(Columns.TYPE.toString()));
                    MedusaEvent medusaEvent = fromJson(event, type);
                    if (medusaEvent != null) {
                        events.add(medusaEvent);
                    }
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            _lock.writeLock().unlock();
        }
        return events;
    }

    private MedusaEvent fromJson(String jsonEvent, @EventType int eventType) {
        Type classType = getClassType(eventType);
        if (eventType != EVENT_NONE) {
            return (MedusaEvent) _gson.fromJson(jsonEvent, classType);
        } else {
            return null;
        }
    }

    private String toJson(MedusaEvent event) {
        Type classType = getClassType(getEventType(event));
        return _gson.toJson(event, classType);
    }

    @EventType
    private int getEventType(MedusaEvent event) {
        if (event instanceof AllApps) {
            return EVENT_ALL_APPS;
        } else if (event instanceof AppInstall) {
            return EVENT_APP_INSTALL;
        } else if (event instanceof AppUninstall) {
            return EVENT_APP_UNINSTALL;
        } else if (event instanceof SearchKeyword) {
            return EVENT_SEARCH_KEYWORD;
        } else if (event instanceof SearchCountEvent) {
            return EVENT_SEARCH_COUNT;
        } else {
            return EVENT_NONE;
        }
    }

    private Type getClassType(@EventType int eventType) {
        switch (eventType) {
            case EVENT_ALL_APPS:
                return AllApps.class;
            case EVENT_APP_INSTALL:
                return AppInstall.class;
            case EVENT_APP_UNINSTALL:
                return AppUninstall.class;
            case EVENT_SEARCH_KEYWORD:
                return SearchKeyword.class;
            case EVENT_SEARCH_COUNT:
                return SearchCountEvent.class;
            default:
                throw new ClassCastException("Unknown medusa event");
        }
    }

    private enum Columns {
        EVENT, TIMESTAMP, TYPE
    }

    @IntDef({EVENT_NONE, EVENT_ALL_APPS, EVENT_APP_INSTALL, EVENT_APP_UNINSTALL, EVENT_SEARCH_KEYWORD, EVENT_SEARCH_COUNT})
    @Retention(RetentionPolicy.SOURCE)
    private @interface EventType {
    }
}

Open in new window



My question is why use annotation here. What benefit is this serving. I can simply use the static final variables without the annotation.

Thanks
ASKER CERTIFIED SOLUTION
Avatar of dpearson
dpearson

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial