SimpleSafeTable.java

package org.microspace.table;

import org.microspace.specific.CurrentTimeProvider;
import org.microspace.table.query.TableQuery;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * A simple table that is thread-safe, all reads and writes are auto-committed, therefore, not transactional.
 */
public class SimpleSafeTable<T> implements Table<T> {
    private final SimpleUnsafeTable<T> delegate;
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    public SimpleSafeTable(Class<T> clazz) {
        delegate = new SimpleUnsafeTable<T>(clazz);
    }

    public SimpleSafeTable(Class<T> clazz, CurrentTimeProvider timeProvider) {
        delegate = new SimpleUnsafeTable<T>(clazz, timeProvider);
    }

    @Override
    public void write(T row) {
        T copy = delegate.getObjectCopy(row);
        lock.writeLock().lock();
        try {
            delegate.write(copy);
        } finally {
            lock.writeLock().unlock();
        }
    }

    @Override
    public T read(TableQuery<T> query) {
        T ret = null;
        lock.readLock().lock();
        try {
            ret = delegate.read(query);
        } finally {
            lock.readLock().unlock();
        }
        return delegate.getObjectCopy(ret);
    }

    @Override
    public List<T> readMultiple(TableQuery<T> query) {
        List<T> ret = null;
        lock.readLock().lock();
        try {
            ret = delegate.readMultiple(query);
        } finally {
            lock.readLock().unlock();
        }
        return delegate.getObjectListCopy(ret);
    }

    @Override
    public T take(TableQuery<T> query) {
        T ret = null;
        lock.writeLock().lock();
        try {
            ret = delegate.take(query);
        } finally {
            lock.writeLock().unlock();
        }
        return delegate.getObjectCopy(ret);
    }

    @Override
    public List<T> takeMultiple(TableQuery<T> query) {
        List<T> ret = null;
        lock.writeLock().lock();
        try {
            ret = delegate.takeMultipleAndRemove(query);
        } finally {
            lock.writeLock().unlock();
        }
        return delegate.getObjectListCopy(ret);
    }

    @Override
    public T readById(Object primaryKey) {
        if (primaryKey == null) {
            throw new NullPointerException("primaryKey is null");
        }
        T ret = null;
        lock.readLock().lock();
        try {
            ret = delegate.readById(primaryKey);
        } finally {
            lock.readLock().unlock();
        }
        return delegate.getObjectCopy(ret);
    }

    @Override
    public CurrentTimeProvider getCurrentTimeProvider() {
        return delegate.getCurrentTimeProvider();
    }

    /* new methods */
    public T takeById(Object primaryKey) {
        if (primaryKey == null) {
            throw new NullPointerException("primaryKey is null");
        }
        T ret = null;
        lock.writeLock().lock();
        try {
            ret = delegate.takeByIdAndRemove(primaryKey);
        } finally {
            lock.writeLock().unlock();
        }
        return delegate.getObjectCopy(ret);
    }

    public int size() {
        int ret = 0;
        lock.readLock().lock();
        try {
            ret = delegate.size();
        } finally {
            lock.readLock().unlock();
        }
        return ret;
    }
}