Author: nbelaevski
Date: 2010-01-03 18:33:55 -0500 (Sun, 03 Jan 2010)
New Revision: 16232
Added:
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/RenderKitUtils.java
Modified:
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/ComponentAttribute.java
Log:
https://jira.jboss.org/jira/browse/RF-8233
Modified:
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/ComponentAttribute.java
===================================================================
---
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/ComponentAttribute.java 2009-12-30
18:06:28 UTC (rev 16231)
+++
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/ComponentAttribute.java 2010-01-03
23:33:55 UTC (rev 16232)
@@ -1,4 +1,3 @@
-package org.richfaces.renderkit;
/*
* JBoss, Home of Professional Open Source
* Copyright 2009, Red Hat, Inc. and individual contributors
@@ -21,15 +20,22 @@
* 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
*/
+package org.richfaces.renderkit;
+
+import java.util.Map;
+import java.util.TreeMap;
+
/**
* @author Nick Belaevski
*/
-public class ComponentAttribute {
+public class ComponentAttribute implements Comparable<ComponentAttribute> {
private final String name;
private final String[] eventNames;
+ //TODO handling for aliases: "styleClass" -> "class"
+
public ComponentAttribute(String name) {
this(name, null);
}
@@ -40,6 +46,16 @@
this.eventNames = eventNames;
}
+ public static final Map<String, ComponentAttribute>
createMap(ComponentAttribute... attributes) {
+ Map<String,ComponentAttribute> result = new TreeMap<String,
ComponentAttribute>();
+
+ for (ComponentAttribute componentAttribute : attributes) {
+ result.put(componentAttribute.getName(), componentAttribute);
+ }
+
+ return result;
+ }
+
/**
* @return the name
*/
@@ -53,4 +69,8 @@
public String[] getEventNames() {
return eventNames;
}
+
+ public int compareTo(ComponentAttribute o) {
+ return getName().compareTo(o.getName());
+ }
}
Added:
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/RenderKitUtils.java
===================================================================
---
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/RenderKitUtils.java
(rev 0)
+++
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/RenderKitUtils.java 2010-01-03
23:33:55 UTC (rev 16232)
@@ -0,0 +1,201 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.renderkit;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIComponentBase;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public final class RenderKitUtils {
+
+ // TODO - check what's in MyFaces
+ private static final String ATTRIBUTES_THAT_ARE_SET = UIComponentBase.class.getName()
+ ".attributesThatAreSet";
+
+ private static final String[] BOOLEAN_ATTRIBUTE_NAMES = { "checked",
"compact", "declare", "defer", "disabled",
+ "ismap", "multiple", "nohref", "noshade",
"nowrap", "readonly", "selected" };
+
+ private static final String[] URI_ATTRIBUTE_NAMES = { "action",
"background", "cite", "classid", "codebase",
+ "data", "href", "longdesc", "profile",
"src", "usemap" };
+
+ private RenderKitUtils() {
+ // utility constructor
+ }
+
+ private static Map<String, List<ClientBehavior>>
getClientBehaviorsMap(UIComponent component) {
+ Map<String, List<ClientBehavior>> result = null;
+ if (component instanceof ClientBehaviorHolder) {
+ ClientBehaviorHolder clientBehaviorHolder = (ClientBehaviorHolder)
component;
+
+ result = clientBehaviorHolder.getClientBehaviors();
+ }
+
+ return result;
+ }
+
+ private static Object createBehaviorsChain(Object inlineHandlerValue,
List<ClientBehavior> behaviors) {
+ // TODO implement properly
+ return inlineHandlerValue;
+ }
+
+ private static boolean shouldRenderAttribute(String attributeName, Object
attributeValue) {
+ if (attributeValue instanceof String) {
+ return true;
+ } else if (attributeValue instanceof Boolean &&
Boolean.FALSE.equals(attributeValue)) {
+ return false;
+ } else if (attributeValue instanceof Integer && (Integer) attributeValue
== Integer.MIN_VALUE) {
+ return false;
+ } else if (attributeValue instanceof Double && (Double) attributeValue ==
Double.MIN_VALUE) {
+ return false;
+ } else if (attributeValue instanceof Character && (Character)
attributeValue == Character.MIN_VALUE) {
+ return false;
+ } else if (attributeValue instanceof Float && (Float) attributeValue ==
Float.MIN_VALUE) {
+ return false;
+ } else if (attributeValue instanceof Short && (Short) attributeValue ==
Short.MIN_VALUE) {
+ return false;
+ } else if (attributeValue instanceof Byte && (Byte) attributeValue ==
Byte.MIN_VALUE) {
+ return false;
+ } else if (attributeValue instanceof Long && (Long) attributeValue ==
Long.MIN_VALUE) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static void renderAttribute(FacesContext facesContext, String attributeName,
Object attributeValue)
+ throws IOException {
+
+ if (!shouldRenderAttribute(attributeName, attributeValue)) {
+ return;
+ }
+
+ ResponseWriter writer = facesContext.getResponseWriter();
+
+ if (Arrays.binarySearch(URI_ATTRIBUTE_NAMES, attributeName) >= 0) {
+ writer.writeURIAttribute(attributeName, attributeValue, attributeName);
+ } else if (Arrays.binarySearch(BOOLEAN_ATTRIBUTE_NAMES, attributeName) >= 0)
{
+ boolean booleanAttributeValue =
Boolean.valueOf(String.valueOf(attributeValue));
+ if (booleanAttributeValue) {
+ writer.writeAttribute(attributeName, attributeName, attributeName);
+ }
+ } else {
+ writer.writeAttribute(attributeName, attributeValue, attributeName);
+ }
+ }
+
+ public static void renderAttributeAndBehaviors(FacesContext facesContext, UIComponent
component,
+ ComponentAttribute componentAttribute) throws IOException {
+
+ if (facesContext == null) {
+ throw new NullPointerException("facesContext");
+ }
+
+ if (component == null) {
+ throw new NullPointerException("component");
+ }
+
+ if (componentAttribute == null) {
+ throw new NullPointerException("componentAttribute");
+ }
+
+ String attributeName = componentAttribute.getName();
+ Object attributeValue = component.getAttributes().get(attributeName);
+
+ Map<String, List<ClientBehavior>> behaviorsMap =
getClientBehaviorsMap(component);
+ if (behaviorsMap != null) {
+ String[] eventNames = componentAttribute.getEventNames();
+ if (eventNames != null) {
+ for (String eventName : eventNames) {
+ List<ClientBehavior> behaviorsList =
behaviorsMap.get(eventName);
+ if (behaviorsList != null) {
+ attributeValue = createBehaviorsChain(attributeValue,
behaviorsList);
+
+ break;
+ }
+ }
+ }
+ }
+
+ renderAttribute(facesContext, attributeName, attributeValue);
+ }
+
+ public static void renderPassThroughAttributesOptimized(FacesContext context,
UIComponent component,
+ Map<String, ComponentAttribute> knownAttributesMap) throws IOException {
+
+ Set<String> handledAttributes = new
HashSet<String>(knownAttributesMap.size());
+ Object attributesThatAreSetObject =
component.getAttributes().get(ATTRIBUTES_THAT_ARE_SET);
+ if (attributesThatAreSetObject instanceof Collection<?>) {
+ Collection<?> attributesThatAreSet = (Collection<?>)
attributesThatAreSetObject;
+ for (Object attributeNameObject : attributesThatAreSet) {
+ if (attributeNameObject == null) {
+ continue;
+ }
+
+ String attributeName = attributeNameObject.toString();
+
+ ComponentAttribute knownAttribute =
knownAttributesMap.get(attributeName);
+ if (knownAttribute != null) {
+ handledAttributes.add(attributeName);
+
+ // TODO check for disabled component
+ renderAttributeAndBehaviors(context, component, knownAttribute);
+ }
+ }
+
+ // render attributes that haven't been processed yet - there can be
behaviors
+ for (Map.Entry<String, ComponentAttribute> knownAttributesMapEntry :
knownAttributesMap.entrySet()) {
+ ComponentAttribute knownAttribute = knownAttributesMapEntry.getValue();
+
+ if (handledAttributes.contains(knownAttribute.getName())) {
+ continue;
+ }
+
+ renderAttributeAndBehaviors(context, component, knownAttribute);
+ }
+ } else {
+ // switch to unoptimized mode
+ renderPassThroughAttributes(context, component, knownAttributesMap);
+ }
+ }
+
+ public static void renderPassThroughAttributes(FacesContext context, UIComponent
component,
+ Map<String, ComponentAttribute> knownAttributesMap) throws IOException {
+
+ for (ComponentAttribute knownAttribute : knownAttributesMap.values()) {
+ renderAttributeAndBehaviors(context, component, knownAttribute);
+ }
+ }
+}