Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Updated PR #100 #103

Merged
merged 3 commits into from

2 participants

@pgelinas

Modification following the comment on PR #100. I've also fixed a minor issue: the json parser was never closed, so things like the symbol table and internal buffers were never released.

@helun helun merged commit 6b4e4f1 into helun:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 12, 2012
  1. @pgelinas

    Don't provide an initial capacity to the array list by using total_ro…

    pgelinas authored
    …ws, since it indicates the total row in a view, not the result.
  2. @pgelinas
  3. @pgelinas

    Formatted.

    pgelinas authored
This page is out of date. Refresh to see the latest.
Showing with 137 additions and 127 deletions.
  1. +137 −127 org.ektorp/src/main/java/org/ektorp/impl/QueryResultParser.java
View
264 org.ektorp/src/main/java/org/ektorp/impl/QueryResultParser.java
@@ -22,84 +22,89 @@
* @author Pascal Gélinas (rewrite for issue #98)
*/
public class QueryResultParser<T> {
- private static final String NOT_FOUND_ERROR = "not_found";
+ private static final String NOT_FOUND_ERROR = "not_found";
private static final String ROWS_FIELD_NAME = "rows";
- private static final String VALUE_FIELD_NAME = "value";
- private static final String ID_FIELD_NAME = "id";
- private static final String ERROR_FIELD_NAME = "error";
- private static final String KEY_FIELD_NAME = "key";
- private static final String INCLUDED_DOC_FIELD_NAME = "doc";
- private static final String TOTAL_ROWS_FIELD_NAME = "total_rows";
- private static final String OFFSET_FIELD_NAME = "offset";
-
- private int totalRows = -1;
- private int offset = -1;
- private List<T> rows;
-
- private String firstId;
- private JsonNode firstKey;
-
- private String lastId;
- private JsonNode lastKey;
-
- private final ObjectMapper mapper;
- private final Class<T> type;
- private boolean ignoreNotFound;
-
- public QueryResultParser(Class<T> type, ObjectMapper mapper) {
- this.type = type;
- this.mapper = mapper;
- }
-
- public void parseResult(InputStream json) throws IOException {
- JsonParser jp = mapper.getFactory().createJsonParser(json);
-
- if (jp.nextToken() != JsonToken.START_OBJECT) {
- throw new DbAccessException("Expected data to start with an Object");
- }
-
- Map<String,String> errorFields = new HashMap<String, String>();
- // Issue #98: Can't assume order of JSON fields.
- while(jp.nextValue() != JsonToken.END_OBJECT){
- String currentName = jp.getCurrentName();
- if(OFFSET_FIELD_NAME.equals(currentName)){
- offset = jp.getIntValue();
- } else if(TOTAL_ROWS_FIELD_NAME.equals(currentName)){
- totalRows = jp.getIntValue();
- } else if (ROWS_FIELD_NAME.equals(currentName)){
- if(totalRows == -1){
- rows = new ArrayList<T>();
- }else{
- rows = new ArrayList<T>(totalRows);
- }
- parseRows(jp);
- }else{
- // Handle cloudant errors.
- errorFields.put(jp.getCurrentName(), jp.getText());
- }
- }
-
- if(!errorFields.isEmpty()){
- JsonNode error = mapper.convertValue(errorFields, JsonNode.class);
+ private static final String VALUE_FIELD_NAME = "value";
+ private static final String ID_FIELD_NAME = "id";
+ private static final String ERROR_FIELD_NAME = "error";
+ private static final String KEY_FIELD_NAME = "key";
+ private static final String INCLUDED_DOC_FIELD_NAME = "doc";
+ private static final String TOTAL_ROWS_FIELD_NAME = "total_rows";
+ private static final String OFFSET_FIELD_NAME = "offset";
+
+ private int totalRows = -1;
+ private int offset = -1;
+ private List<T> rows;
+
+ private String firstId;
+ private JsonNode firstKey;
+
+ private String lastId;
+ private JsonNode lastKey;
+
+ private final ObjectMapper mapper;
+ private final Class<T> type;
+ private boolean ignoreNotFound;
+
+ public QueryResultParser(Class<T> type, ObjectMapper mapper) {
+ this.type = type;
+ this.mapper = mapper;
+ }
+
+ public void parseResult(InputStream json) throws IOException {
+ JsonParser jp = mapper.getFactory().createParser(json);
+
+ try {
+ parseResult(jp);
+ } finally {
+ jp.close();
+ }
+ }
+
+ private void parseResult(JsonParser jp) throws IOException {
+ if (jp.nextToken() != JsonToken.START_OBJECT) {
+ throw new DbAccessException("Expected data to start with an Object");
+ }
+
+ Map<String, String> errorFields = new HashMap<String, String>();
+ // Issue #98: Can't assume order of JSON fields.
+ while (jp.nextValue() != JsonToken.END_OBJECT) {
+ String currentName = jp.getCurrentName();
+ if (OFFSET_FIELD_NAME.equals(currentName)) {
+ offset = jp.getIntValue();
+ } else if (TOTAL_ROWS_FIELD_NAME.equals(currentName)) {
+ totalRows = jp.getIntValue();
+ } else if (ROWS_FIELD_NAME.equals(currentName)) {
+ rows = new ArrayList<T>();
+ parseRows(jp);
+ } else {
+ // Handle cloudant errors.
+ errorFields.put(jp.getCurrentName(), jp.getText());
+ }
+ }
+
+ if (!errorFields.isEmpty()) {
+ JsonNode error = mapper.convertValue(errorFields, JsonNode.class);
throw new DbAccessException(error.toString());
- }
- }
+ }
+ }
- private void parseRows(JsonParser jp) throws IOException{
- if (jp.getCurrentToken() != JsonToken.START_ARRAY) {
+ private void parseRows(JsonParser jp) throws IOException {
+ if (jp.getCurrentToken() != JsonToken.START_ARRAY) {
throw new DbAccessException("Expected rows to start with an Array");
}
-
- // Parses the first row that isn't an error row to find out which field to use (doc or value).
- String dataField = null;
- while (dataField == null && jp.nextToken() == JsonToken.START_OBJECT) {
+
+ // Parses the first row that isn't an error row to find out which field
+ // to use (doc or value).
+ String dataField = null;
+ while (dataField == null && jp.nextToken() == JsonToken.START_OBJECT) {
Row row = jp.readValueAs(Row.class);
if (row.error != null) {
- if (!ignoreError(row.error)){
+ if (!ignoreError(row.error)) {
throw new ViewResultException(row.key, row.error);
}
continue;
- }
+ }
if (row.doc != null) {
dataField = INCLUDED_DOC_FIELD_NAME;
rows.add(mapper.readValue(row.doc.traverse(), type));
@@ -110,86 +115,91 @@ private void parseRows(JsonParser jp) throws IOException{
firstId = row.id;
firstKey = row.key;
}
- // After the while, either we point at END_ARRAY but we have no dataField (all rows were error),
- // or we point at an END_OBJECT (end of a row) and have determined which data field to use.
- if(dataField == null) return;
-
- // Parse all the remaining rows; jp points at START_OBJECT except after the last row
- while(jp.nextToken() != JsonToken.END_ARRAY){
- String currentId = null;
- JsonNode currentKey = null;
+ // After the while, either we point at END_ARRAY but we have no
+ // dataField (all rows were error),
+ // or we point at an END_OBJECT (end of a row) and have determined which
+ // data field to use.
+ if (dataField == null)
+ return;
+
+ // Parse all the remaining rows; jp points at START_OBJECT except after
+ // the last row
+ while (jp.nextToken() != JsonToken.END_ARRAY) {
+ String currentId = null;
+ JsonNode currentKey = null;
String error = null;
- T value = null;
- // Parse the fields of a row; jp points at a value token except after the last field.
- while(jp.nextValue() != JsonToken.END_OBJECT){
- String currentName = jp.getCurrentName();
- if(ID_FIELD_NAME.equals(currentName)){
- currentId = jp.getText();
- } else if (KEY_FIELD_NAME.equals(currentName)){
- currentKey = jp.readValueAsTree();
- } else if(dataField.equals(currentName)){
- value = jp.readValueAs(type);
- } else if(ERROR_FIELD_NAME.equals(currentName)){
+ T value = null;
+ // Parse the fields of a row; jp points at a value token except
+ // after the last field.
+ while (jp.nextValue() != JsonToken.END_OBJECT) {
+ String currentName = jp.getCurrentName();
+ if (ID_FIELD_NAME.equals(currentName)) {
+ currentId = jp.getText();
+ } else if (KEY_FIELD_NAME.equals(currentName)) {
+ currentKey = jp.readValueAsTree();
+ } else if (dataField.equals(currentName)) {
+ value = jp.readValueAs(type);
+ } else if (ERROR_FIELD_NAME.equals(currentName)) {
error = jp.getText();
} else {
// Skip fields value that are of no interest to us.
jp.skipChildren();
}
- }
- if (error != null && !ignoreError(error)){
+ }
+ if (error != null && !ignoreError(error)) {
throw new ViewResultException(currentKey, error);
- }
- // If the current row is an error row, then value will be null
- if(value != null){
- lastId = currentId;
- lastKey = currentKey;
- rows.add(value);
- }
- }
- }
+ }
+ // If the current row is an error row, then value will be null
+ if (value != null) {
+ lastId = currentId;
+ lastKey = currentKey;
+ rows.add(value);
+ }
+ }
+ }
private boolean ignoreError(String error) {
return ignoreNotFound && NOT_FOUND_ERROR.equals(error);
}
- public int getTotalRows() {
- return totalRows;
- }
+ public int getTotalRows() {
+ return totalRows;
+ }
- public int getOffset() {
- return offset;
- }
+ public int getOffset() {
+ return offset;
+ }
- public List<T> getRows() {
- return rows;
- }
-
- public String getLastId() {
+ public List<T> getRows() {
+ return rows;
+ }
+
+ public String getLastId() {
return lastId;
}
-
- public JsonNode getLastKey() {
+
+ public JsonNode getLastKey() {
return lastKey;
}
-
- public String getFirstId() {
+
+ public String getFirstId() {
return firstId;
}
-
- public JsonNode getFirstKey() {
+
+ public JsonNode getFirstKey() {
return firstKey;
}
- public void setIgnoreNotFound(boolean ignoreNotFound) {
- this.ignoreNotFound = ignoreNotFound;
- }
-
- @JsonAutoDetect(fieldVisibility=Visibility.ANY)
- private static class Row {
- private String id;
- private JsonNode key;
- private JsonNode value;
- private JsonNode doc;
- private String error;
- }
+ public void setIgnoreNotFound(boolean ignoreNotFound) {
+ this.ignoreNotFound = ignoreNotFound;
+ }
+
+ @JsonAutoDetect(fieldVisibility = Visibility.ANY)
+ private static class Row {
+ private String id;
+ private JsonNode key;
+ private JsonNode value;
+ private JsonNode doc;
+ private String error;
+ }
}
Something went wrong with that request. Please try again.