2009/05/20 - Apache Shale has been retired.
For more information, please explore the Attic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shale.usecases.rolodex;
19
20 import java.io.UnsupportedEncodingException;
21 import java.net.URLDecoder;
22 import java.util.List;
23
24 import javax.faces.context.FacesContext;
25 import javax.faces.model.SelectItem;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.shale.clay.config.beans.AttributeBean;
30 import org.apache.shale.clay.config.beans.ComponentBean;
31 import org.apache.shale.clay.config.beans.ElementBean;
32 import org.apache.shale.view.AbstractViewController;
33
34 /***
35 * <p>
36 * The ViewController for the rolodex use case. This is a contacts list that is
37 * to demonstrate the reuse ability for the Clay component.
38 * </p>
39 *
40 */
41 public class Rolodex extends AbstractViewController {
42
43 /***
44 * <p>
45 * Commons logging utility object static instance.
46 * </p>
47 */
48 private static Log log;
49 static {
50 log = LogFactory.getLog(Rolodex.class);
51 }
52
53 /***
54 * <p>
55 * The the selected tab index.
56 * </p>
57 */
58 private int selectedTab = 0;
59
60 /***
61 * <p>
62 * Returns the current tab index.
63 * </p>
64 */
65 public int getSelectedTab() {
66 return selectedTab;
67 }
68
69 /***
70 * <p>
71 * The contact that is selected for edit.
72 * </p>
73 */
74 private Contact selectedContact = null;
75
76 /***
77 * <p>
78 * Returns the selected contact for edit.
79 * </p>
80 */
81 public Contact getSelectedContact() {
82 return selectedContact;
83 }
84
85 /***
86 * <p>
87 * Sets the selected contact for edit.
88 * </p>
89 */
90 public void setSelectedContact(Contact contact) {
91 selectedContact = contact;
92 }
93
94 /***
95 * <p>
96 * Records a change in tab index.
97 * </p>
98 */
99 public void setSelectedTab(int index) {
100 if (log.isInfoEnabled())
101 log.info("Switching from tab " + selectedTab + " to tab " + index);
102
103 selectedTab = index;
104 contacts = null;
105 }
106
107 /***
108 * <p>
109 * Creates an object graph uses to build the rolodex folder tabs dynamically.
110 * </p>
111 *
112 * @param item -
113 * SelectItem holding the information to create the tab link
114 * @param context -
115 * FacesContext
116 * @return returns a top level clay meta component bean
117 */
118 protected ElementBean createCommandLinkMetadata(SelectItem item,
119 FacesContext context) {
120
121
122 ElementBean link = new ElementBean();
123 link.setRenderId(generateId());
124 link.setJsfid("commandLink");
125 link.setComponentType("javax.faces.HtmlCommandLink");
126
127
128 AttributeBean attr = new AttributeBean();
129 attr.setName("value");
130 attr.setValue(item.getLabel());
131 link.addAttribute(attr);
132
133
134
135 attr = new AttributeBean();
136 attr.setName("immediate");
137 attr.setValue("true");
138 link.addAttribute(attr);
139
140
141 attr = new AttributeBean();
142 attr.setName("action");
143 attr.setValue("#{@managed-bean-name.changeTab}");
144 link.addAttribute(attr);
145
146
147 ElementBean param = new ElementBean();
148 param.setJsfid("param");
149 param.setComponentType("javax.faces.Parameter");
150
151 param.setRenderId(generateId());
152
153
154
155 attr = new AttributeBean();
156 attr.setName("name");
157 attr.setValue("tabIndex");
158 param.addAttribute(attr);
159
160
161 attr = new AttributeBean();
162 attr.setName("value");
163 attr.setValue(((Integer) item.getValue()).toString());
164 param.addAttribute(attr);
165
166
167 link.addChild(param);
168
169 return link;
170 }
171
172 /***
173 * <p>
174 * A sequential counter to generate a unique renderId.
175 * </p>
176 */
177 int renderId = 0;
178
179 /***
180 * <p>
181 * Returns the next sequential renderId. Because the logic builds the list
182 * in a linear fashion, a sequential unintelligent counter works.
183 * </p>
184 */
185 private int generateId() {
186 return renderId++;
187 }
188
189 /***
190 * <p>
191 * This method builds a verbatim meta tag. It is passed a "rendered"
192 * expression that will be evaluated to determine if the component is
193 * visible.
194 * </p>
195 *
196 * @param html
197 * The HTML tag to write to the document
198 * @param renderExp
199 * A value binding EL for the "rendered" attribute.
200 * @param context
201 * faces context
202 * @return A clay element bean used to construct a faces outputText
203 * component.
204 */
205 protected ElementBean createVerbatimMetadata(String html, String renderExp,
206 FacesContext context) {
207 ElementBean text = createVerbatimMetadata(html, context);
208
209
210 AttributeBean attr = new AttributeBean();
211 attr.setName("rendered");
212 attr.setValue(renderExp);
213 attr.setBindingType(AttributeBean.BINDING_TYPE_VALUE);
214 text.addAttribute(attr);
215
216 return text;
217
218 }
219
220 /***
221 * <p>
222 * This mehtod builds a simple verbatim meta tag. The value will not be
223 * escaped.
224 * <p>
225 *
226 * @param html
227 * HTML tag to write to the document
228 * @param context -
229 * faces context
230 * @return A clay element bean used to construct a faces outputText
231 * component.
232 */
233 protected ElementBean createVerbatimMetadata(String html,
234 FacesContext context) {
235
236
237 ElementBean text = new ElementBean();
238 text.setRenderId(generateId());
239 text.setJsfid("f:verbatim");
240 text.setComponentType("javax.faces.HtmlOutputText");
241
242
243 AttributeBean attr = new AttributeBean();
244 attr.setName("value");
245 attr.setValue(html);
246 text.addAttribute(attr);
247
248
249 attr = new AttributeBean();
250 attr.setName("escape");
251 attr.setValue(Boolean.FALSE.toString());
252 text.addAttribute(attr);
253
254
255 attr = new AttributeBean();
256 attr.setName("isTransient");
257 attr.setValue(Boolean.TRUE.toString());
258 text.addAttribute(attr);
259
260 return text;
261 }
262
263 /***
264 * <p>
265 * This action event is fired when clicking on a tab link. The
266 * <code>selectedTab</code> is set with the value of the
267 * <code>tabIndex</code> request parameter.
268 * </p>
269 */
270 public String changeTab() {
271 if (log.isInfoEnabled())
272 log.info("changeTab()");
273
274 QueryParam paramObj = (QueryParam) getBean("queryParam");
275 String tabIndex = paramObj.getTabIndex();
276
277 if (tabIndex != null) {
278 setSelectedTab(Integer.parseInt(tabIndex));
279
280
281 setSelectedContact(null);
282 }
283
284 return "rolodex$test";
285 }
286
287 /***
288 * <p>
289 * This is a method binding event fired from the <strong>Clay</strong>
290 * component before building the component tree. The method signature is a
291 * "Validator" event signature and the binding attribute is
292 * <code>shapeValidator</code>.
293 * </p>
294 *
295 * @param context
296 * facesContext
297 * @param component
298 * @param displayElementRoot
299 */
300 public void createTabs(javax.faces.context.FacesContext context,
301 javax.faces.component.UIComponent component,
302 java.lang.Object displayElementRoot) {
303
304 if (log.isInfoEnabled())
305 log.info("createTabs()");
306
307
308 RolodexDao dao = (RolodexDao) getBean("rolodexDao");
309
310
311 List tabs = dao.getTabs();
312
313 ComponentBean root = (ComponentBean) displayElementRoot;
314 root.setComponentType("javax.faces.HtmlPanelGroup");
315 root.addChild(createVerbatimMetadata("<ul id=\"menu\">", context));
316
317 for (int i = 0; i < tabs.size(); i++) {
318 SelectItem item = (SelectItem) tabs.get(i);
319
320 root.addChild(createVerbatimMetadata("<li id=\"", context));
321
322 root.addChild(createVerbatimMetadata("nav-sel",
323 "#{@managed-bean-name.selectedTab == " + i + "}", context));
324 root.addChild(createVerbatimMetadata("nav",
325 "#{@managed-bean-name.selectedTab != " + i + "}", context));
326
327 root.addChild(createVerbatimMetadata("\">", context));
328 root.addChild(createCommandLinkMetadata(item, context));
329 root.addChild(createVerbatimMetadata("</li>", context));
330 }
331
332 root.addChild(createVerbatimMetadata("</ul>", context));
333
334 }
335
336 /***
337 * <p>Caches the current contacts.</p>
338 */
339 private List contacts = null;
340
341 /***
342 * <p>
343 * This is called by the data table component to return a list of
344 * {@link Contact}s that belong within the selected index.
345 * </p>
346 */
347 public List getContactsForTab() {
348 if (log.isInfoEnabled())
349 log.info("getContactsForTab()");
350
351 if (contacts == null) {
352
353 RolodexDao dao = (RolodexDao) getBean("rolodexDao");
354
355
356 contacts = dao.findContactsForTab(getSelectedTab());
357 }
358
359 return contacts;
360 }
361
362
363 /***
364 * <p>
365 * This is an action event fired from clicking on a contact in the data
366 * grid. The latest contact is located using the data access object and is
367 * set as the "select" contact.
368 * </p>
369 */
370 public String selectContact() {
371 if (log.isInfoEnabled())
372 log.info("selectContact()");
373
374
375 QueryParam paramObj = (QueryParam) getBean("queryParam");
376 String name = paramObj.getSelectedName();
377
378 if (name != null) {
379
380 RolodexDao dao = (RolodexDao) getBean("rolodexDao");
381
382
383 try {
384 name = URLDecoder.decode(name, "UTF-8");
385 } catch (UnsupportedEncodingException e) {}
386
387
388 setSelectedContact(dao.findContact(name));
389 }
390
391 return "rolodex$test";
392 }
393
394 /***
395 * <p>
396 * Saves a {@link Contact} to the mock data store.
397 * </p>
398 */
399 public String saveContact() {
400 if (log.isInfoEnabled())
401 log.info("saveContact()");
402
403 if (getSelectedContact() != null) {
404 RolodexDao dao = (RolodexDao) getBean("rolodexDao");
405
406
407 setSelectedTab(dao.saveContact(getSelectedContact()));
408 }
409
410 return "rolodex$test";
411 }
412
413 /***
414 * <p>
415 * Removes a {@link Contact} from the mock data store.
416 * </p>
417 */
418 public String deleteContact() {
419 if (log.isInfoEnabled())
420 log.info("deleteContact()");
421
422 if (getSelectedContact() != null) {
423 RolodexDao dao = (RolodexDao) getBean("rolodexDao");
424 dao.deleteContact(getSelectedContact());
425 setSelectedContact(null);
426 contacts = null;
427 }
428
429 return "rolodex$test";
430 }
431
432 /***
433 * <p>
434 * Creates a new {@link Contact} instance to be entered and saved.
435 * </p>
436 */
437 public String newContact() {
438 if (log.isInfoEnabled())
439 log.info("newContact()");
440
441 setSelectedContact(new Contact());
442
443 return "rolodex$test";
444 }
445
446 }