You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by al...@apache.org on 2010/07/31 00:37:34 UTC

svn commit: r980988 [5/8] - in /myfaces/gsoc/html5-comp-lib/trunk: ./ html5-comp-lib-core/ html5-comp-lib-core/src/ html5-comp-lib-core/src/main/ html5-comp-lib-core/src/main/java/ html5-comp-lib-core/src/main/java/META-INF/ html5-comp-lib-core/src/mai...

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/AbstractMediaRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/AbstractMediaRenderer.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/AbstractMediaRenderer.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/AbstractMediaRenderer.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.media;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.myfaces.html5.component.media.AbstractMedia;
+import org.apache.myfaces.html5.model.MediaInfo;
+import org.apache.myfaces.html5.renderkit.util.HTML5;
+import org.apache.myfaces.html5.renderkit.util.Html5RendererUtils;
+import org.apache.myfaces.shared_html5.renderkit.JSFAttr;
+import org.apache.myfaces.shared_html5.renderkit.RendererUtils;
+import org.apache.myfaces.shared_html5.renderkit.html.HtmlRenderer;
+
+/**
+ * Abstract base for media renderers.
+ * 
+ * @author Ali Ok
+ * 
+ */
+public abstract class AbstractMediaRenderer extends HtmlRenderer
+{
+    private static final Logger log = Logger.getLogger(AbstractMediaRenderer.class.getName());
+
+    protected static final String FACET_FALLBACK = "fallback";
+
+    @Override
+    public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
+    {
+        if (log.isLoggable(Level.FINE))
+            log.fine("encodeBegin");
+
+        super.encodeBegin(facesContext, uiComponent);
+
+        RendererUtils.checkParamValidity(facesContext, uiComponent, AbstractMedia.class);
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        AbstractMedia component = (AbstractMedia) uiComponent;
+
+        writer.startElement(getHtmlElementName(), uiComponent);
+
+        // write id
+        writer.writeAttribute(HTML5.ID_ATTR, component.getClientId(facesContext), null);
+
+        // get the value and render the src attr
+        String src = org.apache.myfaces.shared_html5.renderkit.RendererUtils.getStringValue(facesContext, component);
+        if (log.isLoggable(Level.FINE))
+            log.fine("writing src '" + src + "'");
+        if (src != null && !src.isEmpty())
+            writer.writeAttribute(HTML5.SRC_ATTR, src, JSFAttr.VALUE_ATTR);
+
+        // no need to check the value of preload, it is bypassed anyway.
+        // _checkPreload(component);
+
+        renderPassThruAttrsAndEvents(facesContext, uiComponent);
+
+    }
+
+    // to make this extendible
+    protected void renderPassThruAttrsAndEvents(FacesContext facesContext, UIComponent uiComponent) throws IOException
+    {
+        Map<String, List<ClientBehavior>> clientBehaviors = ((ClientBehaviorHolder) uiComponent).getClientBehaviors();
+
+        Html5RendererUtils.renderPassThroughClientBehaviorEventHandlers(facesContext, uiComponent,
+                getPassThroughClientBehaviorEvents(), clientBehaviors);
+
+        Html5RendererUtils.renderPassThroughAttributes(facesContext.getResponseWriter(), uiComponent,
+                getPassThroughAttributes());
+    }
+
+    protected abstract Map<String, String> getPassThroughClientBehaviorEvents();
+
+    // package-private, since extensibility of this is not desired
+    abstract String getHtmlElementName();
+
+    protected abstract Map<String, String> getPassThroughAttributes();
+
+    @Override
+    public void encodeChildren(FacesContext facesContext, UIComponent uiComponent) throws IOException
+    {
+        // don't call super.encodeChildren(...), since it lets children to encode themselves
+        if (log.isLoggable(Level.FINE))
+            log.fine("encodeChildren");
+
+        RendererUtils.checkParamValidity(facesContext, uiComponent, AbstractMedia.class);
+
+        renderFallbackFacet(facesContext, uiComponent);
+
+        renderMediaSources(facesContext, uiComponent);
+
+    }
+
+    @Override
+    public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException
+    {
+        if (log.isLoggable(Level.FINE))
+            log.fine("encodeEnd");
+        // just close the element
+        super.encodeEnd(facesContext, component);
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        writer.endElement(getHtmlElementName());
+    }
+
+    @Override
+    public boolean getRendersChildren()
+    {
+        return true;
+    }
+
+    /**
+     * Renders extracted media sources.
+     */
+    protected void renderMediaSources(FacesContext facesContext, UIComponent uiComponent) throws IOException
+    {
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        // type check is done above with RendererUtils.checkParamValidity(...)
+        AbstractMedia component = (AbstractMedia) uiComponent;
+
+        // render MediaInfo instances
+        Set<MediaInfo> mediaInfoSet = component.getMediaInfos();
+        if (mediaInfoSet != null)
+        {
+            for (MediaInfo mediaInfo : mediaInfoSet)
+            {
+                if (mediaInfo.isDisabled())
+                    continue;
+
+                writer.startElement(HTML5.SOURCE_ELEM, null);
+
+                // src is reqired to be present and not empty!
+                if (mediaInfo.getSrc() == null || mediaInfo.getSrc().isEmpty())
+                    // WIKI: add a wiki page
+                    throw new FacesException("'src' field of MediaInfo has to be defined and nonempty for component " + RendererUtils.getPathToComponent(uiComponent) + ".");
+
+                writer.writeAttribute(HTML5.SRC_ATTR, mediaInfo.getSrc(), null);
+
+                String typeVal = _getTypeForSource(mediaInfo);
+                if (typeVal != null) // write even if empty str
+                    writer.writeAttribute(HTML5.TYPE_ATTR, typeVal, null);
+
+                if (mediaInfo.getMedia() != null) // write even if empty str
+                    writer.writeAttribute(HTML5.MEDIA_ATTR, mediaInfo.getMedia(), null);
+
+                writer.endElement(HTML5.SOURCE_ELEM);
+            }
+        }
+    }
+
+    protected void renderFallbackFacet(FacesContext facesContext, UIComponent uiComponent) throws IOException
+    {
+        UIComponent fallbackFacet = uiComponent.getFacet(FACET_FALLBACK);
+        if (fallbackFacet != null && fallbackFacet.isRendered())
+        {
+            if (log.isLoggable(Level.FINE))
+                log.fine("rendering fallback facet");
+            fallbackFacet.encodeAll(facesContext);
+        }
+    }
+
+    /**
+     * Returns the value of "type" attribute of Html5 <source> element. <br/>
+     * e.g.: 'video/mp4;codecs="avc1.4D401E, mp4a.40.2"'
+     */
+    private String _getTypeForSource(MediaInfo mediaInfo)
+    {
+        String contentType = mediaInfo.getContentType();
+        String codec = mediaInfo.getCodec();
+
+        boolean contentTypeDefined = contentType != null && !contentType.isEmpty();
+        boolean codecDefined = codec != null && !codec.isEmpty();
+
+        // if codec is set, then contentType should be set too!
+        if (codecDefined && !contentTypeDefined)
+            // WIKI: add a wiki and ref it here
+            throw new FacesException(
+                    "'codec' is defined but 'contentType' is not. If 'codec' is defined, 'contentType' has to be defined too.");
+
+        String retVal = null;
+        if (contentTypeDefined)
+        {
+            StringBuilder builder = new StringBuilder();
+            builder.append(contentType);
+            // aliok: I tried <video> <source> with no codec on browser, and no problem experienced.
+            if (codecDefined)
+            {
+                builder.append("; codec='").append(codec).append("'");
+            }
+
+            retVal = builder.toString();
+        }
+
+        return retVal;
+    }
+
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/AudioRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/AudioRenderer.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/AudioRenderer.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/AudioRenderer.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.media;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFRenderer;
+import org.apache.myfaces.html5.component.media.Audio;
+import org.apache.myfaces.html5.renderkit.util.HTML5;
+import org.apache.myfaces.html5.renderkit.util.PassThroughAttributes;
+import org.apache.myfaces.html5.renderkit.util.PassThroughClientBehaviorEvents;
+import org.apache.myfaces.shared_html5.renderkit.RendererUtils;
+
+/**
+ * Renderer for < hx:audio > component.
+ * 
+ * @author Ali Ok
+ * 
+ */
+@JSFRenderer(renderKitId = "HTML_BASIC", family = "org.apache.myfaces.Media", type = "org.apache.myfaces.html5.Audio")
+public class AudioRenderer extends AbstractMediaRenderer
+{
+
+    @Override
+    public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
+    {
+        RendererUtils.checkParamValidity(facesContext, uiComponent, Audio.class);
+
+        super.encodeBegin(facesContext, uiComponent);
+    }
+
+    @Override
+    protected Map<String, String> getPassThroughAttributes()
+    {
+        return PassThroughAttributes.AUDIO;
+    }
+    
+    @Override
+    protected Map<String, String> getPassThroughClientBehaviorEvents()
+    {
+        return PassThroughClientBehaviorEvents.AUDIO;
+    }
+
+    @Override
+    String getHtmlElementName()
+    {
+        return HTML5.AUDIO_ELEM;
+    }
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/VideoRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/VideoRenderer.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/VideoRenderer.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/media/VideoRenderer.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.media;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFRenderer;
+import org.apache.myfaces.html5.component.media.Video;
+import org.apache.myfaces.html5.renderkit.util.HTML5;
+import org.apache.myfaces.html5.renderkit.util.PassThroughAttributes;
+import org.apache.myfaces.html5.renderkit.util.PassThroughClientBehaviorEvents;
+import org.apache.myfaces.shared_html5.renderkit.RendererUtils;
+
+/**
+ * Renderer for < hx:video > component.
+ * 
+ * @author Ali Ok
+ * 
+ */
+@JSFRenderer(renderKitId = "HTML_BASIC", family = "org.apache.myfaces.Media", type = "org.apache.myfaces.html5.Video")
+public class VideoRenderer extends AbstractMediaRenderer
+{
+
+    @Override
+    public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
+    {
+        RendererUtils.checkParamValidity(facesContext, uiComponent, Video.class);
+
+        super.encodeBegin(facesContext, uiComponent);
+    }
+
+    @Override
+    protected Map<String, String> getPassThroughAttributes()
+    {
+        return PassThroughAttributes.VIDEO;
+    }
+
+    @Override
+    protected Map<String, String> getPassThroughClientBehaviorEvents()
+    {
+        return PassThroughClientBehaviorEvents.VIDEO;
+    }
+
+    @Override
+    String getHtmlElementName()
+    {
+        return HTML5.VIDEO_ELEM;
+    }
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/panel/DivRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/panel/DivRenderer.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/panel/DivRenderer.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/panel/DivRenderer.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.panel;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFRenderer;
+import org.apache.myfaces.html5.component.panel.AbstractDiv;
+import org.apache.myfaces.html5.renderkit.util.HTML5;
+import org.apache.myfaces.html5.renderkit.util.Html5RendererUtils;
+import org.apache.myfaces.html5.renderkit.util.PassThroughAttributes;
+import org.apache.myfaces.html5.renderkit.util.PassThroughClientBehaviorEvents;
+import org.apache.myfaces.shared_html5.renderkit.RendererUtils;
+import org.apache.myfaces.shared_html5.renderkit.html.HtmlRenderer;
+import org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils;
+
+/**
+ * Div renderer.
+ * 
+ * @author Ali Ok
+ * 
+ */
+@JSFRenderer(renderKitId = "HTML_BASIC", family = "org.apache.myfaces.Div", type = "org.apache.myfaces.html5.Div")
+public class DivRenderer extends HtmlRenderer
+{
+
+    private static final Logger log = Logger.getLogger(DivRenderer.class.getName());
+
+    @Override
+    public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
+    {
+        if (log.isLoggable(Level.FINE))
+            log.fine("encodeBegin");
+
+        super.encodeBegin(facesContext, uiComponent);
+
+        RendererUtils.checkParamValidity(facesContext, uiComponent, AbstractDiv.class);
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        AbstractDiv component = (AbstractDiv) uiComponent;
+
+        writer.startElement(HTML5.DIV_ELEM, uiComponent);
+
+        // write id
+        writer.writeAttribute(HTML5.ID_ATTR, component.getClientId(facesContext), null);
+
+        renderPassThruAttrsAndEvents(facesContext, uiComponent);
+
+    }
+
+    // to make extensible rendering those, extracted into a protected method.
+    protected void renderPassThruAttrsAndEvents(FacesContext facesContext, UIComponent uiComponent) throws IOException
+    {
+        Map<String, List<ClientBehavior>> clientBehaviors = ((ClientBehaviorHolder) uiComponent).getClientBehaviors();
+
+        Html5RendererUtils.renderPassThroughClientBehaviorEventHandlers(facesContext, uiComponent,
+                PassThroughClientBehaviorEvents.DIV, clientBehaviors);
+
+        Html5RendererUtils.renderPassThroughAttributes(facesContext.getResponseWriter(), uiComponent,
+                PassThroughAttributes.DIV);
+    }
+
+    @Override
+    public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException
+    {
+        if (log.isLoggable(Level.FINE))
+            log.fine("encodeEnd");
+        // just close the element
+        super.encodeEnd(facesContext, component);
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        writer.endElement(HTML5.DIV_ELEM);
+    }
+
+    @Override
+    public boolean getRendersChildren()
+    {
+        return false;
+    }
+
+    @Override
+    public void decode(FacesContext context, UIComponent component)
+    {
+        // Check for npe
+        super.decode(context, component);
+
+        HtmlRendererUtils.decodeClientBehaviors(context, component);
+    }
+
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/AttributeMap.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/AttributeMap.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/AttributeMap.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/AttributeMap.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.util;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Map that is used for holding the pass through attributes and events for components.
+ * 
+ * @author Ali Ok
+ * @see PassThroughAttributes
+ * @see PassThroughClientBehaviorEvents
+ */
+class AttributeMap<K, V>
+{
+    private Map<String, String> _innerMap;
+
+    private AttributeMap()
+    {
+        this._innerMap = new HashMap<String, String>();
+    }
+
+    private AttributeMap(int initialCapacity)
+    {
+        this._innerMap = new HashMap<String, String>(initialCapacity, 0.5F);
+    }
+
+    AttributeMap<K, V> attr(String jsfAttrName, String htmlAttrName)
+    {
+        this._innerMap.put(jsfAttrName, htmlAttrName);
+        return this;
+    }
+
+    /**
+     * Assumes the html attribute name is same with jsf property name.
+     */
+    AttributeMap<K, V> attr(String jsfAttrName)
+    {
+        this._innerMap.put(jsfAttrName, jsfAttrName);
+        return this;
+    }
+
+    AttributeMap<K, V> attrs(Map<String, String> attrs)
+    {
+        this._innerMap.putAll(attrs);
+        return this;
+    }
+
+    AttributeMap<K, V> event(String jsfAttrName, String eventName)
+    {
+        this._innerMap.put(jsfAttrName, eventName);
+        return this;
+    }
+
+    AttributeMap<K, V> events(Map<String, String> events)
+    {
+        this._innerMap.putAll(events);
+        return this;
+    }
+
+    Map<String, String> unmodifiable()
+    {
+        return Collections.unmodifiableMap(this._innerMap);
+    }
+
+    // stuff for static import
+    static AttributeMap<String, String> map()
+    {
+        return new AttributeMap<String, String>();
+    }
+
+    /**
+     * @param initialCapacity
+     *            For performance optimization.
+     */
+    static AttributeMap<String, String> map(int initialCapacity)
+    {
+        return new AttributeMap<String, String>(initialCapacity);
+    }
+
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/BehaviorScriptUtils.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/BehaviorScriptUtils.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/BehaviorScriptUtils.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/BehaviorScriptUtils.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.util;
+
+
+/**
+ * Contains utility methods for converting Java objects to Javascript objects to use in behavior renderers.
+ * 
+ * @author Ali Ok
+ *
+ */
+public class BehaviorScriptUtils
+{
+    /**
+     * Converts the given array to Javascript literal array. <br/>
+     * For example the Java string array <code>{"Kobe", "LeBron", "Shaq"}</code> will be converted to <code>['Kobe','LeBron','Shaq']</code> .
+     * 
+     * @param arr
+     * @return null if arr is null, <code>[]</code> if arr is empty array.
+     */
+    public static String convertToSafeJavascriptLiteralArray(String[] arr)
+    {
+        if (arr == null)
+            return null;
+
+        if (arr.length == 0)
+        {
+            return "[]";
+        }
+
+        StringBuilder builder = new StringBuilder();
+        builder.append('[');
+        for (String string : arr)
+        {
+            builder.append('\'').append(string).append('\'').append(',');
+        }
+        builder.deleteCharAt(builder.length() - 1); // delete the last comma
+        builder.append(']');
+
+        return builder.toString();
+    }
+
+    /**
+     * Converts the given string to Javascript string. <br/>
+     * For example, a call with <code>String str = "Celtics".</code> will return <code>'Celtics'</code>;
+     * 
+     * @param str
+     * @return null if str is null;
+     */
+    public static String convertToSafeJavascriptLiteral(String str)
+    {
+        if (str == null)
+            return null;
+
+        return "'" + str + "'";
+    }
+
+    /**
+     * Returns the Javascript space separated representation of the given array.<br/>
+     * For example, for <code>String[] arr = {"idOne", "idTwo"}</code>, the returned value will be <code>'idOne idTwo'</code>.
+     * 
+     * @param arr
+     * @return null if arr is null or empty.
+     */
+    public static String convertToSpaceSeperatedJSLiteral(String[] arr)
+    {
+        if (arr == null || arr.length == 0)
+            return null;
+
+        StringBuilder builder = new StringBuilder();
+        builder.append("'");
+        for (String string : arr)
+        {
+            builder.append(string).append(' ');
+        }
+        builder.deleteCharAt(builder.length() - 1); // delete the last space
+        builder.append("'");
+
+        return builder.toString();
+    }
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/ClientBehaviorEvents.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/ClientBehaviorEvents.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/ClientBehaviorEvents.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/ClientBehaviorEvents.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.util;
+
+/**
+ * Holds the client behavior events. <br/>
+ * Note that this interface does not contain all of the events specified in Html5 spec, it contains only the used ones
+ * in MyFaces Html5 Components.
+ * 
+ * @author Ali Ok
+ */
+public interface ClientBehaviorEvents
+{
+    // DnD Events
+    String DRAG_EVENT = "drag";
+    String DROP_EVENT = "drop";
+    String DRAGENTER_EVENT = "dragenter";
+    String DRAGLEAVE_EVENT = "dragleave";
+    String DRAGOVER_EVENT = "dragover";
+    String DRAGSTART_EVENT = "dragstart";
+    String DRAGEND_EVENT = "dragend";
+
+    // Form events that are new with Html5
+    String FORMCHANGE_EVENT = "formchange";
+    String FORMINPUT_EVENT = "forminput";
+    String INPUT_EVENT = "input";
+    String INVALID_EVENT = "invalid";
+
+    // Mouse event that is new with Html5
+    String MOUSEWHEEL_EVENT = "mousewheel";
+
+    // Video and audio events
+    String ENDED_EVENT = "ended";
+    String ERROR_EVENT = "error";
+    String LOADEDDATA_EVENT = "loadeddata";
+    String LOADEDMETADATA_EVENT = "loadedmetadata";
+    String LOADSTART_EVENT = "loadstart";
+    String PAUSE_EVENT = "pause";
+    String PLAY_EVENT = "play";
+    String PLAYING_EVENT = "playing";
+    String PROGRESS_EVENT = "progress";
+    String SEEKED_EVENT = "seeked";
+    String SEEKING_EVENT = "seeking";
+    String VOLUMECHANGE_EVENT = "volumechange";
+    String WAITING_EVENT = "waiting";
+
+    // Events that are NOT new with Html5
+    String BLUR_EVENT = "blur";
+    String CLICK_EVENT = "click";
+    String DBLCLICK_EVENT = "dblclick";
+    String FOCUS_EVENT = "focus";
+    String KEYDOWN_EVENT = "keydown";
+    String KEYPRESS_EVENT = "keypress";
+    String KEYUP_EVENT = "keyup";
+    String MOUSEDOWN_EVENT = "mousedown";
+    String MOUSEMOVE_EVENT = "mousemove";
+    String MOUSEOUT_EVENT = "mouseout";
+    String MOUSEOVER_EVENT = "mouseover";
+    String MOUSEUP_EVENT = "mouseup";
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/HTML5.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/HTML5.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/HTML5.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/HTML5.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.util;
+
+/**
+ * Html constants for using in renderers. Does not extend {@link org.apache.myfaces.shared_html5.renderkit.html.HTML} on
+ * purpose, since there are ugly constants like
+ * "COMMON_FIELD_PASSTROUGH_ATTRIBUTES_WITHOUT_DISABLED_AND_ONFOCUS_AND_ONCLICK" in there. <br/>
+ * Note that, this interface does not contain all of the element names and attribute names specified in Html5 spec. It
+ * only contains used ones in MyFaces Html5 components, and may not contain the attributes which have the same name with
+ * the Jsf component property.
+ * 
+ * @author Ali Ok
+ * @see org.apache.myfaces.shared_html5.renderkit.html.HTML
+ */
+public interface HTML5
+{
+
+    // new html5 elements
+    String VIDEO_ELEM = "video";
+    String AUDIO_ELEM = "audio";
+    String SOURCE_ELEM = "source";
+    String DATALIST_ELEM = "datalist";
+
+    // html elements
+    String TEXTAREA_ELEM = "textarea";
+    String DIV_ELEM = "div";
+
+    // general attrs
+    String ID_ATTR = "id";
+    String HEIGHT_ATTR = "height";
+    String WIDTH_ATTR = "width";
+    String SRC_ATTR = "src";
+    String TYPE_ATTR = "type";
+    String CLASS_ATTR = "class";
+    String VALUE_ATTR = "value";
+
+    // media attrs
+    String CONTROLS_ATTR = "controls"; // not pass thru
+
+    // video attrs
+    String POSTER_ATTR = "poster";
+
+    // media source attrs
+    String MEDIA_ATTR = "media";
+
+    // input types
+    String INPUT_TYPE_TEXT = "text";
+    String INPUT_TYPE_PASSWORD = "password";
+    // new HTML5 input types
+    String INPUT_TYPE_COLOR = "color";
+    String INPUT_TYPE_SEARCH = "search";
+    String INPUT_TYPE_TEL = "tel";
+    String INPUT_TYPE_URL = "url";
+    String INPUT_TYPE_EMAIL = "email";
+    String INPUT_TYPE_RANGE = "range";
+    String INPUT_TYPE_NUMBER = "number";
+    String INPUT_TYPE_DATETIME = "datetime";
+    String INPUT_TYPE_DATE = "date";
+    String INPUT_TYPE_TIME = "time";
+    String INPUT_TYPE_MONTH = "month";
+    String INPUT_TYPE_WEEK = "week";
+    String INPUT_TYPE_DATETIME_LOCAL = "datetime-local";
+
+    // input attrs
+    String LIST_ATTR = "list";
+    String PATTERN_ATTR = "pattern";
+    String MIN_ATTR = "min";
+    String MAX_ATTR = "max";
+    String STEP_ATTR = "step";
+
+    // new Html5 attributes which is boolean but not Html5 boolean
+    // @see Html5RendererUtils#renderHTMLAttribute(javax.faces.context.ResponseWriter, String, String, Object)
+    String DRAGGABLE_ATTR = "draggable";
+    String CONTENTEDITABLE_ATTR = "contenteditable";
+    String SPELLCHECK_ATTR = "spellcheck";
+
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/Html5RendererUtils.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/Html5RendererUtils.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/Html5RendererUtils.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/Html5RendererUtils.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.util;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIOutput;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.convert.Converter;
+
+import org.apache.myfaces.html5.component.input.Html5BaseInputText;
+import org.apache.myfaces.shared_html5.renderkit.RendererUtils;
+import org.apache.myfaces.shared_html5.renderkit.html.HtmlRendererUtils;
+
+/**
+ * Renderer utils for common stuff.
+ * <p>
+ * Does not extend org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils on purpose, since this class should not
+ * expose methods like
+ * {@link org.apache.myfaces.shared_html5.renderkit.html.HtmlRendererUtils#renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIComponent, java.util.Map)}
+ * 
+ * @author Ali Ok
+ * 
+ */
+public class Html5RendererUtils
+{
+
+    private static final List<String> BOOLEAN_BUT_NOT_HTML5_BOOLEAN_ATTRS = Arrays.asList(HTML5.CONTENTEDITABLE_ATTR,
+            HTML5.DRAGGABLE_ATTR, HTML5.SPELLCHECK_ATTR);
+
+    private static final String HTML_EVENT_ATTR_PREFIX = "on";
+
+    /**
+     * Renders the pass through attributes of the component. Value of the JSF properties will be written with the
+     * matching Html attribute name.
+     * 
+     * @param writer
+     * @param component
+     * @param passThruAttrs
+     *            map that holds jsf property names as keys and html attribute names as values matched.
+     * 
+     * @return true, if an attribute was written
+     * @throws java.io.IOException
+     */
+    public static boolean renderPassThroughAttributes(ResponseWriter writer, UIComponent component,
+            Map<String, String> passThruAttrs) throws IOException
+    {
+        boolean somethingDone = false;
+        Set<String> passThruJsfProperties = passThruAttrs.keySet();
+        for (String passThruJsfPropertyName : passThruJsfProperties)
+        {
+            String passThruHtmlAttrName = passThruAttrs.get(passThruJsfPropertyName);
+            Object value = component.getAttributes().get(passThruJsfPropertyName);
+
+            if (renderHTMLAttribute(writer, passThruJsfPropertyName, passThruHtmlAttrName, value))
+            {
+                somethingDone = true;
+            }
+        }
+        return somethingDone;
+    }
+
+    /**
+     * Renders the attribute if the value is not the default value defined in the component. <br/>
+     * For three Html5 attributes (draggable, contenteditable and spellcheck), "true" will be written instead of the
+     * attribute's name as the value if the value is true. This behavior is necessary, since Html5 spec does not define
+     * those attributes as "Boolean Attribute"s. <br/>
+     * See related sections of Html5 spec for more:
+     * <ul>
+     * <li><a href="http://www.whatwg.org/specs/web-apps/current-work/#boolean-attribute">Boolean Attribute</a></li>
+     * <li><a
+     * href="http://www.whatwg.org/specs/web-apps/current-work/multipage/section-index.html#attributes-1">Attributes</a>
+     * </li>
+     * </ul>
+     * 
+     * @return true, if the attribute was written
+     * @throws java.io.IOException
+     */
+    public static boolean renderHTMLAttribute(ResponseWriter writer, String componentProperty, String attrName,
+            Object value) throws IOException
+    {
+        if (!RendererUtils.isDefaultAttributeValue(value))
+        {
+            if (BOOLEAN_BUT_NOT_HTML5_BOOLEAN_ATTRS.contains(attrName))
+            {
+                /*
+                 * these attrs are not Html5 "Booolean Attribute"s : contenteditable draggable spellcheck
+                 * http://www.whatwg.org/specs/web-apps/current-work/#boolean-attribute
+                 * http://www.whatwg.org/specs/web-apps/current-work/multipage/section-index.html#attributes-1
+                 * 
+                 * so draggable="draggable" is a syntax error. for these attrs, we need to render ="true" like
+                 * draggable="true". so, to prevent writer.writeAttribute(...) render that, this is the workaround!
+                 * 
+                 * TODO: file a ticket on JIRA for this issue
+                 */
+
+                if (value instanceof Boolean)
+                {
+                    value = String.valueOf(((Boolean) value).booleanValue());
+                }
+            }
+            writer.writeAttribute(attrName, value, componentProperty);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Renders the client behavior event handlers for the component by investigating both client behaviors and values of
+     * the behaviorized attributes.
+     */
+    public static void renderPassThroughClientBehaviorEventHandlers(FacesContext facesContext, UIComponent uiComponent,
+            Map<String, String> passThroughClientBehaviors, Map<String, List<ClientBehavior>> clientBehaviors)
+            throws IOException
+    {
+
+        Set<String> keySet = passThroughClientBehaviors.keySet();
+        for (String property : keySet)
+        {
+            String eventName = passThroughClientBehaviors.get(property);
+            String htmlAttrName = HTML_EVENT_ATTR_PREFIX + eventName;
+
+            org.apache.myfaces.shared_html5.renderkit.html.HtmlRendererUtils.renderBehaviorizedAttribute(facesContext,
+                    facesContext.getResponseWriter(), property, uiComponent, eventName, clientBehaviors, htmlAttrName);
+        }
+
+    }
+
+    /**
+     * Resolves string values from comma separated strings, string arrays or string collections.
+     * 
+     * @param value
+     * @return null if value param is null or empty
+     * @throws IllegalArgumentException
+     *             if value is not comma separated strings or String[] or Collection<String>.
+     * @see Html5RendererUtils#resolveStrings(Object, String[])
+     */
+    public static String[] resolveStrings(Object value) throws IllegalArgumentException
+    {
+        return resolveStrings(value, null);
+    }
+
+    /**
+     * Resolves string values from comma separated strings, string arrays or string collections.
+     * 
+     * @param value
+     *            Object to resolve
+     * @param defaultValue
+     *            Return value if value param is null or empty
+     * @throws IllegalArgumentException
+     *             if value is not comma separated strings or String[] or Collection<String>.
+     */
+    @SuppressWarnings("unchecked")
+    public static String[] resolveStrings(Object value, String[] defaultValue) throws IllegalArgumentException
+    {
+
+        if (value == null)
+        {
+            return defaultValue;
+        }
+
+        Collection<String> valuesCollection = null;
+
+        if (value instanceof String)
+        {
+
+            String strValues = (String) value;
+            if (strValues.isEmpty())
+                return defaultValue;
+
+            // if value is comma separated words, split it
+            String[] strValueElements = strValues.split(",");
+
+            valuesCollection = new ArrayList<String>(strValueElements.length);
+
+            for (String strValueElement : strValueElements)
+            {
+                strValueElement = strValueElement.trim();
+
+                if (!strValueElement.isEmpty())
+                    valuesCollection.add(strValueElement);
+            }
+        }
+        else if (value instanceof String[])
+        {
+            valuesCollection = Arrays.asList((String[]) value);
+        }
+        else if (value instanceof Collection<?>)
+        {
+            valuesCollection = (Collection<String>) value;
+        }
+        else
+        {
+            throw new IllegalArgumentException(
+                    "Value should be one of comma separeted strings, String[] or Collection of \"String\"s");
+        }
+
+        try
+        {
+            if (valuesCollection.isEmpty())
+                return defaultValue;
+            else
+                return valuesCollection.toArray(new String[0]);
+        }
+        catch (ArrayStoreException e)
+        {
+            // if there is one non-String element in the collection, we'll fall in here during conversion to array.
+            throw new IllegalArgumentException("All elements of the value must be an instance of String.", e);
+        }
+    }
+
+    /**
+     * Finds the converter of the component in a safe way.
+     * 
+     * @return null if no converter found or an exception occured inside
+     */
+    public static Converter findUIOutputConverterFailSafe(FacesContext facesContext, UIComponent component)
+    {
+        if(!(component instanceof UIOutput))
+            return null;
+        
+        return HtmlRendererUtils.findUIOutputConverterFailSafe(facesContext, component);
+    }
+
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/JsfProperties.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/JsfProperties.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/JsfProperties.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/JsfProperties.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.util;
+
+/**
+ * Includes constants for JSF component property names. <br/>
+ * Note that, this interface does not contain all of the properties of all components. Pass thru properties will be here
+ * for sure though.
+ * 
+ * @author Ali Ok
+ * 
+ */
+public interface JsfProperties
+{
+    // common props
+    String ID_PROP = "id";
+    String DIR_PROP = "dir";
+    String LANG_PROP = "lang";
+    String STYLE_PROP = "style";
+    String STYLECLASS_PROP = "styleClass";
+    String TITLE_PROP = "title";
+    String ACCESSKEY_PROP = "accesskey";
+    String TABINDEX_PROP = "tabindex";
+    String SRC_PROP = "src";
+    String WIDTH_PROP = "width";
+    String HEIGHT_PROP = "height";
+
+    // new Html5 common props
+    String HIDDEN_PROP = "hidden";
+    String DRAGGABLE_PROP = "draggable";
+
+    // media props
+    String PRELOAD_PROP = "preload";
+    String SHOW_CONTROLS_PROP = "showControls";
+    String LOOP_PROP = "loop";
+    String AUTOPLAY_PROP = "autoplay";
+    String POSTER_PROP = "poster";
+
+    // common event props
+    String ONBLUR_PROP = "onblur";
+    String ONCLICK_PROP = "onclick";
+    String ONDBLCLICK_PROP = "ondblclick";
+    String ONFOCUS_PROP = "onfocus";
+
+    //DnD props
+    String ONDRAG_PROP = "ondrag";
+    String ONDRAGEND_PROP = "ondragend";
+    String ONDRAGENTER_PROP = "ondragenter";
+    String ONDRAGLEAVE_PROP = "ondragleave";
+    String ONDRAGOVER_PROP = "ondragover";
+    String ONDRAGSTART_PROP = "ondragstart";
+    String ONDROP_PROP = "ONDROP";
+
+    // media event props
+    String ONENDED_PROP = "onended";
+    String ONERROR_PROP = "onerror";
+    String ONLOADEDDATA_PROP = "onloadeddata";
+    String ONLOADEDMETADATA_PROP = "onloadedmetadata";
+    String ONLOADSTART_PROP = "onloadstart";
+    String ONPAUSE_PROP = "onpause";
+    String ONPLAY_PROP = "onplay";
+    String ONPLAYING_PROP = "onplaying";
+    String ONPROGRESS_PROP = "onprogress";
+    String ONSEEKED_PROP = "onseeked";
+    String ONSEEKING_PROP = "onseeking";
+    String ONVOLUMECHANGE_PROP = "onvolumechange";
+    String ONWAITING_PROP = "onwaiting";
+
+    //common key props
+    String ONKEYDOWN_PROP = "onkeydown";
+    String ONKEYPRESS_PROP = "onkeypress";
+    String ONKEYUP_PROP = "onkeyup";
+
+    //common mouse props
+    String ONMOUSEDOWN_PROP = "onmousedown";
+    String ONMOUSEMOVE_PROP = "onmousemove";
+    String ONMOUSEOUT_PROP = "onmouseout";
+    String ONMOUSEOVER_PROP = "onmouseover";
+    String ONMOUSEUP_PROP = "onmouseup";
+    String ONMOUSEWHEEL_PROP = "onmousewheel";      //is a new Html5 mouse attribute
+
+    // html5 new input props
+    String DATALIST_PROP = "datalist";
+    String AUTOFOCUS_PROP = "autofocus";
+    String ONFORMCHANGE_PROP = "onformchange";
+    String ONFORMINPUT_PROP = "onforminput";
+    String ONINPUT_PROP = "oninput";
+    String ONINVALID_PROP = "oninvalid";
+
+    // input text props
+    String PLACEHOLDER_PROP = "placeholder";
+    String REQUIRED_PROP = "required";
+    String MAXLENGTH_PROP = "maxlength";
+    String READONLY_PROP = "readonly";
+    String STEP_PROP = "step";
+
+    // input email props
+    String MULTIPLE_PROP = "multiple";
+
+    // possible types for hx:inputText
+    String INPUTTEXT_TYPE_PASSWORD = "password";
+    String INPUTTEXT_TYPE_TEXTAREA = "textarea";
+    String INPUTTEXT_TYPE_TEXT = "text";
+    String INPUTTEXT_TYPE_SEARCH = "search";
+    String INPUTTEXT_TYPE_URL = "url";
+    String INPUTTEXT_TYPE_TEL = "tel";
+
+    //possible types for hx:inputDateTime
+    String INPUTDATETIME_TYPE_DATETIME = "datetime";
+    String INPUTDATETIME_TYPE_DATE = "date";
+    String INPUTDATETIME_TYPE_TIME = "time";
+    String INPUTDATETIME_TYPE_MONTH = "month";
+    String INPUTDATETIME_TYPE_WEEK = "week";
+    String INPUTDATETIME_TYPE_DATETIME_LOCAL = "datetime-local";
+    
+
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughAttributeGroups.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughAttributeGroups.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughAttributeGroups.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughAttributeGroups.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.util;
+
+import static org.apache.myfaces.html5.renderkit.util.AttributeMap.*;
+import static org.apache.myfaces.html5.renderkit.util.JsfProperties.*;
+import static org.apache.myfaces.html5.renderkit.util.HTML5.*;
+
+import java.util.Map;
+
+/**
+ * Includes pass through property groups.
+ * <p>
+ * These groups are not intended to be exposed public, so that's why this is extracted from {@link PassThroughAttributes}. 
+ * @author Ali Ok
+ *
+ */
+interface PassThroughAttributeGroups {
+    
+    Map<String, String> HTML_GLOBAL_PROPS = map(7)
+        .attr(DIR_PROP)
+        .attr(LANG_PROP)
+        .attr(STYLE_PROP)
+        .attr(STYLECLASS_PROP, CLASS_ATTR)
+        .attr(TITLE_PROP)
+        .attr(ACCESSKEY_PROP)
+        .attr(TABINDEX_PROP)
+        .unmodifiable();
+    
+    Map<String, String> DND_PROPS = map(1)
+        .attr(DRAGGABLE_PROP)
+        .unmodifiable();
+    
+    Map<String, String> HTML5_INPUT_PROPS = map(2)
+        .attr(DATALIST_PROP, LIST_ATTR)
+        .attr(AUTOFOCUS_PROP)
+        .unmodifiable();
+    
+    Map<String, String> HTML5_GLOBAL_PROPS = map(2)
+        .attrs(DND_PROPS)
+        .attr(HIDDEN_PROP)
+        .unmodifiable();
+}
\ No newline at end of file

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughAttributes.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughAttributes.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughAttributes.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughAttributes.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.util;
+
+import static org.apache.myfaces.html5.renderkit.util.AttributeMap.map;
+import static org.apache.myfaces.html5.renderkit.util.HTML5.*;
+import static org.apache.myfaces.html5.renderkit.util.JsfProperties.*;
+import org.apache.myfaces.html5.renderkit.util.PassThroughAttributeGroups;
+
+import java.util.Map;
+
+/**
+ * Includes pass through attributes for components.
+ * @author Ali Ok
+ *
+ */
+public interface PassThroughAttributes
+{
+    Map<String, String> AUDIO = map(13)
+        .attrs(PassThroughAttributeGroups.HTML5_GLOBAL_PROPS)
+        //media props
+        .attr(PRELOAD_PROP)
+        .attr(SHOW_CONTROLS_PROP, CONTROLS_ATTR)
+        .attr(LOOP_PROP)
+        .attr(AUTOPLAY_PROP)
+        //standard attrs parent doesn't have
+        .unmodifiable();
+
+    Map<String, String> VIDEO = map(15)
+        .attrs(AUDIO)
+        .attr(POSTER_PROP)
+        .attr(WIDTH_PROP)
+        .attr(HEIGHT_PROP)
+        .unmodifiable();
+
+    Map<String, String> INPUT_COLOR = map(4)
+        .attrs(PassThroughAttributeGroups.HTML5_GLOBAL_PROPS)
+        .attrs(PassThroughAttributeGroups.HTML5_INPUT_PROPS)
+        .unmodifiable();
+
+    Map<String, String> INPUT_TEXT = map(6)
+        .attrs(PassThroughAttributeGroups.HTML5_GLOBAL_PROPS)
+        .attrs(PassThroughAttributeGroups.HTML5_INPUT_PROPS)
+        .attr(PLACEHOLDER_PROP)
+        .attr(REQUIRED_PROP)
+        .unmodifiable();
+    
+    Map<String, String> INPUT_SECRET = map(5)
+        .attrs(PassThroughAttributeGroups.HTML5_GLOBAL_PROPS)
+        .attr(AUTOFOCUS_PROP)
+        .attr(PLACEHOLDER_PROP)
+        .attr(REQUIRED_PROP)
+        .unmodifiable();
+
+    Map<String, String> INPUT_TEXTAREA = map(5)
+        .attrs(PassThroughAttributeGroups.HTML5_GLOBAL_PROPS)
+        .attr(AUTOFOCUS_PROP)
+        .attr(REQUIRED_PROP)
+        .attr(MAXLENGTH_PROP)
+        .unmodifiable();
+
+    Map<String, String> INPUT_EMAIL = map(7)
+        .attrs(PassThroughAttributeGroups.HTML5_GLOBAL_PROPS)
+        .attrs(PassThroughAttributeGroups.HTML5_INPUT_PROPS)
+        .attr(PLACEHOLDER_PROP)
+        .attr(MULTIPLE_PROP)
+        .attr(REQUIRED_PROP)
+        .unmodifiable();
+
+    Map<String, String> DIV = map(7)
+        .attrs(PassThroughAttributeGroups.HTML_GLOBAL_PROPS)
+        .attrs(PassThroughAttributeGroups.HTML5_GLOBAL_PROPS)
+        .unmodifiable();
+
+    Map<String, String> INPUT_NUMBER_SLIDER = map(4)
+        .attrs(PassThroughAttributeGroups.HTML5_GLOBAL_PROPS)
+        .attrs(PassThroughAttributeGroups.HTML5_INPUT_PROPS)
+        .unmodifiable();
+
+    Map<String, String> INPUT_NUMBER_SPINNER = map(6)
+        .attrs(PassThroughAttributeGroups.HTML5_GLOBAL_PROPS)
+        .attrs(PassThroughAttributeGroups.HTML5_INPUT_PROPS)
+        .attr(REQUIRED_PROP)
+        .attr(READONLY_PROP)
+        .unmodifiable();
+
+    Map<String, String> INPUT_DATE_TIME = map(6)
+        .attrs(PassThroughAttributeGroups.HTML5_GLOBAL_PROPS)
+        .attrs(PassThroughAttributeGroups.HTML5_INPUT_PROPS)
+        .attr(REQUIRED_PROP)
+        .attr(READONLY_PROP)
+        .unmodifiable();
+    
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughClientBehaviorEventGroups.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughClientBehaviorEventGroups.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughClientBehaviorEventGroups.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughClientBehaviorEventGroups.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.util;
+
+import static org.apache.myfaces.html5.renderkit.util.AttributeMap.map;
+import static org.apache.myfaces.html5.renderkit.util.JsfProperties.*;
+import static org.apache.myfaces.html5.renderkit.util.ClientBehaviorEvents.*;
+
+import java.util.Map;
+
+/**
+ * Includes pass through behavior event groups.
+ * <p>
+ * These groups are not intended to be exposed public, so that's why this is extracted from {@link PassThroughClientBehaviorEvents}. 
+ * @author Ali Ok
+ *
+ */
+interface PassThroughClientBehaviorEventGroups
+{
+
+    Map<String, String> HTML_GLOBAL_BEHAVIOR_EVENTS = map(12)
+        .event(ONBLUR_PROP, BLUR_EVENT)
+        .event(ONCLICK_PROP, CLICK_EVENT)
+        .event(ONDBLCLICK_PROP, DBLCLICK_EVENT)
+        .event(ONFOCUS_PROP, FOCUS_EVENT)
+        .event(ONKEYDOWN_PROP, KEYDOWN_EVENT)
+        .event(ONKEYPRESS_PROP, KEYPRESS_EVENT)
+        .event(ONKEYUP_PROP, KEYUP_EVENT)
+        .event(ONMOUSEDOWN_PROP, MOUSEDOWN_EVENT)
+        .event(ONMOUSEMOVE_PROP, MOUSEMOVE_EVENT)
+        .event(ONMOUSEOUT_PROP, MOUSEOUT_EVENT)
+        .event(ONMOUSEOVER_PROP, MOUSEOVER_EVENT)
+        .event(ONMOUSEUP_PROP, MOUSEUP_EVENT)
+        .unmodifiable();
+    
+    Map<String, String> DND_BEHAVIOR_EVENTS = map(6)
+        .event(ONDRAG_PROP, DRAG_EVENT)
+        .event(ONDRAGEND_PROP, DRAGEND_EVENT)
+        .event(ONDRAGENTER_PROP, DRAGENTER_EVENT)
+        .event(ONDRAGLEAVE_PROP, DRAGLEAVE_EVENT)
+        .event(ONDRAGOVER_PROP, DRAGOVER_EVENT)
+        .event(ONDRAGSTART_PROP, DRAGSTART_EVENT)
+        .event(ONDROP_PROP, DROP_EVENT)
+        .unmodifiable();
+
+    
+    Map<String, String> HTML5_INPUT_BEHAVIOR_EVENTS = map(4)
+        .event(ONFORMCHANGE_PROP, FORMCHANGE_EVENT)
+        .event(ONFORMINPUT_PROP, FORMINPUT_EVENT)
+        .event(ONINPUT_PROP, INPUT_EVENT)
+        .event(ONINVALID_PROP, INVALID_EVENT)
+        .unmodifiable();
+    
+    
+    Map<String, String> HTML5_GLOBAL_BEHAVIOR_EVENTS = map(7)
+        .events(DND_BEHAVIOR_EVENTS)
+        .event(ONMOUSEWHEEL_PROP, MOUSEWHEEL_EVENT)
+        .unmodifiable();
+    
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughClientBehaviorEvents.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughClientBehaviorEvents.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughClientBehaviorEvents.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/renderkit/util/PassThroughClientBehaviorEvents.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.renderkit.util;
+
+import static org.apache.myfaces.html5.renderkit.util.AttributeMap.map;
+import static org.apache.myfaces.html5.renderkit.util.JsfProperties.*;
+import static org.apache.myfaces.html5.renderkit.util.ClientBehaviorEvents.*;
+
+import java.util.Map;
+
+/**
+ * Includes pass through behavior event definitions for components.
+ * @author Ali Ok
+ *
+ */
+public interface PassThroughClientBehaviorEvents
+{
+
+    Map<String, String> AUDIO = map(32)
+        .events(PassThroughClientBehaviorEventGroups.HTML5_GLOBAL_BEHAVIOR_EVENTS)
+        //media event props
+        .event(ONENDED_PROP, ENDED_EVENT)
+        .event(ONERROR_PROP, ERROR_EVENT)
+        .event(ONLOADEDDATA_PROP, LOADEDDATA_EVENT)
+        .event(ONLOADEDMETADATA_PROP, LOADEDMETADATA_EVENT)
+        .event(ONLOADSTART_PROP, LOADSTART_EVENT)
+        .event(ONPAUSE_PROP, PAUSE_EVENT)
+        .event(ONPLAY_PROP, PLAY_EVENT)
+        .event(ONPLAYING_PROP, PLAYING_EVENT)
+        .event(ONPROGRESS_PROP, PROGRESS_EVENT)
+        .event(ONSEEKED_PROP, SEEKED_EVENT)
+        .event(ONSEEKING_PROP, SEEKING_EVENT)
+        .event(ONVOLUMECHANGE_PROP, VOLUMECHANGE_EVENT)
+        .event(ONWAITING_PROP, WAITING_EVENT)
+        //standard events parent doesn't have
+        .event(ONBLUR_PROP, BLUR_EVENT)
+        .event(ONCLICK_PROP, CLICK_EVENT)
+        .event(ONDBLCLICK_PROP, DBLCLICK_EVENT)
+        .event(ONFOCUS_PROP, FOCUS_EVENT)
+        .event(ONKEYDOWN_PROP, KEYDOWN_EVENT)
+        .event(ONKEYPRESS_PROP, KEYPRESS_EVENT)
+        .event(ONKEYUP_PROP, KEYUP_EVENT)
+        .event(ONMOUSEDOWN_PROP, MOUSEDOWN_EVENT)
+        .event(ONMOUSEMOVE_PROP, MOUSEMOVE_EVENT)
+        .event(ONMOUSEOUT_PROP, MOUSEOUT_EVENT)
+        .event(ONMOUSEOVER_PROP, MOUSEOVER_EVENT)
+        .event(ONMOUSEUP_PROP, MOUSEUP_EVENT)
+        .unmodifiable();
+    
+    Map<String, String> VIDEO = map(32)
+        .events(AUDIO)
+        .unmodifiable();
+    
+    Map<String, String> BASE_INPUT = map(11)
+        .events(PassThroughClientBehaviorEventGroups.HTML5_GLOBAL_BEHAVIOR_EVENTS)
+        .events(PassThroughClientBehaviorEventGroups.HTML5_INPUT_BEHAVIOR_EVENTS)
+        .unmodifiable();
+
+    Map<String, String> DIV = map(11)
+        .events(PassThroughClientBehaviorEventGroups.HTML_GLOBAL_BEHAVIOR_EVENTS)
+        .events(PassThroughClientBehaviorEventGroups.HTML5_GLOBAL_BEHAVIOR_EVENTS)
+        .unmodifiable();
+    
+    
+}

Added: myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/validator/DateTimeRangeValidator.java
URL: http://svn.apache.org/viewvc/myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/validator/DateTimeRangeValidator.java?rev=980988&view=auto
==============================================================================
--- myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/validator/DateTimeRangeValidator.java (added)
+++ myfaces/gsoc/html5-comp-lib/trunk/html5-comp-lib-core/src/main/java/org/apache/myfaces/html5/validator/DateTimeRangeValidator.java Fri Jul 30 22:37:29 2010
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.html5.validator;
+
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.faces.FacesException;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.PartialStateHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.Validator;
+import javax.faces.validator.ValidatorException;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFValidator;
+import org.apache.myfaces.html5.component.input.HtmlInputDateTime;
+import org.apache.myfaces.html5.renderkit.input.util.Html5DateTimeFormatUtils;
+import org.apache.myfaces.html5.renderkit.util.HTML5;
+import org.apache.myfaces.shared_html5.renderkit.RendererUtils;
+
+/**
+ * Validate that the date entered is within a given range. Rendered min/max attributes of hx:inputDateTime is driven by
+ * this validator too. <br />
+ * 
+ * @author Ali Ok
+ * 
+ */
+@JSFValidator(name = "fx:validateDateTimeRange", bodyContent = "empty", tagClass = "org.apache.myfaces.html5.tag.input.ValidateDateTimeRangeTag", id = "org.apache.myfaces.html5.DateTimeRange")
+public class DateTimeRangeValidator implements Validator, PartialStateHolder
+{
+    private static final Logger log = Logger.getLogger(DateTimeRangeValidator.class.getName());
+
+    private Object _minimum = null;
+    private Object _maximum = null;
+    private String exceedMaximumMessage;
+    private String lessThanMinimumMessage;
+    private String notInRangeMessage;
+
+    private Date _resolvedMinimum;
+    private Date _resolvedMaximum;
+
+    private boolean _transient;
+
+    public void validate(FacesContext context, UIComponent uiComponent, Object value) throws ValidatorException
+    {
+        if (context == null)
+            throw new NullPointerException("facesContext");
+        if (uiComponent == null)
+            throw new NullPointerException("uiComponent");
+
+        if (value == null)
+        {
+            return;
+        }
+
+        if (uiComponent instanceof HtmlInputDateTime)
+        {
+            HtmlInputDateTime component = (HtmlInputDateTime) uiComponent;
+
+            if (value instanceof Date)
+            {
+                Date dateValue = (Date) value;
+                Date resolvedMinimum = null;
+                try
+                {
+                    resolvedMinimum = getResolvedMinimum(component.getType());
+                }
+                catch (ParseException e)
+                {
+                    throw new ValidatorException(new FacesMessage("Unable to resolve minimum for component "
+                            + RendererUtils.getPathToComponent(uiComponent) + "."), e);
+                }
+
+                Date resolvedMaximum = null;
+                try
+                {
+                    resolvedMaximum = getResolvedMaximum(component.getType());
+                }
+                catch (ParseException e)
+                {
+                    throw new ValidatorException(new FacesMessage("Unable to resolve maximum for component "
+                            + RendererUtils.getPathToComponent(uiComponent) + "."), e);
+                }
+
+                if (resolvedMinimum != null && resolvedMaximum != null)
+                {
+                    if (!resolvedMinimum.before(resolvedMaximum))
+                    {
+                        // not a ValidatorException since state is illegal
+                        throw new FacesException("Minimum value is before than maximum for component "
+                                + RendererUtils.getPathToComponent(uiComponent) + ".");
+                    }
+                    else
+                    {
+                        if (dateValue.before(resolvedMinimum) || dateValue.after(resolvedMaximum))
+                        {
+                            if (this.notInRangeMessage != null && !this.notInRangeMessage.isEmpty())
+                                throw new ValidatorException(new FacesMessage(this.notInRangeMessage));
+                            else
+                                throw new ValidatorException(
+                                        new FacesMessage("Submitted value is not in allowed range for component "
+                                                + RendererUtils.getPathToComponent(uiComponent) + ". Range is "
+                                                + resolvedMinimum.toString() + " - " + resolvedMaximum.toString() + "."));
+                        }
+                    }
+                }
+
+                if (resolvedMinimum != null && dateValue.before(resolvedMinimum))
+                {
+                    if (this.lessThanMinimumMessage != null && !this.lessThanMinimumMessage.isEmpty())
+                        throw new ValidatorException(new FacesMessage(this.lessThanMinimumMessage));
+                    else
+                        throw new ValidatorException(new FacesMessage("Value is before minimum for component "
+                                + RendererUtils.getPathToComponent(uiComponent) + ". Minimum value is "
+                                + resolvedMinimum.toString() + "."));
+                }
+
+                if (resolvedMaximum != null && dateValue.after(resolvedMaximum))
+                {
+                    if (this.exceedMaximumMessage != null && !this.exceedMaximumMessage.isEmpty())
+                        throw new ValidatorException(new FacesMessage(this.exceedMaximumMessage));
+                    else
+                        throw new ValidatorException(new FacesMessage("Value is after maximum for component "
+                                + RendererUtils.getPathToComponent(uiComponent) + ". Maximum value is "
+                                + resolvedMaximum.toString() + "."));
+                }
+            }
+        }
+        else
+        {
+            // noop
+            if (log.isLoggable(Level.WARNING))
+                log.warning("DateTimeRangeValidator can only be applied to instances of HtmlInputDateTime components.");
+
+        }
+    }
+
+    /**
+     * Resolves the minimum date from the minimum property which accepts both java.util.Date and String.
+     * 
+     * @throws ParseException
+     *             if the value of minimum property is String and cannot be parsed for the given type.
+     */
+    public Date getResolvedMinimum(String type) throws ParseException
+    {
+        // no synchronization necessary
+        if (_resolvedMinimum == null)
+            _resolvedMinimum = _resolveDateFromObject(_minimum, type);
+
+        return _resolvedMinimum;
+    }
+
+    /**
+     * Resolves the maximum date from the maximum property which accepts both java.util.Date and String.
+     * 
+     * @throws ParseException
+     *             if the value of maximum property is String and cannot be parsed for the given type.
+     */
+    public Date getResolvedMaximum(String type) throws ParseException
+    {
+        // no synchronization necessary
+        if (_resolvedMaximum == null)
+            _resolvedMaximum = _resolveDateFromObject(_maximum, type);
+
+        return _resolvedMaximum;
+    }
+
+    //Resolve the date based on parent component's type
+    private Date _resolveDateFromObject(Object value, String type) throws ParseException
+    {
+        if (value == null)
+            return null;
+
+        if (value instanceof String)
+        {
+            String strValue = (String) value;
+            return Html5DateTimeFormatUtils.parseDateTime(strValue, type);
+        }
+        else if (value instanceof Date)
+        {
+            Date dateValue = (Date) value;
+            if (HTML5.INPUT_TYPE_TIME.equals(type))
+            {
+                // XXX: may be it's better to leave this operation to user?
+                // we need to clear the date info (y, m, d) if the type is "time"
+                Calendar cal = Calendar.getInstance();
+                cal.setTime(dateValue);
+                cal.set(Calendar.YEAR, 1970);
+                cal.set(Calendar.MONTH, Calendar.JANUARY);
+                cal.set(Calendar.DAY_OF_MONTH, 1);
+                return cal.getTime();
+            }
+            else
+            {
+                return dateValue;
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException("Value " + type + "is not String nor java.util.Date. Unable to resolve.");
+        }
+
+    }
+
+    /**
+     * Minimum date that can be selected on client-side and is used on validation at server-side.
+     * Value must be either String, or java.util.Date. If String is given, the value must be in the format of parent hx:inputDateTime's type.
+     */
+    @JSFProperty(deferredValueType = "java.lang.Object")
+    public Object getMinimum()
+    {
+        return _minimum;
+    }
+
+    public void setMinimum(Object minimum)
+    {
+        this._minimum = minimum;
+        clearInitialState();
+    }
+
+    /**
+     * Maximum date that can be selected on client-side and is used on validation at server-side.
+     * Value must be either String, or java.util.Date. If String is given, the value must be in the format of parent hx:inputDateTime's type.
+     */
+    @JSFProperty(deferredValueType = "java.lang.Object")
+    public Object getMaximum()
+    {
+        return _maximum;
+    }
+
+    public void setMaximum(Object maximum)
+    {
+        this._maximum = maximum;
+        clearInitialState();
+    }
+
+    /**
+     * Message to show if the minimum is not set and submitted value exceeds specified maximum value.
+     */
+    @JSFProperty(deferredValueType = "java.lang.String")
+    public String getExceedMaximumMessage()
+    {
+        return exceedMaximumMessage;
+    }
+
+    public void setExceedMaximumMessage(String exceedMaximumMessage)
+    {
+        this.exceedMaximumMessage = exceedMaximumMessage;
+        clearInitialState();
+    }
+
+    /**
+     * Message to show if the maximum is not set and submitted value is before than specified minimum value.
+     */
+    @JSFProperty(deferredValueType = "java.lang.String")
+    public String getLessThanMinimumMessage()
+    {
+        return lessThanMinimumMessage;
+    }
+
+    public void setLessThanMinimumMessage(String lessThanMinimumMessage)
+    {
+        this.lessThanMinimumMessage = lessThanMinimumMessage;
+        clearInitialState();
+    }
+
+    /**
+     * Message to show if the minimum and minimum is set and submitted value is not in that range.
+     */
+    @JSFProperty(deferredValueType = "java.lang.String")
+    public String getNotInRangeMessage()
+    {
+        return notInRangeMessage;
+    }
+
+    public void setNotInRangeMessage(String notInRangeMessage)
+    {
+        this.notInRangeMessage = notInRangeMessage;
+        clearInitialState();
+    }
+
+    // RESTORE/SAVE STATE
+    public Object saveState(FacesContext context)
+    {
+        if (!initialStateMarked())
+        {
+            Object values[] = new Object[2];
+            values[0] = _maximum;
+            values[1] = _minimum;
+            return values;
+        }
+        return null;
+    }
+
+    public void restoreState(FacesContext context, Object state)
+    {
+        if (state != null)
+        {
+            Object values[] = (Object[]) state;
+            _maximum = (Double) values[0];
+            _minimum = (Double) values[1];
+        }
+    }
+
+    public boolean isTransient()
+    {
+        return _transient;
+    }
+
+    public void setTransient(boolean transientValue)
+    {
+        _transient = transientValue;
+    }
+
+    private boolean _initialStateMarked = false;
+
+    public void clearInitialState()
+    {
+        _initialStateMarked = false;
+    }
+
+    public boolean initialStateMarked()
+    {
+        return _initialStateMarked;
+    }
+
+    public void markInitialState()
+    {
+        _initialStateMarked = true;
+    }
+
+}