Source Code Cross Referenced for WidgetFinder.java in  » Content-Management-System » apache-lenya-2.0 » org » apache » cocoon » forms » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Content Management System » apache lenya 2.0 » org.apache.cocoon.forms.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.cocoon.forms.util;
018:
019:        import java.util.ArrayList;
020:        import java.util.Collection;
021:        import java.util.HashMap;
022:        import java.util.HashSet;
023:        import java.util.Iterator;
024:        import java.util.List;
025:        import java.util.Map;
026:        import java.util.Set;
027:
028:        import org.apache.cocoon.forms.event.RepeaterEvent;
029:        import org.apache.cocoon.forms.event.RepeaterEventAction;
030:        import org.apache.cocoon.forms.event.RepeaterListener;
031:        import org.apache.cocoon.forms.event.WidgetEventMulticaster;
032:        import org.apache.cocoon.forms.formmodel.Repeater;
033:        import org.apache.cocoon.forms.formmodel.Widget;
034:        import org.apache.commons.lang.StringUtils;
035:
036:        /**
037:         * An utility class to manage list of widgets.
038:         * 
039:         * <p>
040:         * The {@link org.apache.cocoon.forms.formmodel.Widget#lookupWidget(String)} method is able
041:         * to only return one widget, while this class returns a list of widgets. It uses a path syntax containing a /./,
042:         * <code>repeater/./foo</code>, which repreesents all the instances of the foo widget inside the repeater,
043:         * one per row. Note that it also supports finding a widgets inside multi level repeaters, something like 
044:         * invoices/./movements/./amount or courseYears/./exams/./preparatoryCourses/./title . 
045:         * </p>
046:         * <p>
047:         * Class has been designed to offer good performances, since the widget list is built only once and
048:         * is automatically updated when a repeater row is added or removed.
049:         * {@link org.apache.cocoon.forms.event.RepeaterListener}s can be attached directly to receive notifications
050:         * of widget additions or removals. 
051:         * </p>
052:         * <p>
053:         * This class is used in {@link org.apache.cocoon.forms.formmodel.CalculatedField}s and 
054:         * {@link org.apache.cocoon.forms.formmodel.CalculatedFieldAlgorithm}s. 
055:         * </p>
056:         * @version $Id$
057:         */
058:        public class WidgetFinder {
059:
060:            private boolean keepUpdated = false;
061:
062:            // Holds all the widgets not child of a repeater.
063:            private List noRepeaterWidgets = null;
064:            // Map repeater -> Set of Strings containing paths
065:            private Map repeaterPaths = null;
066:            // Map repeater -> Set of Widgets
067:            private Map repeaterWidgets = null;
068:            // A List of recently added widgets, will get cleared when getNewAdditions is called.
069:            private List newAdditions = new ArrayList();
070:
071:            private RefreshingRepeaterListener refreshingListener = new RefreshingRepeaterListener();
072:
073:            private RepeaterListener listener;
074:
075:            /**
076:             * Searches for widgets. It will iterate on the given paths and find all
077:             * corresponding widgets. If a path is in the forms repeater/* /widget
078:             * then all the rows of the repeater will be iterated and subwidgets
079:             * will be fetched. 
080:             * @param context The context widget to start from.
081:             * @param paths An iterator of Strings containing the paths.
082:             * @param keepUpdated If true, listeners will be installed on repeaters
083:             * to keep lists updated without polling.
084:             */
085:            public WidgetFinder(Widget context, Iterator paths,
086:                    boolean keepUpdated) {
087:                this .keepUpdated = keepUpdated;
088:                while (paths.hasNext()) {
089:                    String path = (String) paths.next();
090:                    path = toAsterisk(path);
091:                    if (path.indexOf('*') == -1) {
092:                        addSimpleWidget(context, path);
093:                    } else {
094:                        recurseRepeaters(context, path, true);
095:                    }
096:                }
097:            }
098:
099:            /**
100:             * Searches for widgets. If path is in the forms repeater/* /widget
101:             * then all the rows of the repeater will be iterated and subwidgets
102:             * will be fetched. 
103:             * @param context The context widget to start from.
104:             * @param path Path to search for..
105:             * @param keepUpdated If true, listeners will be installed on repeaters
106:             * to keep lists updated without polling.
107:             */
108:            public WidgetFinder(Widget context, String path, boolean keepUpdated) {
109:                path = toAsterisk(path);
110:                this .keepUpdated = keepUpdated;
111:                if (path.indexOf('*') == -1) {
112:                    addSimpleWidget(context, path);
113:                } else {
114:                    recurseRepeaters(context, path, true);
115:                }
116:            }
117:
118:            private String toAsterisk(String path) {
119:                return StringUtils.replace(path, "/./", "/*/");
120:            }
121:
122:            /**
123:             * Recurses a repeater path with asterisk.
124:             * @param context The context widget.
125:             * @param path The path.
126:             */
127:            private void recurseRepeaters(Widget context, String path,
128:                    boolean root) {
129:                String reppath = path.substring(0, path.indexOf('*') - 1);
130:                String childpath = path.substring(path.indexOf('*') + 2);
131:                Widget wdg = context.lookupWidget(reppath);
132:                if (wdg == null) {
133:                    if (root) {
134:                        throw new IllegalArgumentException(
135:                                "Cannot find a repeater with path " + reppath
136:                                        + " relative to widget "
137:                                        + context.getName());
138:                    } else {
139:                        return;
140:                    }
141:                }
142:                if (!(wdg instanceof  Repeater)) {
143:                    throw new IllegalArgumentException("The widget with path "
144:                            + reppath + " relative to widget "
145:                            + context.getName() + " is not a repeater!");
146:                }
147:                Repeater repeater = (Repeater) wdg;
148:                if (context instanceof  Repeater.RepeaterRow) {
149:                    // Add this repeater to the repeater widgets
150:                    addRepeaterWidget((Repeater) context.getParent(), repeater);
151:                }
152:
153:                addRepeaterPath(repeater, childpath);
154:                if (childpath.indexOf('*') != -1) {
155:                    for (int i = 0; i < repeater.getSize(); i++) {
156:                        Repeater.RepeaterRow row = repeater.getRow(i);
157:                        recurseRepeaters(row, childpath, false);
158:                    }
159:                } else {
160:                    for (int i = 0; i < repeater.getSize(); i++) {
161:                        Repeater.RepeaterRow row = repeater.getRow(i);
162:                        Widget okwdg = row.lookupWidget(childpath);
163:                        if (okwdg != null) {
164:                            addRepeaterWidget(repeater, okwdg);
165:                        }
166:                    }
167:                }
168:            }
169:
170:            /**
171:             * Adds to the list a widget descendant of a repeater.
172:             * @param repeater The repeater.
173:             * @param okwdg The widget.
174:             */
175:            private void addRepeaterWidget(Repeater repeater, Widget okwdg) {
176:                if (this .repeaterWidgets == null)
177:                    this .repeaterWidgets = new HashMap();
178:                Set widgets = (Set) this .repeaterWidgets.get(repeater);
179:                if (widgets == null) {
180:                    widgets = new HashSet();
181:                    this .repeaterWidgets.put(repeater, widgets);
182:                }
183:                widgets.add(okwdg);
184:                newAdditions.add(okwdg);
185:            }
186:
187:            /**
188:             * Adds a repeater monitored path.
189:             * @param repeater The repeater.
190:             * @param childpath The child part of the path.
191:             */
192:            private void addRepeaterPath(Repeater repeater, String childpath) {
193:                if (this .repeaterPaths == null)
194:                    this .repeaterPaths = new HashMap();
195:                Set paths = (Set) this .repeaterPaths.get(repeater);
196:                if (paths == null) {
197:                    paths = new HashSet();
198:                    this .repeaterPaths.put(repeater, paths);
199:                    if (keepUpdated)
200:                        repeater.addRepeaterListener(refreshingListener);
201:                }
202:                paths.add(childpath);
203:            }
204:
205:            /**
206:             * Called when a new row addition event is received from a monitored repeater.
207:             * @param repeater The repeated that generated the event.
208:             * @param index The new row index.
209:             */
210:            protected void refreshForAdd(Repeater repeater, int index) {
211:                Repeater.RepeaterRow row = repeater.getRow(index);
212:                if (this .repeaterPaths == null)
213:                    this .repeaterPaths = new HashMap();
214:                Set paths = (Set) this .repeaterPaths.get(repeater);
215:                for (Iterator iter = paths.iterator(); iter.hasNext();) {
216:                    String path = (String) iter.next();
217:                    if (path.indexOf('*') != -1) {
218:                        recurseRepeaters(row, path, false);
219:                    } else {
220:                        Widget wdg = row.lookupWidget(path);
221:                        if (wdg == null) {
222:                            throw new IllegalStateException(
223:                                    "Even after row addition cannot find a widget with path "
224:                                            + path + " in repeater "
225:                                            + repeater.getName());
226:                        }
227:                        addRepeaterWidget(repeater, wdg);
228:                    }
229:                }
230:            }
231:
232:            /**
233:             * Called when a row deletion event is received from a monitored repeater.
234:             * @param repeater The repeated that generated the event.
235:             * @param index The deleted row index.
236:             */
237:            protected void refreshForDelete(Repeater repeater, int index) {
238:                Repeater.RepeaterRow row = repeater.getRow(index);
239:                Set widgets = (Set) this .repeaterWidgets.get(repeater);
240:                for (Iterator iter = widgets.iterator(); iter.hasNext();) {
241:                    Widget widget = (Widget) iter.next();
242:                    boolean ischild = false;
243:                    Widget parent = widget.getParent();
244:                    while (parent != null) {
245:                        if (parent == row) {
246:                            ischild = true;
247:                            break;
248:                        }
249:                        parent = parent.getParent();
250:                    }
251:                    if (ischild) {
252:                        iter.remove();
253:                        if (widget instanceof  Repeater) {
254:                            if (this .repeaterPaths != null)
255:                                this .repeaterPaths.remove(widget);
256:                            this .repeaterWidgets.remove(widget);
257:                        }
258:                    }
259:                }
260:            }
261:
262:            /**
263:             * Called when a repeater clear event is received from a monitored repeater.
264:             * @param repeater The repeated that generated the event.
265:             */
266:            protected void refreshForClear(Repeater repeater) {
267:                Set widgets = (Set) this .repeaterWidgets.get(repeater);
268:                for (Iterator iter = widgets.iterator(); iter.hasNext();) {
269:                    Widget widget = (Widget) iter.next();
270:                    if (widget instanceof  Repeater) {
271:                        if (this .repeaterPaths != null)
272:                            this .repeaterPaths.remove(widget);
273:                        this .repeaterWidgets.remove(widget);
274:                    }
275:                }
276:                widgets.clear();
277:            }
278:
279:            /**
280:             * Adds a widget not contained in a repeater.
281:             * @param context
282:             * @param path
283:             */
284:            private void addSimpleWidget(Widget context, String path) {
285:                Widget widget = context.lookupWidget(path);
286:                if (widget == null)
287:                    throw new IllegalArgumentException(
288:                            "Cannot find a widget with path " + path
289:                                    + " relative to widget "
290:                                    + context.getName());
291:                if (this .noRepeaterWidgets == null)
292:                    this .noRepeaterWidgets = new ArrayList();
293:                this .noRepeaterWidgets.add(widget);
294:                newAdditions.add(widget);
295:            }
296:
297:            /**
298:             * Return all widgets found for the given paths.
299:             * @return A Collection of {@link Widget}s.
300:             */
301:            public Collection getWidgets() {
302:                List list = new ArrayList();
303:                if (this .noRepeaterWidgets != null)
304:                    list.addAll(this .noRepeaterWidgets);
305:                if (this .repeaterWidgets != null) {
306:                    for (Iterator iter = this .repeaterWidgets.keySet()
307:                            .iterator(); iter.hasNext();) {
308:                        Repeater repeater = (Repeater) iter.next();
309:                        list.addAll((Collection) this .repeaterWidgets
310:                                .get(repeater));
311:                    }
312:                }
313:                return list;
314:            }
315:
316:            /**
317:             * @return true if this finder is mutable (i.e. it's monitoring some repeaters) or false if getWidgets() will always return the same list (i.e. it's not monitoring any widget).
318:             */
319:            public boolean isMutable() {
320:                return (this .repeaterPaths != null)
321:                        && this .repeaterPaths.size() > 0;
322:            }
323:
324:            class RefreshingRepeaterListener implements  RepeaterListener {
325:                public void repeaterModified(RepeaterEvent event) {
326:                    if (event.getAction() == RepeaterEventAction.ROW_ADDED) {
327:                        refreshForAdd((Repeater) event.getSourceWidget(), event
328:                                .getRow());
329:                    }
330:                    if (event.getAction() == RepeaterEventAction.ROW_DELETING) {
331:                        refreshForDelete((Repeater) event.getSourceWidget(),
332:                                event.getRow());
333:                    }
334:                    if (event.getAction() == RepeaterEventAction.ROWS_CLEARING) {
335:                        refreshForClear((Repeater) event.getSourceWidget());
336:                    }
337:                    if (listener != null) {
338:                        listener.repeaterModified(event);
339:                    }
340:                }
341:            }
342:
343:            /**
344:             * @return true if new widgets have been added to this list (i.e. new repeater rows have been created) since last time getNewAdditions() was called. 
345:             */
346:            public boolean hasNewAdditions() {
347:                return this .newAdditions.size() > 0;
348:            }
349:
350:            /**
351:             * Gets the new widgets that has been added to the list, as a consequence of new repeater rows additions, since
352:             * last time this method was called or the finder was initialized. 
353:             * @return A List of {@link Widget}s.
354:             */
355:            public List getNewAdditions() {
356:                List ret = new ArrayList(newAdditions);
357:                newAdditions.clear();
358:                return ret;
359:            }
360:
361:            /**
362:             * Adds a repeater listener. New widget additions or deletions will be notified thru this listener (events received
363:             * from monitored repeaters will be forwarded, use {@link #getNewAdditions()} to retrieve new widgets).
364:             * @param listener The listener to add.
365:             */
366:            public void addRepeaterListener(RepeaterListener listener) {
367:                this .listener = WidgetEventMulticaster.add(this .listener,
368:                        listener);
369:            }
370:
371:            /**
372:             * Removes a listener. See {@link #addRepeaterListener(RepeaterListener)}.
373:             * @param listener The listener to remove.
374:             */
375:            public void removeRepeaterListener(RepeaterListener listener) {
376:                this .listener = WidgetEventMulticaster.remove(this .listener,
377:                        listener);
378:            }
379:
380:            /**
381:             * @return true if there are listeners registered on this instance. See {@link #addRepeaterListener(RepeaterListener)}.
382:             */
383:            public boolean hasRepeaterListeners() {
384:                return this.listener != null;
385:            }
386:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.