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.renderer;
042:
043: import com.sun.rave.web.ui.component.Form;
044: import com.sun.rave.web.ui.model.Markup;
045: import com.sun.rave.web.ui.model.ScriptMarkup;
046: import com.sun.rave.web.ui.util.LogUtil;
047: import com.sun.rave.web.ui.util.RenderingUtilities;
048:
049: import java.io.IOException;
050: import java.util.List;
051: import java.util.Map;
052: import javax.faces.component.NamingContainer;
053: import javax.faces.component.UIComponent;
054: import javax.faces.component.UINamingContainer;
055: import javax.faces.context.FacesContext;
056: import javax.faces.context.ResponseWriter;
057:
058: /**
059: * <p>Renderer for a {@link Form} component.</p>
060: */
061:
062: public class FormRenderer extends AbstractRenderer {
063:
064: // ======================================================== Static Variables
065:
066: /**
067: * <p>The set of String pass-through attributes to be rendered.</p>
068: */
069: private static final String stringAttributes[] = { "enctype",
070: "accessKey", "onReset", "onSubmit", "target" }; //NOI18N
071:
072: private static final String SUBMISSION_COMPONENT_HIDDEN_FIELD = "_submissionComponentId"; //NOI18N
073: private static final String FORM_HIDDEN_FIELD = "_hidden"; //NOI18N
074:
075: // -------------------------------------------------------- Renderer Methods
076:
077: /**
078: * <p>Record a flag indicating whether this was the form (of the several
079: * forms on the current page) that was submitted. Also, if the submission
080: * component id is known, then set the submitted virtual form if
081: * appropriate.</p>
082: *
083: * @param context <code>FacesContext</code> for the current request
084: * @param component <code>UIComponent</code> to be decoded
085: *
086: * @exception NullPointerException if <code>context</code> or
087: * <code>component</code> is <code>null</code>
088: */
089: public void decode(FacesContext context, UIComponent component) {
090:
091: if ((context == null) || (component == null)) {
092: throw new NullPointerException();
093: }
094:
095: Form form = (Form) component;
096: Map map = context.getExternalContext().getRequestParameterMap();
097: boolean b = map.containsKey(form.getClientId(context)
098: + FORM_HIDDEN_FIELD);
099: form.setSubmitted(b);
100: if (LogUtil.fineEnabled()) {
101: LogUtil.fine("Form(id=" + form.getId() + ",submitted="
102: + form.isSubmitted() + ")");
103: }
104:
105: String hiddenFieldClientId = SUBMISSION_COMPONENT_HIDDEN_FIELD;
106: String submissionComponentId = (String) map
107: .get(hiddenFieldClientId);
108: if (submissionComponentId != null) {
109: Form.VirtualFormDescriptor vfd = form
110: .getVirtualFormComponentSubmits(submissionComponentId);
111: if (vfd != null) {
112: form.setSubmittedVirtualForm(vfd);
113: }
114: }
115:
116: }
117:
118: /**
119: * <p>Render the appropriate element start for the outermost
120: * element.</p>
121: *
122: * @param context <code>FacesContext</code> for the current request
123: * @param component <code>EditableValueHolder</code> component whose
124: * submitted value is to be stored
125: * @param writer <code>ResponseWriter</code> to which the element
126: * start should be rendered
127: *
128: * @exception IOException if an input/output error occurs
129: */
130: protected void renderStart(FacesContext context,
131: UIComponent component, ResponseWriter writer)
132: throws IOException {
133:
134: // Start the appropriate element
135: Form form = (Form) component;
136: if (LogUtil.fineEnabled()) {
137: LogUtil.fine("Form(id=" + form.getId() + ")"); //NOI18N
138: }
139: writer.startElement("form", form); //NOI18N
140:
141: //reapply any submitted values erased by the virtual forms mechanism
142: form.restoreNonParticipatingSubmittedValues();
143: }
144:
145: /**
146: * <p>Render the appropriate element attributes.</p>
147: *
148: * @param context <code>FacesContext</code> for the current request
149: * @param component <code>EditableValueHolder</code> component whose
150: * submitted value is to be stored
151: * @param writer <code>ResponseWriter</code> to which the element
152: * start should be rendered
153: *
154: * @exception IOException if an input/output error occurs
155: */
156: protected void renderAttributes(FacesContext context,
157: UIComponent component, ResponseWriter writer)
158: throws IOException {
159:
160: Form form = (Form) component;
161:
162: // Render the core attributes for the "form" element
163: addCoreAttributes(context, form, writer, "form"); //NOI18N
164: writer.writeAttribute("method", "post", null); //NOI18N
165: writer.writeAttribute("action", action(context), null); //NOI18N
166: addStringAttributes(context, form, writer, EVENTS_ATTRIBUTES);
167: addStringAttributes(context, form, writer, stringAttributes);
168:
169: if (!form.isAutoComplete()) {
170: //only render it if it's false
171: writer.writeAttribute("autocomplete", "off", null); // NOI18N
172: }
173: // Render a newline for pretty printing
174: writer.write("\n"); //NOI18N
175:
176: }
177:
178: /**
179: * <p>Render the appropriate element end.</p>
180: *
181: * @param context <code>FacesContext</code> for the current request
182: * @param component <code>EditableValueHolder</code> component whose
183: * submitted value is to be stored
184: * @param writer <code>ResponseWriter</code> to which the element
185: * start should be rendered
186: *
187: * @exception IOException if an input/output error occurs
188: */
189: protected void renderEnd(FacesContext context,
190: UIComponent component, ResponseWriter writer)
191: throws IOException {
192:
193: Form form = (Form) component;
194: List list = null;
195: int n = 0;
196:
197: writer.write("\n"); //NOI18N
198: // Render the hidden field noting this form as being submitted
199: RenderingUtilities.renderHiddenField(component, writer, form
200: .getClientId(context)
201: + FORM_HIDDEN_FIELD, form.getClientId(context)
202: + FORM_HIDDEN_FIELD);
203:
204: writer.write("\n"); //NOI18N
205: context.getApplication().getViewHandler().writeState(context);
206: writer.write("\n"); //NOI18N
207: // Render the end of the form element
208: writer.endElement("form"); //NOI18N
209: writer.write("\n"); //NOI18N
210:
211: if (LogUtil.finestEnabled()) {
212: LogUtil.finest(" Rendering completed"); //NOI18N
213: }
214: }
215:
216: // --------------------------------------------------------- Private Methods
217:
218: /**
219: * <p>Return the URI to which this form should be submitted.</p>
220: *
221: * @param context <code>FacesContext</code> for the current request
222: */
223: private String action(FacesContext context) {
224:
225: String viewId = context.getViewRoot().getViewId();
226: String url = context.getApplication().getViewHandler()
227: .getActionURL(context, viewId);
228: return context.getExternalContext().encodeActionURL(url);
229:
230: }
231:
232: /**
233: * <p>Return the name of a JavaScript function that will be called
234: * by the specified event handler.</p>
235: *
236: * @param context <code>FacesContext</code> for the current request
237: * @param form {@link Form} being rendered
238: * @param handler Name of the event handler that will call
239: */
240: private String function(FacesContext context, Form form,
241: String handler) {
242:
243: String clientId = form.getClientId(context);
244: return handler + "_" + clientId.replace(':', '_'); //NOI18N
245:
246: }
247:
248: /**
249: * <p>Create and return the markup for the specified event handler.</p>
250: *
251: * @param context <code>FacesContext</code> for the current request
252: * @param form {@link Form} being rendered
253: * @param name Name of the event handler to be rendered
254: * @param list List of code elements to be included
255: */
256: private Markup handler(FacesContext context, Form form,
257: String name, List list) {
258:
259: String code = null;
260: Markup markup = new ScriptMarkup();
261: markup.writeRaw("function " + //NOI18N
262: function(context, form, name) + //NOI18N
263: "(form) {\n", null); //NOI18N
264: code = (String) form.getAttributes().get(name);
265: if (code != null) {
266: markup.writeRaw(" ", null); //NOI18N
267: markup.writeRaw(code, null);
268: if (!code.endsWith(";")) { //NOI18N
269: markup.writeRaw(";", null); //NOI18N
270: }
271: markup.writeRaw("\n", null); //NOI18N
272: }
273: for (int i = 0; i < list.size(); i++) {
274: code = ((String) list.get(i)).trim();
275: markup.writeRaw(" ", null); //NOI18N
276: markup.writeRaw(code, null);
277: if (!code.endsWith(";")) {
278: markup.writeRaw(";", null); //NOI18N
279: }
280: markup.writeRaw("\n", null); //NOI18N
281: }
282: markup.writeRaw(" return true;\n", null); //NOI18N
283: markup.writeRaw("}\n", null); //NOI18N
284: return markup;
285:
286: }
287: }
|