Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #70 from dwt/correct-json-for-js

Correct json for js
  • Loading branch information...
commit 59ddf37d6e7bb819f969909971c202eab8c44119 2 parents 004355b + 7cf9280
@mschoch mschoch authored
View
39 TouchDB-Android-JavaScript/src/com/couchbase/touchdb/javascript/TDJavaScriptViewCompiler.java
@@ -1,8 +1,10 @@
package com.couchbase.touchdb.javascript;
+import java.io.IOException;
import java.util.List;
import java.util.Map;
+import org.codehaus.jackson.map.ObjectMapper;
import org.elasticsearch.script.javascript.support.NativeList;
import org.elasticsearch.script.javascript.support.NativeMap;
import org.mozilla.javascript.Context;
@@ -61,6 +63,7 @@ else if(javaObject instanceof List) {
}
}
+// REFACT: Extract superview for both the map and reduce blocks as they do pretty much the same thing
class TDViewMapBlockRhino implements TDViewMapBlock {
private static WrapFactory wrapFactory = new CustomWrapFactory();
@@ -102,21 +105,36 @@ public void map(Map<String, Object> document, TDViewMapEmitBlock emitter) {
// Error in the JavaScript view - CouchDB swallows the error and tries the next document
// REFACT: would be nice to check this in the constructor so we don't have to reparse every time
// should also be much faster if we can insert the map function into this objects globals
- Log.e(TDDatabase.TAG, "Javascript syntax error in view:\n" + src);
+ Log.e(TDDatabase.TAG, "Javascript syntax error in view:\n" + src, e);
return;
}
-
- //find the map function and execute it
- Function mapFun = (Function)globalScope.get("map", globalScope);
- Object[] functionArgs = { document };
+
+ // Need to stringify the json tree, as the ContextWrapper is unable
+ // to correctly convert nested json to their js representation.
+ // More specifically, if a dictionary is included that contains an array as a value
+ // that array will not be wrapped correctly but you'll get the plain
+ // java.util.ArrayList instead - and then an error.
+ ObjectMapper mapper = new ObjectMapper();
+ String json = null;
+ try {
+ json = mapper.writeValueAsString(document);
+ } catch (IOException e) {
+ // Can thrown different subclasses of IOException- but we really do not care,
+ // as this document was unserialized from JSON, so Jackson should be able to serialize it.
+ Log.e(TDDatabase.TAG, "Error reserializing json from the db: " + document, e);
+ return;
+ }
+
+ String mapInvocation = "map(" + json + ");";
try {
- mapFun.call(ctx, globalScope, globalScope, functionArgs);
- } catch (org.mozilla.javascript.RhinoException e) {
+ ctx.evaluateString(globalScope, mapInvocation, "map invocation", 1, null);
+ }
+ catch (org.mozilla.javascript.RhinoException e) {
// Error in the JavaScript view - CouchDB swallows the error and tries the next document
- Log.e(TDDatabase.TAG, "Error in javascript view:\n" + src + "\n with document:\n" + document);
+ Log.e(TDDatabase.TAG, "Error in javascript view:\n" + src + "\n with document:\n" + document, e);
return;
-
}
+
//now pull values out of the place holder and emit them
NativeArray mapResults = (NativeArray)globalScope.get("map_results", globalScope);
for(int i=0; i<mapResults.getLength(); i++) {
@@ -130,9 +148,6 @@ public void map(Map<String, Object> document, TDViewMapEmitBlock emitter) {
}
}
-
-
-
} finally {
Context.exit();
}
View
22 TouchDB-Android-TestApp/src/com/couchbase/touchdb/testapp/javascript/tests/JavaScriptDesignDocument.java
@@ -38,6 +38,7 @@ Object ddocWithMap(String viewName, String mapFunction) throws Exception {
// REFACT: consider pulling up into TouchDBTestCase
List<Object> getView(String fullViewPath) throws Exception {
Map<String, Object> result = (Map<String, Object>) send(server, "GET", fullViewPath, TDStatus.OK, null);
+ assertEquals(0, result.get("offset"));
return (List<Object>) result.get("rows");
}
@@ -197,6 +198,26 @@ public void testRealJavaScriptDesignDocument() {
// Query the view and check the result:
Object res = send(server, "GET", "/rhinodb/_design/doc/_view/test", TDStatus.OK, expectedResult);
}
+
+ public void testJavaScriptDesignDocumentThatDealsWithArrays() throws Exception {
+ Object json = json(
+ "{" +
+ "\"producers\": [ \"\" ]," +
+ "\"collection\": \"product\"" +
+ "}");
+ sendBody(server, "PUT", "/rhinodb/doc1", json, TDStatus.CREATED, null);
+
+ Object ddoc = ddocWithMap("test", "function(doc) { if ('product' === doc.collection && doc.producers) { doc.producers.forEach(function(each) { emit(each, doc); }); } }");
+ sendBody(server, "PUT", "/rhinodb/_design/doc", ddoc, TDStatus.CREATED, null);
+
+ List<Object> rows = getView("/rhinodb/_design/doc/_view/test", 1);
+ Map<String,Object> resultRow = (Map) rows.get(0);
+ assertEquals("doc1", resultRow.get("id"));
+ assertEquals("", resultRow.get("key"));
+ Map<String,Object> value = (Map) resultRow.get("value");
+ assertEquals("doc1", value.get("_id"));
+ }
+
public void testShouldLeaveOutDocumentsWhenMapBlockThrowsAnException() throws Exception {
sendBody(server, "PUT", "/rhinodb/good", json("{}"), TDStatus.CREATED, null);
sendBody(server, "PUT", "/rhinodb/bad", json("{}"), TDStatus.CREATED, null);
@@ -230,5 +251,4 @@ public void testShouldDiscardDocumentsIfViewThrowsEcmaError() throws Exception {
assertEquals("good", resultRow.get("id"));
}
-
}
Please sign in to comment.
Something went wrong with that request. Please try again.