Source Code Cross Referenced for Form.java in  » IDE-Netbeans » visualweb.api.designer » com » sun » rave » web » ui » component » 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.component 
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.component;
0042:
0043:        import java.io.Serializable;
0044:        import java.util.List;
0045:        import java.util.ArrayList;
0046:        import java.util.Iterator;
0047:        import java.util.StringTokenizer;
0048:        import javax.faces.component.EditableValueHolder;
0049:        import javax.faces.component.NamingContainer;
0050:        import javax.faces.component.UIComponent;
0051:        import javax.faces.component.UIData;
0052:        import javax.faces.context.FacesContext;
0053:        import javax.faces.event.FacesEvent;
0054:        import javax.faces.event.ActionEvent;
0055:        import com.sun.data.provider.RowKey;
0056:        import java.util.Map;
0057:        import java.util.HashMap;
0058:        import java.util.Collections;
0059:        import java.util.Set;
0060:        import java.util.HashSet;
0061:        import java.util.Collection;
0062:        import java.util.Arrays;
0063:        import com.sun.rave.web.ui.util.MessageUtil;
0064:
0065:        /**
0066:         * <p>Component that represents an input form.</p>
0067:         */
0068:
0069:        public class Form extends FormBase {
0070:            private VirtualFormDescriptor submittedVirtualForm; //the virtual form that was submitted
0071:            private static final String VF_DELIM_1 = ","; //NOI18N
0072:            private static final String VF_DELIM_2 = "|"; //NOI18N
0073:            private static final String ID_SEP = String
0074:                    .valueOf(NamingContainer.SEPARATOR_CHAR);
0075:            public static final char ID_WILD_CHAR = '*';
0076:            private static final String ID_WILD = String.valueOf(ID_WILD_CHAR);
0077:            private transient Map erasedMap = new HashMap(); //has an EditableValueHolder as the key, and an Object[] value pair or a TableValues as the value
0078:            private transient Set nonDefaultRetainStatusEvhs = new HashSet(); //contains EditableValueHolders with a retain status different from the default
0079:            private static final boolean DEFAULT_RETAIN_STATUS = true; //default for whether non-participating submitted values are retained
0080:
0081:            /**
0082:             * <p>Override <code>UIForm.processDecodes(FacesContext)</code> to ensure
0083:             *	    correct virtual form processing.</p>
0084:             *
0085:             * @param context <code>FacesContext</code> for the current request
0086:             *
0087:             * @exception NullPointerException Thrown when <code>context</code> is null
0088:             */
0089:            public void processDecodes(FacesContext context) {
0090:                if (context == null) {
0091:                    throw new NullPointerException();
0092:                }
0093:
0094:                submittedVirtualForm = null;
0095:                erasedMap.clear();
0096:                //clearing out nonDefaultRetainStatusEvhs occurs in restoreNonParticipatingSubmittedValues
0097:                //(which is called during renderering)
0098:                //so that application code can muck with the retain statuses in preprocess
0099:
0100:                // Process this component itself
0101:                decode(context); //may set submittedVirtualForm
0102:
0103:                // if we're not the submitted form, don't process children.
0104:                if (!isSubmitted()) {
0105:                    return;
0106:                }
0107:
0108:                // Process all facets and children of this component
0109:                Iterator kids = getFacetsAndChildren();
0110:                while (kids.hasNext()) {
0111:                    UIComponent kid = (UIComponent) kids.next();
0112:                    kid.processDecodes(context);
0113:                }
0114:
0115:                if (submittedVirtualForm != null) {
0116:                    //if the children of the Form are known to participate in submittedVirtualForm,
0117:                    //then don't bother erasing
0118:                    if (!childrenAreKnownToParticipate(this ,
0119:                            submittedVirtualForm)) {
0120:                        eraseVirtualFormNonParticipants(this , null, null);
0121:                    }
0122:                }
0123:            }
0124:
0125:            public void queueEvent(FacesEvent event) {
0126:                FacesEvent relevantEvent = event;
0127:                if (event instanceof  WrapperEvent) {
0128:                    WrapperEvent wrapperEvent = (WrapperEvent) event;
0129:                    relevantEvent = wrapperEvent.getFacesEvent();
0130:                }
0131:                if (relevantEvent instanceof  ActionEvent
0132:                        && submittedVirtualForm == null) {
0133:                    UIComponent sourceComp = relevantEvent.getComponent();
0134:                    VirtualFormDescriptor virtualFormComponentSubmits = getVirtualFormComponentSubmits(sourceComp);
0135:                    if (virtualFormComponentSubmits != null) { //if the source component does in fact submit a virtual form
0136:                        submittedVirtualForm = virtualFormComponentSubmits; //then set that virtual form as having been submitted
0137:                    }
0138:                }
0139:                super .queueEvent(event);
0140:            }
0141:
0142:            public void setSubmittedVirtualForm(VirtualFormDescriptor vfd) {
0143:                if (submittedVirtualForm == null && vfd != null) {
0144:                    submittedVirtualForm = vfd;
0145:                }
0146:            }
0147:
0148:            public void setVirtualForms(VirtualFormDescriptor[] vfds) {
0149:                setVirtualForms(vfds, true);
0150:            }
0151:
0152:            private void setVirtualForms(VirtualFormDescriptor[] vfds,
0153:                    boolean sync) {
0154:                super .setVirtualForms(vfds);
0155:                if (sync) {
0156:                    String configStr = generateVirtualFormsConfig(vfds);
0157:                    setVirtualFormsConfig(configStr, false);
0158:                }
0159:            }
0160:
0161:            public void setVirtualFormsConfig(String configStr) {
0162:                setVirtualFormsConfig(configStr, true);
0163:            }
0164:
0165:            private void setVirtualFormsConfig(String configStr, boolean sync) {
0166:                super .setVirtualFormsConfig(configStr);
0167:                if (sync) {
0168:                    VirtualFormDescriptor[] vfds = generateVirtualForms(configStr);
0169:                    setVirtualForms(vfds, false);
0170:                }
0171:            }
0172:
0173:            private VirtualFormDescriptor getVirtualFormComponentSubmitsByFullyQualifiedId(
0174:                    String fqId) {
0175:                if (!isValidFullyQualifiedId(fqId)) {
0176:                    return null;
0177:                }
0178:
0179:                //first try regular configuration
0180:                VirtualFormDescriptor vfd = getVirtualFormComponentSubmitsByFullyQualifiedId(
0181:                        fqId, getVirtualForms());
0182:                if (vfd != null) {
0183:                    return vfd;
0184:                }
0185:
0186:                //try internal configuration
0187:                vfd = getVirtualFormComponentSubmitsByFullyQualifiedId(fqId,
0188:                        getInternalVirtualForms());
0189:                return vfd;
0190:            }
0191:
0192:            private VirtualFormDescriptor getVirtualFormComponentSubmitsByFullyQualifiedId(
0193:                    String fqId, VirtualFormDescriptor[] vfds) {
0194:                if (vfds == null || vfds.length < 1) {
0195:                    return null;
0196:                }
0197:
0198:                //look for matches of fqId against all of vfds's submitters--without any trailing wilds.
0199:                //if no match found, try the parent fqId.
0200:                //this technique ensures that the most appropriate submitter is found first and its vf is returned
0201:                String currentFqId = fqId;
0202:                while (currentFqId.length() > 0) {
0203:                    for (int v = 0; v < vfds.length; v++) {
0204:                        VirtualFormDescriptor vfd = vfds[v];
0205:                        String[] submitters = vfd.getSubmittingIds();
0206:                        for (int s = 0; submitters != null
0207:                                && s < submitters.length; s++) {
0208:                            String submitter = submitters[s];
0209:                            if (submitter == null)
0210:                                continue;
0211:                            String wildSuffix = ID_SEP + ID_WILD;
0212:                            if (submitter.endsWith(wildSuffix)) {
0213:                                submitter = submitter.substring(0, submitter
0214:                                        .length()
0215:                                        - wildSuffix.length());
0216:                            }
0217:                            if (submitter.length() < 1)
0218:                                continue;
0219:                            boolean fqIdMatches = fullyQualifiedIdMatchesPattern(
0220:                                    currentFqId, submitter);
0221:                            if (fqIdMatches) {
0222:                                return vfd;
0223:                            }
0224:                        }
0225:                    }
0226:                    int lastIndexOfSep = currentFqId.lastIndexOf(ID_SEP);
0227:                    currentFqId = currentFqId.substring(0, lastIndexOfSep);
0228:                }
0229:
0230:                return null;
0231:            }
0232:
0233:            private int getVirtualFormCount() {
0234:                VirtualFormDescriptor[] vfds = getVirtualForms();
0235:                VirtualFormDescriptor[] ivfds = getInternalVirtualForms();
0236:                return (vfds == null ? 0 : vfds.length)
0237:                        + (ivfds == null ? 0 : ivfds.length);
0238:            }
0239:
0240:            private VirtualFormDescriptor getVirtualFormComponentSubmits(
0241:                    UIComponent component) {
0242:                if (getVirtualFormCount() < 1) {
0243:                    return null;
0244:                }
0245:                String fqId = getFullyQualifiedId(component);
0246:                VirtualFormDescriptor vfd = getVirtualFormComponentSubmitsByFullyQualifiedId(fqId);
0247:                return vfd;
0248:            }
0249:
0250:            /** Get the virtual form submitted by the component whose id is provided or null if the component does not submit a virtual form. */
0251:            public VirtualFormDescriptor getVirtualFormComponentSubmits(
0252:                    String id) {
0253:                if (getVirtualFormCount() < 1) {
0254:                    return null;
0255:                }
0256:                if (isValidFullyQualifiedId(id)) {
0257:                    return getVirtualFormComponentSubmitsByFullyQualifiedId(id);
0258:                }
0259:                UIComponent component = findComponentById(id);
0260:                return getVirtualFormComponentSubmits(component);
0261:            }
0262:
0263:            //this method is public for designer's use
0264:            /**
0265:             * Given a bare, partially qualified, or fully qualified id, find the component.
0266:             * Unlike the inherited <code>findComponent</code> method, this method does recursively 
0267:             * search NamingContainers.
0268:             */
0269:            public UIComponent findComponentById(String id) {
0270:                if (id == null) {
0271:                    return null;
0272:                }
0273:                if (id.length() == 0 || id.endsWith(ID_WILD)
0274:                        || (!id.equals(ID_SEP) && id.endsWith(ID_SEP))) {
0275:                    return null;
0276:                }
0277:                //see if id indicates the Form itself
0278:                String fqId = getFullyQualifiedId(this );
0279:                if (fullyQualifiedIdMatchesPattern(fqId, id)) {
0280:                    return this ;
0281:                }
0282:                return searchKidsRecursivelyForId(this , id);
0283:            }
0284:
0285:            private UIComponent searchKidsRecursivelyForId(UIComponent parent,
0286:                    String id) {
0287:                Iterator kids = parent.getFacetsAndChildren();
0288:                while (kids.hasNext()) {
0289:                    UIComponent kid = (UIComponent) kids.next();
0290:                    String fqId = getFullyQualifiedId(kid);
0291:                    //see if id indicates kid
0292:                    boolean fqIdMatches = fullyQualifiedIdMatchesPattern(fqId,
0293:                            id);
0294:                    if (fqIdMatches) {
0295:                        return kid;
0296:                    }
0297:                    UIComponent match = searchKidsRecursivelyForId(kid, id);
0298:                    if (match != null) {
0299:                        return match;
0300:                    }
0301:                }
0302:                return null;
0303:            }
0304:
0305:            //return true if a virtual form has been submitted and this component participates in that virtual form
0306:            private boolean participatesInSubmittedVirtualForm(
0307:                    UIComponent component) {
0308:                if (submittedVirtualForm == null) {
0309:                    return false;
0310:                }
0311:                String fqId = getFullyQualifiedId(component);
0312:                return submittedVirtualForm.hasParticipant(fqId);
0313:            }
0314:
0315:            /**
0316:             * <p>Generate an 
0317:             * array of <code>VirtualFormDescriptor</code>s based on a virtual form 
0318:             * configuration <code>String</code>.</p>
0319:             */
0320:            /*
0321:             * Be sure to keep this method in sync with the version in 
0322:             * <code>javax.faces.component.html.HtmlFormDesignInfo</code> 
0323:             * (in jsfcl).</p>
0324:             */
0325:            public static VirtualFormDescriptor[] generateVirtualForms(
0326:                    String configStr) {
0327:                //formname1|pid1 pid2 pid3|sid1 sid2 sid3, formname2|pid4 pid5 pid6|sid4 sid5 sid6
0328:                if (configStr == null) {
0329:                    return null;
0330:                }
0331:                configStr = configStr.trim();
0332:                if (configStr.length() < 1) {
0333:                    return new VirtualFormDescriptor[0];
0334:                }
0335:                //configStr now can't be null, blank, or just ws
0336:
0337:                StringTokenizer st = new StringTokenizer(configStr, VF_DELIM_1);
0338:                List vfs = new ArrayList(); //list of marshalled vfs
0339:                while (st.hasMoreTokens()) {
0340:                    String vf = st.nextToken(); //not null, but could be just whitespace or blank
0341:                    vf = vf.trim();
0342:                    //vf could be a blank string
0343:                    if (vf.length() > 0) {
0344:                        vfs.add(vf);
0345:                    }
0346:                }
0347:
0348:                List descriptors = new ArrayList(); //a list of VirtualFormDescriptors
0349:                for (int i = 0; i < vfs.size(); i++) { //go through each marshalled vf
0350:                    String vf = (String) vfs.get(i); //get the marshalled vf. not mere ws, blank, or null.
0351:                    st = new StringTokenizer(vf, VF_DELIM_2);
0352:                    String[] parts = new String[3]; //part1 is vf name, part2 is participating ids, part3 is submitting ids
0353:                    int partIndex = 0;
0354:                    while (partIndex < parts.length && st.hasMoreTokens()) {
0355:                        String part = st.nextToken(); //not null, but could be whitespace or blank
0356:                        part = part.trim(); //now can't be whitespace, but could be blank
0357:                        if (part.length() > 0) {
0358:                            //part is not null, whitespace, or blank
0359:                            parts[partIndex] = part;
0360:                        }
0361:                        partIndex++;
0362:                    }
0363:
0364:                    VirtualFormDescriptor vfd;
0365:                    if (parts[0] != null) {
0366:                        vfd = new VirtualFormDescriptor();
0367:                        vfd.setName(parts[0]); //won't be null, blank, or just ws
0368:                        descriptors.add(vfd);
0369:                    } else {
0370:                        continue; //this marshalled vf has no name. can't create a descriptor for it. go to next marshalled vf
0371:                    }
0372:
0373:                    if (parts[1] != null) {
0374:                        String pidString = parts[1]; //not null, blank, or just ws
0375:                        st = new StringTokenizer(pidString);
0376:                        List pidList = new ArrayList();
0377:                        while (st.hasMoreTokens()) {
0378:                            String pid = st.nextToken();
0379:                            pidList.add(pid.trim());
0380:                        }
0381:                        String[] pids = (String[]) pidList
0382:                                .toArray(new String[pidList.size()]); //size guaranteed to be at least 1
0383:                        vfd.setParticipatingIds(pids);
0384:                    }
0385:
0386:                    if (parts[2] != null) {
0387:                        String sidString = parts[2]; //not null, blank, or just ws
0388:                        st = new StringTokenizer(sidString);
0389:                        List sidList = new ArrayList();
0390:                        while (st.hasMoreTokens()) {
0391:                            String sid = st.nextToken();
0392:                            sidList.add(sid.trim());
0393:                        }
0394:                        String[] sids = (String[]) sidList
0395:                                .toArray(new String[sidList.size()]); //size guaranteed to be at least 1
0396:                        vfd.setSubmittingIds(sids);
0397:                    }
0398:                }
0399:                return (VirtualFormDescriptor[]) descriptors
0400:                        .toArray(new VirtualFormDescriptor[descriptors.size()]); //might be of size 0, but won't be null
0401:            }
0402:
0403:            /**
0404:             * <p>Generate a virtual form 
0405:             * configuration <code>String</code> based on an 
0406:             * array of <code>VirtualFormDescriptor</code>s.</p>
0407:             */
0408:            /*
0409:             * Be sure to keep this method in sync with the version in 
0410:             * <code>javax.faces.component.html.HtmlFormDesignInfo</code> 
0411:             * (in jsfcl).</p>
0412:             */
0413:            public static String generateVirtualFormsConfig(
0414:                    VirtualFormDescriptor[] descriptors) {
0415:                if (descriptors == null) {
0416:                    return null;
0417:                }
0418:                StringBuffer sb = new StringBuffer();
0419:                for (int i = 0; i < descriptors.length; i++) {
0420:                    if (descriptors[i] != null) {
0421:                        String vf = descriptors[i].toString();
0422:                        if (vf.length() > 0) {
0423:                            if (sb.length() > 0) {
0424:                                sb.append(" , ");
0425:                            }
0426:                            sb.append(vf);
0427:                        }
0428:                    }
0429:                }
0430:                return sb.toString();
0431:            }
0432:
0433:            /**
0434:             * Obtain the virtual form compatible fully-qualified id for the supplied component.
0435:             * A fully-qualified id begins with the <code>NamingContainer.SEPARATOR_CHAR</code>
0436:             * (representing the <code>Form</code> itself), contains component ids of the
0437:             * component's ancestors separated by <code>NamingContainer.SEPARATOR_CHAR</code>,
0438:             * and ends with the component's id.
0439:             */
0440:            /*
0441:             * Be sure to keep this method in sync with the versions in 
0442:             * <code>javax.faces.component.html.HtmlFormDesignInfo</code> 
0443:             * (in jsfcl) and 
0444:             * <code>com.sun.rave.web.ui.component.FormDesignInfo</code> 
0445:             * (in webui).</p>
0446:             */
0447:            public static String getFullyQualifiedId(UIComponent component) {
0448:                if (component == null) {
0449:                    return null;
0450:                }
0451:                if (component instanceof  Form) {
0452:                    return ID_SEP;
0453:                }
0454:                String compId = component.getId();
0455:                if (compId == null) {
0456:                    return null;
0457:                }
0458:                StringBuffer sb = new StringBuffer(compId);
0459:                UIComponent currentComp = component.getParent();
0460:                boolean formEncountered = false;
0461:                while (currentComp != null) {
0462:                    sb.insert(0, ID_SEP);
0463:                    if (currentComp instanceof  Form) {
0464:                        formEncountered = true;
0465:                        break;
0466:                    } else {
0467:                        String currentCompId = currentComp.getId();
0468:                        if (currentCompId == null) {
0469:                            return null;
0470:                        }
0471:                        sb.insert(0, currentCompId);
0472:                    }
0473:                    currentComp = currentComp.getParent();
0474:                }
0475:                if (formEncountered) {
0476:                    return sb.toString();
0477:                } else {
0478:                    return null;
0479:                }
0480:            }
0481:
0482:            /** 
0483:             * Determine if the id provided is non-null and exhibits the traits of a 
0484:             * fully qualified id. This includes beginning with 
0485:             * <code>NamingContainer.SEPARATOR_CHAR</code>, not ending with that
0486:             * character unless it is the only character, not ending in 
0487:             * <code>Form.ID_WILD_CHAR</code>, and not containing spaces.
0488:             */
0489:            /*
0490:             * Be sure to keep this method in sync with the version in 
0491:             * <code>javax.faces.component.html.HtmlFormDesignInfo</code> 
0492:             * (in jsfcl).</p>
0493:             */
0494:            public static boolean isValidFullyQualifiedId(String id) {
0495:                return id != null && id.startsWith(ID_SEP)
0496:                        && (id.length() == 1 || !id.endsWith(ID_SEP))
0497:                        && !id.endsWith(ID_WILD) && id.indexOf(' ') == -1;
0498:            }
0499:
0500:            /**
0501:             * Determine if the fully qualified id provided matches the supplied pattern.
0502:             * The pattern may be a bare, partially qualified, or fully qualified id.
0503:             * The pattern may also end with the 
0504:             * <code>NamingContainer.SEPARATOR_CHAR</code> followed by the 
0505:             * <code>Form.ID_WILD_CHAR</code>, in which case the children of the component
0506:             * indicated by the pattern will be considered a match.
0507:             */
0508:            /*
0509:             * Be sure to keep this method in sync with the version in 
0510:             * <code>javax.faces.component.html.HtmlFormDesignInfo</code> 
0511:             * (in jsfcl).</p>
0512:             */
0513:            public static boolean fullyQualifiedIdMatchesPattern(String fqId,
0514:                    String pattern) {
0515:                if (!isValidFullyQualifiedId(fqId)) {
0516:                    return false;
0517:                }
0518:                if (pattern == null || pattern.length() < 1
0519:                        || pattern.indexOf(' ') != -1) {
0520:                    return false;
0521:                }
0522:                //unless pattern is ":", it should not end with ":"
0523:                if (pattern.endsWith(ID_SEP) && !pattern.equals(ID_SEP)) {
0524:                    return false;
0525:                }
0526:
0527:                String wildSuffix = ID_SEP + ID_WILD;
0528:
0529:                //if ID_WILD appears in pattern, it must be the last character, and preceded by ID_SEP
0530:                int indexOfWildInPattern = pattern.indexOf(ID_WILD);
0531:                if (indexOfWildInPattern != -1) {
0532:                    if (indexOfWildInPattern != pattern.length() - 1) {
0533:                        return false;
0534:                    }
0535:                    if (!pattern.endsWith(wildSuffix)) {
0536:                        return false;
0537:                    }
0538:                }
0539:
0540:                if (pattern.equals(wildSuffix)) {
0541:                    //if pattern was ":*", then any valid fqId is a match
0542:                    return true;
0543:                } else if (pattern.endsWith(wildSuffix)) {
0544:                    String patternPrefix = pattern.substring(0, pattern
0545:                            .length()
0546:                            - wildSuffix.length());
0547:                    if (patternPrefix.startsWith(ID_SEP)) {
0548:                        return fqId.equals(patternPrefix)
0549:                                || fqId.startsWith(patternPrefix + ID_SEP);
0550:                    } else {
0551:                        return fqId.endsWith(ID_SEP + patternPrefix)
0552:                                || fqId
0553:                                        .indexOf(ID_SEP + patternPrefix
0554:                                                + ID_SEP) > -1;
0555:                    }
0556:                } else {
0557:                    if (pattern.startsWith(ID_SEP)) {
0558:                        return fqId.equals(pattern);
0559:                    } else {
0560:                        return fqId.endsWith(ID_SEP + pattern);
0561:                    }
0562:                }
0563:            }
0564:
0565:            /**
0566:             * Add a <code>VirtualFormDescriptor</code> to the internal virtual forms.
0567:             * If an existing VirtualFormDescriptor object is found with the same name,
0568:             * the object is replaced.
0569:             *
0570:             * @param descriptor The <code>VirtualFormDescriptor</code> to add.
0571:             */
0572:            public void addInternalVirtualForm(VirtualFormDescriptor descriptor) {
0573:                if (descriptor == null) {
0574:                    return;
0575:                }
0576:
0577:                // Get current descriptors.
0578:                VirtualFormDescriptor[] oldDescriptors = getInternalVirtualForms();
0579:
0580:                // Iterate over each VirtualFormDescriptor object and check for a match.
0581:                if (oldDescriptors != null) {
0582:                    for (int i = 0; i < oldDescriptors.length; i++) {
0583:                        if (oldDescriptors[i] == null) {
0584:                            continue;
0585:                        }
0586:                        String name = oldDescriptors[i].getName();
0587:                        if (name != null && name.equals(descriptor.getName())) {
0588:                            oldDescriptors[i] = descriptor;
0589:                            return; // No further processing is required.
0590:                        }
0591:                    }
0592:                }
0593:
0594:                // Create array to hold new descriptors.
0595:                int oldLength = (oldDescriptors != null) ? oldDescriptors.length
0596:                        : 0;
0597:                VirtualFormDescriptor[] newDescriptors = new VirtualFormDescriptor[oldLength + 1];
0598:                for (int i = 0; i < oldLength; i++) {
0599:                    newDescriptors[i] = oldDescriptors[i];
0600:                }
0601:
0602:                // Add new VirtualFormDescriptor object.
0603:                newDescriptors[oldLength] = descriptor;
0604:                setInternalVirtualForms(newDescriptors);
0605:            }
0606:
0607:            /*
0608:             * Be sure to keep this class in sync with the version in 
0609:             * <code>javax.faces.component.html.HtmlFormDesignInfo</code> 
0610:             * (in jsfcl).</p>
0611:             */
0612:            public static class VirtualFormDescriptor implements  Serializable {
0613:                private String name; //name of the virtual form
0614:                private String[] participatingIds; //ids of components that participate
0615:                private String[] submittingIds; //ids of components that submit
0616:
0617:                public VirtualFormDescriptor() {
0618:                }
0619:
0620:                public VirtualFormDescriptor(String name) {
0621:                    setName(name);
0622:                }
0623:
0624:                public String getName() {
0625:                    return name;
0626:                }
0627:
0628:                public void setName(String name) {
0629:                    if (name == null) {
0630:                        throw new IllegalArgumentException(getMessage(
0631:                                "nullVfName", null) //NOI18N
0632:                        );
0633:                    }
0634:                    name = name.trim();
0635:                    if (name.length() < 1) {
0636:                        throw new IllegalArgumentException(getMessage(
0637:                                "vfNameWhitespaceOnly", null) //NOI18N
0638:                        );
0639:                    }
0640:                    this .name = name;
0641:                }
0642:
0643:                public String[] getParticipatingIds() {
0644:                    return participatingIds;
0645:                }
0646:
0647:                public void setParticipatingIds(
0648:                        java.lang.String[] participatingIds) {
0649:                    for (int i = 0; participatingIds != null
0650:                            && i < participatingIds.length; i++) {
0651:                        if (participatingIds[i] == null) {
0652:                            throw new IllegalArgumentException(getMessage(
0653:                                    "nullParticipatingIdAtIndex",
0654:                                    new Object[] { new Integer(i) }) //NOI18N
0655:                            );
0656:                        }
0657:                        participatingIds[i] = participatingIds[i].trim();
0658:                        if (participatingIds[i].length() < 1) {
0659:                            throw new IllegalArgumentException(getMessage(
0660:                                    "whitespaceOnlyParticipatingIdAtIndex",
0661:                                    new Object[] { new Integer(i) }) //NOI18N
0662:                            );
0663:                        }
0664:                    }
0665:                    this .participatingIds = participatingIds;
0666:                }
0667:
0668:                public String[] getSubmittingIds() {
0669:                    return submittingIds;
0670:                }
0671:
0672:                public void setSubmittingIds(java.lang.String[] submittingIds) {
0673:                    for (int i = 0; submittingIds != null
0674:                            && i < submittingIds.length; i++) {
0675:                        if (submittingIds[i] == null) {
0676:                            throw new IllegalArgumentException(getMessage(
0677:                                    "nullSubmittingIdAtIndex",
0678:                                    new Object[] { new Integer(i) }) //NOI18N
0679:                            );
0680:                        }
0681:                        submittingIds[i] = submittingIds[i].trim();
0682:                        if (submittingIds[i].length() < 1) {
0683:                            throw new IllegalArgumentException(getMessage(
0684:                                    "whitespaceOnlySubmittingIdAtIndex",
0685:                                    new Object[] { new Integer(i) }) //NOI18N
0686:                            );
0687:                        }
0688:                    }
0689:                    this .submittingIds = submittingIds;
0690:                }
0691:
0692:                //return true if the component id provided submits this virtual form
0693:                public boolean isSubmittedBy(String fqId) {
0694:                    if (!isValidFullyQualifiedId(fqId))
0695:                        return false;
0696:                    for (int i = 0; submittingIds != null
0697:                            && i < submittingIds.length; i++) {
0698:                        if (Form.fullyQualifiedIdMatchesPattern(fqId,
0699:                                submittingIds[i])) {
0700:                            return true;
0701:                        }
0702:                    }
0703:                    return false;
0704:                }
0705:
0706:                //return true if the component id provided participates in this virtual form
0707:                public boolean hasParticipant(String fqId) {
0708:                    if (!isValidFullyQualifiedId(fqId))
0709:                        return false;
0710:                    for (int i = 0; participatingIds != null
0711:                            && i < participatingIds.length; i++) {
0712:                        if (Form.fullyQualifiedIdMatchesPattern(fqId,
0713:                                participatingIds[i])) {
0714:                            return true;
0715:                        }
0716:                    }
0717:                    return false;
0718:                }
0719:
0720:                public String toString() {
0721:                    if (name == null) {
0722:                        return "";
0723:                    } //NOI18N
0724:                    StringBuffer sb = new StringBuffer();
0725:                    sb.append(name);
0726:                    sb.append(" | "); //NOI18N
0727:                    for (int i = 0; participatingIds != null
0728:                            && i < participatingIds.length; i++) {
0729:                        sb.append(participatingIds[i]);
0730:                        sb.append(' ');
0731:                    }
0732:                    sb.append("| "); //NOI18N
0733:                    for (int i = 0; submittingIds != null
0734:                            && i < submittingIds.length; i++) {
0735:                        sb.append(submittingIds[i]);
0736:                        sb.append(' ');
0737:                    }
0738:                    return sb.toString().trim();
0739:                }
0740:            }
0741:
0742:            //Examine the participating ids that end in ID_WILD. If any of them match
0743:            //the component's fully qualified id, then the component's children are known
0744:            //to participate in vfd.
0745:            private static boolean childrenAreKnownToParticipate(
0746:                    UIComponent component, VirtualFormDescriptor vfd) {
0747:                if (vfd == null) {
0748:                    return false;
0749:                }
0750:
0751:                String fqId = getFullyQualifiedId(component);
0752:                if (fqId == null) {
0753:                    return false;
0754:                }
0755:
0756:                String[] participants = vfd.getParticipatingIds();
0757:                for (int i = 0; participants != null && i < participants.length; i++) {
0758:                    String participant = participants[i];
0759:                    String wildSuffix = ID_SEP + ID_WILD;
0760:                    if (participant == null
0761:                            || !participant.endsWith(wildSuffix)) {
0762:                        continue;
0763:                    }
0764:                    if (fullyQualifiedIdMatchesPattern(fqId, participant)) {
0765:                        return true;
0766:                    }
0767:                }
0768:
0769:                return false;
0770:            }
0771:
0772:            /**
0773:             * <p>Recursively erase virtual form non-participants by setting their 
0774:             * submitted values to <code>null</code>. This method caches the submitted 
0775:             * values in the <code>erasedMap</code> before actually erasing.
0776:             * If the <code>parent</code> is embedded in one or more tables, 
0777:             * the <code>contextualTables</code> and <code>contextualRows</code>
0778:             * are used to record the table- and row-based context of the 
0779:             * submitted value, so that such context can be stored in the 
0780:             * <code>erasedMap</code>.</p>
0781:             * <p><b>Note:</b> Restoring of submitted values works for 
0782:             * the braveheart table but not the standard jsf table. However, submitted 
0783:             * values inside a standard jsf table are still cached and an attempt is 
0784:             * made to restore them, in case a third-party component extends 
0785:             * <code>UIData</code> and, unlike <code>UIData</code>, does not discard 
0786:             * its saved state during rendering.</p>
0787:             * @param parent A parent component whose children will be examined and 
0788:             * possibly erased
0789:             * @param contextualTables an array of UIData or TableRowGroup components 
0790:             * in the parent's ancestry (with the most distant ancestor as the first 
0791:             * member of the array), or <code>null</code> if the parent is not embedded
0792:             * within any tables
0793:             * @param contextualRows a parallel array of <code>Integer</code> or 
0794:             * <code>RowKey</code> objects representing a row in the corresponding 
0795:             * contextual table, or <code>null</code> if the parent is not embedded
0796:             * within any tables
0797:             */
0798:            private void eraseVirtualFormNonParticipants(UIComponent parent,
0799:                    Object[] contextualTables, Object[] contextualRows) {
0800:                // Process all facets and children of this component
0801:                synchronized (erasedMap) { //prevent multiple threads from the same session simultaneously accessing erasedMap, nonDefaultRetainStatusEvhs
0802:                    Iterator kids = parent.getFacetsAndChildren();
0803:                    while (kids.hasNext()) {
0804:                        UIComponent kid = (UIComponent) kids.next();
0805:
0806:                        //if this kid is an EditableValueHolder, and it does not participate, set submitted value to null
0807:                        if (kid instanceof  EditableValueHolder
0808:                                && !participatesInSubmittedVirtualForm(kid)) {
0809:                            EditableValueHolder kidEvh = (EditableValueHolder) kid;
0810:                            //cache the submitted value to be erased in eraseMap
0811:                            Object submittedValueToErase = kidEvh
0812:                                    .getSubmittedValue();
0813:                            if (contextualTables == null) {
0814:                                erasedMap.put(kidEvh, submittedValueToErase);
0815:                            } else {
0816:                                addTableValuesEntry(erasedMap, kidEvh, 0,
0817:                                        contextualTables, contextualRows,
0818:                                        submittedValueToErase);
0819:                            }
0820:                            kidEvh.setSubmittedValue(null);
0821:                        }
0822:
0823:                        //if children of kid are known to participate in submittedVirtualForm,
0824:                        //then no need to recurse on kid
0825:                        if (childrenAreKnownToParticipate(kid,
0826:                                submittedVirtualForm)) {
0827:                            continue; //continue to next kid
0828:                        }
0829:
0830:                        //recurse. if kid is a UIData or TableRowGroup, perform a recursive call once per row.
0831:                        //if kid is not a UIData or TableRowGroup, simply perform a recursive call once.
0832:                        if (kid instanceof  UIData) {
0833:                            UIData kidTable = (UIData) kid;
0834:                            int originalRowIndex = kidTable.getRowIndex();
0835:                            int rowIndex = 0;
0836:                            kidTable.setRowIndex(rowIndex);
0837:                            while (kidTable.isRowAvailable()) {
0838:                                Object[] localContextualTables = appendToArray(
0839:                                        contextualTables, kidTable);
0840:                                Object[] localContextualRows = appendToArray(
0841:                                        contextualRows, new Integer(rowIndex));
0842:                                eraseVirtualFormNonParticipants(kidTable,
0843:                                        localContextualTables,
0844:                                        localContextualRows);
0845:                                kidTable.setRowIndex(++rowIndex);
0846:                            }
0847:                            kidTable.setRowIndex(originalRowIndex);
0848:                        } else if (kid instanceof  TableRowGroup) {
0849:                            TableRowGroup group = (TableRowGroup) kid;
0850:                            RowKey[] rowKeys = group.getRowKeys();
0851:                            RowKey oldRowKey = group.getRowKey(); // Save RowKey.
0852:
0853:                            // Check for null TableDataProvider.
0854:                            if (rowKeys != null) {
0855:                                for (int i = 0; i < rowKeys.length; i++) {
0856:                                    group.setRowKey(rowKeys[i]);
0857:                                    if (!group.isRowAvailable()) {
0858:                                        continue;
0859:                                    }
0860:                                    Object[] localContextualTables = appendToArray(
0861:                                            contextualTables, group);
0862:                                    Object[] localContextualRows = appendToArray(
0863:                                            contextualRows, rowKeys[i]);
0864:                                    eraseVirtualFormNonParticipants(group,
0865:                                            localContextualTables,
0866:                                            localContextualRows);
0867:                                }
0868:                            }
0869:                            group.setRowKey(oldRowKey); // Restore RowKey.
0870:                        } else {
0871:                            eraseVirtualFormNonParticipants(kid,
0872:                                    contextualTables, contextualRows);
0873:                        }
0874:                    }
0875:                }
0876:            }
0877:
0878:            /** <p>Recursively add an entry to <code>erasedMap</code>, whose value is a 
0879:             * <code>TableValues</code> (and whose key is an 
0880:             * <code>EditableValueHolder</code>).</p>
0881:             */
0882:            private void addTableValuesEntry(Map map, Object mapKey, int c,
0883:                    Object[] contextualTables, Object[] contextualRows,
0884:                    Object submittedValueToErase) {
0885:                //use the map and mapKey to get a TableValues, using contextualTables[c] to create tsv if necessary
0886:                TableValues tv = (TableValues) map.get(mapKey);
0887:                if (tv == null) {
0888:                    tv = new TableValues(contextualTables[c]);
0889:                    map.put(mapKey, tv);
0890:                }
0891:
0892:                //ensure an entry is populated in tv.values with contextualRows[c] as the key
0893:                Map values = tv.getValues();
0894:                if (c == contextualTables.length - 1) { //if last index in contextualTables
0895:                    values.put(contextualRows[c], submittedValueToErase);
0896:                } else {
0897:                    addTableValuesEntry(values, contextualRows[c], c + 1,
0898:                            contextualTables, contextualRows,
0899:                            submittedValueToErase);
0900:                }
0901:            }
0902:
0903:            private static Object[] appendToArray(Object[] array, Object item) {
0904:                Object[] result;
0905:                if (array == null) {
0906:                    result = new Object[] { item };
0907:                } else {
0908:                    result = new Object[array.length + 1];
0909:                    System.arraycopy(array, 0, result, 0, array.length);
0910:                    result[array.length] = item;
0911:                }
0912:                return result;
0913:            }
0914:
0915:            /** 
0916:             * <p>Restore the submitted values erased by the virtual form mechanism 
0917:             * where appropriate.
0918:             * This method is called in <code>FormRenderer.renderStart</code>. It should
0919:             * not be called by developer code.</p>
0920:             * <p><b>Note:</b> Restoring of submitted values works on 
0921:             * <code>TableRowGroup</code> components, but does not work on the 
0922:             * standard faces data table component. This is because in 
0923:             * <code>UIData.encodeBegin</code>, the table's per-row saved state is 
0924:             * typically discarded. The result is that upon
0925:             * exiting <code>FormRenderer.renderStart</code>, the submitted values will 
0926:             * be restored; however, they will subsequently be discarded.
0927:             * Nonetheless, we still cache and restore those submitted values, in case
0928:             * a third-party component extends 
0929:             * <code>UIData</code> and, unlike <code>UIData</code>, does not discard 
0930:             * its saved state during rendering.</p>
0931:             */
0932:            public void restoreNonParticipatingSubmittedValues() {
0933:                synchronized (erasedMap) { //prevent multiple threads from the same session simultaneously accessing erasedMap, nonDefaultRetainStatusEvhs
0934:                    for (Iterator iter = erasedMap.entrySet().iterator(); iter
0935:                            .hasNext();) {
0936:                        Map.Entry entry = (Map.Entry) iter.next();
0937:                        EditableValueHolder evh = (EditableValueHolder) entry
0938:                                .getKey();
0939:                        //if evh is designated as discarding submitted values, do not restore
0940:                        //if DEFAULT_RETAIN_STATUS==true (retain by default), then nonDefaultRetainStatusEvhs contains evhs that discard
0941:                        //if DEFAULT_RETAIN_STATUS==false (discard by default), then nonDefaultRetainStatusEvhs contains evhs that retain
0942:                        boolean evhAppearsInSet = nonDefaultRetainStatusEvhs
0943:                                .contains(evh);
0944:                        boolean discards = DEFAULT_RETAIN_STATUS ? evhAppearsInSet
0945:                                : !evhAppearsInSet;
0946:                        if (discards) {
0947:                            continue;
0948:                        }
0949:                        //restore
0950:                        Object erasedMapValue = entry.getValue();
0951:                        if (erasedMapValue instanceof  TableValues) {
0952:                            TableValues tv = (TableValues) erasedMapValue;
0953:                            restoreTableValues(tv, evh);
0954:                        } else {
0955:                            evh.setSubmittedValue(erasedMapValue);
0956:                        }
0957:                    }
0958:                    nonDefaultRetainStatusEvhs.clear(); //after restoring, clear out the retain status data
0959:                }
0960:            }
0961:
0962:            /** 
0963:             *  <p>Helper method to restore submitted values for an
0964:             *  <code>EditableValueHolder</code> component from a 
0965:             *  <code>TableValues</code> object, which contains a value for 
0966:             *  each row of each table in the <code>EditableValueHolder</code>'s
0967:             *  ancestry.</p>
0968:             */
0969:            private void restoreTableValues(TableValues tv,
0970:                    EditableValueHolder evh) {
0971:                //capture the old row of the tv and
0972:                //iterate through the tv rows
0973:                Object oldRow; //an Integer or RowKey
0974:                Iterator rowIterator;
0975:                Object table = tv.getTable();
0976:                Map values = tv.getValues();
0977:                if (table instanceof  UIData) {
0978:                    //capture the old row
0979:                    UIData uidata = (UIData) table;
0980:                    int iOldRow = uidata.getRowIndex();
0981:                    oldRow = new Integer(iOldRow);
0982:
0983:                    //get rowIterator
0984:                    List rowList = new ArrayList();
0985:                    rowList.addAll(values.keySet()); //add Set of Integers to List
0986:                    Collections.sort(rowList);
0987:                    rowIterator = rowList.iterator();
0988:                } else {
0989:                    //capture the old row
0990:                    TableRowGroup rowGroup = (TableRowGroup) table;
0991:                    oldRow = rowGroup.getRowKey();
0992:
0993:                    //get rowIterator
0994:                    rowIterator = values.keySet().iterator();
0995:                }
0996:
0997:                while (rowIterator.hasNext()) {
0998:                    Object row = rowIterator.next(); //row is an Integer or RowKey
0999:
1000:                    //set the table to that row
1001:                    if (table instanceof  UIData) {
1002:                        UIData uidata = (UIData) table;
1003:                        Integer rowInt = (Integer) row;
1004:                        int iRow = rowInt.intValue();
1005:                        uidata.setRowIndex(iRow);
1006:                    } else {
1007:                        TableRowGroup rowGroup = (TableRowGroup) table;
1008:                        RowKey rowKey = (RowKey) row;
1009:                        rowGroup.setRowKey(rowKey);
1010:                    }
1011:
1012:                    //get the rowValue for that row, which can be an Object or a TableValues
1013:                    //and restore that rowValue
1014:                    Object rowValue = values.get(row);
1015:                    if (rowValue instanceof  TableValues) {
1016:                        TableValues rowValueTv = (TableValues) rowValue;
1017:                        restoreTableValues(rowValueTv, evh);
1018:                    } else {
1019:                        evh.setSubmittedValue(rowValue);
1020:                    }
1021:                }
1022:
1023:                //set table back to old row
1024:                if (table instanceof  UIData) {
1025:                    UIData uidata = (UIData) table;
1026:                    Integer oldRowInt = (Integer) oldRow;
1027:                    int iOldRow = oldRowInt.intValue();
1028:                    uidata.setRowIndex(iOldRow);
1029:                } else {
1030:                    TableRowGroup rowGroup = (TableRowGroup) table;
1031:                    RowKey oldRowKey = (RowKey) oldRow;
1032:                    rowGroup.setRowKey(oldRowKey);
1033:                }
1034:            }
1035:
1036:            /** <p>Structure that stores a component's submitted value
1037:             * for each row of a table (<code>UIData</code> or 
1038:             * <code>TableRowGroup</code>), either as an 
1039:             * <code>Object</code> or as a 
1040:             * nested <code>TableValues</code>. This permits storing of all the 
1041:             * submitted values for a component in the case where that component has 
1042:             * more than one table in its ancestry.</p>
1043:             */
1044:            private class TableValues {
1045:                private Object table; //store a UIData or TableRowGroup
1046:                private Map values; //has a RowKey or Integer as the key, and a submitted value Object or a TableValues as the value
1047:
1048:                public TableValues(Object table) {
1049:                    this .table = table;
1050:                    values = new HashMap();
1051:                }
1052:
1053:                /** <p>Get the <code>UIData</code> or <code>TableRowGroup</code> 
1054:                 *  for this instance.</p>
1055:                 */
1056:                public Object getTable() {
1057:                    return this .table;
1058:                }
1059:
1060:                /** <p>Get a <code>Map</code> of the values for each row 
1061:                 * of the table in question, where the key is an <code>Integer</code> or 
1062:                 * <code>RowKey</code>, and the value is a submitted value 
1063:                 * <code>Object</code> or a 
1064:                 * <code>TableValues</code> instance.</p>
1065:                 */
1066:                public Map getValues() {
1067:                    return this .values;
1068:                }
1069:            }
1070:
1071:            /**
1072:             * <p>Ensure that the supplied <code>EditableValueHolder</code> component 
1073:             * will discard (rather than retain) its submitted value when a virtual 
1074:             * form is submitted in which the component does not participate.</p>
1075:             * @param inputField An <code>EditableValueHolder</code> component that is 
1076:             * <strong>not</strong> a participant in the virtual form that was submitted
1077:             * on this request.
1078:             * @throws IllegalArgumentException if inputField is null.
1079:             * @throws IllegalArgumentException if a virtual form has been
1080:             * submitted and the supplied inputField participates in it.
1081:             */
1082:            public void discardSubmittedValue(EditableValueHolder inputField) {
1083:                if (inputField == null) {
1084:                    throw new IllegalArgumentException(getMessage(
1085:                            "nullInputField", null) //NOI18N
1086:                    );
1087:                }
1088:                if (inputField instanceof  UIComponent) { //just defensive
1089:                    UIComponent uicInputField = (UIComponent) inputField;
1090:                    if (participatesInSubmittedVirtualForm(uicInputField)) {
1091:                        throw new IllegalArgumentException(getMessage(
1092:                                "supplyNonParticipatingInputField",
1093:                                new Object[] { uicInputField.getId(),
1094:                                        "discardSubmittedValue" }) //NOI18N
1095:                        );
1096:
1097:                    }
1098:                }
1099:                List evhCollection = new ArrayList();
1100:                evhCollection.add(inputField);
1101:                setRetainWhenNonParticipating(evhCollection, false);
1102:            }
1103:
1104:            /**
1105:             * <p>Ensure that the participants in the supplied virtual form 
1106:             * will discard (rather than retain) their submitted values when a 
1107:             * different virtual form is submitted.</p>
1108:             * @param virtualFormName The name of a virtual form on this page which 
1109:             * has not been submitted.
1110:             * @throws IllegalArgumentException if no virtual form exists with the 
1111:             * supplied name.
1112:             * @throws IllegalArgumentException if the supplied virtual form has been 
1113:             * submitted on this request.
1114:             */
1115:            public void discardSubmittedValues(String virtualFormName) {
1116:                VirtualFormDescriptor vfd = getVirtualFormByName(virtualFormName);
1117:                if (vfd == null) {
1118:                    throw new IllegalArgumentException(getMessage(
1119:                            "unrecognizedVfName",
1120:                            new Object[] { virtualFormName }) //NOI18N
1121:                    );
1122:                }
1123:                if (vfd == submittedVirtualForm) {
1124:                    throw new IllegalArgumentException(
1125:                            getMessage("supplyUnsubmittedVirtualForm",
1126:                                    new Object[] { virtualFormName,
1127:                                            "discardSubmittedValues" }) //NOI18N
1128:                    );
1129:                }
1130:                setRetainWhenNonParticipating(vfd, false);
1131:            }
1132:
1133:            private void setRetainWhenNonParticipating(
1134:                    VirtualFormDescriptor vfd, boolean retain) {
1135:                String[] pids = vfd.getParticipatingIds();
1136:                if (pids == null || pids.length < 1) {
1137:                    return;
1138:                }
1139:                List evhList = new ArrayList();
1140:                for (int i = 0; i < pids.length; i++) {
1141:                    UIComponent uic = findComponentById(pids[i]);
1142:                    if (uic instanceof  EditableValueHolder) {
1143:                        evhList.add(uic);
1144:                    }
1145:                }
1146:                setRetainWhenNonParticipating(evhList, retain);
1147:            }
1148:
1149:            private void setRetainWhenNonParticipating(Collection evhs,
1150:                    boolean retain) {
1151:                if (evhs == null || evhs.size() < 1) {
1152:                    return;
1153:                }
1154:                synchronized (erasedMap) { //prevent multiple threads from the same session simultaneously accessing erasedMap, nonDefaultRetainStatusEvhs
1155:                    //if we retain by default, then nonDefaultRetainStatusEvhs should contain evhs only if we want evhs to discard
1156:                    //if we discard by default, then nonDefaultRetainStatusEvhs should contain evhs only if we want evhs to retain
1157:                    boolean shouldContain = DEFAULT_RETAIN_STATUS ? !retain
1158:                            : retain;
1159:                    if (shouldContain) {
1160:                        nonDefaultRetainStatusEvhs.addAll(evhs);
1161:                    } else {
1162:                        nonDefaultRetainStatusEvhs.removeAll(evhs);
1163:                    }
1164:                }
1165:            }
1166:
1167:            private VirtualFormDescriptor getVirtualFormByName(
1168:                    String virtualFormName) {
1169:                if (virtualFormName == null) {
1170:                    return null;
1171:                }
1172:                VirtualFormDescriptor[] vfds = getVirtualForms();
1173:                for (int i = 0; vfds != null && i < vfds.length; i++) {
1174:                    if (virtualFormName.equals(vfds[i].getName())) {
1175:                        return vfds[i];
1176:                    }
1177:                }
1178:                return null;
1179:            }
1180:
1181:            private static String getMessage(String key, Object[] args) {
1182:                String baseName = Form.class.getPackage().getName() + ".Bundle";
1183:                return MessageUtil.getMessage(
1184:                        FacesContext.getCurrentInstance(), baseName, key, args);
1185:            }
1186:
1187:            public String getEnctype() {
1188:                String encType = super .getEnctype();
1189:                if (encType == null || encType.length() == 0) {
1190:                    encType = "application/x-www-form-urlencoded"; //NOI18N
1191:                    super.setEnctype(encType);
1192:                }
1193:                return encType;
1194:            }
1195:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.