Skip to content
Browse files

added initial implementation of javascript views

  • Loading branch information...
1 parent b184566 commit 6418f48ad25209f0145499cc51b03c4307354c4d @mschoch mschoch committed Feb 19, 2012
View
9 TouchDB-Android-JavaScript/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="lib" path="libs/js.jar"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
View
17 TouchDB-Android-JavaScript/.gitignore
@@ -0,0 +1,17 @@
+# built application files
+*.apk
+*.ap_
+
+# files for the dex VM
+*.dex
+
+# Java class files
+*.class
+
+# generated files
+/bin/
+/gen/
+
+# Local configuration file (sdk path, etc)
+local.properties
+build.properties
View
33 TouchDB-Android-JavaScript/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>TouchDB-Android-JavaScript</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
View
14 TouchDB-Android-JavaScript/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.couchbase.touchdb.javascript"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="8" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ </application>
+
+</manifest>
View
BIN TouchDB-Android-JavaScript/libs/js.jar
Binary file not shown.
View
40 TouchDB-Android-JavaScript/proguard.cfg
@@ -0,0 +1,40 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+ public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
View
13 TouchDB-Android-JavaScript/project.properties
@@ -0,0 +1,13 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-8
+android.library=true
+android.library.reference.1=../TouchDB-Android
View
BIN TouchDB-Android-JavaScript/res/drawable-hdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN TouchDB-Android-JavaScript/res/drawable-ldpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN TouchDB-Android-JavaScript/res/drawable-mdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
12 TouchDB-Android-JavaScript/res/layout/main.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout>
View
7 TouchDB-Android-JavaScript/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="hello">Hello World!</string>
+ <string name="app_name">TouchDB-Android-JavaScript</string>
+
+</resources>
View
121 ...hDB-Android-JavaScript/src/com/couchbase/touchdb/javascript/TDJavaScriptViewCompiler.java
@@ -0,0 +1,121 @@
+package com.couchbase.touchdb.javascript;
+
+import java.util.Map;
+
+import org.elasticsearch.script.javascript.support.NativeMap;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeArray;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.WrapFactory;
+
+import android.util.Log;
+
+import com.couchbase.touchdb.TDDatabase;
+import com.couchbase.touchdb.TDViewCompiler;
+import com.couchbase.touchdb.TDViewMapBlock;
+import com.couchbase.touchdb.TDViewMapEmitBlock;
+import com.couchbase.touchdb.TDViewReduceBlock;
+
+public class TDJavaScriptViewCompiler implements TDViewCompiler {
+
+ @Override
+ public TDViewMapBlock compileMapFunction(String mapSource, String language) {
+ if (language.equals("javascript")) {
+ return new TDViewMapBlockRhino(mapSource);
+ }
+ throw new IllegalArgumentException(language + " is not supported");
+ }
+
+ @Override
+ public TDViewReduceBlock compileReduceFunction(String reduceSource,
+ String language) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
+
+class TDViewMapBlockRhino implements TDViewMapBlock {
+
+ private static WrapFactory wrapFactory = new CustomWrapFactory();
+ private Scriptable globalScope;
+ private String src;
+
+ public TDViewMapBlockRhino(String src) {
+ this.src = src;
+ Context ctx = Context.enter();
+ try {
+ ctx.setOptimizationLevel(-1);
+ ctx.setWrapFactory(wrapFactory);
+ globalScope = ctx.initStandardObjects(null, true);
+ } finally {
+ Context.exit();
+ }
+ }
+
+ @Override
+ public void map(Map<String, Object> document, TDViewMapEmitBlock emitter) {
+ Context ctx = Context.enter();
+ try {
+ ctx.setOptimizationLevel(-1);
+ ctx.setWrapFactory(wrapFactory);
+
+ //create a place to hold results
+ String placeHolder = "var map_results = [];";
+ ctx.evaluateString(globalScope, placeHolder, "placeHolder", 1, null);
+
+ //register the emit function
+ String emitFunction = "var emit = function(key, value) { map_results.push([key, value]); };";
+ ctx.evaluateString(globalScope, emitFunction, "emit", 1, null);
+
+ //register the map function
+ String mapSrc = "var map = " + src + ";";
+ ctx.evaluateString(globalScope, mapSrc, "map", 1, null);
+
+ //find the map function and execute it
+ Function mapFun = (Function)globalScope.get("map", globalScope);
+ Object[] functionArgs = { document };
+ mapFun.call(ctx, globalScope, globalScope, functionArgs);
+
+ //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++) {
+ NativeArray mapResultItem = (NativeArray)mapResults.get(i);
+ if(mapResultItem.getLength() == 2) {
+ Object key = mapResultItem.get(0);
+ Object value = mapResultItem.get(1);
+ emitter.emit(key, value);
+ } else {
+ Log.e(TDDatabase.TAG, "Expected 2 element array with key and value");
+ }
+
+ }
+
+
+
+ } finally {
+ Context.exit();
+ }
+
+ }
+
+ /**
+ * Wrap Factory for Rhino Script Engine
+ */
+ public static class CustomWrapFactory extends WrapFactory {
+
+ public CustomWrapFactory() {
+ setJavaPrimitiveWrap(false); // RingoJS does that..., claims its annoying...
+ }
+
+ public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject, Class staticType) {
+ if (javaObject instanceof Map) {
+ return new NativeMap(scope, (Map) javaObject);
+ }
+
+ return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
+ }
+ }
+
+}
View
223 TouchDB-Android-JavaScript/src/org/elasticsearch/script/javascript/support/NativeMap.java
@@ -0,0 +1,223 @@
+/*
+ * 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.Iterator;
+import java.util.Map;
+
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.Wrapper;
+
+/**
+ * Wrapper for exposing maps in Rhino scripts.
+ *
+ *
+ */
+public class NativeMap implements Scriptable, Wrapper {
+ private static final long serialVersionUID = 3664761893203964569L;
+
+ private Map<Object, Object> map;
+ private Scriptable parentScope;
+ private Scriptable prototype;
+
+
+ /**
+ * Construct
+ *
+ * @param scope
+ * @param map
+ * @return native map
+ */
+ public static NativeMap wrap(Scriptable scope, Map<Object, Object> map) {
+ return new NativeMap(scope, map);
+ }
+
+ /**
+ * Construct
+ *
+ * @param scope
+ * @param map
+ */
+ public NativeMap(Scriptable scope, Map<Object, Object> map) {
+ this.parentScope = scope;
+ this.map = map;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mozilla.javascript.Wrapper#unwrap()
+ */
+
+ public Object unwrap() {
+ return map;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mozilla.javascript.Scriptable#getClassName()
+ */
+
+ public String getClassName() {
+ return "NativeMap";
+ }
+
+ /* (non-Javadoc)
+ * @see org.mozilla.javascript.Scriptable#get(java.lang.String, org.mozilla.javascript.Scriptable)
+ */
+
+ public Object get(String name, Scriptable start) {
+ // get the property from the underlying QName map
+ if ("length".equals(name)) {
+ return map.size();
+ } else {
+ return map.get(name);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.mozilla.javascript.Scriptable#get(int, org.mozilla.javascript.Scriptable)
+ */
+
+ public Object get(int index, Scriptable start) {
+ Object value = null;
+ int i = 0;
+ Iterator itrValues = map.values().iterator();
+ while (i++ <= index && itrValues.hasNext()) {
+ value = itrValues.next();
+ }
+ return value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mozilla.javascript.Scriptable#has(java.lang.String, org.mozilla.javascript.Scriptable)
+ */
+
+ public boolean has(String name, Scriptable start) {
+ // locate the property in the underlying map
+ return map.containsKey(name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.mozilla.javascript.Scriptable#has(int, org.mozilla.javascript.Scriptable)
+ */
+
+ public boolean has(int index, Scriptable start) {
+ return (index >= 0 && map.values().size() > index);
+ }
+
+ /* (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) {
+ map.put(name, value);
+ }
+
+ /* (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) {
+ // TODO: implement?
+ }
+
+ /* (non-Javadoc)
+ * @see org.mozilla.javascript.Scriptable#delete(java.lang.String)
+ */
+
+ public void delete(String name) {
+ map.remove(name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.mozilla.javascript.Scriptable#delete(int)
+ */
+
+ public void delete(int index) {
+ int i = 0;
+ Iterator itrKeys = map.keySet().iterator();
+ while (i <= index && itrKeys.hasNext()) {
+ Object key = itrKeys.next();
+ if (i == index) {
+ map.remove(key);
+ break;
+ }
+ }
+ }
+
+ /* (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() {
+ return map.keySet().toArray();
+ }
+
+ /* (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 Map.class.isInstance(instance);
+ }
+
+}

0 comments on commit 6418f48

Please sign in to comment.
Something went wrong with that request. Please try again.