package er.ajax; import com.webobjects.appserver.WOAssociation; import com.webobjects.appserver.WOComponent; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSMutableDictionary; /** * AjaxOption provides a bridge between a binding value in an AjaxComponent or AjaxDynamicElement and one JavaScript formatted * key-value pair in a dictionary. An AjaxOption consists of four values: * <ul> * <li><b>Name</b>: the key value in the dictionary</li> * <li><b>Binding Name</b>: the name of the binding in an AjaxComponent or AjaxDynamicElement to get the Java value from</li> * <li><b>Default Value</b>: optional default value if binding name evaluates to a null value</li> * <li><b>Type</b>: one of the AjaxOption.Type constants in AjaxOption</li> * </ul> * * @see AjaxOptions * @see AjaxValue */ public class AjaxOption { public static final AjaxOption.Type DEFAULT = new AjaxOption.Type(0); public static final AjaxOption.Type STRING = new AjaxOption.Type(1); public static final AjaxOption.Type SCRIPT = new AjaxOption.Type(2); public static final AjaxOption.Type NUMBER = new AjaxOption.Type(3); public static final AjaxOption.Type ARRAY = new AjaxOption.Type(4); public static final AjaxOption.Type STRING_ARRAY = new AjaxOption.Type(5); public static final AjaxOption.Type BOOLEAN = new AjaxOption.Type(6); public static final AjaxOption.Type STRING_OR_ARRAY = new AjaxOption.Type(7); public static final AjaxOption.Type DICTIONARY = new AjaxOption.Type(8); public static final AjaxOption.Type FUNCTION = new AjaxOption.Type(9); // Function with no args public static final AjaxOption.Type FUNCTION_1 = new AjaxOption.Type(9);// Function with one arg public static final AjaxOption.Type FUNCTION_2 = new AjaxOption.Type(9);// Function with two args /** * AjaxOption.Type is a simple enumeration of the types that AjaxValue can interpret. */ public static class Type { private int _number; // This class might make more sense on AjaxValue? public Type(int number) { _number = number; } } private String _name; private String _bindingName; private Object _defaultValue; private AjaxOption.Type _type; /* * Creates an AjaxOption with: * <ul> * <li>Name: name</li> * <li>Binding Name: name</li> * <li>Default Value: none</li> * <li>Type: AjaxOption.DEFAULT</li> * </ul> */ public AjaxOption(String name) { this(name, name, null, AjaxOption.DEFAULT); } /* * Creates an AjaxOption with: * <ul> * <li>Name: name</li> * <li>Binding Name: name</li> * <li>Default Value: none</li> * <li>Type: type</li> * </ul> */ public AjaxOption(String name, AjaxOption.Type type) { this(name, name, null, type); } /* * Creates an AjaxOption with: * <ul> * <li>Name: name</li> * <li>Binding Name: name</li> * <li>Default Value: defaultValue</li> * <li>Type: type</li> * </ul> */ public AjaxOption(String name, Object defaultValue, AjaxOption.Type type) { this(name, name, defaultValue, type); } /* * Creates an AjaxOption with: * <ul> * <li>Name: name</li> * <li>Binding Name: bindingName</li> * <li>Default Value: defaultValue</li> * <li>Type: type</li> * </ul> */ public AjaxOption(String name, String bindingName, Object defaultValue, AjaxOption.Type type) { _name = name; _bindingName = bindingName; _type = type; _defaultValue = defaultValue; } public String name() { return _name; } public AjaxOption.Type type() { return _type; } /** * @param obj the Object to return an AjaxValue for * @return an AjaxValue encapsulating obj with the same type as this AjaxOption */ public AjaxValue valueForObject(Object obj) { return new AjaxValue(_type, obj); } public Object defaultValue() { return _defaultValue; } /* * Bridge to an AjaxComponent. */ protected Object valueInComponent(WOComponent component) { Object value = component.valueForBinding(_bindingName); if (value instanceof WOAssociation) { WOAssociation association = (WOAssociation) value; value = association.valueInComponent(component); } if (value == null) { value = _defaultValue; } return value; } /* * Bridge to an AjaxDynamicElement. */ protected Object valueInComponent(WOComponent component, NSDictionary<String, ? extends WOAssociation> associations) { Object value = null; if (associations != null) { value = associations.objectForKey(_bindingName); // This is needed for the double step to resolve the value for ^ notation if (value instanceof WOAssociation) { WOAssociation association = (WOAssociation) value; value = association.valueInComponent(component); } } if (value == null) { value = _defaultValue; } return value; } /** * Evaluates this AjaxOption on a WOComponent and adds the name and JavaScript formatted value to dictionary. * * @param component WOComponent to get binding value from * @param dictionary mutable dictionary to add key-value pair to */ public void addToDictionary(WOComponent component, NSMutableDictionary<String, String> dictionary) { Object value = valueInComponent(component); String strValue = valueForObject(value).javascriptValue(); if (strValue != null) { dictionary.setObjectForKey(strValue, _name); } } /** * Evaluates this AjaxOption on a WODynamicElement and adds the name and JavaScript formatted value to dictionary. * * @param component WOComponent to get binding value from * @param associations dictionary of associations to get WOAssocation providing value from * @param dictionary mutable dictionary to add key-value pair to */ protected void addToDictionary(WOComponent component, NSDictionary<String, ? extends WOAssociation> associations, NSMutableDictionary<String, String> dictionary) { Object value = valueInComponent(component, associations); String strValue = valueForObject(value).javascriptValue(); if (strValue != null) { dictionary.setObjectForKey(strValue, _name); } } /** * @param ajaxOptions list of AjaxOption to evaluate on component * @param component WOComponent to get binding value from * * @return dictionary produced by evaluating the array of AjaxOption on a WOComponent and adding the resulting name and JavaScript formatted values */ public static NSMutableDictionary<String, String> createAjaxOptionsDictionary(NSArray<AjaxOption> ajaxOptions, WOComponent component) { NSMutableDictionary<String, String> optionsDictionary = new NSMutableDictionary<>(); for (AjaxOption ajaxOption : ajaxOptions) { ajaxOption.addToDictionary(component, optionsDictionary); } return optionsDictionary; } /** * @param ajaxOptions list of AjaxOption to evaluate on component * @param component WOComponent to get binding value from * @param associations dictionary of associations to get WOAssocation providing value from * * @return dictionary produced by evaluating the array of AjaxOption on a WOComponent and adding the resulting name and JavaScript formatted values */ public static NSMutableDictionary<String, String> createAjaxOptionsDictionary(NSArray<AjaxOption> ajaxOptions, WOComponent component, NSDictionary<String, ? extends WOAssociation> associations) { NSMutableDictionary<String, String> optionsDictionary = new NSMutableDictionary<>(); for (AjaxOption ajaxOption : ajaxOptions) { ajaxOption.addToDictionary(component, associations, optionsDictionary); } return optionsDictionary; } }