Source Code Cross Referenced for VariableResolver.java in  » IDE-Netbeans » visualweb.api.designer » com » sun » rave » web » ui » 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 » IDE Netbeans » visualweb.api.designer » com.sun.rave.web.ui.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:        package com.sun.rave.web.ui.util;
0042:
0043:        import com.sun.rave.web.ui.component.util.descriptors.LayoutElement;
0044:        import com.sun.rave.web.ui.component.util.descriptors.LayoutComponent;
0045:
0046:        import java.lang.reflect.Field;
0047:        import java.lang.reflect.Modifier;
0048:        import java.util.ArrayList;
0049:        import java.util.Iterator;
0050:        import java.util.HashMap;
0051:        import java.util.List;
0052:        import java.util.Map;
0053:        import java.util.ResourceBundle;
0054:        import java.util.Stack;
0055:
0056:        import javax.faces.component.NamingContainer;
0057:        import javax.faces.component.UIComponent;
0058:        import javax.faces.component.UIViewRoot;
0059:        import javax.faces.context.FacesContext;
0060:        import javax.faces.event.ActionEvent;
0061:
0062:        /**
0063:         *  <p>	VariableResolver is used to parse expressions of the format.</p>
0064:         *
0065:         *  <p>	<dd>$&lt;type$gt;{&lt;key&gt;}</dd></p>
0066:         *
0067:         *  <p>	&lt;type&gt; refers to a registerd {@link VariableResolver.DataSource},
0068:         *	custom {@link VariableResolver.DataSource}s can be registered via:
0069:         *	{@link #setDataSource(String key,
0070:         *	    VariableResolver.DataSource dataSource)}.
0071:         *	However, there are many built-in {@link VariableResolver.DataSource}
0072:         *	types that are pre-registered.</p>
0073:         *
0074:         *  <p>	Below are the pre-registered types: </p>
0075:         *
0076:         *  <ul><li>{@link #ATTRIBUTE} -- {@link AttributeDataSource}</li>
0077:         *	<li>{@link #BOOLEAN} -- {@link BooleanDataSource}</li>
0078:         *	<li>{@link #BROWSER} -- {@link BrowserDataSource}</li>
0079:         *	<li>{@link #CONSTANT} -- {@link ConstantDataSource}</li>
0080:         *	<li>{@link #ESCAPE} -- {@link EscapeDataSource}</li>
0081:         *	<li>{@link #HAS_FACET} -- {@link HasFacetDataSource}</li>
0082:         *	<li>{@link #HAS_PROPERTY} -- {@link HasPropertyDataSource}</li>
0083:         *	<li>{@link #INT} -- {@link IntDataSource}</li>
0084:         *	<li>{@link #METHOD_BINDING} -- {@link MethodBindingDataSource}</li>
0085:         *	<li>{@link #PROPERTY} -- {@link PropertyDataSource}</li>
0086:         *	<li>{@link #REQUEST_PARAMETER} --
0087:         *		{@link RequestParameterDataSource}</li>
0088:         *	<li>{@link #RESOURCE} -- {@link ResourceBundleDataSource}</li>
0089:         *	<li>{@link #SESSION} -- {@link SessionDataSource}</li>
0090:         *	<li>{@link #STYLE} -- {@link StyleDataSource}</li>
0091:         *	<li>{@link #THEME_JS} -- {@link ThemeJavaScriptDataSource}</li>
0092:         *	<li>{@link #THIS} -- {@link ThisDataSource}</li></ul>
0093:         *
0094:         *  @author Ken Paulsen (ken.paulsen@sun.com)
0095:         */
0096:        public class VariableResolver {
0097:
0098:            /**
0099:             *	<p> This method will substitute variables into the given String, or
0100:             *	    return the variable if the substitution is the whole String.  This
0101:             *	    method looks for the LAST occurance of startToken in the given
0102:             *	    String.  It then searches from that location (if found) to the
0103:             *	    first occurance of typeDelim.  The value inbetween is used as the
0104:             *	    type of substitution to perform (i.e. request attribute, session,
0105:             *	    etc.).  It next looks for the next occurance of endToken.  The
0106:             *	    value inbetween is used as the key passed to the
0107:             *	    {@link VariableResolver.DataSource} specified by the type.  The
0108:             *	    String value from the {@link VariableResolver.DataSource} replaces
0109:             *	    the portion of the String from the startToken to the endToken.  If
0110:             *	    this is the entire String, the Object is returned instead of the
0111:             *	    String value.  This process is repeated until no more
0112:             *	    substitutions are *  needed.</p>
0113:             *
0114:             *	<p> This algorithm will accomodate nested variables (e.g. "${A{$x}}").
0115:             *	    It also allows the replacement value itself to contain variables.
0116:             *	    Care should be taken to ensure that the replacement String included
0117:             *	    does not directly or indirectly refer to itself -- this will cause
0118:             *	    an infinite loop.</p>
0119:             *
0120:             *	<p> There is one special case where the string to be evaluated begins
0121:             *	    with the startToken and ends with the endToken.  In this case,
0122:             *	    string substitution is NOT performed.  Instead the value of the
0123:             *	    request attribute is returned.</p>
0124:             *
0125:             *	@param	ctx		The FacesContext
0126:             *	@param	desc		The closest LayoutElement to this string
0127:             *	@param	component	The assoicated UIComponent
0128:             *	@param	string		The string to be evaluated.
0129:             *	@param	startToken	Marks the beginning		    "$"
0130:             *	@param	typeDelim	Marks separation of type/variable   "{"
0131:             *	@param	endToken	Marks the end of the variable	    "}"
0132:             *
0133:             *	@return The new string with substitutions, or the specified request
0134:             *		attribute value.
0135:             */
0136:            public static Object resolveVariables(FacesContext ctx,
0137:                    LayoutElement desc, UIComponent component, String string,
0138:                    String startToken, String typeDelim, String endToken) {
0139:
0140:                int stringLen = string.length();
0141:                int delimIndex;
0142:                int endIndex;
0143:                int parenSemi;
0144:                int startTokenLen = startToken.length();
0145:                int delimLen = typeDelim.length();
0146:                int endTokenLen = endToken.length();
0147:                boolean expressionIsWholeString = false;
0148:                char firstEndChar = SUB_END.charAt(0);
0149:                char firstDelimChar = SUB_TYPE_DELIM.charAt(0);
0150:                char currChar;
0151:                String type;
0152:                Object variable;
0153:
0154:                for (int startIndex = string.lastIndexOf(startToken); startIndex != -1; startIndex = string
0155:                        .lastIndexOf(startToken, startIndex - 1)) {
0156:
0157:                    // Find first typeDelim
0158:                    delimIndex = string.indexOf(typeDelim, startIndex
0159:                            + startTokenLen);
0160:                    if (delimIndex == -1) {
0161:                        continue;
0162:                    }
0163:
0164:                    // Next find the end token
0165:                    parenSemi = 0;
0166:                    endIndex = -1;
0167:                    // Iterate through the string looking for the matching end
0168:                    for (int curr = delimIndex + delimLen; curr < stringLen;) {
0169:                        // Get the next char...
0170:                        currChar = string.charAt(curr);
0171:                        if ((currChar == firstDelimChar)
0172:                                && typeDelim.equals(string.substring(curr, curr
0173:                                        + delimLen))) {
0174:                            // Found the start of another... inc the semi
0175:                            parenSemi++;
0176:                            curr += delimLen;
0177:                            continue;
0178:                        }
0179:                        if ((currChar == firstEndChar)
0180:                                && endToken.equals(string.substring(curr, curr
0181:                                        + endTokenLen))) {
0182:                            parenSemi--;
0183:                            if (parenSemi < 0) {
0184:                                // Found the right one!
0185:                                endIndex = curr;
0186:                                break;
0187:                            }
0188:                            // Found one, but this isn't the right one
0189:                            curr += endTokenLen;
0190:                            continue;
0191:                        }
0192:                        curr++;
0193:                    }
0194:                    if (endIndex == -1) {
0195:                        // We didn't find a matching end...
0196:                        continue;
0197:                    }
0198:
0199:                    /*
0200:                     // Next find end token
0201:                     endIndex = string.indexOf(endToken, delimIndex+delimLen);
0202:                     matchingIndex = string.lastIndexOf(typeDelim, endIndex);
0203:                     while ((endIndex != -1) && (matchingIndex != delimIndex)) {
0204:                     // We found a endToken, but not the matching one...keep looking
0205:                     endIndex = string.indexOf(endToken, endIndex+endTokenLen);
0206:                     matchingIndex = string.lastIndexOf(typeDelim,
0207:                     matchingIndex-delimLen);
0208:                     }
0209:                     if ((endIndex == -1) || (matchingIndex == -1)) {
0210:                     continue;
0211:                     }
0212:                     */
0213:
0214:                    // Handle special case where string starts with startToken and ends
0215:                    // with endToken (and no replacements inbetween).  This is special
0216:                    // because we don't want to convert the attribute to a string, we
0217:                    // want to return it (this allows Object types).
0218:                    if ((startIndex == 0)
0219:                            && (endIndex == string.lastIndexOf(endToken))
0220:                            && (string.endsWith(endToken))) {
0221:                        // This is the special case...
0222:                        expressionIsWholeString = true;
0223:                    }
0224:
0225:                    // Pull off the type...
0226:                    type = string.substring(startIndex + startTokenLen,
0227:                            delimIndex);
0228:                    DataSource ds = (DataSource) dataSourceMap.get(type);
0229:                    if (ds == null) {
0230:                        throw new IllegalArgumentException("Invalid type '"
0231:                                + type + "' in attribute value: '" + string
0232:                                + "'.");
0233:                    }
0234:
0235:                    // Pull off the variable...
0236:                    variable = string
0237:                            .substring(delimIndex + delimLen, endIndex);
0238:
0239:                    // Get the value...
0240:                    variable = ds.getValue(ctx, desc, component,
0241:                            (String) variable);
0242:                    if (expressionIsWholeString) {
0243:                        return variable;
0244:                    }
0245:
0246:                    // Make new string
0247:                    string = string.substring(0, startIndex)
0248:                            + // Before replacement
0249:                            ((variable == null) ? "" : variable.toString())
0250:                            + string.substring(endIndex + endTokenLen); // After
0251:                    stringLen = string.length();
0252:                }
0253:
0254:                // Return the string
0255:                return string;
0256:            }
0257:
0258:            /**
0259:             *	This method replaces the ${..} variables with their values.  It will
0260:             *	only do this for Strings and List's that contain Strings.
0261:             *
0262:             *	@param	desc	    The <code>LayoutElement</code> descriptor
0263:             *	@param	component   The <code>UIComponent</code>
0264:             *	@param	value	    The value to resolve
0265:             *
0266:             *	@return The result
0267:             */
0268:            public static Object resolveVariables(LayoutElement desc,
0269:                    UIComponent component, Object value) {
0270:                if (value == null) {
0271:                    return null;
0272:                }
0273:                return VariableResolver.resolveVariables(FacesContext
0274:                        .getCurrentInstance(), desc, component, value);
0275:            }
0276:
0277:            /**
0278:             *	This method replaces the ${..} variables with their attribute values.
0279:             *	It will only do this for Strings and List's that contain Strings.
0280:             *
0281:             *	@param	ctx	    The <code>FacesContext</code>
0282:             *	@param	desc	    The <code>LayoutElement</code> descriptor
0283:             *	@param	component   The <code>UIComponent</code>
0284:             *	@param	value	    The value to resolve
0285:             *
0286:             *	@return	The result
0287:             */
0288:            public static Object resolveVariables(FacesContext ctx,
0289:                    LayoutElement desc, UIComponent component, Object value) {
0290:                if (value == null) {
0291:                    return null;
0292:                }
0293:                if (value instanceof  String) {
0294:                    value = VariableResolver.resolveVariables(ctx, desc,
0295:                            component, (String) value,
0296:                            VariableResolver.SUB_START,
0297:                            VariableResolver.SUB_TYPE_DELIM,
0298:                            VariableResolver.SUB_END);
0299:                } else if (value instanceof  List) {
0300:                    // Create a new List b/c invalid to change shared List
0301:                    List list = ((List) value);
0302:                    int size = list.size();
0303:                    List newList = new ArrayList(size);
0304:                    Iterator it = list.iterator();
0305:                    while (it.hasNext()) {
0306:                        newList.add(VariableResolver.resolveVariables(ctx,
0307:                                desc, component, it.next()));
0308:                    }
0309:                    return newList;
0310:                }
0311:                return value;
0312:            }
0313:
0314:            /**
0315:             *	<p> This method looks up the requested
0316:             *	    {@link VariableResolver.DataSource} by the given key.
0317:             *
0318:             *	@param	key	The key identifying the desired
0319:             *			{@link VariableResolver.DataSource}
0320:             *
0321:             *	@return	    The requested {@link VariableResolver.DataSource}
0322:             */
0323:            public static VariableResolver.DataSource getDataSource(String key) {
0324:                return (VariableResolver.DataSource) dataSourceMap.get(key);
0325:            }
0326:
0327:            /**
0328:             *	<p> This method sets the given {@link VariableResolver.DataSource} to
0329:             *	    be used for $[type]{...} when key matches type.</p>
0330:             *
0331:             *	@param	key		The key identifying the
0332:             *				{@link VariableResolver.DataSource}
0333:             *	@param	dataSource	The {@link VariableResolver.DataSource}
0334:             */
0335:            public static void setDataSource(String key,
0336:                    VariableResolver.DataSource dataSource) {
0337:                dataSourceMap.put(key, dataSource);
0338:            }
0339:
0340:            /**
0341:             *	<p> This interface defines a String substitution data source.  This
0342:             *	    is used to retrieve values when a $&lt;type&gt;{&lt;data&gt;} is
0343:             *	    encountered within a parameter value.</p>
0344:             *
0345:             *	<p> Implementations of this interface may register themselves
0346:             *	    statically to extend the capabilities of the ${} substitution
0347:             *	    mechanism.</p>
0348:             */
0349:            public interface DataSource {
0350:                /**
0351:                 *  <p>	This method should return the resolved value based on the
0352:                 *	given key and contextual information.</p>
0353:                 *
0354:                 *  @param  ctx		The <code>FacesContext</code>
0355:                 *  @param  desc	The <code>LayoutElement</code>
0356:                 *  @param  component	The <code>UIComponent</code>
0357:                 *  @param  key		The key used to obtain information from this
0358:                 *			<code>DataSource</code>.
0359:                 *
0360:                 *  @return The value resolved from key.
0361:                 */
0362:                Object getValue(FacesContext ctx, LayoutElement desc,
0363:                        UIComponent component, String key);
0364:            }
0365:
0366:            /**
0367:             *	<p> This {@link VariableResolver.DataSource} provides access to
0368:             *	    HttpRequest attributes.  It uses the data portion of the
0369:             *	    substitution String as a key to the HttpRequest attribute Map.</p>
0370:             */
0371:            public static class AttributeDataSource implements  DataSource {
0372:                /**
0373:                 *  <p>	See class JavaDoc.</p>
0374:                 *
0375:                 *  @param  ctx		The <code>FacesContext</code>
0376:                 *  @param  desc	The <code>LayoutElement</code>
0377:                 *  @param  component	The <code>UIComponent</code>
0378:                 *  @param  key		The key used to obtain information from this
0379:                 *			<code>DataSource</code>.
0380:                 *
0381:                 *  @return The value resolved from key.
0382:                 */
0383:                public Object getValue(FacesContext ctx, LayoutElement desc,
0384:                        UIComponent component, String key) {
0385:                    return ctx.getExternalContext().getRequestMap().get(key);
0386:                }
0387:            }
0388:
0389:            /**
0390:             *	<p> This {@link VariableResolver.DataSource} provides access to
0391:             *	    PageSession attributes.  It uses the data portion of the
0392:             *	    substitution String as a key to the PageSession attribute Map.</p>
0393:            public static class PageSessionDataSource implements DataSource {
0394:            /**
0395:             *  <p>	See class JavaDoc.</p>
0396:             *
0397:             *  @param  ctx		The <code>FacesContext</code>
0398:             *  @param  desc	The <code>LayoutElement</code>
0399:             *  @param  component	The <code>UIComponent</code>
0400:             *  @param  key		The key used to obtain information from this
0401:             *			<code>DataSource</code>.
0402:             *
0403:             *  @return The value resolved from key.
0404:            public Object getValue(FacesContext ctx, LayoutElement desc,
0405:            	UIComponent component, String key) {
0406:                while (desc.getParent() != null) {
0407:            	desc = desc.getParent();
0408:                }
0409:                return ((ViewBean)desc.getView(ctx)).getPageSessionAttribute(key);
0410:            }
0411:            }
0412:             */
0413:
0414:            /**
0415:             *	<p> This {@link VariableResolver.DataSource} provides access to
0416:             *	    HttpRequest Parameters.  It uses the data portion of the
0417:             *	    substitution String as a key to the HttpRequest Parameter Map.</p>
0418:             */
0419:            public static class RequestParameterDataSource implements 
0420:                    DataSource {
0421:                /**
0422:                 *  <p>	See class JavaDoc.</p>
0423:                 *
0424:                 *  @param  ctx		The <code>FacesContext</code>
0425:                 *  @param  desc	The <code>LayoutElement</code>
0426:                 *  @param  component	The <code>UIComponent</code>
0427:                 *  @param  key		The key used to obtain information from this
0428:                 *			<code>DataSource</code>.
0429:                 *
0430:                 *  @return The value resolved from key.
0431:                 */
0432:                public Object getValue(FacesContext ctx, LayoutElement desc,
0433:                        UIComponent component, String key) {
0434:                    return ctx.getExternalContext().getRequestParameterMap()
0435:                            .get(key);
0436:                }
0437:            }
0438:
0439:            /**
0440:             *	<p> This {@link VariableResolver.DataSource} provides access to
0441:             *	    UIComponent Properties.  It uses the data portion of the
0442:             *	    substitution String as a key to the UIComponent's properties via
0443:             *	    the attribute Map.  If the property is null, it will attempt to
0444:             *	    look at the parent's properties.</p>
0445:             */
0446:            public static class PropertyDataSource implements  DataSource {
0447:                /**
0448:                 *  <p>	See class JavaDoc.</p>
0449:                 *
0450:                 *  @param  ctx		The <code>FacesContext</code>
0451:                 *  @param  desc	The <code>LayoutElement</code>
0452:                 *  @param  component	The <code>UIComponent</code>
0453:                 *  @param  key		The key used to obtain information from this
0454:                 *			<code>DataSource</code>.
0455:                 *
0456:                 *  @return The value resolved from key.
0457:                 */
0458:                public Object getValue(FacesContext ctx, LayoutElement desc,
0459:                        UIComponent component, String key) {
0460:
0461:                    // Check to see if we should walk up the tree or not
0462:                    int idx = key.indexOf(',');
0463:                    boolean walk = false;
0464:                    if (idx > 0) {
0465:                        walk = Boolean.valueOf(key.substring(idx + 1))
0466:                                .booleanValue();
0467:                        key = key.substring(0, idx);
0468:                    }
0469:
0470:                    Object value = component.getAttributes().get(key);
0471:                    while (walk && (value == null)
0472:                            && (component.getParent() != null)) {
0473:                        component = component.getParent();
0474:                        value = component.getAttributes().get(key);
0475:                    }
0476:                    /*
0477:                     if (LogUtil.finestEnabled()) {
0478:                     // Trace information
0479:                     LogUtil.finest(this, "RESOLVING ('" + key + "') for ('"
0480:                     + component.getId() + "'): '" + value + "'");
0481:                     }
0482:                     */
0483:                    return value;
0484:                }
0485:            }
0486:
0487:            /**
0488:             *	<p> This {@link VariableResolver.DataSource} tests if the given
0489:             *	    property exists on the UIComponent.  It uses the data portion of
0490:             *	    the substitution String as a key to the UIComponent's properties
0491:             *	    via the attribute Map.</p>
0492:             */
0493:            public static class HasPropertyDataSource implements  DataSource {
0494:                /**
0495:                 *  <p>	See class JavaDoc.</p>
0496:                 *
0497:                 *  @param  ctx		The <code>FacesContext</code>
0498:                 *  @param  desc	The <code>LayoutElement</code>
0499:                 *  @param  component	The <code>UIComponent</code>
0500:                 *  @param  key		The key used to obtain information from this
0501:                 *			<code>DataSource</code>.
0502:                 *
0503:                 *  @return The value resolved from key.
0504:                 */
0505:                public Object getValue(FacesContext ctx, LayoutElement desc,
0506:                        UIComponent component, String key) {
0507:                    boolean hasKey = component.getAttributes().containsKey(key);
0508:                    if (!hasKey) {
0509:                        // Check the getter... JSF sucks when wrt attrs vs. props
0510:                        if (component.getAttributes().get(key) != null) {
0511:                            hasKey = true;
0512:                        }
0513:                    }
0514:                    if (!hasKey && (desc instanceof  LayoutComponent)) {
0515:                        // In some cases, the component is a TemplateComponent child
0516:                        return getValue(ctx, desc.getParent(), component
0517:                                .getParent(), key);
0518:                    }
0519:                    return Boolean.valueOf(hasKey);
0520:                }
0521:            }
0522:
0523:            /**
0524:             *	<p> This {@link VariableResolver.DataSource} tests if the given facet
0525:             *	    exists on the UIComponent.  It uses the data portion of the
0526:             *	    substitution String as a key to the UIComponent's facets.</p>
0527:             */
0528:            public static class HasFacetDataSource implements  DataSource {
0529:                /**
0530:                 *  <p>	See class JavaDoc.</p>
0531:                 *
0532:                 *  @param  ctx		The <code>FacesContext</code>
0533:                 *  @param  desc	The <code>LayoutElement</code>
0534:                 *  @param  component	The <code>UIComponent</code>
0535:                 *  @param  key		The key used to obtain information from this
0536:                 *			<code>DataSource</code>.
0537:                 *
0538:                 *  @return The value resolved from key.
0539:                 */
0540:                public Object getValue(FacesContext ctx, LayoutElement desc,
0541:                        UIComponent component, String key) {
0542:                    boolean hasFacet = component.getFacets().containsKey(key);
0543:                    if (!hasFacet && (desc instanceof  LayoutComponent)) {
0544:                        // In some cases, the component is a TemplateComponent child
0545:                        return getValue(ctx, desc.getParent(), component
0546:                                .getParent(), key);
0547:                    }
0548:                    return Boolean.valueOf(hasFacet);
0549:                }
0550:            }
0551:
0552:            /**
0553:             *	<p> This {@link VariableResolver.DataSource} simply returns the key
0554:             *	    that it is given.  This is useful for supplying ${}'s around the
0555:             *	    string you wish to mark as a string.  If not used, characters such
0556:             *	    as '=' will be interpretted as a separator causing your string to
0557:             *	    be split -- which can be very undesirable. Mostly useful in "if"
0558:             *	    statements.</p>
0559:             */
0560:            public static class EscapeDataSource implements  DataSource {
0561:                /**
0562:                 *  <p>	See class JavaDoc.</p>
0563:                 *
0564:                 *  @param  ctx		The <code>FacesContext</code>
0565:                 *  @param  desc	The <code>LayoutElement</code>
0566:                 *  @param  component	The <code>UIComponent</code>
0567:                 *  @param  key		The key used to obtain information from this
0568:                 *			<code>DataSource</code>.
0569:                 *
0570:                 *  @return The value resolved from key.
0571:                 */
0572:                public Object getValue(FacesContext ctx, LayoutElement desc,
0573:                        UIComponent component, String key) {
0574:                    return key;
0575:                }
0576:            }
0577:
0578:            /**
0579:             *	<p> This {@link VariableResolver.DataSource} converts the given
0580:             *	    <code>key</code> to a <code>Boolean</code>.  This is needed because
0581:             *	    JSF does not do this for you.  When you call
0582:             *	    <code>UIComponent.getAttributes().put(key, value)</code>,
0583:             *	    <code>value</code> is expected to be the correct type.  Often
0584:             *	    <code>Boolean</code> types are needed.  This
0585:             *	    {@link VariableResolver.DataSource} provides a means to supply a
0586:             *	    <code>Boolean</code> value.</p>
0587:             */
0588:            public static class BooleanDataSource implements  DataSource {
0589:                /**
0590:                 *  <p>	See class JavaDoc.</p>
0591:                 *
0592:                 *  @param  ctx		The <code>FacesContext</code>
0593:                 *  @param  desc	The <code>LayoutElement</code>
0594:                 *  @param  component	The <code>UIComponent</code>
0595:                 *  @param  key		The key used to obtain information from this
0596:                 *			<code>DataSource</code>.
0597:                 *
0598:                 *  @return The value resolved from key.
0599:                 */
0600:                public Object getValue(FacesContext ctx, LayoutElement desc,
0601:                        UIComponent component, String key) {
0602:                    return Boolean.valueOf(key);
0603:                }
0604:            }
0605:
0606:            /**
0607:             *	<p> This {@link VariableResolver.DataSource} uses the given
0608:             *	    <code>key</code> to check various properties of the browser that
0609:             *	    submitted the request.  The valid keys are:</p>
0610:             *
0611:             *	<ul><li>getUserAgent</li>
0612:             *	    <li>getUserAgentMajor</li>
0613:             *	    <li>isIe</li>
0614:             *	    <li>isNav</li>
0615:             *	    <li>isGecko</li>
0616:             *	    <li>isSun</li>
0617:             *	    <li>isWin</li>
0618:             *	    <li>isIe5up</li>
0619:             *	    <li>isIe6up</li>
0620:             *	    <li>isNav7up</li>
0621:             *	    <li>isIe6</li>
0622:             *	    <li>isIe5</li>
0623:             *	    <li>isIe4</li>
0624:             *	    <li>isIe3</li>
0625:             *	    <li>isNav70</li>
0626:             *	    <li>isNav7</li>
0627:             *	    <li>isNav6up</li>
0628:             *	    <li>isNav6</li>
0629:             *	    <li>isNav4up</li>
0630:             *	    <li>isNav4</li></ul>
0631:             *
0632:             *	@see ClientSniffer
0633:             */
0634:            public static class BrowserDataSource implements  DataSource {
0635:                /**
0636:                 *  <p>	See class JavaDoc.</p>
0637:                 *
0638:                 *  @param  ctx		The <code>FacesContext</code>
0639:                 *  @param  desc	The <code>LayoutElement</code>
0640:                 *  @param  component	The <code>UIComponent</code>
0641:                 *  @param  key		The key used to obtain information from this
0642:                 *			<code>DataSource</code>.
0643:                 *
0644:                 *  @return The value resolved from key.
0645:                 */
0646:                public Object getValue(FacesContext ctx, LayoutElement desc,
0647:                        UIComponent component, String key) {
0648:                    DataSource ds = (DataSource) innerDataSources.get(key);
0649:                    if (ds == null) {
0650:                        throw new IllegalArgumentException("'" + key
0651:                                + "' is not a valid key for BrowserDataSource!");
0652:                    }
0653:                    return ds.getValue(ctx, desc, component, key);
0654:                }
0655:
0656:                /**
0657:                 *  <p>	For efficiency, we will implement the branching as a Map of
0658:                 *	DataSources.</p>
0659:                 */
0660:                private static Map innerDataSources = new HashMap();
0661:
0662:                static {
0663:                    innerDataSources.put("getUserAgent", new DataSource() {
0664:                        public Object getValue(FacesContext ctx,
0665:                                LayoutElement desc, UIComponent component,
0666:                                String key) {
0667:                            return ClientSniffer.getInstance(ctx)
0668:                                    .getUserAgent();
0669:                        }
0670:                    });
0671:                    innerDataSources.put("getUserAgentMajor", new DataSource() {
0672:                        public Object getValue(FacesContext ctx,
0673:                                LayoutElement desc, UIComponent component,
0674:                                String key) {
0675:                            return new Integer(ClientSniffer.getInstance(ctx)
0676:                                    .getUserAgentMajor());
0677:                        }
0678:                    });
0679:                    innerDataSources.put("isIe", new DataSource() {
0680:                        public Object getValue(FacesContext ctx,
0681:                                LayoutElement desc, UIComponent component,
0682:                                String key) {
0683:                            return Boolean.valueOf(ClientSniffer.getInstance(
0684:                                    ctx).isIe());
0685:                        }
0686:                    });
0687:                    innerDataSources.put("isNav", new DataSource() {
0688:                        public Object getValue(FacesContext ctx,
0689:                                LayoutElement desc, UIComponent component,
0690:                                String key) {
0691:                            return Boolean.valueOf(ClientSniffer.getInstance(
0692:                                    ctx).isNav());
0693:                        }
0694:                    });
0695:                    innerDataSources.put("isGecko", new DataSource() {
0696:                        public Object getValue(FacesContext ctx,
0697:                                LayoutElement desc, UIComponent component,
0698:                                String key) {
0699:                            return Boolean.valueOf(ClientSniffer.getInstance(
0700:                                    ctx).isGecko());
0701:                        }
0702:                    });
0703:                    innerDataSources.put("isSun", new DataSource() {
0704:                        public Object getValue(FacesContext ctx,
0705:                                LayoutElement desc, UIComponent component,
0706:                                String key) {
0707:                            return Boolean.valueOf(ClientSniffer.getInstance(
0708:                                    ctx).isSun());
0709:                        }
0710:                    });
0711:                    innerDataSources.put("isWin", new DataSource() {
0712:                        public Object getValue(FacesContext ctx,
0713:                                LayoutElement desc, UIComponent component,
0714:                                String key) {
0715:                            return Boolean.valueOf(ClientSniffer.getInstance(
0716:                                    ctx).isWin());
0717:                        }
0718:                    });
0719:                    innerDataSources.put("isIe5up", new DataSource() {
0720:                        public Object getValue(FacesContext ctx,
0721:                                LayoutElement desc, UIComponent component,
0722:                                String key) {
0723:                            return Boolean.valueOf(ClientSniffer.getInstance(
0724:                                    ctx).isIe5up());
0725:                        }
0726:                    });
0727:                    innerDataSources.put("isIe6up", new DataSource() {
0728:                        public Object getValue(FacesContext ctx,
0729:                                LayoutElement desc, UIComponent component,
0730:                                String key) {
0731:                            return Boolean.valueOf(ClientSniffer.getInstance(
0732:                                    ctx).isIe6up());
0733:                        }
0734:                    });
0735:                    innerDataSources.put("isNav7up", new DataSource() {
0736:                        public Object getValue(FacesContext ctx,
0737:                                LayoutElement desc, UIComponent component,
0738:                                String key) {
0739:                            return Boolean.valueOf(ClientSniffer.getInstance(
0740:                                    ctx).isNav7up());
0741:                        }
0742:                    });
0743:                    innerDataSources.put("isIe6", new DataSource() {
0744:                        public Object getValue(FacesContext ctx,
0745:                                LayoutElement desc, UIComponent component,
0746:                                String key) {
0747:                            return Boolean.valueOf(ClientSniffer.getInstance(
0748:                                    ctx).isIe6());
0749:                        }
0750:                    });
0751:                    innerDataSources.put("isIe5", new DataSource() {
0752:                        public Object getValue(FacesContext ctx,
0753:                                LayoutElement desc, UIComponent component,
0754:                                String key) {
0755:                            return Boolean.valueOf(ClientSniffer.getInstance(
0756:                                    ctx).isIe5());
0757:                        }
0758:                    });
0759:                    innerDataSources.put("isIe4", new DataSource() {
0760:                        public Object getValue(FacesContext ctx,
0761:                                LayoutElement desc, UIComponent component,
0762:                                String key) {
0763:                            return Boolean.valueOf(ClientSniffer.getInstance(
0764:                                    ctx).isIe4());
0765:                        }
0766:                    });
0767:                    innerDataSources.put("isIe3", new DataSource() {
0768:                        public Object getValue(FacesContext ctx,
0769:                                LayoutElement desc, UIComponent component,
0770:                                String key) {
0771:                            return Boolean.valueOf(ClientSniffer.getInstance(
0772:                                    ctx).isIe3());
0773:                        }
0774:                    });
0775:                    innerDataSources.put("isNav70", new DataSource() {
0776:                        public Object getValue(FacesContext ctx,
0777:                                LayoutElement desc, UIComponent component,
0778:                                String key) {
0779:                            return Boolean.valueOf(ClientSniffer.getInstance(
0780:                                    ctx).isNav70());
0781:                        }
0782:                    });
0783:                    innerDataSources.put("isNav7", new DataSource() {
0784:                        public Object getValue(FacesContext ctx,
0785:                                LayoutElement desc, UIComponent component,
0786:                                String key) {
0787:                            return Boolean.valueOf(ClientSniffer.getInstance(
0788:                                    ctx).isNav7());
0789:                        }
0790:                    });
0791:                    innerDataSources.put("isNav6up", new DataSource() {
0792:                        public Object getValue(FacesContext ctx,
0793:                                LayoutElement desc, UIComponent component,
0794:                                String key) {
0795:                            return Boolean.valueOf(ClientSniffer.getInstance(
0796:                                    ctx).isNav6up());
0797:                        }
0798:                    });
0799:                    innerDataSources.put("isNav6", new DataSource() {
0800:                        public Object getValue(FacesContext ctx,
0801:                                LayoutElement desc, UIComponent component,
0802:                                String key) {
0803:                            return Boolean.valueOf(ClientSniffer.getInstance(
0804:                                    ctx).isNav6());
0805:                        }
0806:                    });
0807:                    innerDataSources.put("isNav4up", new DataSource() {
0808:                        public Object getValue(FacesContext ctx,
0809:                                LayoutElement desc, UIComponent component,
0810:                                String key) {
0811:                            return Boolean.valueOf(ClientSniffer.getInstance(
0812:                                    ctx).isNav4up());
0813:                        }
0814:                    });
0815:                    innerDataSources.put("isNav4", new DataSource() {
0816:                        public Object getValue(FacesContext ctx,
0817:                                LayoutElement desc, UIComponent component,
0818:                                String key) {
0819:                            return Boolean.valueOf(ClientSniffer.getInstance(
0820:                                    ctx).isNav4());
0821:                        }
0822:                    });
0823:                }
0824:            }
0825:
0826:            /**
0827:             *	<p> This {@link VariableResolver.DataSource} converts the given
0828:             *	    <code>key</code> to an <code>Integer</code>.  This is needed
0829:             *	    because JSF does not do this for you.  When you call
0830:             *	    <code>UIComponent.getAttributes().put(key, value)</code>,
0831:             *	    <code>value</code> is expected to be the correct type.  Often
0832:             *	    <code>Integer</code> types are needed.  This
0833:             *	    {@link VariableResolver.DataSource} provides a means to supply an
0834:             *	    <code>Integer</code> value.</p>
0835:             */
0836:            public static class IntDataSource implements  DataSource {
0837:                /**
0838:                 *  <p>	See class JavaDoc.</p>
0839:                 *
0840:                 *  @param  ctx		The <code>FacesContext</code>
0841:                 *  @param  desc	The <code>LayoutElement</code>
0842:                 *  @param  component	The <code>UIComponent</code>
0843:                 *  @param  key		The key used to obtain information from this
0844:                 *			<code>DataSource</code>.
0845:                 *
0846:                 *  @return The value resolved from key.
0847:                 */
0848:                public Object getValue(FacesContext ctx, LayoutElement desc,
0849:                        UIComponent component, String key) {
0850:                    return Integer.valueOf(key);
0851:                }
0852:            }
0853:
0854:            /**
0855:             *	<p> This {@link VariableResolver.DataSource} allows access to constants
0856:             *	    in java classes.  It expects the key to be a fully qualified Java
0857:             *	    classname plus the variable name. Example:</p>
0858:             *
0859:             *	<p> $constant{java.lang.Integer.MAX_VALUE} </p>
0860:             */
0861:            public static class ConstantDataSource implements  DataSource {
0862:                /**
0863:                 *  <p>	See class JavaDoc.</p>
0864:                 *
0865:                 *  @param  ctx		The <code>FacesContext</code>
0866:                 *  @param  desc	The <code>LayoutElement</code>
0867:                 *  @param  component	The <code>UIComponent</code>
0868:                 *  @param  key		The key used to obtain information from this
0869:                 *			<code>DataSource</code>.
0870:                 *
0871:                 *  @return The value resolved from key.
0872:                 */
0873:                public Object getValue(FacesContext ctx, LayoutElement desc,
0874:                        UIComponent component, String key) {
0875:                    // First check to see if we've already found the value before.
0876:                    Object value = constantMap.get(key);
0877:                    if (value == null) {
0878:                        // Not found, lets resolve it, duplicate the old Map to avoid
0879:                        // sync problems
0880:                        Map map = new HashMap(constantMap);
0881:                        value = resolveValue(map, key);
0882:
0883:                        // Replace the shared Map w/ this new one.
0884:                        constantMap = map;
0885:                    }
0886:                    return value;
0887:                }
0888:
0889:                /**
0890:                 *  <p>	This method resolves key.  Key is expected to be in the
0891:                 *	format:</p>
0892:                 *
0893:                 *  <p>	some.package.Class.STATIC_VARIBLE</p>
0894:                 *
0895:                 *  <p>	This method will first resolve Class. It will then walk
0896:                 *	through all its variables adding each static final variable to
0897:                 *	the Map.</p>
0898:                 *
0899:                 *  @param  map	    The map to add variables to
0900:                 *  @param  key	    The fully qualified CONSTANT name
0901:                 *
0902:                 *  @return The value of the CONSTANT, or null if not found
0903:                 */
0904:                private Object resolveValue(Map map, String key) {
0905:                    int lastDot = key.lastIndexOf('.');
0906:                    if (lastDot == -1) {
0907:                        throw new IllegalArgumentException(
0908:                                "Unable to resolve '"
0909:                                        + key
0910:                                        + "' in $constant{"
0911:                                        + key
0912:                                        + "}.  '"
0913:                                        + key
0914:                                        + "' must be a "
0915:                                        + "fully qualified classname plus the constant name.");
0916:                    }
0917:
0918:                    // Get the classname / constant name
0919:                    String className = key.substring(0, lastDot);
0920:
0921:                    // Add all constants to the Map
0922:                    try {
0923:                        addConstants(map, Class.forName(className));
0924:                    } catch (ClassNotFoundException ex) {
0925:                        RuntimeException iae = new IllegalArgumentException(
0926:                                "'"
0927:                                        + className
0928:                                        + "' was not found!  This must be a valid "
0929:                                        + "classname.  This was found in expression $constant{"
0930:                                        + key + "}.");
0931:                        iae.initCause(ex);
0932:                        throw iae;
0933:                    }
0934:
0935:                    // The constant hopefully is in the Map now, null if not
0936:                    return map.get(key);
0937:                }
0938:
0939:                /**
0940:                 *  This method adds all constants in the given class to the Map.  The
0941:                 *  Map key will be the fully qualified class name, plus a '.', plus
0942:                 *  the constant name.
0943:                 *
0944:                 *  @param  map	<code>Map</code> to store <code>cls</code>
0945:                 *  @param  cls	The <code>Class</code> to store in <code>map</code>
0946:                 */
0947:                private void addConstants(Map map, Class cls) {
0948:                    // Get the class name
0949:                    String className = cls.getName();
0950:
0951:                    // Get the fields
0952:                    Field fields[] = cls.getFields();
0953:
0954:                    // Add the static final fields to the Map
0955:                    Field field = null;
0956:                    for (int count = 0; count < fields.length; count++) {
0957:                        field = fields[count];
0958:                        if (Modifier.isStatic(field.getModifiers())
0959:                                && Modifier.isFinal(field.getModifiers())) {
0960:                            try {
0961:                                map.put(className + '.' + field.getName(),
0962:                                        field.get(null));
0963:                            } catch (IllegalAccessException ex) {
0964:                                throw new RuntimeException(ex);
0965:                            }
0966:                        }
0967:                    }
0968:                }
0969:
0970:                /**
0971:                 *  This embedded Map caches constant value lookups.  It is static and
0972:                 *  is shared by all users.
0973:                 */
0974:                private static Map constantMap = new HashMap();
0975:            }
0976:
0977:            /**
0978:             *	<p> This {@link VariableResolver.DataSource} creates a MethodBinding
0979:             *	    from the supplied key.  Example:</p>
0980:             *
0981:             *	<p> $methodBinding{#{bean.bundleKey}}</p>
0982:             */
0983:            public static class MethodBindingDataSource implements  DataSource {
0984:                /**
0985:                 *  <p>	See class JavaDoc.</p>
0986:                 *
0987:                 *  @param  ctx		The <code>FacesContext</code>
0988:                 *  @param  desc	The <code>LayoutElement</code>
0989:                 *  @param  component	The <code>UIComponent</code>
0990:                 *  @param  key		The key used to obtain information from this
0991:                 *			<code>DataSource</code>.
0992:                 *
0993:                 *  @return The value resolved from key.
0994:                 */
0995:                public Object getValue(FacesContext ctx, LayoutElement desc,
0996:                        UIComponent component, String key) {
0997:                    return ctx.getApplication().createMethodBinding(key,
0998:                            actionArgs);
0999:                }
1000:            }
1001:
1002:            /**
1003:             *	<p> This {@link VariableResolver.DataSource} allows access to resource
1004:             *	    bundle keys.  It expects the key to be a resource bundle key plus a
1005:             *	    '.' then the actual resouce bundle key Example:</p>
1006:             *
1007:             *	<p> $resource{bundleID.bundleKey} </p>
1008:             *
1009:             *	<p> The bundleID should not contain '.' characters.  The bundleKey
1010:             *	    may.</p>
1011:             */
1012:            public static class ResourceBundleDataSource implements  DataSource {
1013:                /**
1014:                 *  <p>	See class JavaDoc.</p>
1015:                 *
1016:                 *  @param  ctx		The <code>FacesContext</code>
1017:                 *  @param  desc	The <code>LayoutElement</code>
1018:                 *  @param  component	The <code>UIComponent</code>
1019:                 *  @param  key		The key used to obtain information from this
1020:                 *			<code>DataSource</code>.
1021:                 *
1022:                 *  @return The value resolved from key.
1023:                 */
1024:                public Object getValue(FacesContext ctx, LayoutElement desc,
1025:                        UIComponent component, String key) {
1026:                    // Get the Request attribute key
1027:                    int separator = key.indexOf(".");
1028:                    if (separator == -1) {
1029:                        throw new IllegalArgumentException(
1030:                                "'"
1031:                                        + key
1032:                                        + "' is not in format: \"[bundleID].[bundleKey]\"!");
1033:                    }
1034:                    String value = key.substring(0, separator);
1035:
1036:                    // Get the Resource Bundle
1037:                    ResourceBundle bundle = (ResourceBundle) ctx
1038:                            .getExternalContext().getRequestMap().get(value);
1039:
1040:                    // Make sure we have the bundle
1041:                    if (bundle == null) {
1042:                        // Should we throw an exception?  For now just return the key
1043:                        return key;
1044:                    }
1045:
1046:                    // Return the result of the ResouceBundle lookup
1047:                    value = bundle.getString(key.substring(separator + 1));
1048:                    if (value == null) {
1049:                        value = key;
1050:                    }
1051:
1052:                    return value;
1053:                }
1054:            }
1055:
1056:            /**
1057:             *	<p> This {@link VariableResolver.DataSource} provides access to
1058:             *	    HttpSession attributes.  It uses the data portion of the
1059:             *	    substitution String as a key to the HttpSession Map.</p>
1060:             */
1061:            public static class SessionDataSource implements  DataSource {
1062:                /**
1063:                 *  <p>	See class JavaDoc.</p>
1064:                 *
1065:                 *  @param  ctx		The <code>FacesContext</code>
1066:                 *  @param  desc	The <code>LayoutElement</code>
1067:                 *  @param  component	The <code>UIComponent</code>
1068:                 *  @param  key		The key used to obtain information from this
1069:                 *			<code>DataSource</code>.
1070:                 *
1071:                 *  @return The value resolved from key.
1072:                 */
1073:                public Object getValue(FacesContext ctx, LayoutElement desc,
1074:                        UIComponent component, String key) {
1075:                    return ctx.getExternalContext().getSessionMap().get(key);
1076:                }
1077:            }
1078:
1079:            /**
1080:             *	<p> This {@link VariableResolver.DataSource} retrieves style classes
1081:             *	    from the current {@link com.sun.rave.web.ui.theme.Theme}.  The data
1082:             *	    portion of the substitution String as the
1083:             *	    {@link com.sun.rave.web.ui.theme.Theme} key.</p>
1084:             */
1085:            public static class StyleDataSource implements  DataSource {
1086:                /**
1087:                 *  <p>	See class JavaDoc.</p>
1088:                 *
1089:                 *  @param  ctx		The <code>FacesContext</code>
1090:                 *  @param  desc	The <code>LayoutElement</code>
1091:                 *  @param  component	The <code>UIComponent</code>
1092:                 *  @param  key		The key used to obtain information from this
1093:                 *			<code>DataSource</code>.
1094:                 *
1095:                 *  @return The value resolved from key.
1096:                 */
1097:                public Object getValue(FacesContext ctx, LayoutElement desc,
1098:                        UIComponent component, String key) {
1099:                    return ThemeUtilities.getTheme(ctx).getStyleClass(key);
1100:                }
1101:            }
1102:
1103:            /**
1104:             *	<p> This {@link VariableResolver.DataSource} retrieves Theme messages
1105:             *	    from the {@link com.sun.rave.web.ui.theme.Theme}.  The data portion of
1106:             *	    the substitution String is the {@link com.sun.rave.web.ui.theme.Theme}
1107:             *	    message key.</p>
1108:             */
1109:            public static class ThemeDataSource implements  DataSource {
1110:                /**
1111:                 *  <p>	See class JavaDoc.</p>
1112:                 *
1113:                 *  @param  ctx		The <code>FacesContext</code>
1114:                 *  @param  desc	The <code>LayoutElement</code>
1115:                 *  @param  component	The <code>UIComponent</code>
1116:                 *  @param  key		The key used to obtain information from this
1117:                 *			<code>DataSource</code>.
1118:                 *
1119:                 *  @return The value resolved from key.
1120:                 */
1121:                public Object getValue(FacesContext ctx, LayoutElement desc,
1122:                        UIComponent component, String key) {
1123:                    return ThemeUtilities.getTheme(ctx).getMessage(key);
1124:                }
1125:            }
1126:
1127:            /**
1128:             *	<p> This {@link VariableResolver.DataSource} retrieves the path to a
1129:             *	    JavaScript file from the {@link com.sun.rave.web.ui.theme.Theme}.  The
1130:             *	    data portion of the substitution String is the
1131:             *	    {@link com.sun.rave.web.ui.theme.Theme} key for the JavaScript file.</p>
1132:             */
1133:            public static class ThemeJavaScriptDataSource implements  DataSource {
1134:                /**
1135:                 *  <p>	See class JavaDoc.</p>
1136:                 *
1137:                 *  @param  ctx		The <code>FacesContext</code>
1138:                 *  @param  desc	The <code>LayoutElement</code>
1139:                 *  @param  component	The <code>UIComponent</code>
1140:                 *  @param  key		The key used to obtain information from this
1141:                 *			<code>DataSource</code>.
1142:                 *
1143:                 *  @return The value resolved from key.
1144:                 */
1145:                public Object getValue(FacesContext ctx, LayoutElement desc,
1146:                        UIComponent component, String key) {
1147:                    return ThemeUtilities.getTheme(ctx).getPathToJSFile(key);
1148:                }
1149:            }
1150:
1151:            /**
1152:             *	<p> This {@link VariableResolver.DataSource} provides access to
1153:             *	    DisplayField values.  It uses the data portion of the substitution
1154:             *	    String as the DisplayField name to find.  This is a non-qualified
1155:             *	    DisplayField name.  It will walk up the View tree starting at the
1156:             *	    View object cooresponding to the LayoutElement which contained this
1157:             *	    expression.  At each ContainerView, it will look for a child with
1158:             *	    a matching name.</p>
1159:            public static class DisplayFieldDataSource implements DataSource {
1160:            public Object getValue(FacesContext ctx, LayoutElement desc,
1161:            	UIComponent component, String key) {
1162:                while (desc != null) {
1163:            	View view = desc.getView(ctx);
1164:            	if (view instanceof ContainerView) {
1165:            	    View child = null;
1166:            //FIXME: use a better way to find if 'key' is a child of 'view'
1167:            	    try {
1168:            		child = (((ContainerView)(view)).getChild(key));
1169:            	    } catch (Exception ex) {
1170:            	    }
1171:            	    if (child != null) {
1172:            		return ((ContainerView) view).getDisplayFieldValue(key);
1173:            	    }
1174:            	}
1175:            	desc = desc.getParent();
1176:                }
1177:                return null;
1178:            }
1179:            }
1180:             */
1181:
1182:            /**
1183:             *	<p> This class provides an implementation for the syntax $this{xyz}
1184:             *	    where xyz can be any of the following.</p>
1185:             *
1186:             *	<ul><li>component -- Current <code>UIComponent</code></li>
1187:             *	    <li>clientId -- Current <code>UIComponent</code>'s client id</li>
1188:             *	    <li>id -- Current <code>UIComponent</code>'s id</li>
1189:             *	    <li>layoutElement -- Current {@link LayoutElement}</li>
1190:             *	    <li>parent -- Parent <code>UIComponent</code></li>
1191:             *	    <li>parentId -- Parent <code>UIComponent</code>'s client id</li>
1192:             *	    <li>parentLayoutElement -- Parent {@link LayoutElement}</li>
1193:             *	    <li>namingContainer -- Nearest <code>NamingContainer</code></li>
1194:             *	    <li>valueBinding -- <code>ValueBinding</code> representing the
1195:             *		<code>UIComponent</code></li>
1196:             *	</ul>
1197:             */
1198:            public static class ThisDataSource implements  DataSource {
1199:                /**
1200:                 *  <p>	See class JavaDoc.</p>
1201:                 *
1202:                 *  @param  ctx		The <code>FacesContext</code>
1203:                 *  @param  desc	The <code>LayoutElement</code>
1204:                 *  @param  comp	The <code>UIComponent</code>
1205:                 *  @param  key		The key used to obtain information from this
1206:                 *			<code>DataSource</code>.
1207:                 *
1208:                 *  @return The value resolved from key.
1209:                 */
1210:                public Object getValue(FacesContext ctx, LayoutElement desc,
1211:                        UIComponent comp, String key) {
1212:                    Object value = null;
1213:
1214:                    if ((key.equalsIgnoreCase(CLIENT_ID))
1215:                            || (key.length() == 0)) {
1216:                        value = comp.getClientId(ctx);
1217:                    } else if (key.equalsIgnoreCase(ID)) {
1218:                        value = comp.getId();
1219:                    } else if (key.equalsIgnoreCase(COMPONENT)) {
1220:                        value = comp;
1221:                    } else if (key.equalsIgnoreCase(LAYOUT_ELEMENT)) {
1222:                        value = desc;
1223:                    } else if (key.equalsIgnoreCase(PARENT_ID)) {
1224:                        value = comp.getParent().getId();
1225:                    } else if (key.equalsIgnoreCase(PARENT_CLIENT_ID)) {
1226:                        value = comp.getParent().getClientId(ctx);
1227:                    } else if (key.equalsIgnoreCase(PARENT)) {
1228:                        value = comp.getParent();
1229:                    } else if (key.equalsIgnoreCase(PARENT_LAYOUT_ELEMENT)) {
1230:                        value = desc.getParent();
1231:                    } else if (key.equalsIgnoreCase(NAMING_CONTAINER)) {
1232:                        for (value = comp.getParent(); value != null; value = ((UIComponent) value)
1233:                                .getParent()) {
1234:                            if (value instanceof  NamingContainer) {
1235:                                break;
1236:                            }
1237:                        }
1238:                    } else if (key.equalsIgnoreCase(VALUE_BINDING)) {
1239:                        // Walk backward up the tree generate the path
1240:                        Stack stack = new Stack();
1241:                        String id = null;
1242:                        // FIXME: b/c of a bug, the old behavior actually returned the
1243:                        // FIXME: parent component... the next line is here to persist
1244:                        // FIXME: this behavior b/c some code depends on this, fix this
1245:                        // FIXME: when you have a chance.
1246:                        comp = comp.getParent();
1247:                        while ((comp != null) && !(comp instanceof  UIViewRoot)) {
1248:                            id = comp.getId();
1249:                            if (id == null) {
1250:                                // Generate an id based on the clientId
1251:                                id = comp.getClientId(ctx);
1252:                                id = id
1253:                                        .substring(id
1254:                                                .lastIndexOf(NamingContainer.SEPARATOR_CHAR) + 1);
1255:                            }
1256:                            stack.push(id);
1257:                            comp = comp.getParent();
1258:                        }
1259:                        StringBuffer buf = new StringBuffer();
1260:                        buf.append("view");
1261:                        while (!stack.empty()) {
1262:                            buf.append("." + stack.pop());
1263:                        }
1264:                        value = buf.toString();
1265:                    } else {
1266:                        throw new IllegalArgumentException("'" + key
1267:                                + "' is not valid in $this{" + key + "}.");
1268:                    }
1269:
1270:                    return value;
1271:                }
1272:
1273:                /**
1274:                 *  <p> Defines "component" in $this{component}.  Returns the
1275:                 *	UIComponent object.</p>
1276:                 */
1277:                public static final String COMPONENT = "component";
1278:
1279:                /**
1280:                 *  <p> Defines "clientId" in $this{clientId}.  Returns
1281:                 *	the String representing the client id for the UIComponent.</p>
1282:                 */
1283:                public static final String CLIENT_ID = "clientId";
1284:
1285:                /**
1286:                 *  <p> Defines "id" in $this{id}.  Returns the String representing
1287:                 *	the id for the UIComponent.</p>
1288:                 */
1289:                public static final String ID = "id";
1290:
1291:                /**
1292:                 *  <p> Defines "layoutElement" in $this{layoutElement}.  Returns
1293:                 *	the LayoutElement.</p>
1294:                 */
1295:                public static final String LAYOUT_ELEMENT = "layoutElement";
1296:
1297:                /**
1298:                 *  <p> Defines "parent" in $this{parent}.  Returns the
1299:                 *	parent UIComponent object.</p>
1300:                 */
1301:                public static final String PARENT = "parent";
1302:
1303:                /**
1304:                 *  <p> Defines "parentId" in $this{parentId}.  Returns the
1305:                 *	parent UIComponent object's Id.</p>
1306:                 */
1307:                public static final String PARENT_ID = "parentId";
1308:
1309:                /**
1310:                 *  <p> Defines "parentClientId" in $this{parentClientId}.  Returns the
1311:                 *	parent UIComponent object's client Id.</p>
1312:                 */
1313:                public static final String PARENT_CLIENT_ID = "parentClientId";
1314:
1315:                /**
1316:                 *  <p> Defines "parentLayoutElement" in $this{parentLayoutElement}.
1317:                 *	Returns the parent LayoutElement.</p>
1318:                 */
1319:                public static final String PARENT_LAYOUT_ELEMENT = "parentLayoutElement";
1320:
1321:                /**
1322:                 *  <p> Defines "namingContainer" in $this{namingContainer}.  Returns
1323:                 *	the nearest naming container object (i.e. the form).</p>
1324:                 */
1325:                public static final String NAMING_CONTAINER = "namingContainer";
1326:
1327:                /**
1328:                 *  <p> Defines "valueBinding" in $this{valueBinding}.  Returns
1329:                 *	a <code>ValueBinding</code> to this UIComponent.</p>
1330:                 */
1331:                public static final String VALUE_BINDING = "valueBinding";
1332:            }
1333:
1334:            /**
1335:             *	The main function for this class provides some simple test cases.
1336:             *
1337:             *	@param	args	The commandline arguments.
1338:             */
1339:            public static void main(String args[]) {
1340:                String test = null;
1341:                String good = null;
1342:
1343:                test = ""
1344:                        + VariableResolver.resolveVariables(null, null, null,
1345:                                "$escape($escape(LayoutElement))", "$", "(",
1346:                                ")");
1347:                good = "LayoutElement";
1348:                System.out.println("Expected Result: '" + good + "'");
1349:                System.out.println("         Result: '" + test + "'");
1350:                if (!test.equals(good)) {
1351:                    System.out.println("FAILED!!!!");
1352:                }
1353:
1354:                test = ""
1355:                        + VariableResolver.resolveVariables(null, null, null,
1356:                                "$escape($escape(EEPersistenceManager))", "$",
1357:                                "(", ")");
1358:                good = "EEPersistenceManager";
1359:                System.out.println("Expected Result: '" + good + "'");
1360:                System.out.println("         Result: '" + test + "'");
1361:                if (!test.equals(good)) {
1362:                    System.out.println("FAILED!!!!");
1363:                }
1364:
1365:                test = ""
1366:                        + VariableResolver.resolveVariables(null, null, null,
1367:                                "$es$cape$escape(EEPersistenceManager))", "$",
1368:                                "(", ")");
1369:                good = "$es$capeEEPersistenceManager)";
1370:                System.out.println("Expected Result: '" + good + "'");
1371:                System.out.println("         Result: '" + test + "'");
1372:                if (!test.equals(good)) {
1373:                    System.out.println("FAILED!!!!");
1374:                }
1375:
1376:                test = ""
1377:                        + VariableResolver.resolveVariables(null, null, null,
1378:                                "$escape($escapeEEP$ersistenceManager))", "$",
1379:                                "(", ")");
1380:                good = "$escapeEEP$ersistenceManager)";
1381:                System.out.println("Expected Result: '" + good + "'");
1382:                System.out.println("         Result: '" + test + "'");
1383:                if (!test.equals(good)) {
1384:                    System.out.println("FAILED!!!!");
1385:                }
1386:
1387:                test = ""
1388:                        + VariableResolver.resolveVariables(null, null, null,
1389:                                "$escape($escape(EEPersistenceManager)))", "$",
1390:                                "(", ")");
1391:                good = "EEPersistenceManager)";
1392:                System.out.println("Expected Result: '" + good + "'");
1393:                System.out.println("         Result: '" + test + "'");
1394:                if (!test.equals(good)) {
1395:                    System.out.println("FAILED!!!!");
1396:                }
1397:
1398:                test = ""
1399:                        + VariableResolver.resolveVariables(null, null, null,
1400:                                "$escape($escape(EEPersistenceManager())", "$",
1401:                                "(", ")");
1402:                good = "$escape(EEPersistenceManager()";
1403:                System.out.println("Expected Result: '" + good + "'");
1404:                System.out.println("         Result: '" + test + "'");
1405:                if (!test.equals(good)) {
1406:                    System.out.println("FAILED!!!!");
1407:                }
1408:
1409:                test = ""
1410:                        + VariableResolver.resolveVariables(null, null, null,
1411:                                "$escape($escape($escape(EEPersistenceManager()))==$escape("
1412:                                        + "EEPersistenceManager()))", "$", "(",
1413:                                ")");
1414:                good = "EEPersistenceManager()==EEPersistenceManager()";
1415:                System.out.println("Expected Result: '" + good + "'");
1416:                System.out.println("         Result: '" + test + "'");
1417:                if (!test.equals(good)) {
1418:                    System.out.println("FAILED!!!!");
1419:                }
1420:
1421:                test = ""
1422:                        + VariableResolver.resolveVariables(null, null, null,
1423:                                "$escape($escape($escape(EEPersistenceManager()))==$escape("
1424:                                        + "EEPersistenceManager()))", "$", "(",
1425:                                ")");
1426:                good = "EEPersistenceManager()==EEPersistenceManager()";
1427:                System.out.println("Expected Result: '" + good + "'");
1428:                System.out.println("         Result: '" + test + "'");
1429:                if (!test.equals(good)) {
1430:                    System.out.println("FAILED!!!!");
1431:                }
1432:
1433:                /*
1434:                for (int x = 0; x < 100000; x++) {
1435:                    System.out.println("" + VariableResolver.resolveVariables(
1436:                	null, null, null,
1437:                	"$escape($escape(EEPers" + x + "istenceManager()))==$escape("
1438:                	+ "EEPersistenceManager())", "$", "(", ")"));
1439:                }
1440:                 */
1441:            }
1442:
1443:            /**
1444:             *	<p> Contains the {@link VariableResolver.DataSource}'s for
1445:             *	    $&lt;type&gt;{&lt;variable&gt;} syntax.</p>
1446:             */
1447:            private static Map dataSourceMap = new HashMap();
1448:
1449:            /**
1450:             *	<p> Defines "attribute" in $attribute{...}.  This allows you to
1451:             *	    retrieve an HttpRequest attribute.</p>
1452:             */
1453:            public static final String ATTRIBUTE = "attribute";
1454:
1455:            /**
1456:             *	<p> Defines "pageSession" in $pageSession{...}.  This allows you to
1457:             *	    retrieve a PageSession attribute.</p>
1458:            public static final String	    PAGE_SESSION	= "pageSession";
1459:             */
1460:
1461:            /**
1462:             *	<p> Defines "property" in $property{...}.  This allows you to
1463:             *	    retrieve a property from the UIComponent.</p>
1464:             */
1465:            public static final String PROPERTY = "property";
1466:
1467:            /**
1468:             *	<p> Defines "hasProperty" in $hasProperty{...}.  This allows you to
1469:             *	    see if a property from the UIComponent exists.</p>
1470:             */
1471:            public static final String HAS_PROPERTY = "hasProperty";
1472:
1473:            /**
1474:             *	<p> Defines "hasFacet" in $hasFacet{...}.  This allows you to
1475:             *	    see if a facet from the UIComponent exists.</p>
1476:             */
1477:            public static final String HAS_FACET = "hasFacet";
1478:
1479:            /**
1480:             *	<p> Defines "session" in $session{...}.  This allows you to retrieve
1481:             *	    an HttpSession attribute.
1482:             */
1483:            public static final String SESSION = "session";
1484:
1485:            /**
1486:             *	<p> Defines "style" in $style{...}.  This allows you to retrieve
1487:             *	    a style classes from the current {@link com.sun.rave.web.ui.theme.Theme}.
1488:             */
1489:            public static final String STYLE = "style";
1490:
1491:            /**
1492:             *	<p> Defines "theme" in $theme{...}.  This allows you to
1493:             *	    retrieve a Theme message from the current
1494:             *	    {@link com.sun.rave.web.ui.theme.Theme}.
1495:             */
1496:            public static final String THEME = "theme";
1497:
1498:            /**
1499:             *	<p> Defines "themeScript" in $themeScript{...}.  This allows you to
1500:             *	    retrieve a JavaScript classes from the current
1501:             *	    {@link com.sun.rave.web.ui.theme.Theme}.
1502:             */
1503:            public static final String THEME_JS = "themeScript";
1504:
1505:            /**
1506:             *	<p> Defines "requestParameter" in $requestParameter{...}.  This allows
1507:             *	    you to retrieve a HttpRequest parameter (QUERY_STRING
1508:             *	    parameter).</p>
1509:             */
1510:            public static final String REQUEST_PARAMETER = "requestParameter";
1511:
1512:            /**
1513:             *	<p> Defines "display" in $display{...}.  This allows you to retrive
1514:             *	    a DisplayField value.</p>
1515:            public static final String	    DISPLAY             = "display";
1516:             */
1517:
1518:            /**
1519:             *	<p> Defines "this" in $this{...}.  This allows you to retrieve a
1520:             *	    number of different objects related to the relative placement of
1521:             *	    this expression.</p>
1522:             *
1523:             *	@see ThisDataSource
1524:             */
1525:            public static final String THIS = "this";
1526:
1527:            /**
1528:             *	<p> Defines "escape" in $escape{...}.  This allows some reserved
1529:             *	    characters to be escaped in "if" attributes.  Such as '=' or
1530:             *	    '|'.</p>
1531:             */
1532:            public static final String ESCAPE = "escape";
1533:
1534:            /**
1535:             *	<p> Defines "boolean" in $boolean{...}.  This converts the given
1536:             *	    String to a Boolean.</p>
1537:             */
1538:            public static final String BOOLEAN = "boolean";
1539:
1540:            /**
1541:             *	<p> Defines "browser" in $browser{...}.  This checks properties of the
1542:             *	    browser that sent the request.</p>
1543:             */
1544:            public static final String BROWSER = "browser";
1545:
1546:            /**
1547:             *	<p> Defines "int" in $int{...}.  This converts the given String to an
1548:             *	    Integer.</p>
1549:             */
1550:            public static final String INT = "int";
1551:
1552:            /**
1553:             *	<p> Defines "methodBinding" in $methodBinding{...}.  This allows
1554:             *	    MethodBindings in to be created.</p>
1555:             */
1556:            public static final String METHOD_BINDING = "methodBinding";
1557:
1558:            /**
1559:             *	<p> Defines "constant" in $constant{...}.  This allows constants
1560:             *	    in java classes to be accessed.</p>
1561:             */
1562:            public static final String CONSTANT = "constant";
1563:
1564:            /**
1565:             *	<p> Defines "resource" in $resource{...}.  This allows resource
1566:             *	    to be accessed.</p>
1567:             */
1568:            public static final String RESOURCE = "resource";
1569:
1570:            // Static initializer to setup DataSources
1571:            static {
1572:                AttributeDataSource attrDS = new AttributeDataSource();
1573:                dataSourceMap.put(ATTRIBUTE, attrDS);
1574:                dataSourceMap.put("", attrDS);
1575:                //	dataSourceMap.put(PAGE_SESSION, new PageSessionDataSource());
1576:                dataSourceMap.put(PROPERTY, new PropertyDataSource());
1577:                dataSourceMap.put(HAS_PROPERTY, new HasPropertyDataSource());
1578:                dataSourceMap.put(HAS_FACET, new HasFacetDataSource());
1579:                dataSourceMap.put(SESSION, new SessionDataSource());
1580:                dataSourceMap.put(STYLE, new StyleDataSource());
1581:                dataSourceMap.put(THEME, new ThemeDataSource());
1582:                dataSourceMap.put(THEME_JS, new ThemeJavaScriptDataSource());
1583:                dataSourceMap.put(REQUEST_PARAMETER,
1584:                        new RequestParameterDataSource());
1585:                //	dataSourceMap.put(DISPLAY, new DisplayFieldDataSource());
1586:                dataSourceMap.put(THIS, new ThisDataSource());
1587:                dataSourceMap.put(ESCAPE, new EscapeDataSource());
1588:                dataSourceMap.put(INT, new IntDataSource());
1589:                dataSourceMap.put(BOOLEAN, new BooleanDataSource());
1590:                dataSourceMap.put(BROWSER, new BrowserDataSource());
1591:                dataSourceMap.put(CONSTANT, new ConstantDataSource());
1592:                dataSourceMap.put(RESOURCE, new ResourceBundleDataSource());
1593:                dataSourceMap
1594:                        .put(METHOD_BINDING, new MethodBindingDataSource());
1595:            }
1596:
1597:            /**
1598:             *	Constant defining the arguments required for a Action MethodBinding.
1599:             */
1600:            private static Class actionArgs[] = { ActionEvent.class };
1601:
1602:            /**
1603:             *	The '$' character marks the beginning of a substituion in a String.
1604:             */
1605:            public static final String SUB_START = "$";
1606:
1607:            /**
1608:             *	The '(' character marks the beginning of the data content of a String
1609:             *	substitution.
1610:             */
1611:            public static final String SUB_TYPE_DELIM = "{";
1612:
1613:            /**
1614:             *	The ')' character marks the end of the data content for a String
1615:             *	substitution.
1616:             */
1617:            public static final String SUB_END = "}";
1618:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.