Source Code Cross Referenced for Select.java in  » Library » Apache-beehive-1.0.2-src » org » apache » beehive » netui » tags » html » 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 » Library » Apache beehive 1.0.2 src » org.apache.beehive.netui.tags.html 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         *
0017:         * $Header:$
0018:         */
0019:        package org.apache.beehive.netui.tags.html;
0020:
0021:        import org.apache.beehive.netui.util.internal.InternalStringBuilder;
0022:
0023:        import org.apache.beehive.netui.pageflow.ProcessPopulate;
0024:        import org.apache.beehive.netui.pageflow.RequestParameterHandler;
0025:        import org.apache.beehive.netui.script.common.DataAccessProviderStack;
0026:        import org.apache.beehive.netui.script.common.IDataAccessProvider;
0027:        import org.apache.beehive.netui.tags.ByRef;
0028:        import org.apache.beehive.netui.tags.naming.FormDataNameInterceptor;
0029:        import org.apache.beehive.netui.tags.naming.IndexedNameInterceptor;
0030:        import org.apache.beehive.netui.tags.naming.PrefixNameInterceptor;
0031:        import org.apache.beehive.netui.tags.rendering.*;
0032:        import org.apache.beehive.netui.util.Bundle;
0033:        import org.apache.beehive.netui.util.iterator.ArrayIterator;
0034:        import org.apache.beehive.netui.util.iterator.IteratorFactory;
0035:        import org.apache.beehive.netui.util.logging.Logger;
0036:
0037:        import javax.servlet.ServletRequest;
0038:        import javax.servlet.jsp.JspException;
0039:        import java.util.*;
0040:
0041:        /**
0042:         * Renders a select containing a set of SelectOptions.
0043:         *
0044:         * Select binds to an Iterator of Strings.
0045:         *
0046:         * If Select uses any Format tags, it must have those tags come before any nested
0047:         * SelectOption tags.
0048:         * @jsptagref.tagdescription Renders an HTML <select> tag containing a set of selectable options.
0049:         *
0050:         * <p>The &lt;netui:select> tag can generate a set of
0051:         * selectable options in two ways:
0052:         *
0053:         * <blockquote>
0054:         * <ol>
0055:         * <li>they can be dynamically generated by pointing the
0056:         * &lt;netui:select> tag at a String[] object or
0057:         * {@link java.util.HashMap java.util.HashMap}</li>
0058:         * <li>they can be statically generated by providing a set of children
0059:         * {@link SelectOption}
0060:         * tags</li>
0061:         * </ol>
0062:         * </blockquote>
0063:         *
0064:         * <p><b>Dynamically Generated Options</b>
0065:         *
0066:         * <p>You can dynamically generate a set of selectable options by
0067:         * pointing the &lt;netui:select> tag at a String[].
0068:         *
0069:         * <pre>    public String[] colors = {"red", "green", "blue", "orange", "pink", "aqua", "black", "brown", "tan"};
0070:         *
0071:         *    public String[] getColors()
0072:         *    {
0073:         *        return colors;
0074:         *    }</pre>
0075:         *
0076:         * <p>To point the &lt;netui:select> tag at the String[] object use the
0077:         * <code>optionsDataSource</code> attribute.</p>
0078:         *
0079:         * <pre>    &lt;netui:select dataSource="actionForm.selection"
0080:         *                  optionsDataSource="${pageFlow.colors}"/></pre>
0081:         *
0082:         * Note that you can make the display value and the submitted value differ by pointing the
0083:         * optionsDataSource attribute of the &lt;netui:select> tag at a HashMap object.
0084:         * (Any object that implements the {@link java.util.Map java.util.Map} interface will work.)
0085:         *
0086:         * <pre>    public HashMap optionsMap = new HashMap();
0087:         *
0088:         *    protected HashMap getOptionsMap()
0089:         *    {
0090:         *        return optionsMap;
0091:         *    }
0092:         *
0093:         *    protected void onCreate()
0094:         *    {
0095:         *        optionsMap.put("#ff3333", "red");
0096:         *        optionsMap.put("#3333ff", "blue");
0097:         *        optionsMap.put("#33ff33", "green");
0098:         *    }</pre>
0099:         *
0100:         * <p>However, you cannot use a Map object if you choose to use the Select as a repeater
0101:         * (setting the attribute repeater="true").</p>
0102:         *
0103:         * <p>Point the &lt;netui:select> at the Map object using the <code>optionsDataSource</code> attribute.</p>
0104:         *
0105:         * <pre>    &lt;netui:select dataSource="actionForm.selection"
0106:         *                  optionsDataSource="${pageFlow.optionsMap}"/></pre>
0107:         *
0108:         * The following HTML will be generated.
0109:         *
0110:         * <pre>    &lt;select name="wlw-select_key:{actionForm.selection}">
0111:         *        &lt;option value="#3333ff">blue&lt;/option>
0112:         *        &lt;option value="#33ff33">green&lt;/option>
0113:         *        &lt;option value="#ff3333">red&lt;/option>
0114:         *    &lt;/select></pre>
0115:         *
0116:         * <p><b>Statically Generated Options</b></p>
0117:         *
0118:         * <p>To statically generate selecable options, place a set of &lt;netui:selectOption> tags inside
0119:         * the &lt;netui:select> tag.
0120:         *
0121:         * <pre>    &lt;netui:select dataSource="actionForm.selection" size="5">
0122:         *        &lt;netui:selectOption value="red" />
0123:         *        &lt;netui:selectOption value="blue" />
0124:         *        &lt;netui:selectOption value="green" />
0125:         *        &lt;netui:selectOption value="yellow" />
0126:         *        &lt;netui:selectOption value="orange" />
0127:         *    &lt;/netui:select></pre>
0128:         *
0129:         * <p><b>Submitting Selections</b></p>
0130:         *
0131:         * <p>A &lt;netui:select> is submitted as a String or String[] object, depending on whether the
0132:         * <code>multiple</code> attribute is set to true.  In the following example, the <code>dataSource</code>
0133:         * attribute points at a String[] object.</p>
0134:         *
0135:         * <pre>    &lt;/netui:select dataSource="actionForm.selections"...</pre>
0136:         *
0137:         * <p>In this case, the &lt;netui:select> tag submits to a String[] field of a Form Bean.</p>
0138:         *
0139:         * <pre>    public static class SubmitForm extends FormData
0140:         *    {
0141:         *        private String[] selections;
0142:         *
0143:         *        public void setSelections(String[] selections)
0144:         *        {
0145:         *            this.selections = selections;
0146:         *        }
0147:         *
0148:         *        public String[] getSelections()
0149:         *        {
0150:         *            return this.selections;
0151:         *        }
0152:         *    }</pre>
0153:         *
0154:         * <p><b>Use Select as a Repeater with Multiple Repeating Types</b></p>
0155:         *
0156:         * <p>Optionally, use the &lt;netui:select> tag as a repeater to render multiple options
0157:         * from the <code>dataSource</code> and <code>defaultValue</code> attributes as well as
0158:         * the <code>optionsDataSource</code>. The &lt;netui:select> element can dynamically generate
0159:         * option elements for different repeating types of "option", "dataSource", "default",
0160:         * (optionsDataSource, dataSource, and defaultValue attributes respectively) and "null".
0161:         * The Select <code>repeatingOrder</code> attribute sets the order that repeating types
0162:         * are generated. The <code>repeatingType</code> attribute on the &lt;netui:selectOption>
0163:         * tag identifies each of the types to be rendered.</p>
0164:         *
0165:         * <p>Use JSTL boolean conditional tags with the &lt;netui:selectOption> elements
0166:         * to help manage repeaters of different data types.
0167:         * For example, the <code>dataSource</code> could point to a String[] while
0168:         * the <code>optionsDataSource</code> points to an Object[] where each object has
0169:         * name and value fields...</p>
0170:         *
0171:         * <pre>    &lt;netui:select dataSource="actionForm.selections"
0172:         *                  optionsDataSource="${pageFlow.options}"
0173:         *                  repeatingOrder="dataSource,option"
0174:         *                  repeater="true" multiple="true">
0175:         *        &lt;c:if test="${container.metadata.dataSourceStage}">
0176:         *            &lt;netui:selectOption  repeatingType="dataSource" value="${container.item}">
0177:         *                &lt;netui:span value="${container.item}" />
0178:         *            &lt;/netui:selectOption>
0179:         *        &lt;/c:if>
0180:         *        &lt;c:if test="${container.metadata.optionStage}">
0181:         *            &lt;netui:selectOption  repeatingType="option" value="${container.item.name}">
0182:         *                &lt;netui:span value="${container.item.value}" />
0183:         *            &lt;/netui:selectOption>
0184:         *        &lt;/c:if>
0185:         *    &lt;/netui:select>
0186:         * </pre>
0187:         * @example The following sample uses the <code>optionsDataSource</code> attribute to reference a
0188:         * dynamically generated dropdown list.
0189:         *
0190:         * <pre>
0191:         *    &lt;netui:select dataSource="actionForm.selectedOption"
0192:         *                  optionsDataSource="${actionForm.itemOptions}" />
0193:         * </pre>
0194:         *
0195:         * <p>Assume that the <code>optionsDataSource</code> attribute refers to
0196:         * a <code>java.util.Map</code> object.
0197:         * The Map object will be rendered as a series
0198:         * of &lt;option> tags. HTML that is similar to the following will be
0199:         * rendered in the browser:</p>
0200:         *
0201:         * <pre>    &lt;select name="wlw-select_key:{actionForm.itemOptions}">
0202:         *        &lt;option value="633">Aurora Bridge&lt;/option>
0203:         *        &lt;option value="631">FA-18 fighter jet&lt;/option>
0204:         *        &lt;option value="635">Space Needle&lt;/option>
0205:         *        &lt;option value="642">Thin Mints&lt;/option>
0206:         * 	      ...
0207:         *    &lt;/select></pre>
0208:         * @netui:tag name="select" description="Defines a multiple-choice menu or drop-down list within a netui:form element."
0209:         * @netui:attribute name="onSelect" hide="true" description=""
0210:         */
0211:        public class Select extends HtmlOptionsDataSourceTag implements 
0212:                IDataAccessProvider, IFormattable {
0213:            // @todo: needs to create DRT tests for: verification of errors, verirication of data sources matching,
0214:            // @todo: verification of formating inside a repeater.
0215:            // @todo: on the null tag, we need to default the null value to NULL_VALUE
0216:            // @todo: need to handle null, in the options
0217:            // @todo: should handle no optionDataSource when repeating...
0218:
0219:            private static final Logger logger = Logger
0220:                    .getInstance(Select.class);
0221:
0222:            private SelectTag.State _state = new SelectTag.State();
0223:            private OptionTag.State _optionState = new OptionTag.State();
0224:            private InputHiddenTag.State _hiddenState = new InputHiddenTag.State();
0225:            private boolean _formatterError = false;
0226:
0227:            private static Object[] NULL_INSTANCE = { null };
0228:
0229:            /**
0230:             * This enum defines stages through the possible option values.
0231:             */
0232:            public static class RepeatingStages {
0233:                private static final int INT_BEFORE = 0;
0234:                private static final int INT_OPTION = 1;
0235:                private static final int INT_DEFAULT = 2;
0236:                private static final int INT_DATASOURCE = 3;
0237:                private static final int INT_NULL = 4;
0238:                private static final int INT_DONE = 5;
0239:
0240:                static final RepeatingStages BEFORE = new RepeatingStages(
0241:                        INT_BEFORE);
0242:                static final RepeatingStages OPTION = new RepeatingStages(
0243:                        INT_OPTION);
0244:                static final RepeatingStages DEFAULT = new RepeatingStages(
0245:                        INT_DEFAULT);
0246:                static final RepeatingStages DATASOURCE = new RepeatingStages(
0247:                        INT_DATASOURCE);
0248:                static final RepeatingStages NULL = new RepeatingStages(
0249:                        INT_NULL);
0250:                static final RepeatingStages DONE = new RepeatingStages(
0251:                        INT_DONE);
0252:
0253:                /**
0254:                 * These are the publically exposed stages, <code>REPEATING_OPTION, REPEATING_DEFAULT,
0255:                 * REPEATING_DATASOURCE and REPEATING_NULL</code>.
0256:                 */
0257:                public static final String REPEATING_OPTION = "option";
0258:                public static final String REPEATING_DEFAULT = "default";
0259:                public static final String REPEATING_DATASOURCE = "dataSource";
0260:                public static final String REPEATING_NULL = "null";
0261:
0262:                public int value;
0263:
0264:                // prevent construction...
0265:                private RepeatingStages(int val) {
0266:                    value = val;
0267:                }
0268:
0269:                int getValue() {
0270:                    return value;
0271:                }
0272:
0273:                /**
0274:                 * Returns the String value that can be used to order the selection.
0275:                 * @return The String Value.
0276:                 */
0277:                public String toString() {
0278:                    switch (value) {
0279:                    case INT_OPTION:
0280:                        return REPEATING_OPTION;
0281:                    case INT_DEFAULT:
0282:                        return REPEATING_DEFAULT;
0283:                    case INT_DATASOURCE:
0284:                        return REPEATING_DATASOURCE;
0285:                    case INT_NULL:
0286:                        return REPEATING_NULL;
0287:                    default:
0288:                        return "Unknown Stage";
0289:                    }
0290:                }
0291:
0292:                /**
0293:                 * Given a String value defined above, return the enum value for it.
0294:                 * @param value a String value matching one of the public Strings defined for the class.
0295:                 * @return the matching RepeatingStages or null.
0296:                 */
0297:                public static RepeatingStages parseString(String value) {
0298:                    if (REPEATING_OPTION.equals(value))
0299:                        return OPTION;
0300:                    if (REPEATING_DEFAULT.equals(value))
0301:                        return DEFAULT;
0302:                    if (REPEATING_DATASOURCE.equals(value))
0303:                        return DATASOURCE;
0304:                    if (REPEATING_NULL.equals(value))
0305:                        return NULL;
0306:                    return null;
0307:                }
0308:            }
0309:
0310:            /**
0311:             * This defines the default order of processing the options when repeating.
0312:             */
0313:            private static final RepeatingStages[] DEFAULT_ORDER = {
0314:                    RepeatingStages.BEFORE, RepeatingStages.OPTION,
0315:                    RepeatingStages.DATASOURCE, RepeatingStages.DEFAULT,
0316:                    RepeatingStages.NULL };
0317:
0318:            /**
0319:             * Default value of the options <code>value</code> attribute.
0320:             */
0321:            public static final String NULL_VALUE = "netui_null";
0322:
0323:            /**
0324:             * Constant value of the <code>repeatingType</code> attribute for options handling the <code>null</code> option.
0325:             */
0326:            //public static final String REPEATING_NULL = "Null";
0327:            private static final String SELECT_KEY = "select_key";
0328:            private static final String OLDVALUE_SUFFIX = "OldValue";
0329:
0330:            // IDataAccessProvider support
0331:            private int _repIdx = 0; // The current index for repeating over the optionsDataSource
0332:            private RepeatingStages _repCurStage = RepeatingStages.BEFORE; // The current stage defined by the stage constants above
0333:            private boolean _repeater; // Boolean flag indicating if this is a repeater or not
0334:            private Object _repCurItem; // The current item access by the IDataAccessProvider
0335:            private Iterator _repeaterIterator; // The iterator being used to output the options.
0336:            private RepeatingStages[] _order = DEFAULT_ORDER;
0337:
0338:            private Object _dynamicOptions; // The interator (or map) for the options data source, repeating this is current var
0339:
0340:            private String _saveBody;
0341:            private String _nullableOptionText;
0342:
0343:            private List _defaultSelections;
0344:            private ArrayList _formatters;
0345:            private ArrayList _optionList;
0346:            private String[] _match; // The actual values we will match against
0347:            private boolean _nullable;
0348:            private TagRenderingBase _optRb;
0349:
0350:            private static final List _internalNamingChain;
0351:
0352:            static {
0353:                List l = new ArrayList(3);
0354:                l.add(new FormDataNameInterceptor());
0355:                l.add(new IndexedNameInterceptor());
0356:                l.add(new PrefixNameInterceptor(SELECT_KEY));
0357:                _internalNamingChain = Collections.unmodifiableList(l);
0358:
0359:                org.apache.beehive.netui.pageflow.ProcessPopulate
0360:                        .registerPrefixHandler(SELECT_KEY,
0361:                                new SelectPrefixHandler());
0362:            }
0363:
0364:            /**
0365:             */
0366:            public static class SelectPrefixHandler implements 
0367:                    RequestParameterHandler {
0368:                public void process(
0369:                        javax.servlet.http.HttpServletRequest request,
0370:                        String key, String expr,
0371:                        ProcessPopulate.ExpressionUpdateNode node) {
0372:                    String[] returnArray = null;
0373:
0374:                    if (!key.endsWith(OLDVALUE_SUFFIX)) {
0375:                        //This select has values and should stay that way
0376:                        returnArray = request.getParameterValues(key);
0377:                    } else {
0378:                        //Check the request to see if select also exists
0379:                        String newKey = key.substring(0, key
0380:                                .indexOf(OLDVALUE_SUFFIX));
0381:                        String[] select = request.getParameterValues(newKey);
0382:                        if (select != null) {
0383:                            returnArray = select;
0384:                        } else {
0385:                            returnArray = new String[0]; //null;
0386:                        }
0387:                    }
0388:
0389:                    if (node.expression.endsWith(OLDVALUE_SUFFIX)) {
0390:                        node.expression = node.expression.substring(0,
0391:                                node.expression.indexOf(OLDVALUE_SUFFIX));
0392:                    }
0393:
0394:                    //Check for the NULL_VALUE, replace it with null
0395:                    for (int i = 0; i < returnArray.length; i++) {
0396:                        if (returnArray[i].equals(NULL_VALUE)) {
0397:                            returnArray[i] = null;
0398:                        }
0399:                    }
0400:
0401:                    node.values = returnArray;
0402:
0403:                    if (logger.isDebugEnabled()) {
0404:                        logger
0405:                                .debug("\n*********************************************\n"
0406:                                        + "process with key \""
0407:                                        + key
0408:                                        + "\" and expression \""
0409:                                        + node.expression
0410:                                        + "\""
0411:                                        + "and result size: "
0412:                                        + (returnArray != null ? ""
0413:                                                + returnArray.length : null)
0414:                                        + "\n"
0415:                                        + "*********************************************\n");
0416:                    }
0417:                }
0418:            }
0419:
0420:            public Select() {
0421:                super ();
0422:            }
0423:
0424:            /**
0425:             * Return the name of the Tag.
0426:             */
0427:            public String getTagName() {
0428:                return "Select";
0429:            }
0430:
0431:            public String getDataSource() {
0432:                return "{" + _dataSource.toString() + "}";
0433:            }
0434:
0435:            /**
0436:             * This method will return the state associated with the tag.  This is used by this
0437:             * base class to access the individual state objects created by the tags.
0438:             * @return a subclass of the <code>AbstractHtmlState</code> class.
0439:             */
0440:            protected AbstractHtmlState getState() {
0441:                return _state;
0442:            }
0443:
0444:            /**
0445:             * Return an <code>ArrayList</code> which represents a chain of <code>INameInterceptor</code>
0446:             * objects.  This method by default returns <code>null</code> and should be overridden
0447:             * by objects that support naming.
0448:             * @return an <code>ArrayList</code> that will contain <code>INameInterceptor</code> objects.
0449:             */
0450:            protected List getNamingChain() {
0451:                return _internalNamingChain;
0452:            }
0453:
0454:            /**
0455:             * Evaluate the defaultValues
0456:             */
0457:            protected Object evaluateDefaultValue() throws JspException {
0458:                Object val = _defaultValue;
0459:
0460:                List defaults = null;
0461:                if (val instanceof  String) {
0462:                    defaults = new ArrayList();
0463:                    defaults.add(val);
0464:                } else {
0465:                    Iterator optionsIterator = null;
0466:                    optionsIterator = IteratorFactory.createIterator(val);
0467:
0468:                    // default value is optional so only warn
0469:                    if (optionsIterator == null && _defaultValue != null)
0470:                        logger.warn(Bundle.getString("Tags_IteratorError",
0471:                                new Object[] { getTagName(), "defaultValue",
0472:                                        _defaultValue }));
0473:
0474:                    if (optionsIterator == null)
0475:                        optionsIterator = IteratorFactory.EMPTY_ITERATOR;
0476:
0477:                    defaults = new ArrayList();
0478:                    while (optionsIterator.hasNext()) {
0479:                        Object o = optionsIterator.next();
0480:                        defaults.add(o.toString());
0481:                    }
0482:                }
0483:
0484:                return defaults;
0485:            }
0486:
0487:            /**
0488:             * Set whether multiple selections are allowed.
0489:             * @param multiple the multiple value ("true" or "false")
0490:             * @jsptagref.attributedescription Boolean. Whether or not multi-selection is enabled.
0491:             * If multiple selection is enabled, a null option will not be displayed, even if
0492:             * the <code>nullable</code> is set to true.
0493:             * @jsptagref.databindable false
0494:             * @jsptagref.attributesyntaxvalue <i>boolean_multipleSelectEnabled</i>
0495:             * @netui:attribute required="false" rtexprvalue="true" type="boolean"
0496:             * description="Whether or not multi-selection is enabled.
0497:             * If multiple selection is enabled, a null option will not be displayed, even if
0498:             * the nullable is set to true."
0499:             */
0500:            public void setMultiple(boolean multiple) {
0501:                _state.multiple = multiple;
0502:            }
0503:
0504:            /**
0505:             * Set whether repeating of contained options is on.
0506:             * @param repeater the repeater value ("true" or "false")
0507:             * @jsptagref.attributedescription Set whether repeating of contained options is on.
0508:             * @jsptagref.databindable false
0509:             * @jsptagref.attributesyntaxvalue <i>boolean_repeater</i>
0510:             * @netui:attribute required="false" rtexprvalue="true" type="boolean"
0511:             * description="Set whether repeating of contained options is on."
0512:             */
0513:            public void setRepeater(boolean repeater) {
0514:                _repeater = repeater;
0515:            }
0516:
0517:            /**
0518:             * Gets whether a repeating contained options is on.
0519:             * @return the repeater value
0520:             */
0521:            public boolean isRepeater() {
0522:                return _repeater;
0523:            }
0524:
0525:            /**
0526:             * This method will set the order of the options generated in the select.  It must contain a
0527:             * comma separated string listing the order or the stages that the repeating types are processed.
0528:             * These values are "option", "dataSource", "default", and "null".
0529:             * @param order comma separated ordering of items when there is a repeating select.
0530:             * @jsptagref.attributedescription Define the order of options generated for a repeating Select.
0531:             * It must contain a comma separated string listing the order or the stages that the repeating types
0532:             * are processed. These values are "option", "dataSource", "default", and "null". For example,
0533:             * <pre>    repeatingOrder="dataSource,option"</pre>
0534:             *
0535:             * Then a &lt;netui:selectOption> element could set the repeatingType attribute to "dataSource"
0536:             * while another is defined for "option".
0537:             * @jsptagref.databindable false
0538:             * @jsptagref.attributesyntaxvalue <i>string_order</i>
0539:             * @netui:attribute required="false" rtexprvalue="true"
0540:             * description="Define the order of options for a repeating Select"
0541:             */
0542:            public void setRepeatingOrder(String order) throws JspException {
0543:                String[] options = order.split(",");
0544:                RepeatingStages[] stageOrder = new RepeatingStages[options.length + 1];
0545:                stageOrder[0] = RepeatingStages.BEFORE;
0546:                for (int i = 0; i < options.length; i++) {
0547:                    String opt = options[i].trim();
0548:                    stageOrder[i + 1] = RepeatingStages.parseString(opt);
0549:                    if (stageOrder[i + 1] == null) {
0550:                        String s = Bundle.getString(
0551:                                "Tags_SelectBadRepeatingStage",
0552:                                new Object[] { opt });
0553:                        registerTagError(s, null);
0554:                    }
0555:                }
0556:                _order = stageOrder;
0557:            }
0558:
0559:            /**
0560:             * Set whether a null option is desired.
0561:             * @param nullable the nullable value
0562:             * @jsptagref.attributedescription Boolean.
0563:             * Whether a option with the value null should be added to the bottom of the list.
0564:             * If &lt;select> has the multiple <code>attribute</code> set to true, the null option won't be shown.
0565:             * @jsptagref.databindable false
0566:             * @jsptagref.attributesyntaxvalue <i>boolean_nullable</i>
0567:             * @netui:attribute required="false"  rtexprvalue="true" type="boolean"
0568:             * description="Whether a option with the value null should be added to the bottom of the list.
0569:             * If <select> has the multiple attribute set to true, the null option won't be shown."
0570:             */
0571:            public void setNullable(boolean nullable) {
0572:                _nullable = nullable;
0573:            }
0574:
0575:            /**
0576:             * Gets the options datasource value (an expression).
0577:             * @return the options datasource
0578:             */
0579:            public Object getOptionsDataSource() {
0580:                return _optionsDataSource;
0581:            }
0582:
0583:            /**
0584:             * Set the text of the nullable option.
0585:             * If the <code>nullable<code> option is true, this is
0586:             * the text of that option. The default is "";
0587:             * @jsptagref.attributedescription Boolean.
0588:             * If the <code>nullable</code> attribute is set to true, then the <code>nullableOptionText</code>
0589:             * attribute determines the display text of the null option.
0590:             * The default is to use the empty string, "", as the display text.
0591:             * @jsptagref.databindable false
0592:             * @jsptagref.attributesyntaxvalue <i>boolean_nullableOptionText</i>
0593:             * @netui:attribute required="false" rtexprvalue="true" type="boolean"
0594:             * description="If the nullable attribute is set to true, then the nullableOptionText
0595:             * attribute determines the display text of the null option.
0596:             */
0597:            public void setNullableOptionText(String nullableOptionText) {
0598:                _nullableOptionText = nullableOptionText;
0599:            }
0600:
0601:            /**
0602:             * This method will return the object representing the <code>optionsDataSource</code>.  This
0603:             * is overridden from the base class, because there are only two types which will be
0604:             * retunred from the method.  The <code>optionsDataSource</code> will either be a instance of a <code>Map</code>
0605:             * or and instanceof a <code>Iterator</code>.
0606:             * @return the object instance object representing the objectsDataSource.  This may be null.
0607:             * @throws JspException on an error
0608:             */
0609:            protected Object evaluateOptionsDataSource() throws JspException {
0610:                Object val = _optionsDataSource;
0611:                if (val == null) {
0612:                    // optionsDataSource is option so this is a warning
0613:                    if (_optionsDataSource != null)
0614:                        logger.warn(Bundle
0615:                                .getString("Tags_IteratorError", new Object[] {
0616:                                        getTagName(), "optionsDataSource",
0617:                                        _optionsDataSource }));
0618:                    return null;
0619:                }
0620:
0621:                if (val instanceof  Map)
0622:                    return val;
0623:
0624:                Iterator options = null;
0625:                options = IteratorFactory.createIterator(val);
0626:                if (options == null)
0627:                    options = IteratorFactory.EMPTY_ITERATOR;
0628:
0629:                return options;
0630:            }
0631:
0632:            /**
0633:             * Sets how many options are displayed.
0634:             * @param size the size (a number)
0635:             * @jsptagref.attributedescription The number of visible options
0636:             * @jsptagref.databindable false
0637:             * @jsptagref.attributesyntaxvalue <i>integer_size</i>
0638:             * @netui:attribute required="false" rtexprvalue="true" type="int"
0639:             * description="The number of visible options"
0640:             */
0641:            public void setSize(int size) {
0642:                _state.size = size;
0643:            }
0644:
0645:            /**
0646:             * Does the specified value match one of those we are looking for?
0647:             * @param value Value to be compared
0648:             */
0649:            public boolean isMatched(String value) {
0650:                if (value == null)
0651:                    return false;
0652:                if ((_match != null)) {
0653:                    for (int i = 0; i < _match.length; i++) {
0654:                        if (value.equals(_match[i]))
0655:                            return true;
0656:                    }
0657:                } else {
0658:                    if (_defaultSelections != null) {
0659:                        return (_defaultSelections.contains(value));
0660:                    }
0661:                }
0662:
0663:                return false;
0664:
0665:            }
0666:
0667:            //********************************** IDataAccessProvider Interface  ******************************
0668:            // setDataSource is implemented by the HtmlDataSourceTag class
0669:            // getDataSource is implemented by the HtmlDataSourceTag class
0670:
0671:            /**
0672:             * Get the current index in this iteration.  This should be a
0673:             * zero based integer that increments after each iteration.
0674:             * @return the current index of iteration or 0
0675:             */
0676:            public int getCurrentIndex() {
0677:                return _repIdx;
0678:            }
0679:
0680:            /**
0681:             * Get the current data item in this IDataAccessProvider.
0682:             * @return the current data item or <code>null</code>
0683:             */
0684:            public Object getCurrentItem() {
0685:                return _repCurItem;
0686:            }
0687:
0688:            /**
0689:             * Get a metadata object for the current item.  This interface
0690:             * is optional, and implementations of this interface are
0691:             * provided by the IDataAccessProvider interface.  See these
0692:             * implementations for information about their support for
0693:             * current item metadata.
0694:             * @return the current metadata or <code>null</code> if no metadata can be
0695:             *         found or metadata is not supported by a IDataAccessProvider implementation
0696:             */
0697:            public Object getCurrentMetadata() {
0698:                return this ;
0699:            }
0700:
0701:            /**
0702:             * Get the parent IDataAccessProvider of a IDataAccessProvider.  A IDataAccessProvider
0703:             * implementation may be able to nest IDataAccessProviders.  In this case,
0704:             * it can be useful to be able to also nest access to data from parent
0705:             * providers.  Implementations of this interface are left with having
0706:             * to discover and export parents.  The return value from this call
0707:             * on an implementing Object can be <code>null</code>.
0708:             * @return the parent IDataAccessProvider or <code>null</code> if this method
0709:             *         is not supported or the parent can not be found.
0710:             */
0711:            public IDataAccessProvider getProviderParent() {
0712:                return (IDataAccessProvider) findAncestorWithClass(this ,
0713:                        IDataAccessProvider.class);
0714:            }
0715:
0716:            /**
0717:             * Return the enum value of the currently repeating stage.
0718:             * @return The currently repeating stage.
0719:             */
0720:            public RepeatingStages getRepeatingStage() {
0721:                return _repCurStage;
0722:            }
0723:
0724:            /**
0725:             * Boolean indicating that we are processing the optionsDataSource.
0726:             * @return <code>true</code> if we are processing the optionsDataSource.
0727:             */
0728:            public boolean isOptionStage() {
0729:                return _repCurStage == RepeatingStages.OPTION;
0730:            }
0731:
0732:            /**
0733:             * Boolean indicating that we are processing the defaultValue.
0734:             * @return <code>true</code> if we are processing the defaultValue.
0735:             */
0736:            public boolean isDefaultStage() {
0737:                return _repCurStage == RepeatingStages.DEFAULT;
0738:            }
0739:
0740:            /**
0741:             * Boolean indicating that we are processing the dataSource.
0742:             * @return <code>true</code> if we are processing the dataSource.
0743:             */
0744:            public boolean isDataSourceStage() {
0745:                return _repCurStage == RepeatingStages.DATASOURCE;
0746:            }
0747:
0748:            /**
0749:             * Boolean indicating that we are processing the defined null value.
0750:             * @return <code>true</code> if we are processing the defined null value.
0751:             */
0752:            public boolean isNullStage() {
0753:                return _repCurStage == RepeatingStages.NULL;
0754:            }
0755:
0756:            /**
0757:             * Render the beginning of this select.
0758:             * @throws JspException if a JSP exception has occurred
0759:             */
0760:            public int doStartTag() throws JspException {
0761:                Object val = evaluateDataSource();
0762:                _defaultSelections = (List) evaluateDefaultValue();
0763:
0764:                // if there were expression errors report them
0765:                if (hasErrors())
0766:                    return SKIP_BODY;
0767:
0768:                buildMatch(val);
0769:                if (hasErrors())
0770:                    return SKIP_BODY;
0771:
0772:                _formatters = new ArrayList();
0773:                _optionList = new ArrayList();
0774:
0775:                // Walk the options data source
0776:                _dynamicOptions = evaluateOptionsDataSource();
0777:                if (_repeater) {
0778:                    _repCurStage = _order[0];
0779:                    boolean valid = doRepeaterAfterBody();
0780:                    if (!valid)
0781:                        return SKIP_BODY;
0782:                    DataAccessProviderStack.addDataAccessProvider(this ,
0783:                            pageContext);
0784:                }
0785:
0786:                // Continue processing this page
0787:                return EVAL_BODY_BUFFERED;
0788:            }
0789:
0790:            /**
0791:             * Save any body content of this tag, which will generally be the
0792:             * option(s) representing the values displayed to the user.
0793:             * @throws JspException if a JSP exception has occurred
0794:             */
0795:            public int doAfterBody() throws JspException {
0796:                if (hasErrors()) {
0797:                    return SKIP_BODY;
0798:                }
0799:
0800:                // if this is a repeater we need to repeater over the body...
0801:                if (_repeater) {
0802:                    if (doRepeaterAfterBody())
0803:                        return EVAL_BODY_AGAIN;
0804:                }
0805:
0806:                if (bodyContent != null) {
0807:                    String value = bodyContent.getString();
0808:                    bodyContent.clearBody();
0809:                    if (value == null)
0810:                        value = "";
0811:                    _saveBody = value.trim();
0812:                }
0813:                return SKIP_BODY;
0814:            }
0815:
0816:            /**
0817:             * Render the end of this select.
0818:             * @throws JspException if a JSP exception has occurred
0819:             */
0820:            public int doEndTag() throws JspException {
0821:                ServletRequest req = pageContext.getRequest();
0822:
0823:                String fmtErrors = null;
0824:                if (_formatterError) {
0825:                    fmtErrors = getErrorsFromBody();
0826:                }
0827:                if (hasErrors())
0828:                    return reportAndExit(EVAL_PAGE);
0829:
0830:                _state.disabled = isDisabled();
0831:
0832:                //Create hidden field for state tracking
0833:                ByRef ref = new ByRef();
0834:                nameHtmlControl(_state, ref);
0835:
0836:                if (hasErrors())
0837:                    return reportAndExit(EVAL_PAGE);
0838:
0839:                // Only write out the hidden field if the select is not
0840:                // disabled.  If it is disabled, then nothing will be posted
0841:                // back from this.
0842:                WriteRenderAppender writer = new WriteRenderAppender(
0843:                        pageContext);
0844:                if (!_state.disabled) {
0845:                    _hiddenState.clear();
0846:                    String hiddenParamName = null;
0847:                    hiddenParamName = _state.name + OLDVALUE_SUFFIX;
0848:                    _hiddenState.name = hiddenParamName;
0849:                    _hiddenState.value = "true";
0850:
0851:                    TagRenderingBase hiddenTag = TagRenderingBase.Factory
0852:                            .getRendering(TagRenderingBase.INPUT_HIDDEN_TAG,
0853:                                    req);
0854:                    hiddenTag.doStartTag(writer, _hiddenState);
0855:                    hiddenTag.doEndTag(writer);
0856:                    write("\n");
0857:                }
0858:
0859:                // Render any formatting errors that may have occurred.
0860:                if (fmtErrors != null)
0861:                    write(fmtErrors);
0862:
0863:                TagRenderingBase br = TagRenderingBase.Factory.getRendering(
0864:                        TagRenderingBase.SELECT_TAG, req);
0865:                br.doStartTag(writer, _state);
0866:
0867:                // Render the content of the body, these would be the options
0868:                if (_saveBody != null) {
0869:                    write(_saveBody);
0870:                }
0871:
0872:                // if we are repeating then the body contained the options so we can exit here
0873:                if (_repeater) {
0874:
0875:                    if (hasErrors())
0876:                        return reportAndExit(EVAL_PAGE);
0877:
0878:                    br.doEndTag(writer);
0879:                    if (!ref.isNull())
0880:                        write((String) ref.getRef());
0881:
0882:                    // Continue processing this page
0883:                    localRelease();
0884:                    return EVAL_PAGE;
0885:                }
0886:
0887:                // All of the code below will pass through the optionsDataSource, the dataSource and defaultValue and
0888:                // create a full Select.
0889:                if (_dynamicOptions != null) {
0890:                    if (_dynamicOptions instanceof  Map) {
0891:                        Map dynamicOptionsMap = (Map) _dynamicOptions;
0892:                        Iterator keyIterator = dynamicOptionsMap.keySet()
0893:                                .iterator();
0894:                        while (keyIterator.hasNext()) {
0895:                            Object optionValue = keyIterator.next();
0896:                            String optionDisplay = null;
0897:                            if (dynamicOptionsMap.get(optionValue) != null) {
0898:                                optionDisplay = dynamicOptionsMap.get(
0899:                                        optionValue).toString();
0900:                            }
0901:
0902:                            if (optionValue != null) {
0903:                                addOption(req, optionValue.toString(),
0904:                                        optionDisplay);
0905:                            }
0906:                        }
0907:                    } else if (_dynamicOptions instanceof  Iterator) {
0908:                        Iterator dynamicOptionsIterator = (Iterator) evaluateOptionsDataSource();
0909:                        while (dynamicOptionsIterator.hasNext()) {
0910:                            Object o = dynamicOptionsIterator.next();
0911:                            if (o != null) {
0912:                                String optionValue = o.toString();
0913:                                addOption(req, optionValue, optionValue);
0914:                            }
0915:                        }
0916:                    }
0917:                }
0918:
0919:                // add the value from the DataSource and Default value
0920:                addDatasourceIfNeeded(req);
0921:                addDefaultsIfNeeded(req);
0922:                if (_nullable && !isMultiple()) {
0923:                    String txt = (_nullableOptionText != null) ? _nullableOptionText
0924:                            : "";
0925:                    addOption(req, NULL_VALUE, txt);
0926:                }
0927:
0928:                br.doEndTag(writer);
0929:                if (!ref.isNull())
0930:                    write((String) ref.getRef());
0931:
0932:                // Continue processing this page
0933:                localRelease();
0934:                return EVAL_PAGE;
0935:            }
0936:
0937:            /**
0938:             * Release any acquired resources.
0939:             */
0940:            protected void localRelease() {
0941:                if (_repeater)
0942:                    DataAccessProviderStack
0943:                            .removeDataAccessProvider(pageContext);
0944:
0945:                super .localRelease();
0946:                _state.clear();
0947:
0948:                _defaultSelections = null;
0949:                _formatters = null;
0950:                _match = null;
0951:                _saveBody = null;
0952:                _nullable = false;
0953:                _nullableOptionText = null;
0954:                _optionList = null;
0955:
0956:                _repIdx = 0;
0957:                _repeater = false;
0958:                _repCurItem = null;
0959:                _repCurStage = RepeatingStages.BEFORE;
0960:                _dynamicOptions = null;
0961:                _formatterError = false;
0962:                _optRb = null;
0963:
0964:                _order = DEFAULT_ORDER;
0965:            }
0966:
0967:            private String getErrorsFromBody() {
0968:                final String END_TOKEN = "</span>";
0969:                assert (_saveBody != null);
0970:                InternalStringBuilder body = new InternalStringBuilder(
0971:                        _saveBody.length());
0972:                InternalStringBuilder error = new InternalStringBuilder(
0973:                        _saveBody.length());
0974:
0975:                // pull out all of the spans  These should be legally constructed, otherwise we will ignore them.
0976:                int len = _saveBody.length();
0977:                int pos = 0;
0978:                while (pos < len) {
0979:
0980:                    // find the start of a span, if we dont' find one then it's over....
0981:                    int start = _saveBody.indexOf("<span", pos);
0982:                    if (start == -1)
0983:                        break;
0984:
0985:                    // if we don't find the end of the <span> then we don't have a legal span so ignore it
0986:                    int end = _saveBody.indexOf(END_TOKEN);
0987:                    if (end == -1)
0988:                        break;
0989:
0990:                    // copy the pos to start into the body
0991:                    int realEnd = end + END_TOKEN.length() + 1;
0992:                    body.append(_saveBody.substring(pos, start));
0993:                    error.append(_saveBody.substring(start, realEnd));
0994:                    pos = realEnd;
0995:                }
0996:
0997:                // recreate the remainder of the body, everything not left
0998:                body.append(_saveBody.substring(pos, len));
0999:                _saveBody = body.toString();
1000:
1001:                // return the error
1002:                return error.toString();
1003:            }
1004:
1005:            /**
1006:             * This method will side affects the <code>_repCurItem</code> to insure that it
1007:             * is set to the next item in the iteration set.  It will return <code>true</code>
1008:             * if there is a next item, and <code>false</code> when we are done with the iteration
1009:             * @return returns <code>true</code> when <code>_repCurItem</code> contains the next item and
1010:             *         <code>false</code> when we are done.
1011:             * @throws JspException
1012:             */
1013:            private boolean doRepeaterAfterBody() throws JspException {
1014:                switch (_repCurStage.getValue()) {
1015:                case RepeatingStages.INT_BEFORE:
1016:                    if (!moveNext())
1017:                        return false;
1018:                    return doRepeaterAfterBody();
1019:                case RepeatingStages.INT_OPTION:
1020:                    assert (_repeaterIterator instanceof  Iterator);
1021:                    while (_repeaterIterator.hasNext()) {
1022:                        _repCurItem = _repeaterIterator.next();
1023:                        if (_repCurItem != null) {
1024:                            _optionList.add(_repCurItem);
1025:                            return true;
1026:                        }
1027:                    }
1028:                    if (!moveNext())
1029:                        return false;
1030:                    return doRepeaterAfterBody();
1031:
1032:                case RepeatingStages.INT_DEFAULT:
1033:                case RepeatingStages.INT_DATASOURCE:
1034:                case RepeatingStages.INT_NULL:
1035:                    assert (_repeaterIterator instanceof  Iterator);
1036:                    while (_repeaterIterator.hasNext()) {
1037:                        _repCurItem = _repeaterIterator.next();
1038:                        if (!_optionList.contains(_repCurItem)) {
1039:                            _optionList.add(_repCurItem);
1040:                            return true;
1041:                        }
1042:                    }
1043:                    if (!moveNext())
1044:                        return false;
1045:                    return doRepeaterAfterBody();
1046:                }
1047:                return false;
1048:            }
1049:
1050:            /**
1051:             * This method will move to the next iteration type.  The order of the
1052:             * iteration is defined by the <code>_order</code> array.  The result
1053:             * is side affecting the _repeaterIterator by initializing it.  If there
1054:             * is nothing further, then we will return false, otherwise we return true.
1055:             * @return
1056:             * @throws JspException
1057:             */
1058:            private boolean moveNext() throws JspException {
1059:                // increment the current position, if we are beyond the end of the array return
1060:                _repIdx++;
1061:                if (_repIdx == _order.length)
1062:                    return false;
1063:
1064:                // Get the next stage and clear the _repeaterIterator
1065:                _repCurStage = _order[_repIdx];
1066:                _repeaterIterator = null;
1067:
1068:                // process each type of iteration...
1069:                // Each will recursively call moveNext, if that stage doesn't support iteration
1070:                switch (_repCurStage.getValue()) {
1071:                case RepeatingStages.INT_BEFORE:
1072:                    break;
1073:                case RepeatingStages.INT_OPTION:
1074:                    // This produces an error if the optionsDataSource is an instance of an iterator
1075:                    if (!(_dynamicOptions instanceof  Iterator)) {
1076:                        String s = Bundle
1077:                                .getString("Tags_OptionsDSIteratorError");
1078:                        registerTagError(s, null);
1079:                        return false;
1080:                    }
1081:
1082:                    assert (_dynamicOptions instanceof  Iterator);
1083:                    _repeaterIterator = (Iterator) _dynamicOptions;
1084:                    break;
1085:
1086:                case RepeatingStages.INT_DEFAULT:
1087:                    if (_defaultSelections != null)
1088:                        _repeaterIterator = _defaultSelections.iterator();
1089:                    break;
1090:                case RepeatingStages.INT_DATASOURCE:
1091:                    if (_match != null)
1092:                        _repeaterIterator = Arrays.asList(_match).iterator();
1093:                    break;
1094:                case RepeatingStages.INT_NULL:
1095:                    if (_nullable)
1096:                        _repeaterIterator = new ArrayIterator(NULL_INSTANCE);
1097:                    break;
1098:                }
1099:
1100:                // return true when we set the iterator, otherwise move to the next stage.
1101:                return (_repeaterIterator != null) ? true : moveNext();
1102:            }
1103:
1104:            /**
1105:             * This method builds the list of selected items so that they can be marked as selected.
1106:             * @param val The <code>dataSource</code>
1107:             */
1108:            private void buildMatch(Object val) {
1109:                // create the match data
1110:                if (val != null) {
1111:                    if (val instanceof  String) {
1112:                        _match = new String[] { (String) val };
1113:                    } else if (val instanceof  String[]) {
1114:                        String[] s = (String[]) val;
1115:                        int cnt = 0;
1116:                        for (int i = 0; i < s.length; i++) {
1117:                            if (s[i] != null)
1118:                                cnt++;
1119:                        }
1120:                        if (cnt == s.length)
1121:                            _match = s;
1122:                        else {
1123:                            if (cnt > 0) {
1124:                                _match = new String[cnt];
1125:                                cnt = 0;
1126:                                for (int i = 0; i < s.length; i++) {
1127:                                    if (s[i] != null) {
1128:                                        _match[cnt++] = s[i];
1129:                                    }
1130:                                }
1131:                            }
1132:                        }
1133:                    } else {
1134:                        Iterator matchIterator = null;
1135:                        // val is never null so this would be an error
1136:                        matchIterator = IteratorFactory.createIterator(val);
1137:                        if (matchIterator == null) {
1138:                            matchIterator = IteratorFactory.EMPTY_ITERATOR;
1139:                        }
1140:
1141:                        ArrayList matchList = new ArrayList();
1142:                        while (matchIterator.hasNext()) {
1143:                            Object o = matchIterator.next();
1144:                            if (o == null)
1145:                                continue;
1146:                            matchList.add(o);
1147:                        }
1148:
1149:                        int size = matchList.size();
1150:                        _match = new String[size];
1151:                        for (int i = 0; i < size; i++) {
1152:                            assert (matchList.get(i) != null);
1153:                            assert (matchList.get(i).toString() != null);
1154:                            _match[i] = matchList.get(i).toString();
1155:                        }
1156:                    }
1157:                    if (logger.isDebugEnabled()) {
1158:                        logger.debug("****** Select Matches ******");
1159:                        if (_match != null) {
1160:                            for (int i = 0; i < _match.length; i++) {
1161:                                logger.debug(i + ": " + _match[i]);
1162:                            }
1163:                        }
1164:                    }
1165:                } else {
1166:                    if (_nullable
1167:                            && !isMultiple()
1168:                            && (_defaultSelections == null || _defaultSelections
1169:                                    .size() == 0)) {
1170:                        _match = new String[] { NULL_VALUE };
1171:                    }
1172:                }
1173:            }
1174:
1175:            // add the default values specified in the tag if they are needed.
1176:            private void addDefaultsIfNeeded(ServletRequest req)
1177:                    throws JspException {
1178:                if (_defaultSelections != null) {
1179:                    Iterator iterator = _defaultSelections.iterator();
1180:                    while (iterator.hasNext()) {
1181:                        Object selection = iterator.next();
1182:                        if (!_optionList.contains(selection)) {
1183:                            addOption(req, selection.toString(), selection
1184:                                    .toString());
1185:                        }
1186:                    }
1187:                }
1188:            }
1189:
1190:            private boolean isMultiple() {
1191:                return _state.multiple;
1192:            }
1193:
1194:            // add dthe datasource values if needed.
1195:            private void addDatasourceIfNeeded(ServletRequest req)
1196:                    throws JspException {
1197:                if (_match == null)
1198:                    return;
1199:
1200:                for (int i = 0; i < _match.length; i++) {
1201:                    if (!_optionList.contains(_match[i])) {
1202:                        if (!_match[i].equals(NULL_VALUE))
1203:                            addOption(req, _match[i], _match[i]);
1204:                    }
1205:                }
1206:            }
1207:
1208:            private void addOption(ServletRequest req, String optionValue,
1209:                    String optionDisplay) throws JspException {
1210:                assert (optionValue != null);
1211:                assert (optionDisplay != null);
1212:
1213:                write("\n");
1214:                _optionState.clear();
1215:                _optionState.value = optionValue;
1216:                _optionState.style = _state.style;
1217:                _optionState.styleClass = _state.styleClass;
1218:
1219:                if (isMatched(optionValue)) {
1220:                    _optionState.selected = true;
1221:                }
1222:
1223:                WriteRenderAppender writer = new WriteRenderAppender(
1224:                        pageContext);
1225:                if (_optRb == null)
1226:                    _optRb = TagRenderingBase.Factory.getRendering(
1227:                            TagRenderingBase.OPTION_TAG, req);
1228:                _optRb.doStartTag(writer, _optionState);
1229:
1230:                if (optionDisplay != null) {
1231:                    write(formatText(optionDisplay));
1232:                } else {
1233:                    write("&lt;");
1234:                    write(optionValue);
1235:                    write(">");
1236:                }
1237:
1238:                _optRb.doEndTag(writer);
1239:
1240:                addOptionToList(optionValue);
1241:            }
1242:
1243:            /**
1244:             * Adds a FormatTag.Formatter to the Select's set of formatters
1245:             * @param formatter a FormatTag.Formatter added by a child FormatTag.
1246:             */
1247:            public void addFormatter(FormatTag.Formatter formatter) {
1248:                _formatters.add(formatter);
1249:            }
1250:
1251:            /**
1252:             * Indicate that a formatter has reported an error so the formatter should output it's
1253:             * body text.
1254:             */
1255:            public void formatterHasError() {
1256:                _formatterError = true;
1257:            }
1258:
1259:            /**
1260:             */
1261:            public void addOptionToList(String value) {
1262:                _optionList.add(value);
1263:            }
1264:
1265:            /**
1266:             * Apply the Select's set of formatters to the given text
1267:             * @param text the text to format.
1268:             * @return the formatted text
1269:             */
1270:            public String formatText(Object text) throws JspException {
1271:                int cnt = _formatters.size();
1272:                for (int i = 0; i < cnt; i++) {
1273:                    FormatTag.Formatter currentFormatter = (FormatTag.Formatter) _formatters
1274:                            .get(i);
1275:                    try {
1276:                        text = currentFormatter.format(text);
1277:                    } catch (JspException e) {
1278:                        registerTagError(e.getMessage(), e);
1279:                    }
1280:                }
1281:                return text.toString();
1282:            }
1283:
1284:            /* ==================================================================
1285:             *
1286:             * This tag's publically exposed HTML, CSS, and JavaScript attributes
1287:             *
1288:             * ==================================================================
1289:             */
1290:
1291:            /**
1292:             * Sets the accessKey attribute value.  This should key value of the
1293:             * keyboard navigation key.  It is recommended not to use the following
1294:             * values because there are often used by browsers <code>A, C, E, F, G,
1295:             * H, V, left arrow, and right arrow</code>.
1296:             * @param accessKey the accessKey value.
1297:             * @jsptagref.attributedescription The keyboard navigation key for the element.
1298:             * The following values are not recommended because they
1299:             * are often used by browsers: <code>A, C, E, F, G,
1300:             * H, V, left arrow, and right arrow</code>
1301:             * @jsptagref.databindable false
1302:             * @jsptagref.attributesyntaxvalue <i>string_accessKey</i>
1303:             * @netui:attribute required="false" rtexprvalue="true" type="char"
1304:             * description="The keyboard navigation key for the element.
1305:             * The following values are not recommended because they
1306:             * are often used by browsers: A, C, E, F, G,
1307:             * H, V, left arrow, and right arrow"
1308:             */
1309:            public void setAccessKey(char accessKey) {
1310:                _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
1311:                        ACCESSKEY, Character.toString(accessKey));
1312:            }
1313:
1314:            /**
1315:             * Sets the tabIndex of the rendered html tag.
1316:             * @param tabindex the tab index.
1317:             * @jsptagref.attributedescription The tabIndex of the rendered HTML tag.  This attribute determines the position of the
1318:             * tag in the sequence of page elements that the user may advance through by pressing the TAB key.
1319:             * @jsptagref.databindable false
1320:             * @jsptagref.attributesyntaxvalue <i>string_tabIndex</i>
1321:             * @netui:attribute required="false" rtexprvalue="true" type="int"
1322:             * description="The tabIndex of the rendered HTML tag.  This attribute determines the position of the
1323:             * tag in the sequence of page elements that the user may advance through by pressing the TAB key."
1324:             */
1325:            public void setTabindex(int tabindex) {
1326:                _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
1327:                        TABINDEX, Integer.toString(tabindex));
1328:            }
1329:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.