001: /*
002: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
003: *
004: * "The contents of this file are subject to the Mozilla Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License at
007: * http://www.mozilla.org/MPL/
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
011: * License for the specific language governing rights and limitations under
012: * the License.
013: *
014: * The Original Code is ICEfaces 1.5 open source software code, released
015: * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
016: * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
017: * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
018: *
019: * Contributor(s): _____________________.
020: *
021: * Alternatively, the contents of this file may be used under the terms of
022: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
023: * License), in which case the provisions of the LGPL License are
024: * applicable instead of those above. If you wish to allow use of your
025: * version of this file only under the terms of the LGPL License and not to
026: * allow others to use your version of this file under the MPL, indicate
027: * your decision by deleting the provisions above and replace them with
028: * the notice and other provisions required by the LGPL License. If you do
029: * not delete the provisions above, a recipient may use your version of
030: * this file under either the MPL or the LGPL License."
031: *
032: */
033:
034: package com.icesoft.faces.renderkit.dom_html_basic;
035:
036: import javax.faces.FacesException;
037: import javax.faces.component.UIComponent;
038: import javax.faces.context.ResponseWriter;
039: import java.io.IOException;
040: import java.util.ArrayList;
041: import java.util.Arrays;
042: import java.util.Iterator;
043: import java.util.List;
044: import java.util.Map;
045:
046: /**
047: * This class is used by ReponseWriter based renderers to render html
048: * pass thru attributes.
049: *
050: * @author gmccleary
051: */
052: public class PassThruAttributeWriter {
053:
054: private static List passThruAttributeNames = new ArrayList();
055: private static List booleanPassThruAttributeNames = new ArrayList();
056:
057: static {
058: passThruAttributeNames.add("accept");
059: passThruAttributeNames.add("accesskey");
060: passThruAttributeNames.add("alt");
061: passThruAttributeNames.add("bgcolor");
062: passThruAttributeNames.add("border");
063: passThruAttributeNames.add("cellpadding");
064: passThruAttributeNames.add("cellspacing");
065: passThruAttributeNames.add("charset");
066: passThruAttributeNames.add("cols");
067: passThruAttributeNames.add("coords");
068: passThruAttributeNames.add("dir");
069: passThruAttributeNames.add("enctype");
070: passThruAttributeNames.add("frame");
071: passThruAttributeNames.add("height");
072: passThruAttributeNames.add("hreflang");
073: passThruAttributeNames.add("lang");
074: passThruAttributeNames.add("longdesc");
075: passThruAttributeNames.add("maxlength");
076: passThruAttributeNames.add("onblur");
077: passThruAttributeNames.add("onchange");
078: passThruAttributeNames.add("onclick");
079: passThruAttributeNames.add("ondblclick");
080: passThruAttributeNames.add("onfocus");
081: passThruAttributeNames.add("onkeydown");
082: passThruAttributeNames.add("onkeypress");
083: passThruAttributeNames.add("onkeyup");
084: passThruAttributeNames.add("onload");
085: passThruAttributeNames.add("onmousedown");
086: passThruAttributeNames.add("onmousemove");
087: passThruAttributeNames.add("onmouseout");
088: passThruAttributeNames.add("onmouseover");
089: passThruAttributeNames.add("onmouseup");
090: passThruAttributeNames.add("onreset");
091: passThruAttributeNames.add("onselect");
092: passThruAttributeNames.add("onsubmit");
093: passThruAttributeNames.add("onunload");
094: passThruAttributeNames.add("rel");
095: passThruAttributeNames.add("rev");
096: passThruAttributeNames.add("rows");
097: passThruAttributeNames.add("rules");
098: passThruAttributeNames.add("shape");
099: passThruAttributeNames.add("size");
100: passThruAttributeNames.add("style");
101: passThruAttributeNames.add("summary");
102: passThruAttributeNames.add("tabindex");
103: passThruAttributeNames.add("target");
104: passThruAttributeNames.add("title");
105: passThruAttributeNames.add("usemap");
106: passThruAttributeNames.add("width");
107: passThruAttributeNames.add("width");
108: passThruAttributeNames.add("onclickeffect");
109: passThruAttributeNames.add("ondblclickeffect");
110: passThruAttributeNames.add("onmousedowneffect");
111: passThruAttributeNames.add("onmouseupeffect");
112: passThruAttributeNames.add("onmousemoveeffect");
113: passThruAttributeNames.add("onmouseovereffect");
114: passThruAttributeNames.add("onmouseouteffect");
115: passThruAttributeNames.add("onchangeeffect");
116: passThruAttributeNames.add("onreseteffect");
117: passThruAttributeNames.add("onsubmiteffect");
118: passThruAttributeNames.add("onkeypresseffect");
119: passThruAttributeNames.add("onkeydowneffect");
120: passThruAttributeNames.add("onkeyupeffect");
121: passThruAttributeNames.add("autocomplete");
122:
123: booleanPassThruAttributeNames.add("disabled");
124: booleanPassThruAttributeNames.add("readonly");
125: booleanPassThruAttributeNames.add("ismap");
126: }
127:
128: /**
129: * Write pass thru attributes associated with the UIComponent parameter. The
130: * excludedAttributes argument is a String array of the names of attributes
131: * to omit. Do not render attributes contained in the excludedAttributes
132: * argument.
133: *
134: * @param writer
135: * @param uiComponent
136: * @param excludedAttributes attributes to exclude
137: * @throws IOException
138: */
139: public static void renderAttributes(ResponseWriter writer,
140: UIComponent uiComponent, String[] excludedAttributes)
141: throws IOException {
142: renderNonBooleanAttributes(writer, uiComponent,
143: excludedAttributes);
144: renderBooleanAttributes(writer, uiComponent, excludedAttributes);
145: }
146:
147: /**
148: * ToDo: Render the icefaces onfocus handler to the root element. This
149: * should be restricted to input type elements and commandlinks.
150: *
151: * @param writer
152: * @throws IOException
153: */
154: public static void renderOnFocus(ResponseWriter writer)
155: throws IOException {
156: writer.writeAttribute("onfocus", "setFocus(this.id);",
157: "onfocus");
158: }
159:
160: /**
161: * ToDo: Render the icefaces onblur handler to the root element. This should
162: * be restricted to input type elements and commandlinks.
163: *
164: * @param writer
165: * @throws IOException
166: */
167: public static void renderOnBlur(ResponseWriter writer)
168: throws IOException {
169: writer.writeAttribute("onfocus", "setFocus('');", "onfocus");
170: }
171:
172: private static void renderBooleanAttributes(ResponseWriter writer,
173: UIComponent uiComponent, String[] excludedAttributes)
174: throws IOException {
175:
176: if (writer == null) {
177: throw new FacesException("Null pointer exception");
178: }
179: if (uiComponent == null) {
180: throw new FacesException("Null pointer exception");
181: }
182:
183: List excludedAttributesList = null;
184: if (excludedAttributes != null && excludedAttributes.length > 0)
185: excludedAttributesList = Arrays.asList(excludedAttributes);
186:
187: Object nextPassThruAttributeName;
188: Object nextPassThruAttributeValue = null;
189: Iterator passThruNameIterator = booleanPassThruAttributeNames
190: .iterator();
191: boolean primitiveAttributeValue;
192:
193: while (passThruNameIterator.hasNext()) {
194: nextPassThruAttributeName = (passThruNameIterator.next());
195: if (excludedAttributesList != null) {
196: if (excludedAttributesList
197: .contains(nextPassThruAttributeName))
198: continue;
199: }
200: nextPassThruAttributeValue = uiComponent.getAttributes()
201: .get(nextPassThruAttributeName);
202: if (nextPassThruAttributeValue != null) {
203: if (nextPassThruAttributeValue instanceof Boolean) {
204: primitiveAttributeValue = ((Boolean) nextPassThruAttributeValue)
205: .booleanValue();
206: } else {
207: if (!(nextPassThruAttributeValue instanceof String)) {
208: nextPassThruAttributeValue = nextPassThruAttributeValue
209: .toString();
210: }
211: primitiveAttributeValue = (new Boolean(
212: (String) nextPassThruAttributeValue))
213: .booleanValue();
214: }
215: if (primitiveAttributeValue) {
216: writer.writeAttribute(nextPassThruAttributeName
217: .toString(), nextPassThruAttributeValue,
218: nextPassThruAttributeName.toString());
219: }
220:
221: }
222: }
223: }
224:
225: private static void renderNonBooleanAttributes(
226: ResponseWriter writer, UIComponent uiComponent,
227: String[] excludedAttributes)
228:
229: throws IOException {
230: if (writer == null) {
231: throw new FacesException("Null pointer exception");
232: }
233:
234: if (uiComponent == null) {
235: throw new FacesException("Component instance is null");
236: }
237:
238: List excludedAttributesList = null;
239: if (excludedAttributes != null && excludedAttributes.length > 0)
240: excludedAttributesList = Arrays.asList(excludedAttributes);
241:
242: Object nextPassThruAttributeName = null;
243: Object nextPassThruAttributeValue = null;
244: Iterator passThruNameIterator = passThruAttributeNames
245: .iterator();
246: while (passThruNameIterator.hasNext()) {
247: nextPassThruAttributeName = (passThruNameIterator.next());
248: if (excludedAttributesList != null) {
249: if (excludedAttributesList
250: .contains(nextPassThruAttributeName))
251: continue;
252: }
253: nextPassThruAttributeValue = uiComponent.getAttributes()
254: .get(nextPassThruAttributeName);
255: // Only render non-null attributes.
256: // Some components have attribute values
257: // set to the Wrapper classes' minimum value - don't render
258: // an attribute with this sentinel value.
259: if (nextPassThruAttributeValue != null
260: && !attributeValueIsSentinel(nextPassThruAttributeValue)) {
261: writer.writeAttribute(nextPassThruAttributeName
262: .toString(), nextPassThruAttributeValue,
263: nextPassThruAttributeValue.toString());
264: }
265: }
266: }
267:
268: /**
269: * Determine whether any of the attributes defined for the UIComponent
270: * instance are pass thru attributes.
271: *
272: * @param uiComponent
273: * @return true if the UIComponent parameter has one or more attributes
274: * defined that are pass thru attributes
275: */
276: public static boolean passThruAttributeExists(
277: UIComponent uiComponent) {
278: if (uiComponent == null) {
279: return false;
280: }
281: Map componentAttributes = uiComponent.getAttributes();
282: if (componentAttributes.size() <= 0) {
283: return false;
284: }
285: if (componentAttributesIncludePassThruAttribute(
286: componentAttributes, passThruAttributeNames)) {
287: return true;
288: }
289: if (componentAttributesIncludePassThruAttribute(
290: componentAttributes, booleanPassThruAttributeNames)) {
291: return true;
292: }
293: return false;
294: }
295:
296: private static boolean attributeValueIsSentinel(Object value) {
297: if (value == null) {
298: return false;
299: }
300: if (value instanceof Boolean) {
301: if (((Boolean) value).booleanValue() == false) {
302: return true;
303: }
304: return false;
305: }
306: if (value instanceof Number) {
307: if (value instanceof Integer) {
308: if (((Integer) value).intValue() == Integer.MIN_VALUE) {
309: return true;
310: }
311: return false;
312: }
313: if (value instanceof Long) {
314: if (((Long) value).longValue() == Long.MIN_VALUE) {
315: return true;
316: }
317: return false;
318: }
319: if (value instanceof Short) {
320: if (((Short) value).shortValue() == Short.MIN_VALUE) {
321: return true;
322: }
323: return false;
324: }
325: if (value instanceof Float) {
326: if (((Float) value).floatValue() == Float.MIN_VALUE) {
327: return true;
328: }
329: return false;
330: }
331: if (value instanceof Double) {
332: if (((Double) value).doubleValue() == Double.MIN_VALUE) {
333: return true;
334: }
335: return false;
336: }
337: if (value instanceof Byte) {
338: if (((Byte) value).byteValue() == Byte.MIN_VALUE) {
339: return true;
340: }
341: return false;
342: }
343: }
344: if (value instanceof Character) {
345: if (((Character) value).charValue() == Character.MIN_VALUE) {
346: return true;
347: }
348: return false;
349: }
350: return false;
351: }
352:
353: private static boolean componentAttributesIncludePassThruAttribute(
354: Map componentAttributes, List passThru) {
355: Object componentAttributeKey;
356: Object componentAttributeValue;
357: Iterator attributeKeys = componentAttributes.keySet()
358: .iterator();
359: while (attributeKeys.hasNext()) {
360: componentAttributeKey = attributeKeys.next();
361: if (passThru.contains(componentAttributeKey)) {
362: componentAttributeValue = componentAttributes
363: .get(componentAttributeKey);
364: if ((componentAttributeValue != null)
365: && (componentAttributeValue != "")) {
366: return true;
367: }
368: }
369: }
370: return false;
371: }
372:
373: static final List getpassThruAttributeNames() {
374: return passThruAttributeNames;
375: }
376: }
|