001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.util;
042:
043: import javax.faces.component.NamingContainer;
044: import javax.faces.component.UIComponent;
045: import javax.faces.component.UIViewRoot;
046: import javax.faces.context.FacesContext;
047:
048: import java.io.IOException;
049: import java.util.Collections;
050: import java.util.Iterator;
051: import java.util.List;
052:
053: /*
054: * Utilities for retrieving messages from FacesMessages
055: * TODO: Move to a superclass for Message and MessageGroup only
056: */
057:
058: public class FacesMessageUtils {
059:
060: /**
061: * Return a iterator that can be used to retrieve messages from
062: * FacesContext.
063: *
064: * @param context The FacesContext of the request
065: * @param forComponentId The component associated with the message(s)
066: * @param msgComponent The Message, MessageGroup component
067: *
068: * @return an Iterator over FacesMessages that are queued.
069: */
070: public static Iterator getMessageIterator(FacesContext context,
071: String forComponentId, UIComponent msgComponent) {
072:
073: Iterator messageIterator = null;
074:
075: // Return messages for the specified component
076: if (forComponentId != null) {
077: if (forComponentId.length() == 0) {
078: // Return global messages - not associated with any component.
079: messageIterator = context.getMessages(null);
080: } else {
081: // Get messages for the specified component only.
082: UIComponent forComponent = getForComponent(context,
083: forComponentId, msgComponent);
084: if (forComponent != null) {
085: String clientId = forComponent.getClientId(context);
086: messageIterator = context.getMessages(clientId);
087: } else {
088: messageIterator = Collections.EMPTY_LIST.iterator();
089: }
090: }
091: } else {
092: // No component specified return all messages.
093: messageIterator = context.getMessages();
094: }
095:
096: return messageIterator;
097: }
098:
099: /**
100: * Walk the component tree looking for the specified component.
101: *
102: * @param context The FacesContext of the request
103: * @param forComponentId The component to look for
104: * @param msgComponent The Message, MessageGroup component to start
105: * the search.
106: *
107: * @return the matching component, or null if no match is found.
108: */
109: private static UIComponent getForComponent(FacesContext context,
110: String forComponentId, UIComponent msgComponent) {
111:
112: if (forComponentId == null || forComponentId.length() == 0) {
113: return null;
114: }
115:
116: UIComponent forComponent = null;
117: UIComponent currentParent = msgComponent;
118: try {
119: // Check the naming container of the current
120: // component for the forComponent
121: while (currentParent != null) {
122: // If the current component is a NamingContainer,
123: // see if it contains what we're looking for.
124: forComponent = currentParent
125: .findComponent(forComponentId);
126: if (forComponent != null)
127: break;
128: // if not, start checking further up in the view
129: currentParent = currentParent.getParent();
130: }
131:
132: // no hit from above, scan for a NamingContainer
133: // that contains the component we're looking for from the root.
134: if (forComponent == null) {
135: forComponent = findUIComponentBelow(context
136: .getViewRoot(), forComponentId);
137: }
138: } catch (Throwable t) {
139: //TODO: fix.
140: throw new IllegalArgumentException(
141: "For component not found");
142: }
143:
144: if (forComponent == null) {
145: // Log a message.
146: }
147: return forComponent;
148: }
149:
150: /**
151: * Recursively searches for NamingContainers from the top of the tree
152: * looking for the specified component
153: *
154: * @param context The FacesContext of the request
155: * @param forComponentId the component to search for
156: *
157: * @return the matching component, or null if no match is found.
158: *
159: */
160: private static UIComponent findUIComponentBelow(
161: UIComponent startComponent, String forComponentId) {
162:
163: UIComponent forComponent = null;
164: List children = startComponent.getChildren();
165:
166: for (int i = 0, size = children.size(); i < size; i++) {
167: UIComponent comp = (UIComponent) children.get(i);
168:
169: if (comp instanceof NamingContainer) {
170: forComponent = comp.findComponent(forComponentId);
171: }
172:
173: if (forComponent == null) {
174: if (comp.getChildCount() > 0) {
175: forComponent = findUIComponentBelow(comp,
176: forComponentId);
177: }
178: }
179:
180: if (forComponent != null)
181: break;
182: }
183: return forComponent;
184: }
185: }
|