/** * Queries a view. * * @param <K> Object type K (key) * @param <V> Object type V (value) * @param classOfK The class of type K. * @param classOfV The class of type V. * @param classOfT The class of type T. * @return The View result entries. */ public <K, V, T> ViewResult<K, V, T> queryView( Class<K> classOfK, Class<V> classOfV, Class<T> classOfT) { InputStream instream = null; try { Reader reader = new InputStreamReader(instream = queryForStream(), Charsets.UTF_8); JsonObject json = new JsonParser().parse(reader).getAsJsonObject(); ViewResult<K, V, T> vr = new ViewResult<K, V, T>(); vr.setTotalRows(getAsLong(json, "total_rows")); vr.setOffset(getAsInt(json, "offset")); vr.setUpdateSeq(getAsLong(json, "update_seq")); JsonArray jsonArray = json.getAsJsonArray("rows"); if (jsonArray.size() == 0) { // validate available rows throw new NoDocumentException("No result was returned by this view query."); } for (JsonElement e : jsonArray) { ViewResult<K, V, T>.Rows row = vr.new Rows(); row.setId(JsonToObject(gson, e, "id", String.class)); row.setKey(JsonToObject(gson, e, "key", classOfK)); row.setValue(JsonToObject(gson, e, "value", classOfV)); if (Boolean.TRUE.equals(this.includeDocs)) { row.setDoc(JsonToObject(gson, e, "doc", classOfT)); } vr.getRows().add(row); } return vr; } finally { close(instream); } }
/** @return The previous page. */ private <T> Page<T> queryPreviousPage( int rowsPerPage, String currentStartKey, String currentStartKeyDocId, String startKey, String startKeyDocId, Class<T> classOfT) { // set view query params limit(rowsPerPage + 1); includeDocs(true); descending(true); // read backward startKey(currentStartKey); startKeyDocId(currentStartKeyDocId); // init page, query view final Page<T> page = new Page<T>(); final List<T> pageList = new ArrayList<T>(); final ViewResult<String, String, T> vr = queryView(String.class, String.class, classOfT); final List<ViewResult<String, String, T>.Rows> rows = vr.getRows(); final int resultRows = rows.size(); final int offset = vr.getOffset(); final long totalRows = vr.getTotalRows(); Collections.reverse(rows); // fix order // holds page params final JsonObject currentKeys = new JsonObject(); final JsonObject jsonNext = new JsonObject(); final JsonObject jsonPrev = new JsonObject(); currentKeys.addProperty(CURRENT_START_KEY, rows.get(0).getKey()); currentKeys.addProperty(CURRENT_START_KEY_DOC_ID, rows.get(0).getId()); for (int i = 0; i < resultRows; i++) { // set keys for the next page if (i == resultRows - 1) { // last element (i.e rowsPerPage + 1) if (resultRows >= rowsPerPage) { // if not last page page.setHasNext(true); jsonNext.addProperty(START_KEY, rows.get(i).getKey()); jsonNext.addProperty(START_KEY_DOC_ID, rows.get(i).getId()); jsonNext.add(CURRENT_KEYS, currentKeys); jsonNext.addProperty(ACTION, NEXT); page.setNextParam(Base64.encodeBase64URLSafeString(jsonNext.toString().getBytes())); continue; } } pageList.add(rows.get(i).getDoc()); } // set keys for the previous page if (offset != (totalRows - rowsPerPage - 1)) { // if not first page page.setHasPrevious(true); jsonPrev.addProperty(START_KEY, currentStartKey); jsonPrev.addProperty(START_KEY_DOC_ID, currentStartKeyDocId); jsonPrev.add(CURRENT_KEYS, currentKeys); jsonPrev.addProperty(ACTION, PREVIOUS); page.setPreviousParam(Base64.encodeBase64URLSafeString(jsonPrev.toString().getBytes())); } // calculate paging display info page.setResultList(pageList); page.setTotalResults(totalRows); page.setResultFrom((int) totalRows - (offset + rowsPerPage)); final int resultTo = (int) totalRows - offset - 1; page.setResultTo(resultTo); page.setPageNumber(resultTo / rowsPerPage); return page; }
/** @return The next page. */ private <T> Page<T> queryNextPage( int rowsPerPage, String currentStartKey, String currentStartKeyDocId, String startKey, String startKeyDocId, Class<T> classOfT) { // set view query params limit(rowsPerPage + 1); includeDocs(true); if (startKey != null) { startKey(startKey); startKeyDocId(startKeyDocId); } // init page, query view final Page<T> page = new Page<T>(); final List<T> pageList = new ArrayList<T>(); final ViewResult<String, String, T> vr = queryView(String.class, String.class, classOfT); final List<ViewResult<String, String, T>.Rows> rows = vr.getRows(); final int resultRows = rows.size(); final int offset = vr.getOffset(); final long totalRows = vr.getTotalRows(); // holds page params final JsonObject currentKeys = new JsonObject(); final JsonObject jsonNext = new JsonObject(); final JsonObject jsonPrev = new JsonObject(); currentKeys.addProperty(CURRENT_START_KEY, rows.get(0).getKey()); currentKeys.addProperty(CURRENT_START_KEY_DOC_ID, rows.get(0).getId()); for (int i = 0; i < resultRows; i++) { // set keys for the next page if (i == resultRows - 1) { // last element (i.e rowsPerPage + 1) if (resultRows > rowsPerPage) { // if not last page page.setHasNext(true); jsonNext.addProperty(START_KEY, rows.get(i).getKey()); jsonNext.addProperty(START_KEY_DOC_ID, rows.get(i).getId()); jsonNext.add(CURRENT_KEYS, currentKeys); jsonNext.addProperty(ACTION, NEXT); page.setNextParam(Base64.encodeBase64URLSafeString(jsonNext.toString().getBytes())); continue; // exclude } } pageList.add(rows.get(i).getDoc()); } // set keys for the previous page if (offset != 0) { // if not first page page.setHasPrevious(true); jsonPrev.addProperty(START_KEY, currentStartKey); jsonPrev.addProperty(START_KEY_DOC_ID, currentStartKeyDocId); jsonPrev.add(CURRENT_KEYS, currentKeys); jsonPrev.addProperty(ACTION, PREVIOUS); page.setPreviousParam(Base64.encodeBase64URLSafeString(jsonPrev.toString().getBytes())); } // calculate paging display info page.setResultList(pageList); page.setTotalResults(totalRows); page.setResultFrom(offset + 1); final int resultTo = rowsPerPage > resultRows ? resultRows : rowsPerPage; // fix when rowsPerPage exceeds returned rows page.setResultTo(offset + resultTo); page.setPageNumber((int) Math.ceil(page.getResultFrom() / Double.valueOf(rowsPerPage))); return page; }