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
Rohit BajajAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

dpearsonCommented:
Annotations are generally used so that some other part of the code can find these marked elements and do some additional processing.

So the question is - what is checking for this annotation?  Since it's marked as "SOURCE", the annotation isn't present at runtime so it won't be a process using reflection.  There may be some other part of your code using an AnnotationProcessor?

You can read about examples of this here:
http://www.informit.com/articles/article.aspx?p=2027052&seqNum=6

If not, another option is that the person who wrote this just wanted an "enum" and didn't realize they could do that directly rather than using an annotation to build something similar.

Hope that helps,

Doug
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.