package er.ajax;
import java.util.Enumeration;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSKeyValueCoding;
/**
* AjaxValue provides a method for serializing Objects into a JavaScript-compatible format
* with hinting via AjaxOption.Type constants.
*
* @author mschrag
*/
public class AjaxValue {
private AjaxOption.Type _type;
private Object _value;
/**
* @param obj Object to convert to String and escape
* @return obj converted to a string and escaped for use as a quoted JS string
*/
public static String javaScriptEscaped(Object obj) {
String escapedValue = String.valueOf(obj);
escapedValue = escapedValue.replaceAll("\\\\", "\\\\\\\\");
escapedValue = escapedValue.replaceAll("'", "\\\\'");
// Handle line breaks
escapedValue = escapedValue.replaceAll("\\r\\n", "\\\\n");
escapedValue = escapedValue.replaceAll("\\n", "\\\\n");
escapedValue = "'" + escapedValue + "'";
return escapedValue;
}
/**
* Creates AjaxValue for value with the type guessed at.
*
* @see #AjaxValue(er.ajax.AjaxOption.Type, Object)
*
* @param value the value to make into an AjaxValue
*/
public AjaxValue(Object value) {
this(AjaxOption.DEFAULT, value);
}
/**
* Creates AjaxValue for value with the indicated type. If type is AjaxOption.DEFAULT, then
* the actual type will be inferred if value is String, Number, Boolean, NSArray, NSDictionary,
* or AjaxValue (if value is an AjaxValue then both type and value are taken from value).
*
* @see #AjaxValue(Object)
* @see AjaxOption.Type
*
* @param type one of AjaxOption.Type constants from AjaxOption
* @param value the value to make into an AjaxValue
*/
public AjaxValue(AjaxOption.Type type, Object value) {
_type = type;
_value = value;
if (type == AjaxOption.DEFAULT) {
if (value instanceof String) {
_type = AjaxOption.STRING;
}
else if (value instanceof Number) {
_type = AjaxOption.NUMBER;
}
else if (value instanceof Boolean) {
_type = AjaxOption.BOOLEAN;
}
else if (value instanceof NSArray) {
_type = AjaxOption.ARRAY;
}
else if (value instanceof NSDictionary) {
_type = AjaxOption.DICTIONARY;
}
else if (value instanceof AjaxValue) {
_type = ((AjaxValue)value)._type;
_value = ((AjaxValue)value)._value;
}
}
}
/**
* @return a String representing this AjaxValue in a form suitable for use in JavaScript
*/
public String javascriptValue() {
String strValue;
AjaxOption.Type type = _type;
if (type == AjaxOption.STRING_OR_ARRAY) {
if (_value == null) {
type = AjaxOption.STRING;
}
else if (_value instanceof NSArray) {
type = AjaxOption.ARRAY;
}
else if (_value instanceof String) {
strValue = (String) _value;
if (strValue.startsWith("[")) {
type = AjaxOption.ARRAY;
}
else {
type = AjaxOption.STRING;
}
}
}
if (_value == null || _value == NSKeyValueCoding.NullValue) {
strValue = null;
}
else if (type == AjaxOption.STRING) {
strValue = javaScriptEscaped(_value);
}
else if (type == AjaxOption.NUMBER) {
strValue = _value.toString();
}
else if (type == AjaxOption.ARRAY) {
if (_value instanceof NSArray) {
NSArray arrayValue = (NSArray) _value;
StringBuilder sb = new StringBuilder();
sb.append('[');
Enumeration objEnum = arrayValue.objectEnumerator();
while (objEnum.hasMoreElements()) {
Object o = objEnum.nextElement();
sb.append(new AjaxValue(o).javascriptValue());
if (objEnum.hasMoreElements()) {
sb.append(',');
}
}
sb.append(']');
strValue = sb.toString();
}
else {
strValue = _value.toString();
}
}
else if (type == AjaxOption.DICTIONARY) {
if (_value instanceof NSDictionary) {
NSDictionary dictValue = (NSDictionary) _value;
StringBuilder sb = new StringBuilder();
sb.append('{');
Enumeration keyEnum = dictValue.keyEnumerator();
while (keyEnum.hasMoreElements()) {
Object key = keyEnum.nextElement();
Object value = dictValue.objectForKey(key);
sb.append(new AjaxValue(key).javascriptValue());
sb.append(':');
sb.append(new AjaxValue(value).javascriptValue());
if (keyEnum.hasMoreElements()) {
sb.append(',');
}
}
sb.append('}');
strValue = sb.toString();
}
else {
strValue = _value.toString();
}
}
else if (type == AjaxOption.STRING_ARRAY) {
if (_value instanceof NSArray) {
NSArray arrayValue = (NSArray) _value;
int count = arrayValue.count();
if (count == 1) {
strValue = new AjaxValue(AjaxOption.STRING, arrayValue.objectAtIndex(0)).javascriptValue();
}
else if (count > 0) {
StringBuilder sb = new StringBuilder();
sb.append('[');
Enumeration objEnum = arrayValue.objectEnumerator();
while (objEnum.hasMoreElements()) {
Object o = objEnum.nextElement();
sb.append(new AjaxValue(AjaxOption.STRING, o).javascriptValue());
if (objEnum.hasMoreElements()) {
sb.append(',');
}
}
sb.append(']');
strValue = sb.toString();
}
else {
strValue = "[]";
}
}
else {
strValue = _value.toString();
}
}
else if (type == AjaxOption.SCRIPT) {
strValue = _value.toString();
}
else if (type == AjaxOption.FUNCTION) {
strValue = "function() {" + _value.toString() + "}";
}
else if (type == AjaxOption.FUNCTION_1) {
strValue = "function(v) {" + _value.toString() + "}";
}
else if (type == AjaxOption.FUNCTION_2) {
strValue = "function(v1, v2) {" + _value.toString() + "}";
}else {
strValue = _value.toString();
}
return strValue;
}
}