Friday, December 21, 2012

jsni - overlay types - js arrays Java API

Hi all. I'm porting some javascript libraries to GWT and in this thread I hope I can share and learn best ways of accessing Js native arrays from java language.

I try to add the minimun overhead so I'm using GWT's JsArray, JsArrayMixed, JsArrayString, etc for referencing arrays whenever I can. But this is not so friendly for a Java programmer accustomed to work with real java arryas (String[]) or with java.util.Collection API.

The first thing I thought of was convert js arrays to Java arrays. Unfortunately i didn't found a way of doing this without (linear overhead);

public static JsArrayNumber toJsArrayDouble(double[]a) {
    if(a==null)
        return null;
    JsArrayNumber jsa = (JsArrayNumber) JsArrayNumber.createArray();
    for (int i = 0; i < a.length; i++) {
        jsa.push(a[i]);
    }
    return jsa;
}

Now I'm experimenting on wrapping a Js Array into a java Collection. For this I made a simple Java class that extends java.util.AbstractCollection [0] and wrapps a pure js array. So from jsni code now I can return Java Collections instead JsArray like types and the final user of my libs can write java statements like for(String s : myOverlay.getArrayProp()) {..}. 

Also this solution adds very few (constant) overhead. So now I'm using two getters for js arrays, one that return the real js array object using GWT's JsArray* and other that return a Java Collection:

/**
 * Returns 'columns' property (JavaScript array)
 * @return
 */
public native final JsArrayString columns() /*-{
    return this["columns"];
}-*/;
/**
 * Returns 'columns' property (Java Collection)
 * @return
 */
public native final Collection<String> getColumns() /*-{   
    return @org.sgx.test1.client.JsUtil::toJavaCollection(Lcom/google/gwt/core/client/JavaScriptObject;)(this["columns"]);
}-*/;


I would like to hear what others in the same situation do. Use JsArray* GWT's classes vs more Java friendly API ???  Thanks in advance any suggestion or comment is most appreciated.



[0] - Source code for my Java Collection class wrapper


import java.util.AbstractCollection;
import java.util.Iterator;
import com.google.gwt.core.client.JavaScriptObject;

/**
 * a Java Friendly way of working with Js Arrays using the Java.util.Collection API
 * @author sg
 *
 * @param <T>
 */
public class JsArrayCollection<T> extends  AbstractCollection<T> {

    private JsArr<T> _data;
    /**
     * creates an empty array
     */
    public JsArrayCollection() {
        _data = JsArr.create().cast();
    }
    /**
     * creates JsArrayCollection wrapping an existing js array
     */
    public JsArrayCollection(JavaScriptObject data) {
        this._data = data.cast();
    }
    public static <T> JsArrayCollection<T> create(JavaScriptObject data) {
        return new JsArrayCollection<T>(data);
    }


@Override
public Iterator<T> iterator() {
    return new JsArrayIterator<T>(this);
}

@Override
public int size() {
    return _data.size();
}


public static class JsArrayIterator<T> implements Iterator<T> {

    private JsArrayCollection<T> arr;
    int currentIndex;
    public JsArrayIterator(JsArrayCollection<T> arr) {
        this.arr = arr;
        currentIndex=0;
    }
   
    @Override
    public boolean hasNext() {
//        System.out.println(currentIndex+" - "+arr.size());
        return currentIndex < arr.size();
    }

    @Override
    public T next() {
        currentIndex++;
        return arr._data.get(currentIndex-1);
    }

    @Override
    public void remove() {
        arr._data.slice(currentIndex-1, currentIndex);
    }
   
}

/** untyped array */
private static class JsArr<T> extends JavaScriptObject {
protected JsArr(){}
public native final JsArr<T> slice(int start, int end)/*-{
    return this.slice(start, end);
}-*/;
public static final native <T> JsArr<T> create() /*-{
    return [];
}-*/;
public final native int size() /*-{
    return this.length;
}-*/;
public final native T get(int i) /*-{
return this[i];
}-*/;
}


}

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-web-toolkit/-/DbMp1hrjhVUJ.
To post to this group, send email to google-web-toolkit@googlegroups.com.
To unsubscribe from this group, send email to google-web-toolkit+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.

No comments:

Post a Comment