1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
201 }
202
203 public WOResponse generateResponse()
204 {
205 return null;
206 }
207
208 }