package net.davidvoid.thor.lightning.data.access;

import java.util.ArrayList;
import java.util.List;

import net.davidvoid.thor.lightning.data.source.MongoDataSource;
import net.davidvoid.thor.lightning.entity.Entity;
import net.davidvoid.thor.lightning.exception.ResourceNotFoundException;

import org.springframework.beans.factory.annotation.Autowired;

import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;

public abstract class AbstractStore {
    @Autowired
    private MongoDataSource data_source = null;

    @Autowired
    private Counter counter = null;

    final public void add(Entity entity) {
        assert (!entity.has_valid_id());

        generateId(entity);
        DBObject object = toDBObject(entity);
        getCollection().insert(object);
    }

    final public void delete(Entity entity) {
        assert (entity.has_valid_id());

        DBObject query = getModifyQuery(entity);
        getCollection().remove(query);
    }

    final public void update(Entity entity) {
        assert (entity.has_valid_id());

        DBObject query = getModifyQuery(entity);
        DBObject update = toDBObject(entity);
        getCollection().update(query, update, false, true);
    }

    final protected List<Entity> get(DBObject query) {
        DBCursor cursor = getCollection().find(query);

        return retrieveAll(cursor);
    }

    final protected List<Entity> retrieveAll(DBCursor cursor) {
        ArrayList<Entity> list = new ArrayList<Entity>();
        while (cursor.hasNext()) {
            Entity entity = toEntity(cursor.next());
            list.add(entity);
        }
        return list;
    }

    final protected Entity getOne(DBObject query) {
        DBObject object = getCollection().findOne(query);
        if (object == null)
            throw new ResourceNotFoundException("resource not found in db");

        return toEntity(object);
    }

    final protected long generateNextId(String name) {
        return counter.getNextId(name);
    }

    final protected DBCollection getCollection() {
        return data_source.getDatabase().getCollection(getCollectionName());
    }

    protected abstract DBObject toDBObject(Entity entity);

    protected abstract Entity toEntity(DBObject object);

    private void generateId(Entity entity) {
        entity.setId(generateNextId(getCollectionName()));
    }

    protected abstract DBObject getModifyQuery(Entity entity);

    protected abstract String getCollectionName();
}

@@ -42,24 +42,81 @@
 .access;%0D%0A%0D%0A
+import static org.springframework.util.Assert.isTrue;%0D%0A%0D%0A
 import java.
@@ -415,16 +415,66 @@
 owired;%0D
+%0Aimport static org.springframework.util.Assert.*;%0D
 %0A%0D%0Aimpor
@@ -781,38 +781,133 @@
     
-assert (!entity.has_valid_id()
+notNull(entity);%0D%0A        isTrue(!entity.has_valid_id(),%0D%0A                %22the entity to be saved should not have a valid id%22
 );%0D%0A
@@ -1093,37 +1093,130 @@
     
-assert (entity.has_valid_id()
+notNull(entity);%0D%0A        isTrue(entity.has_valid_id(),%0D%0A                %22the entity to be deleted should have a valid id%22
 );%0D%0A
@@ -1303,24 +1303,56 @@
 ve(query);%0D%0A
+        entity.setInvalidId();%0D%0A
     %7D%0D%0A%0D%0A   
@@ -1407,37 +1407,130 @@
     
-assert (entity.has_valid_id()
+notNull(entity);%0D%0A        isTrue(entity.has_valid_id(),%0D%0A                %22the entity to be updated should have a valid id%22
 );%0D%0A
@@ -1746,32 +1746,101 @@
 bject query) %7B%0D%0A
+        assert query != null : %22mongodb query should be be null%22;%0D%0A%0D%0A
         DBCursor
@@ -1875,26 +1875,24 @@
 nd(query);%0D%0A
-%0D%0A
         retu
@@ -2257,32 +2257,101 @@
 bject query) %7B%0D%0A
+        assert query != null : %22mongodb query should be be null%22;%0D%0A%0D%0A
         DBObject
@@ -2613,100 +2613,446 @@
     
-return counter.getNextId(name);%0D%0A    %7D%0D%0A%0D%0A    final protected DBCollection getCollection() %7B
+assert name != null : %22next id collection name should not be null%22;%0D%0A        assert !name.isEmpty() : %22next id collection name should not be empty%22;%0D%0A%0D%0A        return counter.getNextId(name);%0D%0A    %7D%0D%0A%0D%0A    final protected DBCollection getCollection() %7B%0D%0A        assert getCollectionName() != null : %22getCollectionName should not return null%22;%0D%0A        assert !getCollectionName().isEmpty() : %22getCollectionName should not return empty%22;%0D%0A
 %0D%0A  
@@ -3146,44 +3146,29 @@
   pr
-otected abstract DBObject toDBObject
+ivate void generateId
 (Ent
@@ -3182,184 +3182,385 @@
 ity)
-;%0D%0A
+ %7B
 %0D%0A    
-protected abstract Entity toEntity(DBObject object);%0D%0A%0D%0A
+    assert getCollectionName() != null : %22getCollectionName should not return null%22;%0D%0A 
     
-private void generateId(Entity entity) %7B%0D%0A        entity.setId(generateNextId(getCollectionName()));%0D%0A    %7D
+   assert !getCollectionName().isEmpty() : %22getCollectionName should not return empty%22;%0D%0A%0D%0A        entity.setId(generateNextId(getCollectionName()));%0D%0A    %7D%0D%0A%0D%0A    protected abstract DBObject toDBObject(Entity entity);%0D%0A%0D%0A    protected abstract Entity toEntity(DBObject object);
 %0D%0A%0D%0A

add precondition check