package com.couchbase.lite.testapp.ektorp.tests;
import com.couchbase.lite.Database;
import com.couchbase.lite.Emitter;
import com.couchbase.lite.Mapper;
import com.couchbase.lite.Reducer;
import com.couchbase.lite.View;
import com.couchbase.lite.ektorp.CBLiteHttpClient;
import junit.framework.Assert;
import org.ektorp.CouchDbConnector;
import org.ektorp.CouchDbInstance;
import org.ektorp.ViewQuery;
import org.ektorp.ViewResult;
import org.ektorp.http.HttpClient;
import org.ektorp.impl.StdCouchDbInstance;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class Views extends CBLiteEktorpTestCase {
public static final String dDocName = "ddoc";
public static final String dDocId = "_design/" + dDocName;
public static final String viewName = "aview";
public static final String viewReduceName = "aviewreduce";
public void putDocs(CouchDbConnector db) {
TestObject obj2 = new TestObject("22222", "two");
db.create(obj2);
TestObject obj4 = new TestObject("44444", "four");
db.create(obj4);
TestObject obj1 = new TestObject("11111", "one");
db.create(obj1);
TestObject obj3 = new TestObject("33333", "three");
db.create(obj3);
TestObject obj5 = new TestObject("55555", "five");
db.create(obj5);
}
public static View createView(Database db) {
View view = db.getView(String.format("%s/%s", dDocName, viewName));
view.setMap(new Mapper() {
@Override
public void map(Map<String, Object> document, Emitter emitter) {
Assert.assertNotNull(document.get("_id"));
Assert.assertNotNull(document.get("_rev"));
if(document.get("key") != null) {
emitter.emit(document.get("key"), null);
}
}
}, "1");
return view;
}
public static View createViewWithReduce(Database db) {
View view = db.getView(String.format("%s/%s", dDocName, viewReduceName));
view.setMapReduce(new Mapper() {
@Override
public void map(Map<String, Object> document, Emitter emitter) {
Assert.assertNotNull(document.get("_id"));
Assert.assertNotNull(document.get("_rev"));
if (document.get("key") != null) {
emitter.emit(document.get("key"), 1);
}
}
}, new Reducer() {
@Override
public Object reduce(List<Object> keys, List<Object> values, boolean rereduce) {
return View.totalValues(values);
}
}, "1"
);
return view;
}
public void testViewQuery() throws IOException {
HttpClient httpClient = new CBLiteHttpClient(manager);
CouchDbInstance dbInstance = new StdCouchDbInstance(httpClient);
CouchDbConnector dbConnector = dbInstance.createConnector(DEFAULT_TEST_DB, true);
putDocs(dbConnector);
createView(database);
ViewQuery query = new ViewQuery().designDocId(dDocId).viewName(viewName);
ViewResult result = dbConnector.queryView(query);
Assert.assertEquals(5, result.getTotalRows());
Assert.assertEquals("five", result.getRows().get(0).getKey());
Assert.assertEquals("four", result.getRows().get(1).getKey());
Assert.assertEquals("one", result.getRows().get(2).getKey());
Assert.assertEquals("three", result.getRows().get(3).getKey());
Assert.assertEquals("two", result.getRows().get(4).getKey());
// Start/end key query:
query = new ViewQuery().designDocId(dDocId).viewName(viewName).startKey("a").endKey("one");
result = dbConnector.queryView(query);
Assert.assertEquals(3, result.getTotalRows());
Assert.assertEquals("five", result.getRows().get(0).getKey());
Assert.assertEquals("four", result.getRows().get(1).getKey());
Assert.assertEquals("one", result.getRows().get(2).getKey());
// Start/end query without inclusive end:
query = new ViewQuery().designDocId(dDocId).viewName(viewName).startKey("a").endKey("one").inclusiveEnd(false);
result = dbConnector.queryView(query);
Assert.assertEquals(2, result.getTotalRows());
Assert.assertEquals("five", result.getRows().get(0).getKey());
Assert.assertEquals("four", result.getRows().get(1).getKey());
// Reversed:
query = new ViewQuery().designDocId(dDocId).viewName(viewName).startKey("o").endKey("five").inclusiveEnd(true).descending(true);
result = dbConnector.queryView(query);
Assert.assertEquals(2, result.getTotalRows());
Assert.assertEquals("four", result.getRows().get(0).getKey());
Assert.assertEquals("five", result.getRows().get(1).getKey());
// Reversed, no inclusive end:
query = new ViewQuery().designDocId(dDocId).viewName(viewName).startKey("o").endKey("five").inclusiveEnd(false).descending(true);
result = dbConnector.queryView(query);
Assert.assertEquals(1, result.getTotalRows());
Assert.assertEquals("four", result.getRows().get(0).getKey());
// Specific keys:
List<String> keys = new ArrayList<String>();
keys.add("two");
keys.add("four");
query = new ViewQuery().designDocId(dDocId).viewName(viewName).keys(keys);
result = dbConnector.queryView(query);
Assert.assertEquals(2, result.getTotalRows());
Assert.assertEquals("four", result.getRows().get(0).getKey());
Assert.assertEquals("two", result.getRows().get(1).getKey());
// Limit
query = new ViewQuery().designDocId(dDocId).viewName(viewName).limit(3);
result = dbConnector.queryView(query);
Assert.assertEquals(3, result.getTotalRows());
Assert.assertEquals("five", result.getRows().get(0).getKey());
Assert.assertEquals("four", result.getRows().get(1).getKey());
Assert.assertEquals("one", result.getRows().get(2).getKey());
// Limit & Skip
query = new ViewQuery().designDocId(dDocId).viewName(viewName).limit(2).skip(1);
result = dbConnector.queryView(query);
Assert.assertEquals(2, result.getTotalRows());
Assert.assertEquals("four", result.getRows().get(0).getKey());
Assert.assertEquals("one", result.getRows().get(1).getKey());
// All docs filtered by a few keys
query = new ViewQuery().allDocs().includeDocs(true).keys(keys);
result = dbConnector.queryView(query);
Assert.assertEquals(2, result.getTotalRows());
// All docs filtered by empty set of keys
ArrayList ids = new ArrayList<String>();
query = new ViewQuery().allDocs().includeDocs(true).keys(ids);
result = dbConnector.queryView(query);
Assert.assertEquals(-1, result.getTotalRows());
}
public void testViewReduceQuery() throws IOException {
HttpClient httpClient = new CBLiteHttpClient(manager);
CouchDbInstance dbInstance = new StdCouchDbInstance(httpClient);
CouchDbConnector dbConnector = dbInstance.createConnector(DEFAULT_TEST_DB, true);
putDocs(dbConnector);
createViewWithReduce(database);
//because this view has a reduce function it should default to reduce=true
ViewQuery query = new ViewQuery().designDocId(dDocId).viewName(viewReduceName);
ViewResult result = dbConnector.queryView(query);
Assert.assertEquals(1, result.getTotalRows());
Assert.assertEquals(5, result.getRows().get(0).getValueAsInt());
//we should still be able to override it and force reduce=false
query = new ViewQuery().designDocId(dDocId).viewName(viewReduceName).reduce(false);
result = dbConnector.queryView(query);
Assert.assertEquals(5, result.getTotalRows());
}
public void testViewQueryFromWeb() throws IOException {
HttpClient httpClient = new CBLiteHttpClient(manager);
CouchDbInstance dbInstance = new StdCouchDbInstance(httpClient);
CouchDbConnector couchDbConnector = dbInstance.createConnector(DEFAULT_TEST_DB, true);
String dDocName = "ddoc";
String viewName = "people";
View view = database.getView(String.format("%s/%s", dDocName, viewName));
view.setMapReduce(new Mapper() {
@Override
public void map(Map<String, Object> document, Emitter emitter) {
String type = (String) document.get("type");
if ("person".equals(type)) {
emitter.emit(null, document.get("_id"));
}
}
}, new Reducer() {
@Override
public Object reduce(List<Object> keys, List<Object> values, boolean rereduce) {
return null;
}
}, "1"
);
ViewQuery viewQuery = new ViewQuery().designDocId("_design/" + dDocName).viewName(viewName);
//viewQuery.descending(true); //use this to reverse the sorting order of the view
ViewResult viewResult = couchDbConnector.queryView(viewQuery);
Assert.assertEquals(0, viewResult.getTotalRows());
}
}