/*==========================================================================*\ | $Id: DojoFormElement.java,v 1.1 2010/05/11 14:52:00 aallowat Exp $ |*-------------------------------------------------------------------------*| | Copyright (C) 2006-2008 Virginia Tech | | This file is part of Web-CAT. | | Web-CAT is free software; you can redistribute it and/or modify | it under the terms of the GNU Affero General Public License as published | by the Free Software Foundation; either version 3 of the License, or | (at your option) any later version. | | Web-CAT 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 General Public License for more details. | | You should have received a copy of the GNU Affero General Public License | along with Web-CAT; if not, see <http://www.gnu.org/licenses/>. \*==========================================================================*/ package org.webcat.ui._base; import java.util.List; import org.webcat.ui.WCButton; import org.webcat.ui.WCDateTextBox; import org.webcat.ui.util.DojoConstraintsHelper; import org.webcat.ui.util.JSHash; import com.webobjects.appserver.WOAssociation; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WOElement; import com.webobjects.appserver.WORequest; import com.webobjects.appserver.WOResponse; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSMutableDictionary; // ------------------------------------------------------------------------ /** * A base class for any Dojo elements that contain a form field that should be * submitted as part of a form submit operation on a page. * * @author Tony Allevato * @version $Id: DojoFormElement.java,v 1.1 2010/05/11 14:52:00 aallowat Exp $ */ public abstract class DojoFormElement extends DojoElement { //~ Constructor ........................................................... // ---------------------------------------------------------- /** * Creates a new Dojo form element. * * @param name * @param someAssociations * @param template */ public DojoFormElement(String name, NSDictionary<String, WOAssociation> someAssociations, WOElement template) { super(name, someAssociations, template); _name = _associations.removeObjectForKey("name"); _value = _associations.removeObjectForKey("value"); _escapeHTML = _associations.objectForKey("escapeHTML"); _hidden = _associations.objectForKey("hidden"); _disabled = _associations.removeObjectForKey("disabled"); _constraintsHelper = new DojoConstraintsHelper(_associations); } //~ Methods ............................................................... // ---------------------------------------------------------- /** * Gets the value of the "type" attribute that should be written along with * the tag, if it is an <input> element. * @param context TODO * * @return the value of the element's "type" attribute */ protected String inputTypeInContext(WOContext context) { return ""; } // ---------------------------------------------------------- /** * Can be overridden by subclasses to return a value indicating whether the * element can contain content or not. */ @Override protected boolean hasContent() { return hasChildrenElements(); } // ---------------------------------------------------------- protected boolean defaultEscapeHTML() { return true; } // ---------------------------------------------------------- protected NSMutableDictionary<String, String> nameMappingFromContext( WOContext context) { NSMutableDictionary<String, String> mapping = (NSMutableDictionary<String, String>) context.userInfoForKey( NAME_MAPPING_USER_INFO_KEY); if (mapping == null) { mapping = new NSMutableDictionary<String, String>(); context.setUserInfoForKey(mapping, NAME_MAPPING_USER_INFO_KEY); } return mapping; } // ---------------------------------------------------------- protected void insertNameMappingIntoContext(WOContext context) { String name = nameInContext(context); String elementID = context.elementID(); if (name != null && !name.equals(elementID)) { nameMappingFromContext(context).setObjectForKey(elementID, name); } } // ---------------------------------------------------------- protected void removeNameMappingFromContext(WOContext context) { String name = nameInContext(context); if (name != null) { nameMappingFromContext(context).removeObjectForKey(name); } } // ---------------------------------------------------------- /** * If a subclass overrides this and does not call the super implementation, * it must call {@link #insertNameMappingIntoContext} before calling * <tt>context.wasFormSubmitted</tt> and then call * {@link #removeNameMappingFromContext} before returning if it wants to * participate successfully in Ajax partial submits. */ @Override public void takeValuesFromRequest(WORequest request, WOContext context) { insertNameMappingIntoContext(context); if (!isDisabledInContext(context) && context.wasFormSubmitted()) { String name = nameInContext(context); if (name != null && name.length() > 0 && _value != null) { String stringValue = request.stringFormValueForKey(name); Object value = objectForStringValue(stringValue, context); _value.setValue(value, context.component()); } } super.takeValuesFromRequest(request, context); removeNameMappingFromContext(context); } // ---------------------------------------------------------- /** * Gets the name of the element in the specified context. * * @param context * the context * @return the name of the element */ public String nameInContext(WOContext context) { if (_name != null) { Object value = _name.valueInComponent(context.component()); if (value != null) { return value.toString(); } } Object elementID = context.elementID(); if (elementID != null) { return elementID.toString(); } else { throw new IllegalStateException("<" + getClass().getName() + "> " + "Cannot evaluate 'name' attribute, and context element " + "ID is null."); } } // ---------------------------------------------------------- /** * Given the specified string value of the "value" attribute of the form * field for this element from the request, transforms it into an object * that is set in the "value" binding of the hosting component. Can be * overridden by subclasses if special handling of the value is required. * * The default implementation merely returns the same string. * * @param stringValue * the string representation of the value of the field * @param context * the context of the request * @return an object to set into the "value" binding of the hosting * component */ protected Object objectForStringValue(String stringValue, WOContext context) { return stringValue; } // ---------------------------------------------------------- /** * Gets the string that will be written as the value of the "value" * attribute for this element, based on the specified object that was * retrieved from the component binding. * * Subclasses can override this to alter the way that the value is converted * to a string. The default implementation merely calls toString on the * object. * * @param value * the object obtained by querying the "value" binding on the * hosting component * @param context * the context of the request * @return the string representation of the element, to be written into the * "value" attribute of the HTML */ protected String stringValueForObject(Object value, WOContext context) { return value.toString(); } // ---------------------------------------------------------- protected boolean escapeHTMLInContext(WOContext context) { if (_escapeHTML == null) return defaultEscapeHTML(); else return _escapeHTML.booleanValueInComponent(context.component()); } // ---------------------------------------------------------- protected boolean isDisabledInContext(WOContext context) { if (_disabled != null) return _disabled.booleanValueInComponent(context.component()); else return false; } // ---------------------------------------------------------- protected boolean isValueInInputValues(Object input, Object formValues) { boolean result = false; if(input != null && formValues != null) { if(formValues instanceof List) { result = ((List<?>) formValues).contains(input.toString()); } else { result = input.toString().equals(formValues); } } return result; } // ---------------------------------------------------------- protected void appendInputTypeAttributeToResponse(WOResponse response, WOContext context) { boolean hidden = false; if (_hidden != null) hidden = _hidden.booleanValueInComponent(context.component()); String inputType = hidden ? "hidden" : inputTypeInContext(context); if (inputType != null && inputType.length() > 0) { _appendTagAttributeAndValueToResponse(response, "type", inputType, false); } } // ---------------------------------------------------------- protected void appendNameAttributeToResponse(WOResponse response, WOContext context) { String name = nameInContext(context); if (name != null && name.length() > 0) { _appendTagAttributeAndValueToResponse(response, "name", name, escapeHTMLInContext(context)); } } // ---------------------------------------------------------- protected String valueStringInContext(WOContext context) { if (_value == null) { return ""; } else { Object object = _value.valueInComponent(context.component()); if (object != null) { String value = stringValueForObject(object, context); if (value == null) return null; else return value; } else { return ""; } } } // ---------------------------------------------------------- protected void appendValueAttributeToResponse(WOResponse response, WOContext context) { String value = valueStringInContext(context); if (value.length() > 0) { _appendTagAttributeAndValueToResponse(response, "value", value, escapeHTMLInContext(context)); } } // ---------------------------------------------------------- protected void appendDisabledAttributeToResponse(WOResponse response, WOContext context) { if (isDisabledInContext(context)) { _appendTagAttributeAndValueToResponse(response, "disabled", "disabled", false); } } // ---------------------------------------------------------- /** * Subclasses can override this method to provide a dictionary of * additional constraints that should be appended to any constraints * specified in the WOD file. This is useful mainly if an element binding * is intended to map to a constraint but is not named as such (for * example, the dateformat binding on WCDateTextBox). * * @param context * @return a dictionary containing additional constraints that should be * merged with any user-supplied constraints */ protected JSHash additionalConstraints( WOContext context) { return null; } // ---------------------------------------------------------- protected void appendConstraintsAttributeToResponse(WOResponse response, WOContext context) { String constraints = _constraintsHelper.constraintsFromBindingValues( context, additionalConstraints(context)); if (constraints != null) { _appendTagAttributeAndValueToResponse(response, "constraints", constraints, true); } } // ---------------------------------------------------------- @Override public void appendAttributesToResponse(WOResponse response, WOContext context) { super.appendAttributesToResponse(response, context); appendInputTypeAttributeToResponse(response, context); appendDisabledAttributeToResponse(response, context); appendNameAttributeToResponse(response, context); appendValueAttributeToResponse(response, context); appendConstraintsAttributeToResponse(response, context); } //~ Static/instance variables ............................................. protected WOAssociation _disabled; protected WOAssociation _name; protected WOAssociation _value; protected WOAssociation _escapeHTML; protected WOAssociation _hidden; private DojoConstraintsHelper _constraintsHelper; /*package*/ static final String NAME_MAPPING_USER_INFO_KEY = "webcat.ui._base.DojoFormElement.nameMappingKey"; }