1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
/*
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 {
private static final long serialVersionUID = -5383805382837136590L;
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.
*/
@Override
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.
*/
@Override
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.
*/
@Override
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.
*/
@Override
public void appendToResponse(WOResponse aResponse, WOContext aContext) {
// does nothing
}
@Override
public WOResponse generateResponse() {
return null;
}
}
|