View Javadoc

1   /*
2   Wotonomy: OpenStep design patterns for pure Java applications.
3   Copyright (C) 2000 Blacksmith, Inc.
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Lesser General Public License for more details.
14  
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, see http://www.gnu.org
17  */
18  
19  package net.wotonomy.web;
20  
21  import java.util.Enumeration;
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import net.wotonomy.foundation.NSArray;
26  import net.wotonomy.foundation.NSDictionary;
27  import net.wotonomy.foundation.NSMutableDictionary;
28  
29  /***
30  * The base class for dynamic WOElements.  Dynamic elements
31  * are expected to do something useful with user-entered data
32  * in the request and with any binding associations with the
33  * context's current WOComponent.
34  *
35  * @author michael@mpowers.net
36  * @author $Author: cgruber $
37  * @version $Revision: 905 $
38  */
39  public abstract class WODynamicElement
40      extends WOElement
41  {
42  	protected String name;
43  	protected WOElement rootElement;
44      protected NSDictionary associations;   
45  
46      /***
47  	* The default constructor.
48  	*/
49      protected WODynamicElement ()
50      {
51      	name = null;
52  	    associations = new NSMutableDictionary();
53  	    rootElement = null;
54      }
55      
56      /***
57      * Required constructor specifying the class name of the component,
58      * a map of associations, and the root element of the tree that 
59      * contains this element (which may be null).  The map keys 
60      * correspond to properties of this element, and the values are
61      * associations to be applied to the context's current component.
62      */
63      public WODynamicElement (
64      	String aName, NSDictionary anAssociationMap, WOElement aRootElement)
65      {
66      	this();
67  	    name = aName;
68  	    associations = anAssociationMap;
69  	    rootElement = aRootElement;
70      }
71  
72      /***
73      * Package access only.  Called to initialize the component with 
74      * the proper context before the start of the request-response cycle.
75      * If the context has a current component, that component becomes
76      * this component's parent.
77      */
78      void ensureAwakeInContext (WOContext aContext)
79      {
80          if ( rootElement != null )
81          {
82              rootElement.ensureAwakeInContext( aContext );
83          }
84      }
85  
86      /***
87       * Use this method to get a map with the properties that start with
88       * a question mark. These are supposed to go at the end of a URL, and it is
89       * very useful for components that generate URLs, specially with direct
90       * actions.
91       * @param c The component where the values of the properties have to be
92       * retrieved from.
93       */
94      Map urlFields(WOComponent c) {
95          HashMap map = new HashMap(associations.count());
96          Enumeration enumeration = associations.keyEnumerator();
97          while (enumeration.hasMoreElements()) {
98              String key = (String)enumeration.nextElement();
99              if (key.charAt(0) == '?') {
100                 map.put(key.substring(1), valueForProperty(key, c));
101             }
102         }
103         return map;
104     }
105 
106     /*** Convenience method for getting the value of an association. */
107     Object valueForProperty(String key, WOComponent c) {
108         WOAssociation a = (WOAssociation)associations.objectForKey(key);
109         if (a != null)
110             return a.valueInComponent(c);
111         return null;
112     }
113 
114     /*** Convenience method for getting the string value of an association. */
115     String stringForProperty(String key, WOComponent c) {
116         WOAssociation a = (WOAssociation)associations.objectForKey(key);
117         Object result = null;
118         if (a != null) result = a.valueInComponent(c);
119         if ( result == null ) return null;
120         return result.toString();
121     }
122 
123     /*** Convenience method for getting the string value of an association. */
124     boolean booleanForProperty(String key, WOComponent c) {
125         WOAssociation a = (WOAssociation)associations.objectForKey(key);
126         Object result = null;
127         if (a != null) result = a.valueInComponent(c);
128         if ( result == null ) return false;
129         if ( result.toString().toLowerCase().equals( "true" ) ) return true;
130         return Boolean.TRUE.equals( result );
131     }
132 
133     /*** Convenience method for setting the value of an association. */
134     void setValueForProperty(String key, Object value, WOComponent c) {
135         WOAssociation a = (WOAssociation)associations.objectForKey(key);
136         if ( a != null && a.isValueSettable() ) 
137             a.setValue(value, c);
138     }
139 
140     /*** this method composes a String suitable for inclusion inside a HTML tag. It includes
141         the key-value pairs of all the associations not mentioned in the standardProperties
142         parameter. This is very useful for including extra properties in tags without having to worry
143         if the HTML specification has changed or if non-standard tags are being used.
144         @param c The component where the associations' values should be retrieved from.
145         @param standardProperties An array of Strings with all the associations that should be
146         excluded from the resulting string. */
147     String additionalHTMLProperties(WOComponent c, NSArray standardProperties) {
148         Enumeration enumeration = associations.keyEnumerator();
149         StringBuffer buf = new StringBuffer();
150         while (enumeration.hasMoreElements()) {
151             String key = (String)enumeration.nextElement();
152             if (!(standardProperties.containsObject(key) || key.charAt(0)=='?')) {
153                 buf.append(' ');
154                 buf.append(key);
155                 buf.append("=\"");
156                 buf.append(valueForProperty(key, c));
157                 buf.append('\"');
158             }
159         }
160         return buf.toString();
161     }
162 
163     /***
164 	* This method is called to retrieve user-entered data from
165 	* the request.  WOElements should retrieve data from the 
166 	* request based on their elementID and set values in the 
167 	* context's current WOComponent, typically those values that
168 	* are associated with the element in the binding.  This 
169 	* implementation does nothing.
170 	*/
171     public void takeValuesFromRequest (WORequest aRequest, WOContext aContext)
172     {
173     	
174 	}
175 
176     /***
177     * This method is called on all objects and elements of the 
178     * application until a non-null value is returned.
179     * WOElements should first check to see if they are the
180     * target of an action by checking the WOContext's senderID
181     * to see if it matches this element's elementID.  
182     * If this element is the target, it should perform an 
183     * appropriate action on the context's current WOComponent,
184     * usually the action specified in the binding, and return
185     * the result of that action.  This implementation returns null.
186     */
187     public WOActionResults invokeAction (WORequest aRequest, WOContext aContext)
188     {
189     	return null;
190     }
191     
192     /***
193     * This method is called on all elements of the content tree
194     * to build a response to a user request.  The message should 
195     * be forwarded to any child elements so that the entire tree
196     * is traversed.  This implementation does nothing.
197     */
198     public void appendToResponse (WOResponse aResponse, WOContext aContext)
199     {
200     	// does nothing
201     }
202     
203     public WOResponse generateResponse() 
204     {
205         return null;
206     }
207 
208 }