/*
* SmartGWT (GWT for SmartClient)
* Copyright 2008 and beyond, Isomorphic Software, Inc.
*
* SmartGWT is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3
* as published by the Free Software Foundation. SmartGWT is also
* available under typical commercial license terms - see
* http://smartclient.com/license
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.smartgwt.client.util;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsDate;
import com.google.gwt.user.client.Element;
import com.smartgwt.client.core.BaseClass;
import com.smartgwt.client.core.DataClass;
import com.smartgwt.client.core.Function;
import com.smartgwt.client.core.RefDataClass;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.RecordList;
import com.smartgwt.client.data.RelativeDate;
import com.smartgwt.client.data.ResultSet;
import com.smartgwt.client.types.ValueEnum;
import com.smartgwt.client.widgets.BaseWidget;
/**
* Utility class containing many useful static helper methods.
* <p>
**/
/*
* NOTES - low-level detail of how the JS -> Java conversion works:
* In SmartGwtEntryPoint, set up $wnd.SmartGWT.convertToJavaType():
* - Converts simple and primitive JS types to Java equivalents:
* - string
* - the object itself is returned (presumably GWT can automap JS String to Java)
* - number
* - If the stringified number contains a ".", convert to Double
* - Otherwise, convert to Integer if the value is less than Integer.MAX_VALUE, otherwise Long
* - boolean -> Boolean
* - date -> java.util.Date (via JSOHelper.convertToJavaDate)
* - object where _constructor is "DateRange" -> com.smartgwt.client.data.DateRange
* - isJSO(object) == true -> return the object itself
* - array -> return the result of calling JSOHelper.convertToJavaObjectArray(object)
* - If none of the above, gives up and returns the object itself
*
* In SmartGwtEntryPoint, set up $wnd.SmartGWT.convertToJavaObject():
* - Converts complex objects to Java equivalents:
* - null -> return null
* - isc.isA.Object() == false -> return the result of calling convertToJavaType(object) - see above
* - isc.isA.Date() == true -> return a java.util.Date (via JSOHelper.convertToJavaDate)
* - isc.isAn.Array:
* - Iterate over the array members and convert each by calling convertToJavaObject()
* - Add each converted member to a JS array
* - After the iteration, convert the JS array to either a Java array (via SOHelper.convertToJavaObjectArray)
* or an ArrayList, depending on the setting of the incoming "listAsArray" parameter (second param)
* - Return this array or ArrayList
* - If the incoming "forceMap" parameter (third param) is not true (using exact !== test)
* - isJSO(object) == true -> return the object itself
* - Object has a non-null "__ref" property -> return the value of the "__ref" property
* - isc.isA.Canvas() -> return the result of calling com.smartgwt.client.widgets.Canvas.getById()
* with the object's "ID" property
* - object has a "name" property of type String and a "form" property of type "DynamicForm"
* - Create a DynamicForm object by calling com.smartgwt.client.widgets.form.DynamicForm.getOrCreateRef()
* with the value of the object's "form" property
* - Return the result of calling getField() on that form, passing in the object's "name" property
* - object has a "_constructor" property of "RelativeDate" => return a new instance of
* com.smartgwt.client.data.RelativeDate, passing the object to the constructor that accepts a JSO
* - isc.isAn.Instance() == true and the object has a getClassName() method -> return the result of
* calling com.smartgwt.client.util.ObjectFactory.createInstance(), passing the object to the
* constructor that accepts a JSO
* - If the incoming "forceMap" param is true
* - The object has a "__ref" property, and it is a Java Map (checked with JSOHelper::isJavaMap()),
* return the value of the object's __ref property
* - If get to this point without having converted the object, we try to render it as a Map
* - If the object has a property named the same as isc.Tree.getPrototype().treeProperty, we assume
* it is a TreeNode and call isc.Tree.getCleanNodeData() on it
* - Create a new empty map to contain the converted properties
* - Iterate over the property names in object
* - If the property name is not a string, skip
* - If the property name is the same as isc.gwtModule, skip
* - If the property value is an object with a "__ref" property and that __ref property refers
* to a native Java object (as defined by SmartGWT.isNativeJavaObject(), which ultimately calls
* on to isJSO()), add the __ref object to the converted map
* - Otherwise, convert the value by passing it to convertToJavaObject(), then add it to the
* converted map
* - Return the converted map
*/
public class JSOHelper {
private JSOHelper() {
}
/**
* Returns the javascript class name.
* @return
*/
public static native String getClassName(JavaScriptObject javaScriptObject)/*-{
return javaScriptObject.getClassName();
}-*/;
/**
* Returns whether the supplied JavaScriptObject is a SmartClient class instance.
* @param the object to evaluate
* @return whether object is an instance
*/
public static native boolean isScClassInstance(JavaScriptObject javaScriptObject)/*-{
return $wnd.isc.isAn.Instance(javaScriptObject);
}-*/;
/**
* Returns whether the supplied JavaScriptObject is a SmartClient class (a Class object
* itself, rather than an instance of a class).
* @param the object to evaluate
* @return whether object is a Class object
*/
public static native boolean isScClassObject(JavaScriptObject javaScriptObject)/*-{
return $wnd.isc.isA.ClassObject(javaScriptObject);
}-*/;
/**
* Evaluate the passed string as Javascript
*
* @param jsFrag the string to evaluate
* @return the JavaScriptObject upon evaluation
*/
public static native JavaScriptObject eval(String jsFrag) /*-{
if(!($wnd.isc.startsWith(jsFrag, '(') && $wnd.isc.endsWith(jsFrag, ')'))) {
jsFrag = '(' + jsFrag + ')';
}
return $wnd.isc.Class.evaluate(jsFrag);
}-*/;
public static boolean isJSO(Object object) {
return object instanceof JavaScriptObject;
}
public static double doubleValue(Number num) {
if (num == null) return Double.NaN;
if (num instanceof Float) {
// When a `float' is cast to a `double', the significand is zero-extended. This can
// lead to the unexpected scenario where Double.toString((double)f) != Float.toString(f).
// For example, Double.toString(Float.valueOf(0.15f).doubleValue()) is the string
// "0.15000000596046448". This is because the significand of (double)f is
// 0b0011001100110011001101000000000000000000000000000000, but the significand of
// Double.parseDouble("0.15") is:
// 0b0011001100110011001100110011001100110011001100110011
return Double.parseDouble(num.toString());
} else if (num instanceof Long) {
long l = num.longValue();
final double d = (double)l;
if (Math.abs(l) > 9007199254740992L) {
SC.logWarn("The long value " + Long.toString(l) + " cannot be exactly represented in JavaScript. It will be truncated to: " + Long.toString((long)d));
}
return d;
} else {
return num.doubleValue();
}
}
public static native String getAttribute(JavaScriptObject elem, String attr) /*-{
var ret = elem[attr];
return (ret == null ? null : String(ret));
}-*/;
public static native void setAttribute(JavaScriptObject elem, String attr, String value) /*-{
// When setting a string attribute, make sure to convert the value to a normal, non-wrapped
// string as opposed to a String object (i.e. typeof is "string", not "object").
// This is needed because an equality comparison of two String objects can fail even
// though they represent the same string. For example, `new String("test") == new String("test")'
// is `false'.
//
// Also, both $wnd.String() and String() called as functions on a value return the same thing,
// a native browser string that is the result of calling the internal ToString() conversion function
// (Sections 15.5.1.1 and 9.8, ECMA-262). Use String() because it is the fastest:
// http://jsperf.com/cross-frame-tostring/2
elem[attr] = (value == null ? null : String(value));
}-*/;
public static native JavaScriptObject getAttributeAsJavaScriptObject(JavaScriptObject elem, String attr) /*-{
var ret = elem[attr];
return (ret == null ? null : ret);
}-*/;
public static native JavaScriptObject[] getAttributeAsJavaScriptObjectArray(JavaScriptObject elem, String attr) /*-{
var arrayJS = elem[attr];
return (arrayJS === undefined) ? null : @com.smartgwt.client.util.JSOHelper::toArray(Lcom/google/gwt/core/client/JavaScriptObject;)(arrayJS);
}-*/;
public static JavaScriptObject[] toArray(JavaScriptObject array) {
//handle case where a ResultSet is passed
if (com.smartgwt.client.data.ResultSet.isResultSet(array)) {
array = JSOHelper.resultSetToArray(array);
}
final int length = getJavaScriptObjectArraySize(array);
JavaScriptObject[] recs = new JavaScriptObject[length];
for (int i = 0; i < length; i++) {
recs[i] = getValueFromJavaScriptObjectArray(array, i);
}
return recs;
}
private static native JavaScriptObject resultSetToArray(JavaScriptObject rs) /*-{
if (!rs.lengthIsKnown() || !rs.allMatchingRowsCached()) return $wnd.Array.create();
return rs.getRange(0, rs.getLength());
}-*/;
public static native boolean isArray(JavaScriptObject jsObj)/*-{
return $wnd.isc.isA.Array(jsObj);
}-*/;
public static Element[] toElementArray(JavaScriptObject array) {
int length = getJavaScriptObjectArraySize(array);
Element[] recs = new Element[length];
for (int i = 0; i < length; i++) {
recs[i] = getElementValueFromJavaScriptObjectArray(array, i);
}
return recs;
}
public static native void setAttribute(JavaScriptObject elem, String attr, JavaScriptObject[] value) /*-{
elem[attr] = value;
}-*/;
public static void setAttribute(JavaScriptObject elem, String attr, int[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
public static void setAttribute(JavaScriptObject elem, String attr, float[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
public static void setAttribute(JavaScriptObject elem, String attr, double[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
public static void setAttribute(JavaScriptObject elem, String attr, String[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
public static void setAttribute(JavaScriptObject elem, String attr, Integer[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
public static void setAttribute(JavaScriptObject elem, String attr, Float[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
public static void setAttribute(JavaScriptObject elem, String attr, Boolean[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
public static void setAttribute(JavaScriptObject elem, String attr, Double[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
public static void setAttribute(JavaScriptObject elem, String attr, Long[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
public static void setAttribute(JavaScriptObject elem, String attr, Date[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
public static void setAttribute(JavaScriptObject elem, String attr, ValueEnum[] values) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(values));
}
/**
* Set the value of attribute "attr" in object "elem" to the Object "value"
* <P>
* This method converts the value passed in to an equivalent
* object in JavaScript before storing on the underlying data object - see
* {@link com.smartgwt.client.docs.JavaToJavaScriptConversion} for details of the conversions
* that take place.<br>
* Developers can use {@link #setObjectAttribute(JavaScriptObject, String, Object)}
* to store Java objects without converting to JavaScript.
*
* @param elem the JavaScriptObject on which to set the attribute
* @param attr the attribute name
* @param value the attribute value.
*/
public static void setAttribute(JavaScriptObject elem, String attr, Object value) {
if (value == null) {
setNullAttribute(elem, attr);
} else if (value instanceof String || value instanceof Character) {
setAttribute(elem, attr, value.toString());
} else if (value instanceof Number) {
setAttribute(elem, attr, (Number)value);
} else if (value instanceof Boolean) {
setAttribute(elem, attr, ((Boolean)value).booleanValue());
} else if (value instanceof Date) {
setAttribute(elem, attr, (Date)value);
} else if (value instanceof RelativeDate) {
setAttribute(elem, attr, ((RelativeDate)value).getValue());
} else if (value instanceof ValueEnum) {
setAttribute(elem, attr, ((ValueEnum)value).getValue());
} else if (value.getClass().isArray()) {
if (value instanceof Object[]) {
// The Object[] passed in may contain unconvertible elements (POJOs)
// In this case we'll end up with a JavaScript array which contains some
// unconverted sub objects
// We used to pass the extra "strict" parameter in to avoid this and
// instead throw an exception, but that's more intrusive than silently
// storing some unconverted member.
setAttribute(elem, attr, convertToJavaScriptArray((Object[])value));
} else if (value instanceof int[]) {
setAttribute(elem, attr, convertToJavaScriptArray((int[])value));
} else if (value instanceof double[]) {
setAttribute(elem, attr, convertToJavaScriptArray((double[])value));
} else if (value instanceof float[]) {
setAttribute(elem, attr, convertToJavaScriptArray((float[])value));
} else if (value instanceof boolean[]) {
setAttribute(elem, attr, convertToJavaScriptArray((boolean[])value));
} else if (value instanceof char[]) {
setAttribute(elem, attr, convertToJavaScriptArray((char[])value));
} else if (value instanceof byte[]) {
setAttribute(elem, attr, convertToJavaScriptArray((byte[])value));
} else if (value instanceof short[]) {
setAttribute(elem, attr, convertToJavaScriptArray((short[])value));
} else if (value instanceof long[]) {
setAttribute(elem, attr, convertToJavaScriptArray((long[])value));
} else {
assert false : value.getClass() + " should not be an array class.";
setObjectAttribute(elem, attr, value);
}
// As with Object[]s, Java collections may contain unconvertible elements (POJOs)
// In this case we'll end up with a JavaScript array which contains some
// unconverted sub objects
} else if (value instanceof List) {
setAttribute(elem, attr, convertToJavaScriptArray(((List<?>)value).toArray()));
} else if (value instanceof Iterator) {
List listVal = new ArrayList();
while (((Iterator) value).hasNext()) listVal.add(((Iterator) value).next());
setAttribute(elem, attr, convertToJavaScriptArray(((List<?>)listVal).toArray()));
} else if (value instanceof Set) {
setAttribute(elem, attr, JSOHelper.convertToJavaScriptArray(((Set<?>)value).toArray()));
} else if (value instanceof Map) {
setAttribute(elem, attr, convertMapToJavascriptObject((Map<?, ?>) value));
} else {
setObjectAttribute(elem, attr, value);
}
}
public static native void setAttribute(JavaScriptObject elem, String attr, JavaScriptObject value) /*-{
elem[attr] = value;
}-*/;
public static native void setAttribute(JavaScriptObject elem, String attr, int value) /*-{
elem[attr] = value;
}-*/;
public static void setAttribute(JavaScriptObject elem, String attr, Number value) {
if (value == null) {
setNullAttribute(elem, attr);
} else {
setAttribute(elem, attr, doubleValue(value));
}
}
public static void setAttribute(JavaScriptObject elem, String attr, Long value) {
if (value == null) {
setNullAttribute(elem, attr);
} else {
final long l = value.longValue();
final double d = (double)l;
if (Math.abs(l) > 9007199254740992L) {
SC.logWarn("The long value " + Long.toString(l) + " cannot be exactly represented in JavaScript. It will be truncated to: " + Long.toString((long)d));
}
setAttribute(elem, attr, d);
}
}
public static void setAttribute(JavaScriptObject elem, String attr, Boolean value) {
if (value == null) {
setNullAttribute(elem, attr);
} else {
setAttribute(elem, attr, value.booleanValue());
}
}
public static native void setNullAttribute(JavaScriptObject elem, String attr) /*-{
elem[attr] = null;
}-*/;
public static native void deleteAttribute(JavaScriptObject elem, String attr) /*-{
delete elem[attr];
}-*/;
public static native void deleteAttributeIfExists(JavaScriptObject elem, String attr) /*-{
var undef;
if (elem[attr] !== undef) delete elem[attr];
}-*/;
public static native void setAttribute(JavaScriptObject elem, String attr, boolean value) /*-{
elem[attr] = value;
}-*/;
public static native void setAttribute(JavaScriptObject elem, String attr, double value) /*-{
elem[attr] = value;
}-*/;
public static native void setAttribute(JavaScriptObject elem, String attr, Function handler) /*-{
elem[attr] = $entry(function() {
handler.@com.smartgwt.client.core.Function::execute()();
});
}-*/;
public static void setAttribute(JavaScriptObject elem, String attr, Date value) {
setAttribute(elem, attr, convertToJavaScriptDate(value));
}
public static native void setObjectAttribute(JavaScriptObject elem, String attr, Object object) /*-{
elem[attr] = object;
}-*/;
public static native Element getAttributeAsElement(JavaScriptObject elem, String attr) /*-{
var ret = elem[attr];
return (ret === undefined) ? null : ret;
}-*/;
public static native Integer getAttributeAsInt(JavaScriptObject elem, String attr) /*-{
var ret = elem[attr];
return (ret == null ? null : @com.smartgwt.client.util.JSOHelper::toInteger(I)(ret));
}-*/;
public static native Double getAttributeAsDouble(JavaScriptObject elem, String attr) /*-{
var ret = elem[attr];
if (ret === undefined || ret == null) {
return null;
} else {
if(typeof ret == "object") {
return ret;
} else {
return @com.smartgwt.client.util.JSOHelper::toDouble(D)(ret);
}
}
}-*/;
public static native Date getAttributeAsDate(JavaScriptObject elem, String attr) /*-{
var val = elem[attr];
return @com.smartgwt.client.util.JSOHelper::convertToJavaDate(Lcom/google/gwt/core/client/JavaScriptObject;)(val);
}-*/;
public static native Float getAttributeAsFloat(JavaScriptObject elem, String attr) /*-{
var ret = elem[attr];
return (ret == null ? null : @com.smartgwt.client.util.JSOHelper::toFloat(F)(ret));
}-*/;
public static int[] getAttributeAsIntArray(JavaScriptObject elem, String attr) {
int[] rtn = null;
JavaScriptObject hold = getAttributeAsJavaScriptObject(elem, attr);
if (hold != null) {
rtn = new int[getJavaScriptObjectArraySize(hold)];
for (int i = 0; i < rtn.length; i++) {
rtn[i] = getIntValueFromJavaScriptObjectArray(hold, i);
}
}
return rtn;
}
public static double[] getAttributeAsDoubleArray(JavaScriptObject elem, String attr) {
double[] rtn = null;
JavaScriptObject hold = getAttributeAsJavaScriptObject(elem, attr);
if (hold != null) {
rtn = new double[getJavaScriptObjectArraySize(hold)];
for (int i = 0; i < rtn.length; i++) {
rtn[i] = getDoubleValueFromJavaScriptObjectArray(hold, i);
}
}
return rtn;
}
public static String[] getAttributeAsStringArray(JavaScriptObject elem, String attr) {
final JavaScriptObject hold = getAttributeAsJavaScriptObject(elem, attr);
final String[] rtn;
if (hold == null) rtn = null;
else {
rtn = new String[getJavaScriptObjectArraySize(hold)];
for (int i = 0; i < rtn.length; i++) {
rtn[i] = getStringValueFromJavaScriptObjectArray(hold, i);
}
}
return rtn;
}
public static native int getJavaScriptObjectArraySize(JavaScriptObject elem) /*-{
var length;
if (elem) length = elem.length;
if (length == null) length = 0;
return length;
}-*/;
public static native int getIntValueFromJavaScriptObjectArray(JavaScriptObject elem, int i) /*-{
return elem[i];
}-*/;
public static native double getDoubleValueFromJavaScriptObjectArray(JavaScriptObject elem, int i) /*-{
return elem[i];
}-*/;
public static native String getStringValueFromJavaScriptObjectArray(JavaScriptObject elem, int i) /*-{
return elem[i];
}-*/;
public static native JavaScriptObject getValueFromJavaScriptObjectArray(JavaScriptObject elem, int i) /*-{
return elem[i];
}-*/;
// Lists of cells are stored as arrays of 2 element arrays in JS.
// Helpers to convert between this and the equivalent format in Java (int[][])
public static int[][] getCellArray(JavaScriptObject jsCells) {
if (jsCells == null) return null;
int length = JSOHelper.getArrayLength(jsCells);
int[][] cells = new int[length][];
for (int i = 0; i < length; i++) {
JavaScriptObject jsCell = JSOHelper.getValueFromJavaScriptObjectArray(jsCells, i);
cells[i] = new int[2];
cells[i][0] = JSOHelper.getIntArrayValue(jsCell, 0);
cells[i][1] = JSOHelper.getIntArrayValue(jsCell, 1);
}
return cells;
}
public static JavaScriptObject convertToCellArray(int[][] cells) {
if (cells == null) return null;
JavaScriptObject jsCells = JSOHelper.createJavaScriptArray();
for (int i = 0; i < cells.length; i++) {
int[] cell = cells[i];
JavaScriptObject jsCell = JSOHelper.convertToJavaScriptArray(cell);
JSOHelper.setArrayValue(jsCells, i, jsCell);
}
return jsCells;
}
/**
* Returns attribute value set as a Boolean. For convenience in checking boolean
* properties, <code>getAttributeAsBoolean</code> will return Boolean <code>false</code>
* if the attribute value is <code>null</code> or not a Boolean. Use the three parameter
* variant of this API {@link #getAttributeAsBoolean(JavaScriptObject, String, boolean)}
* if you want <code>null</code> returned for <code>null</code> attribute values.
* @param elem the JavaScriptObject containing the property
* @param attr the property name
* @return the property value
*/
public static boolean getAttributeAsBoolean(JavaScriptObject elem, String attr) {
return getAttributeAsBoolean(elem, attr, false);
}
/**
* Returns attribute value set as a Boolean. If the attribute value is <code>null</code>
* or not a Boolean, the return value depends upon <code>allowNull</code>. If
* <code>allowNull</code> is true, <code>null</code> will be returned; otherwise Boolean
* <code>false</code> will be returned. For a simpler approach that never returns
* <codE>null</code>, use the two parameter variant of this API
* {@link #getAttributeAsBoolean(JavaScriptObject, String)}.
* @param elem the JavaScriptObject containing the property
* @param attr the property name
* @param allowNull whether to permit a <code>null</code> return value
* @return the property value
*/
public static native Boolean getAttributeAsBoolean(JavaScriptObject elem, String attr, boolean allowNull) /*-{
var ret = elem[attr];
if ($wnd.isc.isA.Boolean(ret)) ret = ret.valueOf();
else if (!allowNull) ret = false;
else return null;
return @com.smartgwt.client.util.JSOHelper::toBoolean(Z)(ret);
}-*/;
public static native Object getAttributeAsObject(JavaScriptObject elem, String attr) /*-{
var ret = elem[attr];
if (ret === undefined) return null;
if ($wnd.isc.isA.Number(ret) || $wnd.isc.isA.Boolean(ret)) {
ret = $wnd.SmartGWT.convertToJavaType(ret);
}
return ret;
}-*/;
/**
* Returns attribute "attr" of JavaScriptObject "elem", converted to a Map following the rules described
* in the {@link com.smartgwt.client.docs.JavaScriptToJavaConversion JS -> Java conversion article}
*
* @param elem JavaScriptObject containing the attribute
* @param attr The attribute name
* @return The attribute converted to a Java Map
*/
public static Map getAttributeAsMap(JavaScriptObject elem, String attr) {
JavaScriptObject value = getAttributeAsJavaScriptObject(elem, attr);
if (value == null) return null;
return convertToMap(value);
}
public static JavaScriptObject[] listToArray(List list) {
JavaScriptObject[] array = new JavaScriptObject[list.size()];
for (int i = 0; i < array.length; i++) {
array[i] = (JavaScriptObject) list.get(i);
}
return array;
}
public static JavaScriptObject arrayConvert(Object[] array) {
if(array == null) return null;
JavaScriptObject result = newJSArray(array.length);
for (int i = 0; i < array.length; i++) {
arraySet(result, i, array[i]);
}
return result;
}
public static JavaScriptObject arrayConvert(JavaScriptObject[] array) {
if(array == null) return null;
JavaScriptObject result = newJSArray(array.length);
for (int i = 0; i < array.length; i++) {
arraySet(result, i, array[i]);
}
return result;
}
private static native JavaScriptObject newJSArray(int length) /*-{
if (length < 0) {
return $wnd.Array.create();
} else {
var arr = $wnd.Array.create();
arr.setLength(length);
return arr;
}
}-*/;
public static native int arrayLength(JavaScriptObject array) /*-{
return array.length;
}-*/;
public static native Object arrayGetObject(JavaScriptObject array, int index) /*-{
return array[index];
}-*/;
public static native void arraySet(JavaScriptObject array, int index, Object value) /*-{
array[index] = value;
}-*/;
public static native void arraySet(JavaScriptObject array, int index, JavaScriptObject value) /*-{
array[index] = value;
}-*/;
/**
* This is used to access Element array as JavaScriptObject
*/
public static native Element getElementValueFromJavaScriptObjectArray(JavaScriptObject elem, int i) /*-{
return elem[i];
}-*/;
public static native JavaScriptObject createObject() /*-{
return new Object;
}-*/;
public static JavaScriptObject convertToJavaScriptArray(boolean[] array) {
if (array == null) return null;
final JavaScriptObject jsArray = createJavaScriptArray();
for (int i = 0; i < array.length; ++i) {
JSOHelper.setArrayValue(jsArray, i, array[i]);
}
return jsArray;
}
public static JavaScriptObject convertToJavaScriptArray(char[] array) {
if (array == null) return null;
final JavaScriptObject jsArray = createJavaScriptArray();
for (int i = 0; i < array.length; ++i) {
JSOHelper.setArrayValue(jsArray, i, Character.toString(array[i]));
}
return jsArray;
}
public static JavaScriptObject convertToJavaScriptArray(byte[] array) {
if (array == null) return null;
final JavaScriptObject jsArray = createJavaScriptArray();
for (int i = 0; i < array.length; ++i) {
JSOHelper.setArrayValue(jsArray, i, array[i]);
}
return jsArray;
}
public static JavaScriptObject convertToJavaScriptArray(short[] array) {
if (array == null) return null;
final JavaScriptObject jsArray = createJavaScriptArray();
for (int i = 0; i < array.length; ++i) {
JSOHelper.setArrayValue(jsArray, i, array[i]);
}
return jsArray;
}
public static JavaScriptObject convertToJavaScriptArray(int[] array) {
if(array == null) return null;
JavaScriptObject jsArray = createJavaScriptArray();
for (int i = 0; i < array.length; i++) {
JSOHelper.setArrayValue(jsArray, i, array[i]);
}
return jsArray;
}
public static JavaScriptObject convertToJavaScriptArray(float[] array) {
if(array == null) return null;
JavaScriptObject jsArray = createJavaScriptArray();
for (int i = 0; i < array.length; i++) {
JSOHelper.setArrayValue(jsArray, i, array[i]);
}
return jsArray;
}
public static JavaScriptObject convertToJavaScriptArray(double[] array) {
if(array == null) return null;
JavaScriptObject jsArray = createJavaScriptArray();
for (int i = 0; i < array.length; i++) {
JSOHelper.setArrayValue(jsArray, i, array[i]);
}
return jsArray;
}
public static JavaScriptObject convertToJavaScriptArray(long[] array) {
if(array == null) return null;
JavaScriptObject jsArray = createJavaScriptArray();
for (int i = 0; i < array.length; i++) {
JSOHelper.setArrayValue(jsArray, i, array[i]);
}
return jsArray;
}
private static void doAddToMap(Map map, String key, Object value) {
map.put(key, value);
}
private native static Object convertToJava(JavaScriptObject object, boolean listAsArray, boolean forceMap) /*-{
return $wnd.SmartGWT.convertToJavaObject(object, listAsArray, forceMap);
}-*/;
/**
* Convert a JavaScriptObject to the appropriate type of Java Object, following the rules described
* in the {@link com.smartgwt.client.docs.JavaScriptToJavaConversion JS -> Java conversion article}
*
* @param object JavaScriptObject to convert
* @param listAsArray Should arrays be converted to Object[] or List
* @return converted Java object. May be a Map, a List, an Object[], a JavaScriptObject,
* a Canvas or a FormItem, depending on the underlying JavaScript type
*/
public static Object convertToJava(JavaScriptObject object, boolean listAsArray) {
return convertToJava(object, listAsArray, false);
}
/**
* Convert a JavaScriptObject to the appropriate type of Java Object, following the rules described
* in the {@link com.smartgwt.client.docs.JavaScriptToJavaConversion JS -> Java conversion article}.
* Any arrays encountered during conversion will be converted to Java <code>ArrayList</code>s
*
* @param object JavaScriptObject to convert
* @return converted Java object. May be a Map, a List, an Object[], a JavaScriptObject,
* a Canvas or a FormItem, depending on the underlying JavaScript type
*/
public static Object convertToJava(JavaScriptObject object) {
return convertToJava(object, false);
}
/**
* Convert a JavaScript object containing key:value pairs to a Java Map, following the rules described
* in the {@link com.smartgwt.client.docs.JavaScriptToJavaConversion JS -> Java conversion article}
* @param jsObj the JavaScript object to convert
* @param listAsArray Should arrays be converted to Object[] or List
* @return the map
* @throws IllegalArgumentException if unable to convert the passed JavaScript object to a map
*/
public static Map convertToMap(JavaScriptObject jsObj, boolean listAsArray) {
Object javaObj = convertToJava(jsObj, listAsArray, true);
if (javaObj == null) {
return (Map) null;
} else if (javaObj instanceof Map) {
return (Map) javaObj;
} else {
throw new IllegalArgumentException("convertToMap - unable to convert the passed "
+ "JavaScript object to a Map. JavaScript is: " + SC.echo(jsObj));
}
}
/**
* Convert a JavaScript object containing key:value pairs to a Java Map, following the rules described
* in the {@link com.smartgwt.client.docs.JavaScriptToJavaConversion JS -> Java conversion article}.
* Any arrays encountered during the conversion process will be converted to Java <code>ArrayList</code>s
* @param jsObj the JavaScript object to convert
* @return the map
* @throws IllegalArgumentException if unable to convert the passed JavaScript object to a map
*/
public static Map convertToMap(JavaScriptObject jsObj) {
return convertToMap(jsObj, false);
}
/**
* Convert a JavaScript object to an Object[], following the rules described
* in the {@link com.smartgwt.client.docs.JavaScriptToJavaConversion JS -> Java conversion article}.
* If the JavaScript object is not an array in Javascript, a new array will be created
* containing the converted object as the only entry.
* @param object the JavaScript object to convert
* @return the JavaScript object converted to a Java Object array
*/
public static Object[] convertToArray(JavaScriptObject object) {
Object javaObj = convertToJava(object, true);
if (!(javaObj instanceof Object[])) {
javaObj = new Object[] {javaObj};
}
return (Object[])javaObj;
}
/**
* Convert a JavaScript object to a List, following the rules described
* in the {@link com.smartgwt.client.docs.JavaScriptToJavaConversion JS -> Java conversion article}.
* If the JavaScript object is not an array in JavaScript, a new List will be created containing
* the converted object as the only entry.
* @param object the JavaScript object to convert
* @return the JavaScript object converted to a Java List
*/
public static List convertToList(JavaScriptObject object) {
Object javaObj = convertToJava(object, false);
if (!(javaObj instanceof List)) {
List list = new ArrayList();
list.add(javaObj);
javaObj = list;
}
return (List)javaObj;
}
private static native JsDate createJavaScriptDate(double time) /*-{
// Use $wnd.Date.create() instead of JsDate.create() so that instance methods like
// duplicate() are added to the resulting JavaScript date object.
var jsD = $wnd.Date.create();
jsD.setTime(time);
return jsD;
}-*/;
public static JsDate convertToJavaScriptDate(Date date) {
if (date == null) return null;
if (date instanceof LogicalDate) {
return ((LogicalDate)date).toJavaScriptDate();
} else if (date instanceof LogicalTime) {
return ((LogicalTime)date).toJavaScriptDate();
} else {
return createJavaScriptDate(date.getTime());
}
}
public static native Date convertToJavaDate(JavaScriptObject val) /*-{
if (!$wnd.isc.isA.Date(val)) return null;
if (val.logicalDate) {
return @com.smartgwt.client.util.LogicalDate::new(D)(val.getTime());
} else if (val.logicalTime) {
return @com.smartgwt.client.util.LogicalTime::new(D)(val.getTime());
} else {
return @com.smartgwt.client.util.JSOHelper::toDate(D)(val.getTime());
}
}-*/;
//explicitly cast Object to String to workaround GWT hosted mode but in certain browsers when originating string is obtained
//by calling object.toString(). http://code.google.com/p/google-web-toolkit/issues/detail?id=4301
public static String convertToString(Object obj) {
if(obj instanceof String) {
return (String) obj;
} else {
throw new IllegalArgumentException("Object " + obj + " is not of type String");
}
}
/**
* @param obj the object
* @return true if object is a Java Date
*/
public static boolean isJavaDate(Object obj) {
return obj instanceof Date;
}
/**
* @param obj the object
* @return true if object is a Java Number
*/
public static boolean isJavaNumber(Object obj) {
return obj instanceof Number;
}
/**
* @param obj the object
* @return true if object is a Java Integer
*/
public static boolean isJavaInteger(Object obj) {
return obj instanceof Integer;
}
/**
* @param obj the object
* @return true if object is a Java Float
*/
public static boolean isJavaFloat(Object obj) {
return obj instanceof Float;
}
/**
* @param obj the object
* @return true if object is a Java Double
*/
public static boolean isJavaDouble(Object obj) {
return obj instanceof Double;
}
/**
* @param obj the object
* @return true if object is a Java String
*/
public static boolean isJavaString(Object obj) {
return obj instanceof String;
}
/**
* @param obj the object
* @return true if object is a Java Integer
*/
public static boolean isJavaBoolean(Object obj) {
return obj instanceof Boolean;
}
public static boolean isJavaList(Object obj) {
return obj instanceof List;
}
public static boolean isJavaMap(Object obj) {
return obj instanceof Map;
}
/**
* @param obj the object
* @return true if object is a Java Array
*/
public static boolean isJavaArray(Object obj) {
return obj == null ? false : obj.getClass().isArray();
}
public static <O extends JavaScriptObject> JsArray<O> convertToJsArray(O[] array) {
if (array == null) return null;
else {
final JsArray<O> ret = (JsArray<O>)JavaScriptObject.createArray();
ret.setLength(array.length);
for (int i = 0; i < array.length; ++i) {
ret.set(i, array[i]);
}
return ret;
}
}
/**
* Converts the parameter Object array to an equivalent Javascript array - see
* {@link com.smartgwt.client.docs.JavaToJavaScriptConversion} for details of the conversions
* that take place.
*
* @param array the Java Object array to convert
*/
public static JavaScriptObject convertToJavaScriptArray(Object[] array) {
return convertToJavaScriptArray(array, false);
}
public static JavaScriptObject convertToJavaScriptArray(Object[] array, boolean strict) {
if(array == null) return null;
JavaScriptObject jsArray = createJavaScriptArray();
for (int i = 0; i < array.length; i++) {
Object val = array[i];
if (val == null) {
setArrayValue(jsArray, i, (JavaScriptObject) val);
} else if (val instanceof String || val instanceof Character) {
setArrayValue(jsArray, i, val.toString());
} else if (val instanceof Number) {
if (val instanceof Long) setArrayValue(jsArray, i, ((Long) val).longValue());
else setArrayValue(jsArray, i, doubleValue((Number) val));
} else if (val instanceof Boolean) {
JSOHelper.setArrayValue(jsArray, i, ((Boolean) val).booleanValue());
} else if (val instanceof Date) {
JSOHelper.setArrayValue(jsArray, i, (Date) val);
} else if (val instanceof ValueEnum) {
JSOHelper.setArrayValue(jsArray, i, ((ValueEnum) val).getValue());
} else if (val instanceof JavaScriptObject) {
JSOHelper.setArrayValue(jsArray, i, (JavaScriptObject) val);
} else if (val instanceof RecordList) {
if (val instanceof ResultSet) {
val = ((ResultSet)val).getAllCachedRows();
}
val = ((RecordList) val).getRange(0, ((RecordList) val).getLength());
setArrayValue(jsArray, i, convertToJavaScriptArray((Record[])val, strict));
} /*else if (val instanceof JsObject) {
JSOHelper.setArrayValue(jsArray, i, ((JsObject) val).getJsObj());
} */
else if (val instanceof DataClass) {
JSOHelper.setArrayValue(jsArray, i, ((DataClass) val).getJsObj());
} else if (val instanceof BaseClass) {
JSOHelper.setArrayValue(jsArray, i, ((BaseClass) val).getOrCreateJsObj());
} else if (val instanceof BaseWidget) {
JSOHelper.setArrayValue(jsArray, i, ((BaseWidget) val).getOrCreateJsObj());
} else if (val instanceof Record) {
JSOHelper.setArrayValue(jsArray, i, ((Record) val).getJsObj());
} else if (val.getClass().isArray()) {
if (val instanceof Object[]) {
setArrayValue(jsArray, i, convertToJavaScriptArray((Object[])val, strict));
} else if (val instanceof int[]) {
setArrayValue(jsArray, i, convertToJavaScriptArray((int[])val));
} else if (val instanceof double[]) {
setArrayValue(jsArray, i, convertToJavaScriptArray((double[])val));
} else if (val instanceof float[]) {
setArrayValue(jsArray, i, convertToJavaScriptArray((float[])val));
} else if (val instanceof boolean[]) {
setArrayValue(jsArray, i, convertToJavaScriptArray((boolean[])val));
} else if (val instanceof char[]) {
setArrayValue(jsArray, i, convertToJavaScriptArray((char[])val));
} else if (val instanceof byte[]) {
setArrayValue(jsArray, i, convertToJavaScriptArray((byte[])val));
} else if (val instanceof short[]) {
setArrayValue(jsArray, i, convertToJavaScriptArray((short[])val));
} else if (val instanceof long[]) {
setArrayValue(jsArray, i, convertToJavaScriptArray((long[])val));
} else {
assert false : val.getClass() + " should not be an array class.";
setArrayValue(jsArray, i, (JavaScriptObject) null);
}
} else if (val instanceof List) {
setArrayValue(jsArray, i, JSOHelper.convertToJavaScriptArray(((List<?>)val).toArray(), strict));
} else if (val instanceof Iterator) {
List listVal = new ArrayList();
while (((Iterator) val).hasNext()) listVal.add(((Iterator) val).next());
setArrayValue(jsArray, i, JSOHelper.convertToJavaScriptArray(((List<?>)listVal).toArray(), strict));
} else if (val instanceof Set) {
setArrayValue(jsArray, i, JSOHelper.convertToJavaScriptArray(((Set<?>)val).toArray(), strict));
} else if (val instanceof Map) {
setArrayValue(jsArray, i, convertMapToJavascriptObject((Map)val, strict));
} else {
assert val != null;
assert !(val instanceof JavaScriptObject);
if (strict) {
throwUnconvertibleObjectException(val,
"Object is a member of an Array being converted to JavaScript. " +
"Please see the SmartClient documentation of " +
"RPCRequest.data for a table of Java types that can be converted automatically.");
} else {
setArrayValue(jsArray, i, val);
}
}
}
return jsArray;
}
// Helper to throw an exception if we want to convert a method to JS but it's not a convertible type
// This is also called from JSNI when attempting to serialize a Java object as part of an RPC request
// within the SmartClient JS code. See isc.SmartGWT.throwUnconvertibleObjectException() defined in
// SmartGwtEntryPoint
public static void throwUnconvertibleObjectException(Object object, String messageDetail) {
String message;
if (object == null) message = "Null!!!";
else if (object.getClass() == null) message = "NO Class??!!";
else message = "Attempt to convert instance of class " + (object.getClass().getName()) + " to a JavaScript object failed.";
if (messageDetail != null) message += " " + messageDetail;
throw new UnsupportedOperationException(message);
}
public static Integer toInteger(int value) {
return value;
}
public static Long toLong(double value) {
return (long) value;
}
public static Float toFloat(float value) {
return value;
}
public static Double toDouble(double value) {
return value;
}
private static double getTime(Date date) {
return date.getTime();
}
/**
* Converts a time to a Java {@link java.util.Date} object.
*
* <p>Note: If needing to convert a JavaScript object, it is preferable to use
* {@link #convertToJavaDate(JavaScriptObject)} instead because that function is able to
* convert to {@link com.smartgwt.client.util.LogicalDate} and {@link com.smartgwt.client.util.LogicalTime}
* instances as needed.
*
* @param millis number of milliseconds since January 1, 1970, 00:00:00 GMT.
* @return a new {@link java.util.Date} representing the given time.
*/
public static Date toDate(double millis) {
return new Date((long) millis);
}
public static JavaScriptObject toDateJS(Date date) {
return convertToJavaScriptDate(date);
}
// Helper to get logical JS date / time objects. These objects will be recognized
// as logical date / times for formatting / serialization purposes by the SmartClient system.
public static JsDate getJSLogicalDate(Date date) {
return getJSLogicalDate(date.getYear(), date.getMonth(), date.getDate());
}
public static native JsDate getJSLogicalDate(int year, int month, int date) /*-{
return $wnd.Date.createLogicalDate(year, month, date);
}-*/;
public static native JsDate getJSLogicalTime(Date date) /*-{
var time = @com.smartgwt.client.util.JSOHelper::getTime(Ljava/util/Date;)(date);
var jsDate = $wnd.Date.create().setTime(time);
return $wnd.Date.createLogicalTime(jsDate.getHours(), jsDate.getMinutes(), jsDate.getSeconds(), jsDate.getMilliseconds());
}-*/;
public static native JsDate getJSLogicalTime(int hour, int minute, int second, int millisecond) /*-{
return $wnd.Date.createLogicalTime(hour, minute, second, millisecond);
}-*/;
public static Boolean toBoolean(boolean value) {
return value;
}
public static native JavaScriptObject createJavaScriptArray() /*-{
//Important : constructing an array from JSNI using [] or new Array() results in a
//corrupted array object in the final javascript. The array ends up having the correct elements
//but the test (myarr instanceof Array) fails because the JSNI-created array constructor is different.
//Need to construct array within the scope of the application's IFRAME by using `new $wnd.Array'.
return $wnd.Array.create();
}-*/;
public static void setArrayValue(JavaScriptObject array, int index, Date value) {
setArrayValue(array, index, convertToJavaScriptDate(value));
}
public static native void setArrayValue(JavaScriptObject array, int index, String value) /*-{
// See the comments in setAttribute(JavaScriptObject, String, String).
array[index] = (value == null ? null : String(value));
}-*/;
public static native void setArrayValue(JavaScriptObject array, int index, double value) /*-{
array[index] = value;
}-*/;
public static void setArrayValue(JavaScriptObject array, int index, long value) {
final double d = (double)value;
if (Math.abs(value) > 9007199254740992L) {
SC.logWarn("The long value " + Long.toString(value) + " cannot be exactly represented in JavaScript. It will be truncated to: " + Long.toString((long)d));
}
setArrayValue(array, index, d);
}
public static native void setArrayValue(JavaScriptObject array, int index, boolean value) /*-{
array[index] = value;
}-*/;
public static void setArrayValue(JavaScriptObject array, int index, char value) {
setArrayValue(array, index, Character.toString(value));
}
public static native void setArrayValue(JavaScriptObject array, int index, JavaScriptObject value) /*-{
array[index] = value;
}-*/;
public static native void setArrayValue(JavaScriptObject array, int index, Object value) /*-{
array[index] = value;
}-*/;
public static native String getArrayValue(JavaScriptObject array, int index) /*-{
var result = array[index];
return (result == null ? null : String(result));
}-*/;
public static native JavaScriptObject getJSOArrayValue(JavaScriptObject array, int index) /*-{
var result = array[index];
return (result == null ? null : result);
}-*/;
public static native Object getObjectArrayValue(JavaScriptObject array, int index) /*-{
var result = array[index];
return (result == null ? null : result);
}-*/;
public static native Boolean getBooleanArrayValue(JavaScriptObject array, int index) /*-{
var ret = array[index];
return ret == null ? null : @com.smartgwt.client.util.JSOHelper::toBoolean(Z)(ret);
}-*/;
public static native int getIntArrayValue(JavaScriptObject array, int index) /*-{
return array[index];
}-*/;
public static native float getfloatArrayValue(JavaScriptObject array, int index) /*-{
return array[index];
}-*/;
public static native double getdoubleArrayValue(JavaScriptObject array, int index) /*-{
return array[index];
}-*/;
public static native Integer getIntegerArrayValue(JavaScriptObject array, int index) /*-{
var ret = array[index];
return (ret == null ? null : @com.smartgwt.client.util.JSOHelper::toInteger(I)(ret));
}-*/;
public static native Float getFloatArrayValue(JavaScriptObject array, int index) /*-{
var ret = array[index];
return (ret == null ? null : @com.smartgwt.client.util.JSOHelper::toFloat(F)(ret));
}-*/;
public static native Double getDoubleArrayValue(JavaScriptObject array, int index) /*-{
var ret = array[index];
return (ret == null ? null : @com.smartgwt.client.util.JSOHelper::toDouble(D)(ret));
}-*/;
public static native Date getDateArrayValue(JavaScriptObject array, int i) /*-{
if (array == null || !$wnd.isc.isAn.Array(array)) return null;
var val = array[i];
return @com.smartgwt.client.util.JSOHelper::convertToJavaDate(Lcom/google/gwt/core/client/JavaScriptObject;)(val);
}-*/;
public static native int getArrayLength(JavaScriptObject array) /*-{
return array.length;
}-*/;
public static Boolean[] convertToJavaBooleanArray(JavaScriptObject array) {
int length = getArrayLength(array);
Boolean[] arr = new Boolean[length];
for (int i = 0; i < length; i++) {
arr[i] = getBooleanArrayValue(array, i);
}
return arr;
}
public static int[] convertToJavaIntArray(JavaScriptObject array) {
int length = getArrayLength(array);
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = getIntArrayValue(array, i);
}
return arr;
}
/**
* @deprecated deprecated in favor of {@link #convertToJavaIntegerArray}
*/
public static Integer[] convertToJavaInterArray(JavaScriptObject array) {
return convertToJavaIntegerArray(array);
}
public static Integer[] convertToJavaIntegerArray(JavaScriptObject array) {
int length = getArrayLength(array);
Integer[] arr = new Integer[length];
for (int i = 0; i < length; i++) {
arr[i] = getIntegerArrayValue(array, i);
}
return arr;
}
public static String[] convertToJavaStringArray(JavaScriptObject array) {
if (array == null) return new String[]{};
int length = getArrayLength(array);
String[] arr = new String[length];
for (int i = 0; i < length; i++) {
arr[i] = getArrayValue(array, i);
}
return arr;
}
public static Float[] convertToJavaFloatArray(JavaScriptObject array) {
int length = getArrayLength(array);
Float[] arr = new Float[length];
for (int i = 0; i < length; i++) {
arr[i] = getFloatArrayValue(array, i);
}
return arr;
}
public static Double[] convertToJavaDoubleArray(JavaScriptObject array) {
int length = getArrayLength(array);
Double[] arr = new Double[length];
for (int i = 0; i < length; i++) {
arr[i] = getDoubleArrayValue(array, i);
}
return arr;
}
public static Date[] convertToJavaDateArray(JavaScriptObject array) {
int length = getArrayLength(array);
Date[] arr = new Date[length];
for (int i =0; i < length; i++) {
arr[i] = getDateArrayValue(array, i);
}
return arr;
}
public static Object[] convertToJavaObjectArray(JavaScriptObject array) {
if (array == null) return new Object[]{};
int length = getArrayLength(array);
Object[] arr = new Object[length];
for (int i = 0; i < length; i++) {
arr[i] = getObjectArrayValue(array, i);
}
return arr;
}
public static RefDataClass[] convertToJavaRefDataClassArray(JavaScriptObject nativeArray) {
if (nativeArray == null) {
return new RefDataClass[]{};
}
JavaScriptObject[] componentsj = JSOHelper.toArray(nativeArray);
RefDataClass[] objects = new RefDataClass[componentsj.length];
for (int i = 0; i < componentsj.length; i++) {
JavaScriptObject componentJS = componentsj[i];
RefDataClass obj = RefDataClass.getRef(componentJS);
objects[i] = obj;
}
return objects;
}
public static native void apply(JavaScriptObject config, JavaScriptObject jsObj) /*-{
for(var k in config) {
jsObj[k] = config[k];
}
}-*/;
/**
* Sets attribute "attr" on Javascript object "jsObj" to the JavaScript equivalent of "valueMap".
* See {@link com.smartgwt.client.docs.JavaToJavaScriptConversion}
* for details of the conversions that take place.
*
* @param jsObj the JavaScript object on which to set the attribute
* @param attr the name of the attribute to set
* @param valueMap the Java Map to convert and apply as the attribute value
*/
public static void setAttribute(JavaScriptObject jsObj, String attr, Map valueMap) {
JavaScriptObject valueJS = convertMapToJavascriptObject(valueMap);
setAttribute(jsObj, attr, valueJS);
}
/**
* Converts the parameter Map to an equivalent Javascript object - see
* {@link com.smartgwt.client.docs.JavaToJavaScriptConversion}
* for details of the conversions that take place.
*
* @param array the Java Map to convert
*/
public static JavaScriptObject convertMapToJavascriptObject(Map valueMap) {
return convertMapToJavascriptObject(valueMap, false);
}
public static JavaScriptObject convertMapToJavascriptObject(Map valueMap, boolean strict) {
if(valueMap == null) return null;
JavaScriptObject valueJS = JSOHelper.createObject();
for (Iterator iterator = valueMap.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
if (key == null) {
SC.logWarn("JSO::convertMapToJavascriptObject : Map contains null key - dropping this entry.");
continue;
}
if(key.equals("__ref")) {
SC.logWarn("JSO::convertMapToJavascriptObject : skipping __ref in map");
continue;
}
if (key.equals("__module")) {
SC.logWarn("JSO::convertMapToJavascriptObject : skipping __module in map");
continue;
}
Object value = valueMap.get(key);
if (value instanceof JavaScriptObject) {
setAttribute(valueJS, key, (JavaScriptObject) value);
} else if (value instanceof Date) {
setAttribute(valueJS, key, ((Date) value));
} else if (value instanceof Number) {
setAttribute(valueJS, key, doubleValue((Number) value));
} else if (value instanceof String) {
setAttribute(valueJS, key, ((String) value));
} else if (value instanceof Boolean) {
setAttribute(valueJS, key, ((Boolean) value).booleanValue());
} else if (value == null) {
setNullAttribute(valueJS, key);
} else if(value instanceof String[]) {
setAttribute(valueJS, key, convertToJavaScriptArray((String[]) value));
} else if (value instanceof Object[]) {
setAttribute(valueJS, key, convertToJavaScriptArray((Object[]) value, strict));
} else if (value instanceof int[]) {
setAttribute(valueJS, key, convertToJavaScriptArray((int[]) value));
} else if (value instanceof float[]) {
setAttribute(valueJS, key, convertToJavaScriptArray((float[]) value));
} else if (value instanceof double[]) {
setAttribute(valueJS, key, convertToJavaScriptArray((double[]) value));
} else if (value instanceof long[]) {
setAttribute(valueJS, key, convertToJavaScriptArray((long[]) value));
} else if (value instanceof Map) {
JavaScriptObject innerMapJS = convertMapToJavascriptObject((Map) value, strict);
setAttribute(valueJS, key, innerMapJS);
} else if (value instanceof List){
setAttribute(valueJS, key, JSOHelper.convertToJavaScriptArray(((List)value).toArray(), strict));
} else if (value instanceof DataClass) {
setAttribute(valueJS, key, ((DataClass) value).getJsObj());
} else if (value instanceof BaseClass) {
setAttribute(valueJS, key, ((BaseClass) value).getJsObj());
} else if (value instanceof BaseWidget) {
setAttribute(valueJS, key, ((BaseWidget) value).getOrCreateJsObj());
} else if (value instanceof ValueEnum) {
setAttribute(valueJS, key, ((ValueEnum) value).getValue());
} else {
assert value != null;
if (strict) {
throwUnconvertibleObjectException(value,
"Object is stored as attribute " + key + " of a Map being converted to JavaScript. " +
"Please see the SmartClient documentation of " +
"RPCRequest.data for a table of Java types that can be converted automatically.");
} else {
setObjectAttribute(valueJS, key, value);
}
}
}
return valueJS;
}
public static native String[] getProperties(JavaScriptObject jsObj) /*-{
var props = @com.smartgwt.client.util.JSOHelper::createJavaScriptArray()();
for(var k in jsObj) {
props.push(k);
}
return @com.smartgwt.client.util.JSOHelper::convertToJavaStringArray(Lcom/google/gwt/core/client/JavaScriptObject;)(props);
}-*/;
public static native String getPropertiesAsString(JavaScriptObject jsObj) /*-{
var props = '{';
for(var k in jsObj) {
props += '\n' + k;
}
return props + '}';
}-*/;
/**
* Adds all properties and methods from the propertiesObject to the destination object.
*
* @param destination the destination object
* @param propertiesObject the propertiesObject
*/
public static native void addProperties(JavaScriptObject destination,
JavaScriptObject propertiesObject)
/*-{
$wnd.isc.addProperties(destination, propertiesObject);
}-*/;
/**
* Removes non-transferable properties from the supplied object
* (e.g. widget ID), performing a copy first if requested.
*
* @param properties the supplied object to clean
* @param copyProperties whether to copy the object first
* @return the cleaned properties object
*/
public static native JavaScriptObject cleanProperties(JavaScriptObject properties,
boolean copyProperties)
/*-{
if (properties != null) {
if (copyProperties) properties = $wnd.isc.addProperties({}, properties);
delete properties.AUTOIDClass;
delete properties.ID;
delete properties.__ref;
delete properties.__module;
delete properties._autoAssignedID;
}
return properties;
}-*/;
// Invoking functions in JavaScript scope
// Convert Java Object Array to JavaScript array of appropriate types and use function.apply()
/**
* Invoke a method on some JavaScript object, passing in the specified array of parameters.
* <P>
* This method converts the specified parameters to a equivalent
* objects in JavaScript before calling the method in JavaScript scope, and will convert any return
* value to Java before returning it - see
* {@link com.smartgwt.client.docs.JavaToJavaScriptConversion} for details of the conversions
* that take place.<br>
* If the invoked method has no return value, this method will return null.
*
* @param target
* @param methodName
* @param arguments
* @return
*/
public static Object callMethod (JavaScriptObject target, String methodName, Object[] arguments) {
JavaScriptObject argumentsJS = convertToJavaScriptArray(arguments);
JavaScriptObject result = callMethodJS(target, methodName, argumentsJS);
if (result == null) return null;
// Use convertToJava to appropriately wrap things in the right object type.
return convertToJava(result);
}
private static native JavaScriptObject callMethodJS (JavaScriptObject target, String methodName, JavaScriptObject arguments) /*-{
var returnVal = null;
if (target != null && target[methodName] != null) {
returnVal = target[methodName].apply(target, arguments);
}
return returnVal;
}-*/;
}