diff --git a/src/main/java/org/lightcouch/CouchDbClientBase.java b/src/main/java/org/lightcouch/CouchDbClientBase.java index 956eb85..66cf162 100644 --- a/src/main/java/org/lightcouch/CouchDbClientBase.java +++ b/src/main/java/org/lightcouch/CouchDbClientBase.java @@ -146,6 +146,16 @@ public CouchDbDesign design() { public View view(String viewId) { return new View(this, viewId); } + + /** + * Provides access to CouchDB View APIS, passed through a list. + * @param viewId the view id. + * @param listId the list id. + * @return {@link View} + */ + public View list(String viewId, String listId, String mimeType) { + return new ListView(this, viewId, listId, mimeType); + } /** * Provides access to CouchDB replication APIs. @@ -533,7 +543,17 @@ InputStream get(HttpGet httpGet) { } /** - * Performs a HTTP GET request. + * Performs a HTTP GET request with a given mime-type + * @return {@link InputStream} + */ + InputStream get(URI uri, String mimeType) { + HttpGet get = new HttpGet(uri); + get.addHeader("Accept", mimeType); + return get(get); + } + + /** + * Performs a HTTP GET request with the default mime-type of application/json * @return {@link InputStream} */ InputStream get(URI uri) { diff --git a/src/main/java/org/lightcouch/ListView.java b/src/main/java/org/lightcouch/ListView.java new file mode 100644 index 0000000..b6264ce --- /dev/null +++ b/src/main/java/org/lightcouch/ListView.java @@ -0,0 +1,38 @@ +package org.lightcouch; + +import static org.lightcouch.CouchDbUtil.getStream; + +import java.io.InputStream; +import java.net.URI; + +public class ListView extends View { + + private static final String listPath(String viewId, String listId) { + if (!viewId.contains("/")) + throw new IllegalArgumentException("view must look like 'designdoc/viewname'."); + + String[] parts = viewId.split("/"); + return String.format("_design/%s/_list/%s/%s", parts[0], listId, parts[1]); + } + + private String mimeType = "application/json"; + + + public ListView(CouchDbClientBase dbc, String viewId, String listId, String mimeType) { + super(dbc, viewId); + + if (mimeType != null && !mimeType.isEmpty()) + this.mimeType = mimeType; + + this.uriBuilder = URIBuilder.buildUri(dbc.getDBUri()).path(listPath(viewId, listId)); + } + + public InputStream queryForStream() { + URI uri = uriBuilder.build(); + if(allDocsKeys != null) { // bulk docs + return getStream(dbc.post(uri, allDocsKeys)); + } + + return dbc.get(uri, this.mimeType); + } +} diff --git a/src/main/java/org/lightcouch/Page.java b/src/main/java/org/lightcouch/Page.java index e900d12..7c2dfde 100644 --- a/src/main/java/org/lightcouch/Page.java +++ b/src/main/java/org/lightcouch/Page.java @@ -18,6 +18,8 @@ import java.util.List; +import com.google.gson.annotations.SerializedName; + /** * Holds data of a page as result of a view pagination query. * @see View#queryPage(int, String, Class) @@ -25,15 +27,15 @@ * @author Ahmed Yehia */ public class Page { - private boolean isHasPrevious; - private boolean isHasNext; - private List resultList; - private long totalResults; - private int resultFrom; - private int resultTo; - private int pageNumber; - private String nextParam; - private String previousParam; + @SerializedName("has_previous") private boolean isHasPrevious; + @SerializedName("has_next") private boolean isHasNext; + @SerializedName("results") private List resultList; + @SerializedName("total_results") private long totalResults; + @SerializedName("results_from") private int resultFrom; + @SerializedName("results_to") private int resultTo; + @SerializedName("page_number") private int pageNumber; + transient private String nextParam; + transient private String previousParam; public boolean isHasPrevious() { return isHasPrevious; diff --git a/src/main/java/org/lightcouch/View.java b/src/main/java/org/lightcouch/View.java index 1802e63..c3c2a19 100644 --- a/src/main/java/org/lightcouch/View.java +++ b/src/main/java/org/lightcouch/View.java @@ -78,6 +78,14 @@ public class View { private static final String NEXT = "n"; private static final String PREVIOUS = "p"; + private static final String viewPath(String viewId) { + if (!viewId.contains("/")) + return viewId; + + String[] parts = viewId.split("/"); + return String.format("_design/%s/_view/%s", parts[0], parts[1]); + } + // view fields private String key; private String startKey; @@ -95,29 +103,24 @@ public class View { private Boolean inclusiveEnd; private Boolean updateSeq; - private CouchDbClientBase dbc; - private Gson gson; - private URIBuilder uriBuilder; - - private String allDocsKeys; // bulk docs + protected CouchDbClientBase dbc; + protected Gson gson; + protected URIBuilder uriBuilder; + protected String allDocsKeys; // bulk docs + View(CouchDbClientBase dbc, String viewId) { assertNotEmpty(viewId, "View id"); this.dbc = dbc; this.gson = dbc.getGson(); - String view = viewId; - if(viewId.contains("/")) { - String[] v = viewId.split("/"); - view = String.format("_design/%s/_view/%s", v[0], v[1]); - } - this.uriBuilder = URIBuilder.buildUri(dbc.getDBUri()).path(view); + this.uriBuilder = URIBuilder.buildUri(dbc.getDBUri()).path(viewPath(viewId)); } // Query options /** - * Queries a view as an {@link InputStream} + * Queries a view as an {@link InputStream}, potentially requesting a non-default mime-type if given *

The stream should be properly closed after usage, as to avoid connection leaks. * @return The result as an {@link InputStream}. */ @@ -126,7 +129,7 @@ public InputStream queryForStream() { if(allDocsKeys != null) { // bulk docs return getStream(dbc.post(uri, allDocsKeys)); } - + return dbc.get(uri); } diff --git a/src/test/java/org/lightcouch/tests/PageAnnotationTest.java b/src/test/java/org/lightcouch/tests/PageAnnotationTest.java new file mode 100644 index 0000000..0ff9482 --- /dev/null +++ b/src/test/java/org/lightcouch/tests/PageAnnotationTest.java @@ -0,0 +1,39 @@ +package org.lightcouch.tests; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; + +import org.junit.Test; +import org.lightcouch.Document; +import org.lightcouch.Page; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class PageAnnotationTest { + + @Test + public void properJsonSerialization() { + Page page = new Page(); + page.setHasNext(true); + page.setHasPrevious(true); + page.setNextParam("this should not be serialized"); + page.setPageNumber(42); + page.setPreviousParam("this also not"); + page.setResultFrom(1000); + page.setResultList(Collections.singletonList(new Document())); + page.setResultTo(2000); + page.setTotalResults(100000); + + Gson gson = new GsonBuilder() + .create(); + + String json = gson.toJson(page); + + assertTrue(json.contains("has_next"));; + assertTrue(json.contains("results")); + assertFalse(json.contains("nextParam")); + } +}