/* Wotonomy: OpenStep design patterns for pure Java applications. Copyright (C) 2000 Blacksmith, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see http://www.gnu.org */ package net.wotonomy.web; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSMutableDictionary; /** * The base class for dynamic WOElements. Dynamic elements * are expected to do something useful with user-entered data * in the request and with any binding associations with the * context's current WOComponent. * * @author michael@mpowers.net * @author $Author: cgruber $ * @version $Revision: 905 $ */ public abstract class WODynamicElement extends WOElement { protected String name; protected WOElement rootElement; protected NSDictionary associations; /** * The default constructor. */ protected WODynamicElement () { name = null; associations = new NSMutableDictionary(); rootElement = null; } /** * Required constructor specifying the class name of the component, * a map of associations, and the root element of the tree that * contains this element (which may be null). The map keys * correspond to properties of this element, and the values are * associations to be applied to the context's current component. */ public WODynamicElement ( String aName, NSDictionary anAssociationMap, WOElement aRootElement) { this(); name = aName; associations = anAssociationMap; rootElement = aRootElement; } /** * Package access only. Called to initialize the component with * the proper context before the start of the request-response cycle. * If the context has a current component, that component becomes * this component's parent. */ void ensureAwakeInContext (WOContext aContext) { if ( rootElement != null ) { rootElement.ensureAwakeInContext( aContext ); } } /** * Use this method to get a map with the properties that start with * a question mark. These are supposed to go at the end of a URL, and it is * very useful for components that generate URLs, specially with direct * actions. * @param c The component where the values of the properties have to be * retrieved from. */ Map urlFields(WOComponent c) { HashMap map = new HashMap(associations.count()); Enumeration enumeration = associations.keyEnumerator(); while (enumeration.hasMoreElements()) { String key = (String)enumeration.nextElement(); if (key.charAt(0) == '?') { map.put(key.substring(1), valueForProperty(key, c)); } } return map; } /** Convenience method for getting the value of an association. */ Object valueForProperty(String key, WOComponent c) { WOAssociation a = (WOAssociation)associations.objectForKey(key); if (a != null) return a.valueInComponent(c); return null; } /** Convenience method for getting the string value of an association. */ String stringForProperty(String key, WOComponent c) { WOAssociation a = (WOAssociation)associations.objectForKey(key); Object result = null; if (a != null) result = a.valueInComponent(c); if ( result == null ) return null; return result.toString(); } /** Convenience method for getting the string value of an association. */ boolean booleanForProperty(String key, WOComponent c) { WOAssociation a = (WOAssociation)associations.objectForKey(key); Object result = null; if (a != null) result = a.valueInComponent(c); if ( result == null ) return false; if ( result.toString().toLowerCase().equals( "true" ) ) return true; return Boolean.TRUE.equals( result ); } /** Convenience method for setting the value of an association. */ void setValueForProperty(String key, Object value, WOComponent c) { WOAssociation a = (WOAssociation)associations.objectForKey(key); if ( a != null && a.isValueSettable() ) a.setValue(value, c); } /** this method composes a String suitable for inclusion inside a HTML tag. It includes the key-value pairs of all the associations not mentioned in the standardProperties parameter. This is very useful for including extra properties in tags without having to worry if the HTML specification has changed or if non-standard tags are being used. @param c The component where the associations' values should be retrieved from. @param standardProperties An array of Strings with all the associations that should be excluded from the resulting string. */ String additionalHTMLProperties(WOComponent c, NSArray standardProperties) { Enumeration enumeration = associations.keyEnumerator(); StringBuffer buf = new StringBuffer(); while (enumeration.hasMoreElements()) { String key = (String)enumeration.nextElement(); if (!(standardProperties.containsObject(key) || key.charAt(0)=='?')) { buf.append(' '); buf.append(key); buf.append("=\""); buf.append(valueForProperty(key, c)); buf.append('\"'); } } return buf.toString(); } /** * This method is called to retrieve user-entered data from * the request. WOElements should retrieve data from the * request based on their elementID and set values in the * context's current WOComponent, typically those values that * are associated with the element in the binding. This * implementation does nothing. */ public void takeValuesFromRequest (WORequest aRequest, WOContext aContext) { } /** * This method is called on all objects and elements of the * application until a non-null value is returned. * WOElements should first check to see if they are the * target of an action by checking the WOContext's senderID * to see if it matches this element's elementID. * If this element is the target, it should perform an * appropriate action on the context's current WOComponent, * usually the action specified in the binding, and return * the result of that action. This implementation returns null. */ public WOActionResults invokeAction (WORequest aRequest, WOContext aContext) { return null; } /** * This method is called on all elements of the content tree * to build a response to a user request. The message should * be forwarded to any child elements so that the entire tree * is traversed. This implementation does nothing. */ public void appendToResponse (WOResponse aResponse, WOContext aContext) { // does nothing } public WOResponse generateResponse() { return null; } }