Skip to content
This repository has been archived by the owner on Mar 9, 2022. It is now read-only.

Commit

Permalink
fixed bug where lists in documents were not properly wrapped for rhino
Browse files Browse the repository at this point in the history
  • Loading branch information
mschoch committed Jun 30, 2012
1 parent 01f13ea commit 70d89ec
Show file tree
Hide file tree
Showing 3 changed files with 311 additions and 0 deletions.
@@ -1,7 +1,9 @@
package com.couchbase.touchdb.javascript;

import java.util.List;
import java.util.Map;

import org.elasticsearch.script.javascript.support.NativeList;
import org.elasticsearch.script.javascript.support.NativeMap;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
Expand Down Expand Up @@ -113,6 +115,9 @@ public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObje
if (javaObject instanceof Map) {
return new NativeMap(scope, (Map) javaObject);
}
else if(javaObject instanceof List) {
return new NativeList(scope, (List<Object>)javaObject);
}

return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
}
Expand Down
@@ -0,0 +1,207 @@
/*
* Licensed to ElasticSearch and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. ElasticSearch licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.elasticsearch.script.javascript.support;

import java.util.List;

import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.Undefined;
import org.mozilla.javascript.Wrapper;

/**
*
*/
public class NativeList implements Scriptable, Wrapper {
private static final long serialVersionUID = 3664761893203964569L;

private List<Object> list;
private Scriptable parentScope;
private Scriptable prototype;


public static NativeList wrap(Scriptable scope, List<Object> list) {
return new NativeList(scope, list);
}

public NativeList(Scriptable scope, List<Object> list) {
this.parentScope = scope;
this.list = list;
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Wrapper#unwrap()
*/

public Object unwrap() {
return list;
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#getClassName()
*/

public String getClassName() {
return "NativeList";
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#get(java.lang.String, org.mozilla.javascript.Scriptable)
*/

public Object get(String name, Scriptable start) {
if ("length".equals(name)) {
return list.size();
} else {
return Undefined.instance;
}
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#get(int, org.mozilla.javascript.Scriptable)
*/

public Object get(int index, Scriptable start) {
if (index < 0 || index >= list.size()) {
return Undefined.instance;
}
return list.get(index);
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#has(java.lang.String, org.mozilla.javascript.Scriptable)
*/

public boolean has(String name, Scriptable start) {
if ("length".equals(name)) {
return true;
}
return false;
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#has(int, org.mozilla.javascript.Scriptable)
*/

public boolean has(int index, Scriptable start) {
return index >= 0 && index < list.size();
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#put(java.lang.String, org.mozilla.javascript.Scriptable, java.lang.Object)
*/

@SuppressWarnings("unchecked")
public void put(String name, Scriptable start, Object value) {
// do nothing here...
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#put(int, org.mozilla.javascript.Scriptable, java.lang.Object)
*/

public void put(int index, Scriptable start, Object value) {
if (index == list.size()) {
list.add(value);
} else {
list.set(index, value);
}
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#delete(java.lang.String)
*/

public void delete(String name) {
// nothing here
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#delete(int)
*/

public void delete(int index) {
list.remove(index);
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#getPrototype()
*/

public Scriptable getPrototype() {
return this.prototype;
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#setPrototype(org.mozilla.javascript.Scriptable)
*/

public void setPrototype(Scriptable prototype) {
this.prototype = prototype;
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#getParentScope()
*/

public Scriptable getParentScope() {
return this.parentScope;
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#setParentScope(org.mozilla.javascript.Scriptable)
*/

public void setParentScope(Scriptable parent) {
this.parentScope = parent;
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#getIds()
*/

public Object[] getIds() {
int size = list.size();
Object[] ids = new Object[size];
for (int i = 0; i < size; ++i) {
ids[i] = i;
}
return ids;
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#getDefaultValue(java.lang.Class)
*/

public Object getDefaultValue(Class hint) {
return null;
}

/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#hasInstance(org.mozilla.javascript.Scriptable)
*/

public boolean hasInstance(Scriptable value) {
if (!(value instanceof Wrapper))
return false;
Object instance = ((Wrapper) value).unwrap();
return List.class.isInstance(instance);
}

}
Expand Up @@ -83,4 +83,103 @@ public void testJavaScriptDesignDocument() {
server.close();
}

public void testRealJavaScriptDesignDocument() {

TDServer server = null;
try {
server = new TDServer(getServerPath());
} catch (IOException e) {
fail("Creating server caused IOException");
}

//register the javascript view compilter
TDView.setCompiler(new TDJavaScriptViewCompiler());

send(server, "PUT", "/rhinodb", TDStatus.CREATED, null);

// PUT:
Map<String,Object> doc1 = new HashMap<String,Object>();
List<String> cat1 = new ArrayList();
cat1.add("apple");
cat1.add("bannana");
doc1.put("categories", cat1);
Map<String,Object> result = (Map<String,Object>)sendBody(server, "PUT", "/rhinodb/doc1", doc1, TDStatus.CREATED, null);

Map<String,Object> doc2 = new HashMap<String,Object>();
List<String> cat2 = new ArrayList();
cat2.add("clock");
cat2.add("dill");
doc2.put("categories", cat2);
Map<String,Object> result2 = (Map<String,Object>)sendBody(server, "PUT", "/rhinodb/doc2", doc2, TDStatus.CREATED, null);

Map<String,Object> doc3 = new HashMap<String,Object>();
List<String> cat3 = new ArrayList();
cat3.add("elephant");
cat3.add("fun");
doc3.put("categories", cat3);
Map<String,Object> result3 = (Map<String,Object>)sendBody(server, "PUT", "/rhinodb/doc3", doc3, TDStatus.CREATED, null);


Map<String,Object> ddocViewTest = new HashMap<String,Object>();
ddocViewTest.put("map", "function(doc) { if (doc.categories) { for (i in doc.categories) { emit(doc.categories[i], 1); } } }");

Map<String,Object> ddocViews = new HashMap<String,Object>();
ddocViews.put("test", ddocViewTest);

Map<String,Object> ddoc = new HashMap<String,Object>();
ddoc.put("views", ddocViews);
Map<String,Object> ddocresult = (Map<String,Object>)sendBody(server, "PUT", "/rhinodb/_design/doc", ddoc, TDStatus.CREATED, null);

// Build up our expected result

Map<String,Object> row1 = new HashMap<String,Object>();
row1.put("id", "doc1");
row1.put("key", "apple");
row1.put("value", 1.0);

Map<String,Object> row2 = new HashMap<String,Object>();
row2.put("id", "doc1");
row2.put("key", "bannana");
row2.put("value", 1.0);

Map<String,Object> row3 = new HashMap<String,Object>();
row3.put("id", "doc2");
row3.put("key", "clock");
row3.put("value", 1.0);

Map<String,Object> row4 = new HashMap<String,Object>();
row4.put("id", "doc2");
row4.put("key", "dill");
row4.put("value", 1.0);

Map<String,Object> row5 = new HashMap<String,Object>();
row5.put("id", "doc3");
row5.put("key", "elephant");
row5.put("value", 1.0);

Map<String,Object> row6 = new HashMap<String,Object>();
row6.put("id", "doc3");
row6.put("key", "fun");
row6.put("value", 1.0);

List<Map<String,Object>> expectedRows = new ArrayList<Map<String,Object>>();

expectedRows.add(row1);
expectedRows.add(row2);
expectedRows.add(row3);
expectedRows.add(row4);
expectedRows.add(row5);
expectedRows.add(row6);

Map<String,Object> expectedResult = new HashMap<String,Object>();
expectedResult.put("offset", 0);
expectedResult.put("total_rows", 6);
expectedResult.put("rows", expectedRows);

// Query the view and check the result:
Object res = send(server, "GET", "/rhinodb/_design/doc/_view/test", TDStatus.OK, expectedResult);

server.close();
}

}

0 comments on commit 70d89ec

Please sign in to comment.